iwlwifi: pcie: fix polling in various places
[cascardo/linux.git] / drivers / gpu / drm / i915 / intel_sprite.c
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *   Jesse Barnes <jbarnes@virtuousgeek.org>
25  *
26  * New plane/sprite handling.
27  *
28  * The older chips had a separate interface for programming plane related
29  * registers; newer ones are much simpler and we can use the new DRM plane
30  * support.
31  */
32 #include <drm/drmP.h>
33 #include <drm/drm_crtc.h>
34 #include <drm/drm_fourcc.h>
35 #include <drm/drm_rect.h>
36 #include "intel_drv.h"
37 #include <drm/i915_drm.h>
38 #include "i915_drv.h"
39
40 static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
41 {
42         /* paranoia */
43         if (!mode->crtc_htotal)
44                 return 1;
45
46         return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
47 }
48
49 static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
50 {
51         struct drm_device *dev = crtc->base.dev;
52         const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
53         enum pipe pipe = crtc->pipe;
54         long timeout = msecs_to_jiffies_timeout(1);
55         int scanline, min, max, vblank_start;
56         DEFINE_WAIT(wait);
57
58         WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex));
59
60         vblank_start = mode->crtc_vblank_start;
61         if (mode->flags & DRM_MODE_FLAG_INTERLACE)
62                 vblank_start = DIV_ROUND_UP(vblank_start, 2);
63
64         /* FIXME needs to be calibrated sensibly */
65         min = vblank_start - usecs_to_scanlines(mode, 100);
66         max = vblank_start - 1;
67
68         if (min <= 0 || max <= 0)
69                 return false;
70
71         if (WARN_ON(drm_vblank_get(dev, pipe)))
72                 return false;
73
74         local_irq_disable();
75
76         trace_i915_pipe_update_start(crtc, min, max);
77
78         for (;;) {
79                 /*
80                  * prepare_to_wait() has a memory barrier, which guarantees
81                  * other CPUs can see the task state update by the time we
82                  * read the scanline.
83                  */
84                 prepare_to_wait(&crtc->vbl_wait, &wait, TASK_UNINTERRUPTIBLE);
85
86                 scanline = intel_get_crtc_scanline(crtc);
87                 if (scanline < min || scanline > max)
88                         break;
89
90                 if (timeout <= 0) {
91                         DRM_ERROR("Potential atomic update failure on pipe %c\n",
92                                   pipe_name(crtc->pipe));
93                         break;
94                 }
95
96                 local_irq_enable();
97
98                 timeout = schedule_timeout(timeout);
99
100                 local_irq_disable();
101         }
102
103         finish_wait(&crtc->vbl_wait, &wait);
104
105         drm_vblank_put(dev, pipe);
106
107         *start_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
108
109         trace_i915_pipe_update_vblank_evaded(crtc, min, max, *start_vbl_count);
110
111         return true;
112 }
113
114 static void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
115 {
116         struct drm_device *dev = crtc->base.dev;
117         enum pipe pipe = crtc->pipe;
118         u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
119
120         trace_i915_pipe_update_end(crtc, end_vbl_count);
121
122         local_irq_enable();
123
124         if (start_vbl_count != end_vbl_count)
125                 DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u)\n",
126                           pipe_name(pipe), start_vbl_count, end_vbl_count);
127 }
128
129 static void intel_update_primary_plane(struct intel_crtc *crtc)
130 {
131         struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
132         int reg = DSPCNTR(crtc->plane);
133
134         if (crtc->primary_enabled)
135                 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
136         else
137                 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
138 }
139
140 static void
141 vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
142                  struct drm_framebuffer *fb,
143                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
144                  unsigned int crtc_w, unsigned int crtc_h,
145                  uint32_t x, uint32_t y,
146                  uint32_t src_w, uint32_t src_h)
147 {
148         struct drm_device *dev = dplane->dev;
149         struct drm_i915_private *dev_priv = dev->dev_private;
150         struct intel_plane *intel_plane = to_intel_plane(dplane);
151         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
152         int pipe = intel_plane->pipe;
153         int plane = intel_plane->plane;
154         u32 sprctl;
155         unsigned long sprsurf_offset, linear_offset;
156         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
157         u32 start_vbl_count;
158         bool atomic_update;
159
160         sprctl = I915_READ(SPCNTR(pipe, plane));
161
162         /* Mask out pixel format bits in case we change it */
163         sprctl &= ~SP_PIXFORMAT_MASK;
164         sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
165         sprctl &= ~SP_TILED;
166
167         switch (fb->pixel_format) {
168         case DRM_FORMAT_YUYV:
169                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
170                 break;
171         case DRM_FORMAT_YVYU:
172                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
173                 break;
174         case DRM_FORMAT_UYVY:
175                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
176                 break;
177         case DRM_FORMAT_VYUY:
178                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
179                 break;
180         case DRM_FORMAT_RGB565:
181                 sprctl |= SP_FORMAT_BGR565;
182                 break;
183         case DRM_FORMAT_XRGB8888:
184                 sprctl |= SP_FORMAT_BGRX8888;
185                 break;
186         case DRM_FORMAT_ARGB8888:
187                 sprctl |= SP_FORMAT_BGRA8888;
188                 break;
189         case DRM_FORMAT_XBGR2101010:
190                 sprctl |= SP_FORMAT_RGBX1010102;
191                 break;
192         case DRM_FORMAT_ABGR2101010:
193                 sprctl |= SP_FORMAT_RGBA1010102;
194                 break;
195         case DRM_FORMAT_XBGR8888:
196                 sprctl |= SP_FORMAT_RGBX8888;
197                 break;
198         case DRM_FORMAT_ABGR8888:
199                 sprctl |= SP_FORMAT_RGBA8888;
200                 break;
201         default:
202                 /*
203                  * If we get here one of the upper layers failed to filter
204                  * out the unsupported plane formats
205                  */
206                 BUG();
207                 break;
208         }
209
210         /*
211          * Enable gamma to match primary/cursor plane behaviour.
212          * FIXME should be user controllable via propertiesa.
213          */
214         sprctl |= SP_GAMMA_ENABLE;
215
216         if (obj->tiling_mode != I915_TILING_NONE)
217                 sprctl |= SP_TILED;
218
219         sprctl |= SP_ENABLE;
220
221         intel_update_sprite_watermarks(dplane, crtc, src_w, src_h,
222                                        pixel_size, true,
223                                        src_w != crtc_w || src_h != crtc_h);
224
225         /* Sizes are 0 based */
226         src_w--;
227         src_h--;
228         crtc_w--;
229         crtc_h--;
230
231         linear_offset = y * fb->pitches[0] + x * pixel_size;
232         sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
233                                                         obj->tiling_mode,
234                                                         pixel_size,
235                                                         fb->pitches[0]);
236         linear_offset -= sprsurf_offset;
237
238         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
239
240         intel_update_primary_plane(intel_crtc);
241
242         I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
243         I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
244
245         if (obj->tiling_mode != I915_TILING_NONE)
246                 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
247         else
248                 I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
249
250         I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
251         I915_WRITE(SPCNTR(pipe, plane), sprctl);
252         I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
253                    sprsurf_offset);
254
255         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
256
257         if (atomic_update)
258                 intel_pipe_update_end(intel_crtc, start_vbl_count);
259 }
260
261 static void
262 vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
263 {
264         struct drm_device *dev = dplane->dev;
265         struct drm_i915_private *dev_priv = dev->dev_private;
266         struct intel_plane *intel_plane = to_intel_plane(dplane);
267         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
268         int pipe = intel_plane->pipe;
269         int plane = intel_plane->plane;
270         u32 start_vbl_count;
271         bool atomic_update;
272
273         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
274
275         intel_update_primary_plane(intel_crtc);
276
277         I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
278                    ~SP_ENABLE);
279         /* Activate double buffered register update */
280         I915_WRITE(SPSURF(pipe, plane), 0);
281
282         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
283
284         if (atomic_update)
285                 intel_pipe_update_end(intel_crtc, start_vbl_count);
286
287         intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
288 }
289
290 static int
291 vlv_update_colorkey(struct drm_plane *dplane,
292                     struct drm_intel_sprite_colorkey *key)
293 {
294         struct drm_device *dev = dplane->dev;
295         struct drm_i915_private *dev_priv = dev->dev_private;
296         struct intel_plane *intel_plane = to_intel_plane(dplane);
297         int pipe = intel_plane->pipe;
298         int plane = intel_plane->plane;
299         u32 sprctl;
300
301         if (key->flags & I915_SET_COLORKEY_DESTINATION)
302                 return -EINVAL;
303
304         I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
305         I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
306         I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
307
308         sprctl = I915_READ(SPCNTR(pipe, plane));
309         sprctl &= ~SP_SOURCE_KEY;
310         if (key->flags & I915_SET_COLORKEY_SOURCE)
311                 sprctl |= SP_SOURCE_KEY;
312         I915_WRITE(SPCNTR(pipe, plane), sprctl);
313
314         POSTING_READ(SPKEYMSK(pipe, plane));
315
316         return 0;
317 }
318
319 static void
320 vlv_get_colorkey(struct drm_plane *dplane,
321                  struct drm_intel_sprite_colorkey *key)
322 {
323         struct drm_device *dev = dplane->dev;
324         struct drm_i915_private *dev_priv = dev->dev_private;
325         struct intel_plane *intel_plane = to_intel_plane(dplane);
326         int pipe = intel_plane->pipe;
327         int plane = intel_plane->plane;
328         u32 sprctl;
329
330         key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
331         key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
332         key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
333
334         sprctl = I915_READ(SPCNTR(pipe, plane));
335         if (sprctl & SP_SOURCE_KEY)
336                 key->flags = I915_SET_COLORKEY_SOURCE;
337         else
338                 key->flags = I915_SET_COLORKEY_NONE;
339 }
340
341 static void
342 ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
343                  struct drm_framebuffer *fb,
344                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
345                  unsigned int crtc_w, unsigned int crtc_h,
346                  uint32_t x, uint32_t y,
347                  uint32_t src_w, uint32_t src_h)
348 {
349         struct drm_device *dev = plane->dev;
350         struct drm_i915_private *dev_priv = dev->dev_private;
351         struct intel_plane *intel_plane = to_intel_plane(plane);
352         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
353         int pipe = intel_plane->pipe;
354         u32 sprctl, sprscale = 0;
355         unsigned long sprsurf_offset, linear_offset;
356         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
357         u32 start_vbl_count;
358         bool atomic_update;
359
360         sprctl = I915_READ(SPRCTL(pipe));
361
362         /* Mask out pixel format bits in case we change it */
363         sprctl &= ~SPRITE_PIXFORMAT_MASK;
364         sprctl &= ~SPRITE_RGB_ORDER_RGBX;
365         sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
366         sprctl &= ~SPRITE_TILED;
367
368         switch (fb->pixel_format) {
369         case DRM_FORMAT_XBGR8888:
370                 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
371                 break;
372         case DRM_FORMAT_XRGB8888:
373                 sprctl |= SPRITE_FORMAT_RGBX888;
374                 break;
375         case DRM_FORMAT_YUYV:
376                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
377                 break;
378         case DRM_FORMAT_YVYU:
379                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
380                 break;
381         case DRM_FORMAT_UYVY:
382                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
383                 break;
384         case DRM_FORMAT_VYUY:
385                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
386                 break;
387         default:
388                 BUG();
389         }
390
391         /*
392          * Enable gamma to match primary/cursor plane behaviour.
393          * FIXME should be user controllable via propertiesa.
394          */
395         sprctl |= SPRITE_GAMMA_ENABLE;
396
397         if (obj->tiling_mode != I915_TILING_NONE)
398                 sprctl |= SPRITE_TILED;
399
400         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
401                 sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
402         else
403                 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
404
405         sprctl |= SPRITE_ENABLE;
406
407         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
408                 sprctl |= SPRITE_PIPE_CSC_ENABLE;
409
410         intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
411                                        true,
412                                        src_w != crtc_w || src_h != crtc_h);
413
414         /* Sizes are 0 based */
415         src_w--;
416         src_h--;
417         crtc_w--;
418         crtc_h--;
419
420         if (crtc_w != src_w || crtc_h != src_h)
421                 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
422
423         linear_offset = y * fb->pitches[0] + x * pixel_size;
424         sprsurf_offset =
425                 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
426                                                pixel_size, fb->pitches[0]);
427         linear_offset -= sprsurf_offset;
428
429         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
430
431         intel_update_primary_plane(intel_crtc);
432
433         I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
434         I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
435
436         /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
437          * register */
438         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
439                 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
440         else if (obj->tiling_mode != I915_TILING_NONE)
441                 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
442         else
443                 I915_WRITE(SPRLINOFF(pipe), linear_offset);
444
445         I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
446         if (intel_plane->can_scale)
447                 I915_WRITE(SPRSCALE(pipe), sprscale);
448         I915_WRITE(SPRCTL(pipe), sprctl);
449         I915_WRITE(SPRSURF(pipe),
450                    i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
451
452         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
453
454         if (atomic_update)
455                 intel_pipe_update_end(intel_crtc, start_vbl_count);
456 }
457
458 static void
459 ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
460 {
461         struct drm_device *dev = plane->dev;
462         struct drm_i915_private *dev_priv = dev->dev_private;
463         struct intel_plane *intel_plane = to_intel_plane(plane);
464         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
465         int pipe = intel_plane->pipe;
466         u32 start_vbl_count;
467         bool atomic_update;
468
469         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
470
471         intel_update_primary_plane(intel_crtc);
472
473         I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
474         /* Can't leave the scaler enabled... */
475         if (intel_plane->can_scale)
476                 I915_WRITE(SPRSCALE(pipe), 0);
477         /* Activate double buffered register update */
478         I915_WRITE(SPRSURF(pipe), 0);
479
480         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
481
482         if (atomic_update)
483                 intel_pipe_update_end(intel_crtc, start_vbl_count);
484
485         /*
486          * Avoid underruns when disabling the sprite.
487          * FIXME remove once watermark updates are done properly.
488          */
489         intel_wait_for_vblank(dev, pipe);
490
491         intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
492 }
493
494 static int
495 ivb_update_colorkey(struct drm_plane *plane,
496                     struct drm_intel_sprite_colorkey *key)
497 {
498         struct drm_device *dev = plane->dev;
499         struct drm_i915_private *dev_priv = dev->dev_private;
500         struct intel_plane *intel_plane;
501         u32 sprctl;
502         int ret = 0;
503
504         intel_plane = to_intel_plane(plane);
505
506         I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
507         I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
508         I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
509
510         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
511         sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
512         if (key->flags & I915_SET_COLORKEY_DESTINATION)
513                 sprctl |= SPRITE_DEST_KEY;
514         else if (key->flags & I915_SET_COLORKEY_SOURCE)
515                 sprctl |= SPRITE_SOURCE_KEY;
516         I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
517
518         POSTING_READ(SPRKEYMSK(intel_plane->pipe));
519
520         return ret;
521 }
522
523 static void
524 ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
525 {
526         struct drm_device *dev = plane->dev;
527         struct drm_i915_private *dev_priv = dev->dev_private;
528         struct intel_plane *intel_plane;
529         u32 sprctl;
530
531         intel_plane = to_intel_plane(plane);
532
533         key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
534         key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
535         key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
536         key->flags = 0;
537
538         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
539
540         if (sprctl & SPRITE_DEST_KEY)
541                 key->flags = I915_SET_COLORKEY_DESTINATION;
542         else if (sprctl & SPRITE_SOURCE_KEY)
543                 key->flags = I915_SET_COLORKEY_SOURCE;
544         else
545                 key->flags = I915_SET_COLORKEY_NONE;
546 }
547
548 static void
549 ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
550                  struct drm_framebuffer *fb,
551                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
552                  unsigned int crtc_w, unsigned int crtc_h,
553                  uint32_t x, uint32_t y,
554                  uint32_t src_w, uint32_t src_h)
555 {
556         struct drm_device *dev = plane->dev;
557         struct drm_i915_private *dev_priv = dev->dev_private;
558         struct intel_plane *intel_plane = to_intel_plane(plane);
559         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
560         int pipe = intel_plane->pipe;
561         unsigned long dvssurf_offset, linear_offset;
562         u32 dvscntr, dvsscale;
563         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
564         u32 start_vbl_count;
565         bool atomic_update;
566
567         dvscntr = I915_READ(DVSCNTR(pipe));
568
569         /* Mask out pixel format bits in case we change it */
570         dvscntr &= ~DVS_PIXFORMAT_MASK;
571         dvscntr &= ~DVS_RGB_ORDER_XBGR;
572         dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
573         dvscntr &= ~DVS_TILED;
574
575         switch (fb->pixel_format) {
576         case DRM_FORMAT_XBGR8888:
577                 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
578                 break;
579         case DRM_FORMAT_XRGB8888:
580                 dvscntr |= DVS_FORMAT_RGBX888;
581                 break;
582         case DRM_FORMAT_YUYV:
583                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
584                 break;
585         case DRM_FORMAT_YVYU:
586                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
587                 break;
588         case DRM_FORMAT_UYVY:
589                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
590                 break;
591         case DRM_FORMAT_VYUY:
592                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
593                 break;
594         default:
595                 BUG();
596         }
597
598         /*
599          * Enable gamma to match primary/cursor plane behaviour.
600          * FIXME should be user controllable via propertiesa.
601          */
602         dvscntr |= DVS_GAMMA_ENABLE;
603
604         if (obj->tiling_mode != I915_TILING_NONE)
605                 dvscntr |= DVS_TILED;
606
607         if (IS_GEN6(dev))
608                 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
609         dvscntr |= DVS_ENABLE;
610
611         intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
612                                        pixel_size, true,
613                                        src_w != crtc_w || src_h != crtc_h);
614
615         /* Sizes are 0 based */
616         src_w--;
617         src_h--;
618         crtc_w--;
619         crtc_h--;
620
621         dvsscale = 0;
622         if (crtc_w != src_w || crtc_h != src_h)
623                 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
624
625         linear_offset = y * fb->pitches[0] + x * pixel_size;
626         dvssurf_offset =
627                 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
628                                                pixel_size, fb->pitches[0]);
629         linear_offset -= dvssurf_offset;
630
631         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
632
633         intel_update_primary_plane(intel_crtc);
634
635         I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
636         I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
637
638         if (obj->tiling_mode != I915_TILING_NONE)
639                 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
640         else
641                 I915_WRITE(DVSLINOFF(pipe), linear_offset);
642
643         I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
644         I915_WRITE(DVSSCALE(pipe), dvsscale);
645         I915_WRITE(DVSCNTR(pipe), dvscntr);
646         I915_WRITE(DVSSURF(pipe),
647                    i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
648
649         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
650
651         if (atomic_update)
652                 intel_pipe_update_end(intel_crtc, start_vbl_count);
653 }
654
655 static void
656 ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
657 {
658         struct drm_device *dev = plane->dev;
659         struct drm_i915_private *dev_priv = dev->dev_private;
660         struct intel_plane *intel_plane = to_intel_plane(plane);
661         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
662         int pipe = intel_plane->pipe;
663         u32 start_vbl_count;
664         bool atomic_update;
665
666         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
667
668         intel_update_primary_plane(intel_crtc);
669
670         I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
671         /* Disable the scaler */
672         I915_WRITE(DVSSCALE(pipe), 0);
673         /* Flush double buffered register updates */
674         I915_WRITE(DVSSURF(pipe), 0);
675
676         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
677
678         if (atomic_update)
679                 intel_pipe_update_end(intel_crtc, start_vbl_count);
680
681         /*
682          * Avoid underruns when disabling the sprite.
683          * FIXME remove once watermark updates are done properly.
684          */
685         intel_wait_for_vblank(dev, pipe);
686
687         intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
688 }
689
690 static void
691 intel_post_enable_primary(struct drm_crtc *crtc)
692 {
693         struct drm_device *dev = crtc->dev;
694         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
695
696         /*
697          * BDW signals flip done immediately if the plane
698          * is disabled, even if the plane enable is already
699          * armed to occur at the next vblank :(
700          */
701         if (IS_BROADWELL(dev))
702                 intel_wait_for_vblank(dev, intel_crtc->pipe);
703
704         /*
705          * FIXME IPS should be fine as long as one plane is
706          * enabled, but in practice it seems to have problems
707          * when going from primary only to sprite only and vice
708          * versa.
709          */
710         hsw_enable_ips(intel_crtc);
711
712         mutex_lock(&dev->struct_mutex);
713         intel_update_fbc(dev);
714         mutex_unlock(&dev->struct_mutex);
715 }
716
717 static void
718 intel_pre_disable_primary(struct drm_crtc *crtc)
719 {
720         struct drm_device *dev = crtc->dev;
721         struct drm_i915_private *dev_priv = dev->dev_private;
722         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
723
724         mutex_lock(&dev->struct_mutex);
725         if (dev_priv->fbc.plane == intel_crtc->plane)
726                 intel_disable_fbc(dev);
727         mutex_unlock(&dev->struct_mutex);
728
729         /*
730          * FIXME IPS should be fine as long as one plane is
731          * enabled, but in practice it seems to have problems
732          * when going from primary only to sprite only and vice
733          * versa.
734          */
735         hsw_disable_ips(intel_crtc);
736 }
737
738 static int
739 ilk_update_colorkey(struct drm_plane *plane,
740                     struct drm_intel_sprite_colorkey *key)
741 {
742         struct drm_device *dev = plane->dev;
743         struct drm_i915_private *dev_priv = dev->dev_private;
744         struct intel_plane *intel_plane;
745         u32 dvscntr;
746         int ret = 0;
747
748         intel_plane = to_intel_plane(plane);
749
750         I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
751         I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
752         I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
753
754         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
755         dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
756         if (key->flags & I915_SET_COLORKEY_DESTINATION)
757                 dvscntr |= DVS_DEST_KEY;
758         else if (key->flags & I915_SET_COLORKEY_SOURCE)
759                 dvscntr |= DVS_SOURCE_KEY;
760         I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
761
762         POSTING_READ(DVSKEYMSK(intel_plane->pipe));
763
764         return ret;
765 }
766
767 static void
768 ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
769 {
770         struct drm_device *dev = plane->dev;
771         struct drm_i915_private *dev_priv = dev->dev_private;
772         struct intel_plane *intel_plane;
773         u32 dvscntr;
774
775         intel_plane = to_intel_plane(plane);
776
777         key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
778         key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
779         key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
780         key->flags = 0;
781
782         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
783
784         if (dvscntr & DVS_DEST_KEY)
785                 key->flags = I915_SET_COLORKEY_DESTINATION;
786         else if (dvscntr & DVS_SOURCE_KEY)
787                 key->flags = I915_SET_COLORKEY_SOURCE;
788         else
789                 key->flags = I915_SET_COLORKEY_NONE;
790 }
791
792 static bool
793 format_is_yuv(uint32_t format)
794 {
795         switch (format) {
796         case DRM_FORMAT_YUYV:
797         case DRM_FORMAT_UYVY:
798         case DRM_FORMAT_VYUY:
799         case DRM_FORMAT_YVYU:
800                 return true;
801         default:
802                 return false;
803         }
804 }
805
806 static bool colorkey_enabled(struct intel_plane *intel_plane)
807 {
808         struct drm_intel_sprite_colorkey key;
809
810         intel_plane->get_colorkey(&intel_plane->base, &key);
811
812         return key.flags != I915_SET_COLORKEY_NONE;
813 }
814
815 static int
816 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
817                    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
818                    unsigned int crtc_w, unsigned int crtc_h,
819                    uint32_t src_x, uint32_t src_y,
820                    uint32_t src_w, uint32_t src_h)
821 {
822         struct drm_device *dev = plane->dev;
823         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
824         struct intel_plane *intel_plane = to_intel_plane(plane);
825         enum pipe pipe = intel_crtc->pipe;
826         struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
827         struct drm_i915_gem_object *obj = intel_fb->obj;
828         struct drm_i915_gem_object *old_obj = intel_plane->obj;
829         int ret;
830         bool primary_enabled;
831         bool visible;
832         int hscale, vscale;
833         int max_scale, min_scale;
834         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
835         struct drm_rect src = {
836                 /* sample coordinates in 16.16 fixed point */
837                 .x1 = src_x,
838                 .x2 = src_x + src_w,
839                 .y1 = src_y,
840                 .y2 = src_y + src_h,
841         };
842         struct drm_rect dst = {
843                 /* integer pixels */
844                 .x1 = crtc_x,
845                 .x2 = crtc_x + crtc_w,
846                 .y1 = crtc_y,
847                 .y2 = crtc_y + crtc_h,
848         };
849         const struct drm_rect clip = {
850                 .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
851                 .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
852         };
853         const struct {
854                 int crtc_x, crtc_y;
855                 unsigned int crtc_w, crtc_h;
856                 uint32_t src_x, src_y, src_w, src_h;
857         } orig = {
858                 .crtc_x = crtc_x,
859                 .crtc_y = crtc_y,
860                 .crtc_w = crtc_w,
861                 .crtc_h = crtc_h,
862                 .src_x = src_x,
863                 .src_y = src_y,
864                 .src_w = src_w,
865                 .src_h = src_h,
866         };
867
868         /* Don't modify another pipe's plane */
869         if (intel_plane->pipe != intel_crtc->pipe) {
870                 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
871                 return -EINVAL;
872         }
873
874         /* FIXME check all gen limits */
875         if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
876                 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
877                 return -EINVAL;
878         }
879
880         /* Sprite planes can be linear or x-tiled surfaces */
881         switch (obj->tiling_mode) {
882                 case I915_TILING_NONE:
883                 case I915_TILING_X:
884                         break;
885                 default:
886                         DRM_DEBUG_KMS("Unsupported tiling mode\n");
887                         return -EINVAL;
888         }
889
890         /*
891          * FIXME the following code does a bunch of fuzzy adjustments to the
892          * coordinates and sizes. We probably need some way to decide whether
893          * more strict checking should be done instead.
894          */
895         max_scale = intel_plane->max_downscale << 16;
896         min_scale = intel_plane->can_scale ? 1 : (1 << 16);
897
898         hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale);
899         BUG_ON(hscale < 0);
900
901         vscale = drm_rect_calc_vscale_relaxed(&src, &dst, min_scale, max_scale);
902         BUG_ON(vscale < 0);
903
904         visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale);
905
906         crtc_x = dst.x1;
907         crtc_y = dst.y1;
908         crtc_w = drm_rect_width(&dst);
909         crtc_h = drm_rect_height(&dst);
910
911         if (visible) {
912                 /* check again in case clipping clamped the results */
913                 hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale);
914                 if (hscale < 0) {
915                         DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
916                         drm_rect_debug_print(&src, true);
917                         drm_rect_debug_print(&dst, false);
918
919                         return hscale;
920                 }
921
922                 vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale);
923                 if (vscale < 0) {
924                         DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
925                         drm_rect_debug_print(&src, true);
926                         drm_rect_debug_print(&dst, false);
927
928                         return vscale;
929                 }
930
931                 /* Make the source viewport size an exact multiple of the scaling factors. */
932                 drm_rect_adjust_size(&src,
933                                      drm_rect_width(&dst) * hscale - drm_rect_width(&src),
934                                      drm_rect_height(&dst) * vscale - drm_rect_height(&src));
935
936                 /* sanity check to make sure the src viewport wasn't enlarged */
937                 WARN_ON(src.x1 < (int) src_x ||
938                         src.y1 < (int) src_y ||
939                         src.x2 > (int) (src_x + src_w) ||
940                         src.y2 > (int) (src_y + src_h));
941
942                 /*
943                  * Hardware doesn't handle subpixel coordinates.
944                  * Adjust to (macro)pixel boundary, but be careful not to
945                  * increase the source viewport size, because that could
946                  * push the downscaling factor out of bounds.
947                  */
948                 src_x = src.x1 >> 16;
949                 src_w = drm_rect_width(&src) >> 16;
950                 src_y = src.y1 >> 16;
951                 src_h = drm_rect_height(&src) >> 16;
952
953                 if (format_is_yuv(fb->pixel_format)) {
954                         src_x &= ~1;
955                         src_w &= ~1;
956
957                         /*
958                          * Must keep src and dst the
959                          * same if we can't scale.
960                          */
961                         if (!intel_plane->can_scale)
962                                 crtc_w &= ~1;
963
964                         if (crtc_w == 0)
965                                 visible = false;
966                 }
967         }
968
969         /* Check size restrictions when scaling */
970         if (visible && (src_w != crtc_w || src_h != crtc_h)) {
971                 unsigned int width_bytes;
972
973                 WARN_ON(!intel_plane->can_scale);
974
975                 /* FIXME interlacing min height is 6 */
976
977                 if (crtc_w < 3 || crtc_h < 3)
978                         visible = false;
979
980                 if (src_w < 3 || src_h < 3)
981                         visible = false;
982
983                 width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size;
984
985                 if (src_w > 2048 || src_h > 2048 ||
986                     width_bytes > 4096 || fb->pitches[0] > 4096) {
987                         DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
988                         return -EINVAL;
989                 }
990         }
991
992         dst.x1 = crtc_x;
993         dst.x2 = crtc_x + crtc_w;
994         dst.y1 = crtc_y;
995         dst.y2 = crtc_y + crtc_h;
996
997         /*
998          * If the sprite is completely covering the primary plane,
999          * we can disable the primary and save power.
1000          */
1001         primary_enabled = !drm_rect_equals(&dst, &clip) || colorkey_enabled(intel_plane);
1002         WARN_ON(!primary_enabled && !visible && intel_crtc->active);
1003
1004         mutex_lock(&dev->struct_mutex);
1005
1006         /* Note that this will apply the VT-d workaround for scanouts,
1007          * which is more restrictive than required for sprites. (The
1008          * primary plane requires 256KiB alignment with 64 PTE padding,
1009          * the sprite planes only require 128KiB alignment and 32 PTE padding.
1010          */
1011         ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
1012
1013         i915_gem_track_fb(old_obj, obj,
1014                           INTEL_FRONTBUFFER_SPRITE(pipe));
1015         mutex_unlock(&dev->struct_mutex);
1016
1017         if (ret)
1018                 return ret;
1019
1020         intel_plane->crtc_x = orig.crtc_x;
1021         intel_plane->crtc_y = orig.crtc_y;
1022         intel_plane->crtc_w = orig.crtc_w;
1023         intel_plane->crtc_h = orig.crtc_h;
1024         intel_plane->src_x = orig.src_x;
1025         intel_plane->src_y = orig.src_y;
1026         intel_plane->src_w = orig.src_w;
1027         intel_plane->src_h = orig.src_h;
1028         intel_plane->obj = obj;
1029
1030         if (intel_crtc->active) {
1031                 bool primary_was_enabled = intel_crtc->primary_enabled;
1032
1033                 intel_crtc->primary_enabled = primary_enabled;
1034
1035                 if (primary_was_enabled != primary_enabled)
1036                         intel_crtc_wait_for_pending_flips(crtc);
1037
1038                 if (primary_was_enabled && !primary_enabled)
1039                         intel_pre_disable_primary(crtc);
1040
1041                 if (visible)
1042                         intel_plane->update_plane(plane, crtc, fb, obj,
1043                                                   crtc_x, crtc_y, crtc_w, crtc_h,
1044                                                   src_x, src_y, src_w, src_h);
1045                 else
1046                         intel_plane->disable_plane(plane, crtc);
1047
1048                 intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
1049
1050                 if (!primary_was_enabled && primary_enabled)
1051                         intel_post_enable_primary(crtc);
1052         }
1053
1054         /* Unpin old obj after new one is active to avoid ugliness */
1055         if (old_obj) {
1056                 /*
1057                  * It's fairly common to simply update the position of
1058                  * an existing object.  In that case, we don't need to
1059                  * wait for vblank to avoid ugliness, we only need to
1060                  * do the pin & ref bookkeeping.
1061                  */
1062                 if (old_obj != obj && intel_crtc->active)
1063                         intel_wait_for_vblank(dev, intel_crtc->pipe);
1064
1065                 mutex_lock(&dev->struct_mutex);
1066                 intel_unpin_fb_obj(old_obj);
1067                 mutex_unlock(&dev->struct_mutex);
1068         }
1069
1070         return 0;
1071 }
1072
1073 static int
1074 intel_disable_plane(struct drm_plane *plane)
1075 {
1076         struct drm_device *dev = plane->dev;
1077         struct intel_plane *intel_plane = to_intel_plane(plane);
1078         struct intel_crtc *intel_crtc;
1079         enum pipe pipe;
1080
1081         if (!plane->fb)
1082                 return 0;
1083
1084         if (WARN_ON(!plane->crtc))
1085                 return -EINVAL;
1086
1087         intel_crtc = to_intel_crtc(plane->crtc);
1088         pipe = intel_crtc->pipe;
1089
1090         if (intel_crtc->active) {
1091                 bool primary_was_enabled = intel_crtc->primary_enabled;
1092
1093                 intel_crtc->primary_enabled = true;
1094
1095                 intel_plane->disable_plane(plane, plane->crtc);
1096
1097                 if (!primary_was_enabled && intel_crtc->primary_enabled)
1098                         intel_post_enable_primary(plane->crtc);
1099         }
1100
1101         if (intel_plane->obj) {
1102                 if (intel_crtc->active)
1103                         intel_wait_for_vblank(dev, intel_plane->pipe);
1104
1105                 mutex_lock(&dev->struct_mutex);
1106                 intel_unpin_fb_obj(intel_plane->obj);
1107                 i915_gem_track_fb(intel_plane->obj, NULL,
1108                                   INTEL_FRONTBUFFER_SPRITE(pipe));
1109                 mutex_unlock(&dev->struct_mutex);
1110
1111                 intel_plane->obj = NULL;
1112         }
1113
1114         return 0;
1115 }
1116
1117 static void intel_destroy_plane(struct drm_plane *plane)
1118 {
1119         struct intel_plane *intel_plane = to_intel_plane(plane);
1120         intel_disable_plane(plane);
1121         drm_plane_cleanup(plane);
1122         kfree(intel_plane);
1123 }
1124
1125 int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
1126                               struct drm_file *file_priv)
1127 {
1128         struct drm_intel_sprite_colorkey *set = data;
1129         struct drm_plane *plane;
1130         struct intel_plane *intel_plane;
1131         int ret = 0;
1132
1133         if (!drm_core_check_feature(dev, DRIVER_MODESET))
1134                 return -ENODEV;
1135
1136         /* Make sure we don't try to enable both src & dest simultaneously */
1137         if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1138                 return -EINVAL;
1139
1140         drm_modeset_lock_all(dev);
1141
1142         plane = drm_plane_find(dev, set->plane_id);
1143         if (!plane) {
1144                 ret = -ENOENT;
1145                 goto out_unlock;
1146         }
1147
1148         intel_plane = to_intel_plane(plane);
1149         ret = intel_plane->update_colorkey(plane, set);
1150
1151 out_unlock:
1152         drm_modeset_unlock_all(dev);
1153         return ret;
1154 }
1155
1156 int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
1157                               struct drm_file *file_priv)
1158 {
1159         struct drm_intel_sprite_colorkey *get = data;
1160         struct drm_plane *plane;
1161         struct intel_plane *intel_plane;
1162         int ret = 0;
1163
1164         if (!drm_core_check_feature(dev, DRIVER_MODESET))
1165                 return -ENODEV;
1166
1167         drm_modeset_lock_all(dev);
1168
1169         plane = drm_plane_find(dev, get->plane_id);
1170         if (!plane) {
1171                 ret = -ENOENT;
1172                 goto out_unlock;
1173         }
1174
1175         intel_plane = to_intel_plane(plane);
1176         intel_plane->get_colorkey(plane, get);
1177
1178 out_unlock:
1179         drm_modeset_unlock_all(dev);
1180         return ret;
1181 }
1182
1183 void intel_plane_restore(struct drm_plane *plane)
1184 {
1185         struct intel_plane *intel_plane = to_intel_plane(plane);
1186
1187         if (!plane->crtc || !plane->fb)
1188                 return;
1189
1190         intel_update_plane(plane, plane->crtc, plane->fb,
1191                            intel_plane->crtc_x, intel_plane->crtc_y,
1192                            intel_plane->crtc_w, intel_plane->crtc_h,
1193                            intel_plane->src_x, intel_plane->src_y,
1194                            intel_plane->src_w, intel_plane->src_h);
1195 }
1196
1197 void intel_plane_disable(struct drm_plane *plane)
1198 {
1199         if (!plane->crtc || !plane->fb)
1200                 return;
1201
1202         intel_disable_plane(plane);
1203 }
1204
1205 static const struct drm_plane_funcs intel_plane_funcs = {
1206         .update_plane = intel_update_plane,
1207         .disable_plane = intel_disable_plane,
1208         .destroy = intel_destroy_plane,
1209 };
1210
1211 static uint32_t ilk_plane_formats[] = {
1212         DRM_FORMAT_XRGB8888,
1213         DRM_FORMAT_YUYV,
1214         DRM_FORMAT_YVYU,
1215         DRM_FORMAT_UYVY,
1216         DRM_FORMAT_VYUY,
1217 };
1218
1219 static uint32_t snb_plane_formats[] = {
1220         DRM_FORMAT_XBGR8888,
1221         DRM_FORMAT_XRGB8888,
1222         DRM_FORMAT_YUYV,
1223         DRM_FORMAT_YVYU,
1224         DRM_FORMAT_UYVY,
1225         DRM_FORMAT_VYUY,
1226 };
1227
1228 static uint32_t vlv_plane_formats[] = {
1229         DRM_FORMAT_RGB565,
1230         DRM_FORMAT_ABGR8888,
1231         DRM_FORMAT_ARGB8888,
1232         DRM_FORMAT_XBGR8888,
1233         DRM_FORMAT_XRGB8888,
1234         DRM_FORMAT_XBGR2101010,
1235         DRM_FORMAT_ABGR2101010,
1236         DRM_FORMAT_YUYV,
1237         DRM_FORMAT_YVYU,
1238         DRM_FORMAT_UYVY,
1239         DRM_FORMAT_VYUY,
1240 };
1241
1242 int
1243 intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
1244 {
1245         struct intel_plane *intel_plane;
1246         unsigned long possible_crtcs;
1247         const uint32_t *plane_formats;
1248         int num_plane_formats;
1249         int ret;
1250
1251         if (INTEL_INFO(dev)->gen < 5)
1252                 return -ENODEV;
1253
1254         intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1255         if (!intel_plane)
1256                 return -ENOMEM;
1257
1258         switch (INTEL_INFO(dev)->gen) {
1259         case 5:
1260         case 6:
1261                 intel_plane->can_scale = true;
1262                 intel_plane->max_downscale = 16;
1263                 intel_plane->update_plane = ilk_update_plane;
1264                 intel_plane->disable_plane = ilk_disable_plane;
1265                 intel_plane->update_colorkey = ilk_update_colorkey;
1266                 intel_plane->get_colorkey = ilk_get_colorkey;
1267
1268                 if (IS_GEN6(dev)) {
1269                         plane_formats = snb_plane_formats;
1270                         num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1271                 } else {
1272                         plane_formats = ilk_plane_formats;
1273                         num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1274                 }
1275                 break;
1276
1277         case 7:
1278         case 8:
1279                 if (IS_IVYBRIDGE(dev)) {
1280                         intel_plane->can_scale = true;
1281                         intel_plane->max_downscale = 2;
1282                 } else {
1283                         intel_plane->can_scale = false;
1284                         intel_plane->max_downscale = 1;
1285                 }
1286
1287                 if (IS_VALLEYVIEW(dev)) {
1288                         intel_plane->update_plane = vlv_update_plane;
1289                         intel_plane->disable_plane = vlv_disable_plane;
1290                         intel_plane->update_colorkey = vlv_update_colorkey;
1291                         intel_plane->get_colorkey = vlv_get_colorkey;
1292
1293                         plane_formats = vlv_plane_formats;
1294                         num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1295                 } else {
1296                         intel_plane->update_plane = ivb_update_plane;
1297                         intel_plane->disable_plane = ivb_disable_plane;
1298                         intel_plane->update_colorkey = ivb_update_colorkey;
1299                         intel_plane->get_colorkey = ivb_get_colorkey;
1300
1301                         plane_formats = snb_plane_formats;
1302                         num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1303                 }
1304                 break;
1305
1306         default:
1307                 kfree(intel_plane);
1308                 return -ENODEV;
1309         }
1310
1311         intel_plane->pipe = pipe;
1312         intel_plane->plane = plane;
1313         possible_crtcs = (1 << pipe);
1314         ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
1315                              &intel_plane_funcs,
1316                              plane_formats, num_plane_formats,
1317                              false);
1318         if (ret)
1319                 kfree(intel_plane);
1320
1321         return ret;
1322 }