Merge tag 'v3.16-rc4' into drm-intel-next-queued
[sfrench/cifs-2.6.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, pixel_size, true,
222                                        src_w != crtc_w || src_h != crtc_h);
223
224         /* Sizes are 0 based */
225         src_w--;
226         src_h--;
227         crtc_w--;
228         crtc_h--;
229
230         linear_offset = y * fb->pitches[0] + x * pixel_size;
231         sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
232                                                         obj->tiling_mode,
233                                                         pixel_size,
234                                                         fb->pitches[0]);
235         linear_offset -= sprsurf_offset;
236
237         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
238
239         intel_update_primary_plane(intel_crtc);
240
241         I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
242         I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
243
244         if (obj->tiling_mode != I915_TILING_NONE)
245                 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
246         else
247                 I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
248
249         I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
250         I915_WRITE(SPCNTR(pipe, plane), sprctl);
251         I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
252                    sprsurf_offset);
253
254         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
255
256         if (atomic_update)
257                 intel_pipe_update_end(intel_crtc, start_vbl_count);
258 }
259
260 static void
261 vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
262 {
263         struct drm_device *dev = dplane->dev;
264         struct drm_i915_private *dev_priv = dev->dev_private;
265         struct intel_plane *intel_plane = to_intel_plane(dplane);
266         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
267         int pipe = intel_plane->pipe;
268         int plane = intel_plane->plane;
269         u32 start_vbl_count;
270         bool atomic_update;
271
272         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
273
274         intel_update_primary_plane(intel_crtc);
275
276         I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
277                    ~SP_ENABLE);
278         /* Activate double buffered register update */
279         I915_WRITE(SPSURF(pipe, plane), 0);
280
281         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
282
283         if (atomic_update)
284                 intel_pipe_update_end(intel_crtc, start_vbl_count);
285
286         intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
287 }
288
289 static int
290 vlv_update_colorkey(struct drm_plane *dplane,
291                     struct drm_intel_sprite_colorkey *key)
292 {
293         struct drm_device *dev = dplane->dev;
294         struct drm_i915_private *dev_priv = dev->dev_private;
295         struct intel_plane *intel_plane = to_intel_plane(dplane);
296         int pipe = intel_plane->pipe;
297         int plane = intel_plane->plane;
298         u32 sprctl;
299
300         if (key->flags & I915_SET_COLORKEY_DESTINATION)
301                 return -EINVAL;
302
303         I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
304         I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
305         I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
306
307         sprctl = I915_READ(SPCNTR(pipe, plane));
308         sprctl &= ~SP_SOURCE_KEY;
309         if (key->flags & I915_SET_COLORKEY_SOURCE)
310                 sprctl |= SP_SOURCE_KEY;
311         I915_WRITE(SPCNTR(pipe, plane), sprctl);
312
313         POSTING_READ(SPKEYMSK(pipe, plane));
314
315         return 0;
316 }
317
318 static void
319 vlv_get_colorkey(struct drm_plane *dplane,
320                  struct drm_intel_sprite_colorkey *key)
321 {
322         struct drm_device *dev = dplane->dev;
323         struct drm_i915_private *dev_priv = dev->dev_private;
324         struct intel_plane *intel_plane = to_intel_plane(dplane);
325         int pipe = intel_plane->pipe;
326         int plane = intel_plane->plane;
327         u32 sprctl;
328
329         key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
330         key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
331         key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
332
333         sprctl = I915_READ(SPCNTR(pipe, plane));
334         if (sprctl & SP_SOURCE_KEY)
335                 key->flags = I915_SET_COLORKEY_SOURCE;
336         else
337                 key->flags = I915_SET_COLORKEY_NONE;
338 }
339
340 static void
341 ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
342                  struct drm_framebuffer *fb,
343                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
344                  unsigned int crtc_w, unsigned int crtc_h,
345                  uint32_t x, uint32_t y,
346                  uint32_t src_w, uint32_t src_h)
347 {
348         struct drm_device *dev = plane->dev;
349         struct drm_i915_private *dev_priv = dev->dev_private;
350         struct intel_plane *intel_plane = to_intel_plane(plane);
351         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
352         int pipe = intel_plane->pipe;
353         u32 sprctl, sprscale = 0;
354         unsigned long sprsurf_offset, linear_offset;
355         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
356         u32 start_vbl_count;
357         bool atomic_update;
358
359         sprctl = I915_READ(SPRCTL(pipe));
360
361         /* Mask out pixel format bits in case we change it */
362         sprctl &= ~SPRITE_PIXFORMAT_MASK;
363         sprctl &= ~SPRITE_RGB_ORDER_RGBX;
364         sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
365         sprctl &= ~SPRITE_TILED;
366
367         switch (fb->pixel_format) {
368         case DRM_FORMAT_XBGR8888:
369                 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
370                 break;
371         case DRM_FORMAT_XRGB8888:
372                 sprctl |= SPRITE_FORMAT_RGBX888;
373                 break;
374         case DRM_FORMAT_YUYV:
375                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
376                 break;
377         case DRM_FORMAT_YVYU:
378                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
379                 break;
380         case DRM_FORMAT_UYVY:
381                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
382                 break;
383         case DRM_FORMAT_VYUY:
384                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
385                 break;
386         default:
387                 BUG();
388         }
389
390         /*
391          * Enable gamma to match primary/cursor plane behaviour.
392          * FIXME should be user controllable via propertiesa.
393          */
394         sprctl |= SPRITE_GAMMA_ENABLE;
395
396         if (obj->tiling_mode != I915_TILING_NONE)
397                 sprctl |= SPRITE_TILED;
398
399         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
400                 sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
401         else
402                 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
403
404         sprctl |= SPRITE_ENABLE;
405
406         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
407                 sprctl |= SPRITE_PIPE_CSC_ENABLE;
408
409         intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
410                                        src_w != crtc_w || src_h != crtc_h);
411
412         /* Sizes are 0 based */
413         src_w--;
414         src_h--;
415         crtc_w--;
416         crtc_h--;
417
418         if (crtc_w != src_w || crtc_h != src_h)
419                 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
420
421         linear_offset = y * fb->pitches[0] + x * pixel_size;
422         sprsurf_offset =
423                 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
424                                                pixel_size, fb->pitches[0]);
425         linear_offset -= sprsurf_offset;
426
427         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
428
429         intel_update_primary_plane(intel_crtc);
430
431         I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
432         I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
433
434         /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
435          * register */
436         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
437                 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
438         else if (obj->tiling_mode != I915_TILING_NONE)
439                 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
440         else
441                 I915_WRITE(SPRLINOFF(pipe), linear_offset);
442
443         I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
444         if (intel_plane->can_scale)
445                 I915_WRITE(SPRSCALE(pipe), sprscale);
446         I915_WRITE(SPRCTL(pipe), sprctl);
447         I915_WRITE(SPRSURF(pipe),
448                    i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
449
450         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
451
452         if (atomic_update)
453                 intel_pipe_update_end(intel_crtc, start_vbl_count);
454 }
455
456 static void
457 ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
458 {
459         struct drm_device *dev = plane->dev;
460         struct drm_i915_private *dev_priv = dev->dev_private;
461         struct intel_plane *intel_plane = to_intel_plane(plane);
462         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
463         int pipe = intel_plane->pipe;
464         u32 start_vbl_count;
465         bool atomic_update;
466
467         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
468
469         intel_update_primary_plane(intel_crtc);
470
471         I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
472         /* Can't leave the scaler enabled... */
473         if (intel_plane->can_scale)
474                 I915_WRITE(SPRSCALE(pipe), 0);
475         /* Activate double buffered register update */
476         I915_WRITE(SPRSURF(pipe), 0);
477
478         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
479
480         if (atomic_update)
481                 intel_pipe_update_end(intel_crtc, start_vbl_count);
482
483         /*
484          * Avoid underruns when disabling the sprite.
485          * FIXME remove once watermark updates are done properly.
486          */
487         intel_wait_for_vblank(dev, pipe);
488
489         intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
490 }
491
492 static int
493 ivb_update_colorkey(struct drm_plane *plane,
494                     struct drm_intel_sprite_colorkey *key)
495 {
496         struct drm_device *dev = plane->dev;
497         struct drm_i915_private *dev_priv = dev->dev_private;
498         struct intel_plane *intel_plane;
499         u32 sprctl;
500         int ret = 0;
501
502         intel_plane = to_intel_plane(plane);
503
504         I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
505         I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
506         I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
507
508         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
509         sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
510         if (key->flags & I915_SET_COLORKEY_DESTINATION)
511                 sprctl |= SPRITE_DEST_KEY;
512         else if (key->flags & I915_SET_COLORKEY_SOURCE)
513                 sprctl |= SPRITE_SOURCE_KEY;
514         I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
515
516         POSTING_READ(SPRKEYMSK(intel_plane->pipe));
517
518         return ret;
519 }
520
521 static void
522 ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
523 {
524         struct drm_device *dev = plane->dev;
525         struct drm_i915_private *dev_priv = dev->dev_private;
526         struct intel_plane *intel_plane;
527         u32 sprctl;
528
529         intel_plane = to_intel_plane(plane);
530
531         key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
532         key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
533         key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
534         key->flags = 0;
535
536         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
537
538         if (sprctl & SPRITE_DEST_KEY)
539                 key->flags = I915_SET_COLORKEY_DESTINATION;
540         else if (sprctl & SPRITE_SOURCE_KEY)
541                 key->flags = I915_SET_COLORKEY_SOURCE;
542         else
543                 key->flags = I915_SET_COLORKEY_NONE;
544 }
545
546 static void
547 ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
548                  struct drm_framebuffer *fb,
549                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
550                  unsigned int crtc_w, unsigned int crtc_h,
551                  uint32_t x, uint32_t y,
552                  uint32_t src_w, uint32_t src_h)
553 {
554         struct drm_device *dev = plane->dev;
555         struct drm_i915_private *dev_priv = dev->dev_private;
556         struct intel_plane *intel_plane = to_intel_plane(plane);
557         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
558         int pipe = intel_plane->pipe;
559         unsigned long dvssurf_offset, linear_offset;
560         u32 dvscntr, dvsscale;
561         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
562         u32 start_vbl_count;
563         bool atomic_update;
564
565         dvscntr = I915_READ(DVSCNTR(pipe));
566
567         /* Mask out pixel format bits in case we change it */
568         dvscntr &= ~DVS_PIXFORMAT_MASK;
569         dvscntr &= ~DVS_RGB_ORDER_XBGR;
570         dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
571         dvscntr &= ~DVS_TILED;
572
573         switch (fb->pixel_format) {
574         case DRM_FORMAT_XBGR8888:
575                 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
576                 break;
577         case DRM_FORMAT_XRGB8888:
578                 dvscntr |= DVS_FORMAT_RGBX888;
579                 break;
580         case DRM_FORMAT_YUYV:
581                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
582                 break;
583         case DRM_FORMAT_YVYU:
584                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
585                 break;
586         case DRM_FORMAT_UYVY:
587                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
588                 break;
589         case DRM_FORMAT_VYUY:
590                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
591                 break;
592         default:
593                 BUG();
594         }
595
596         /*
597          * Enable gamma to match primary/cursor plane behaviour.
598          * FIXME should be user controllable via propertiesa.
599          */
600         dvscntr |= DVS_GAMMA_ENABLE;
601
602         if (obj->tiling_mode != I915_TILING_NONE)
603                 dvscntr |= DVS_TILED;
604
605         if (IS_GEN6(dev))
606                 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
607         dvscntr |= DVS_ENABLE;
608
609         intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
610                                        src_w != crtc_w || src_h != crtc_h);
611
612         /* Sizes are 0 based */
613         src_w--;
614         src_h--;
615         crtc_w--;
616         crtc_h--;
617
618         dvsscale = 0;
619         if (crtc_w != src_w || crtc_h != src_h)
620                 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
621
622         linear_offset = y * fb->pitches[0] + x * pixel_size;
623         dvssurf_offset =
624                 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
625                                                pixel_size, fb->pitches[0]);
626         linear_offset -= dvssurf_offset;
627
628         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
629
630         intel_update_primary_plane(intel_crtc);
631
632         I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
633         I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
634
635         if (obj->tiling_mode != I915_TILING_NONE)
636                 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
637         else
638                 I915_WRITE(DVSLINOFF(pipe), linear_offset);
639
640         I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
641         I915_WRITE(DVSSCALE(pipe), dvsscale);
642         I915_WRITE(DVSCNTR(pipe), dvscntr);
643         I915_WRITE(DVSSURF(pipe),
644                    i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
645
646         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
647
648         if (atomic_update)
649                 intel_pipe_update_end(intel_crtc, start_vbl_count);
650 }
651
652 static void
653 ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
654 {
655         struct drm_device *dev = plane->dev;
656         struct drm_i915_private *dev_priv = dev->dev_private;
657         struct intel_plane *intel_plane = to_intel_plane(plane);
658         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
659         int pipe = intel_plane->pipe;
660         u32 start_vbl_count;
661         bool atomic_update;
662
663         atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
664
665         intel_update_primary_plane(intel_crtc);
666
667         I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
668         /* Disable the scaler */
669         I915_WRITE(DVSSCALE(pipe), 0);
670         /* Flush double buffered register updates */
671         I915_WRITE(DVSSURF(pipe), 0);
672
673         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
674
675         if (atomic_update)
676                 intel_pipe_update_end(intel_crtc, start_vbl_count);
677
678         /*
679          * Avoid underruns when disabling the sprite.
680          * FIXME remove once watermark updates are done properly.
681          */
682         intel_wait_for_vblank(dev, pipe);
683
684         intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
685 }
686
687 static void
688 intel_post_enable_primary(struct drm_crtc *crtc)
689 {
690         struct drm_device *dev = crtc->dev;
691         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
692
693         /*
694          * BDW signals flip done immediately if the plane
695          * is disabled, even if the plane enable is already
696          * armed to occur at the next vblank :(
697          */
698         if (IS_BROADWELL(dev))
699                 intel_wait_for_vblank(dev, intel_crtc->pipe);
700
701         /*
702          * FIXME IPS should be fine as long as one plane is
703          * enabled, but in practice it seems to have problems
704          * when going from primary only to sprite only and vice
705          * versa.
706          */
707         hsw_enable_ips(intel_crtc);
708
709         mutex_lock(&dev->struct_mutex);
710         intel_update_fbc(dev);
711         mutex_unlock(&dev->struct_mutex);
712 }
713
714 static void
715 intel_pre_disable_primary(struct drm_crtc *crtc)
716 {
717         struct drm_device *dev = crtc->dev;
718         struct drm_i915_private *dev_priv = dev->dev_private;
719         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
720
721         mutex_lock(&dev->struct_mutex);
722         if (dev_priv->fbc.plane == intel_crtc->plane)
723                 intel_disable_fbc(dev);
724         mutex_unlock(&dev->struct_mutex);
725
726         /*
727          * FIXME IPS should be fine as long as one plane is
728          * enabled, but in practice it seems to have problems
729          * when going from primary only to sprite only and vice
730          * versa.
731          */
732         hsw_disable_ips(intel_crtc);
733 }
734
735 static int
736 ilk_update_colorkey(struct drm_plane *plane,
737                     struct drm_intel_sprite_colorkey *key)
738 {
739         struct drm_device *dev = plane->dev;
740         struct drm_i915_private *dev_priv = dev->dev_private;
741         struct intel_plane *intel_plane;
742         u32 dvscntr;
743         int ret = 0;
744
745         intel_plane = to_intel_plane(plane);
746
747         I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
748         I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
749         I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
750
751         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
752         dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
753         if (key->flags & I915_SET_COLORKEY_DESTINATION)
754                 dvscntr |= DVS_DEST_KEY;
755         else if (key->flags & I915_SET_COLORKEY_SOURCE)
756                 dvscntr |= DVS_SOURCE_KEY;
757         I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
758
759         POSTING_READ(DVSKEYMSK(intel_plane->pipe));
760
761         return ret;
762 }
763
764 static void
765 ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
766 {
767         struct drm_device *dev = plane->dev;
768         struct drm_i915_private *dev_priv = dev->dev_private;
769         struct intel_plane *intel_plane;
770         u32 dvscntr;
771
772         intel_plane = to_intel_plane(plane);
773
774         key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
775         key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
776         key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
777         key->flags = 0;
778
779         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
780
781         if (dvscntr & DVS_DEST_KEY)
782                 key->flags = I915_SET_COLORKEY_DESTINATION;
783         else if (dvscntr & DVS_SOURCE_KEY)
784                 key->flags = I915_SET_COLORKEY_SOURCE;
785         else
786                 key->flags = I915_SET_COLORKEY_NONE;
787 }
788
789 static bool
790 format_is_yuv(uint32_t format)
791 {
792         switch (format) {
793         case DRM_FORMAT_YUYV:
794         case DRM_FORMAT_UYVY:
795         case DRM_FORMAT_VYUY:
796         case DRM_FORMAT_YVYU:
797                 return true;
798         default:
799                 return false;
800         }
801 }
802
803 static bool colorkey_enabled(struct intel_plane *intel_plane)
804 {
805         struct drm_intel_sprite_colorkey key;
806
807         intel_plane->get_colorkey(&intel_plane->base, &key);
808
809         return key.flags != I915_SET_COLORKEY_NONE;
810 }
811
812 static int
813 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
814                    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
815                    unsigned int crtc_w, unsigned int crtc_h,
816                    uint32_t src_x, uint32_t src_y,
817                    uint32_t src_w, uint32_t src_h)
818 {
819         struct drm_device *dev = plane->dev;
820         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
821         struct intel_plane *intel_plane = to_intel_plane(plane);
822         enum pipe pipe = intel_crtc->pipe;
823         struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
824         struct drm_i915_gem_object *obj = intel_fb->obj;
825         struct drm_i915_gem_object *old_obj = intel_plane->obj;
826         int ret;
827         bool primary_enabled;
828         bool visible;
829         int hscale, vscale;
830         int max_scale, min_scale;
831         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
832         struct drm_rect src = {
833                 /* sample coordinates in 16.16 fixed point */
834                 .x1 = src_x,
835                 .x2 = src_x + src_w,
836                 .y1 = src_y,
837                 .y2 = src_y + src_h,
838         };
839         struct drm_rect dst = {
840                 /* integer pixels */
841                 .x1 = crtc_x,
842                 .x2 = crtc_x + crtc_w,
843                 .y1 = crtc_y,
844                 .y2 = crtc_y + crtc_h,
845         };
846         const struct drm_rect clip = {
847                 .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
848                 .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
849         };
850         const struct {
851                 int crtc_x, crtc_y;
852                 unsigned int crtc_w, crtc_h;
853                 uint32_t src_x, src_y, src_w, src_h;
854         } orig = {
855                 .crtc_x = crtc_x,
856                 .crtc_y = crtc_y,
857                 .crtc_w = crtc_w,
858                 .crtc_h = crtc_h,
859                 .src_x = src_x,
860                 .src_y = src_y,
861                 .src_w = src_w,
862                 .src_h = src_h,
863         };
864
865         /* Don't modify another pipe's plane */
866         if (intel_plane->pipe != intel_crtc->pipe) {
867                 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
868                 return -EINVAL;
869         }
870
871         /* FIXME check all gen limits */
872         if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
873                 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
874                 return -EINVAL;
875         }
876
877         /* Sprite planes can be linear or x-tiled surfaces */
878         switch (obj->tiling_mode) {
879                 case I915_TILING_NONE:
880                 case I915_TILING_X:
881                         break;
882                 default:
883                         DRM_DEBUG_KMS("Unsupported tiling mode\n");
884                         return -EINVAL;
885         }
886
887         /*
888          * FIXME the following code does a bunch of fuzzy adjustments to the
889          * coordinates and sizes. We probably need some way to decide whether
890          * more strict checking should be done instead.
891          */
892         max_scale = intel_plane->max_downscale << 16;
893         min_scale = intel_plane->can_scale ? 1 : (1 << 16);
894
895         hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale);
896         BUG_ON(hscale < 0);
897
898         vscale = drm_rect_calc_vscale_relaxed(&src, &dst, min_scale, max_scale);
899         BUG_ON(vscale < 0);
900
901         visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale);
902
903         crtc_x = dst.x1;
904         crtc_y = dst.y1;
905         crtc_w = drm_rect_width(&dst);
906         crtc_h = drm_rect_height(&dst);
907
908         if (visible) {
909                 /* check again in case clipping clamped the results */
910                 hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale);
911                 if (hscale < 0) {
912                         DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
913                         drm_rect_debug_print(&src, true);
914                         drm_rect_debug_print(&dst, false);
915
916                         return hscale;
917                 }
918
919                 vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale);
920                 if (vscale < 0) {
921                         DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
922                         drm_rect_debug_print(&src, true);
923                         drm_rect_debug_print(&dst, false);
924
925                         return vscale;
926                 }
927
928                 /* Make the source viewport size an exact multiple of the scaling factors. */
929                 drm_rect_adjust_size(&src,
930                                      drm_rect_width(&dst) * hscale - drm_rect_width(&src),
931                                      drm_rect_height(&dst) * vscale - drm_rect_height(&src));
932
933                 /* sanity check to make sure the src viewport wasn't enlarged */
934                 WARN_ON(src.x1 < (int) src_x ||
935                         src.y1 < (int) src_y ||
936                         src.x2 > (int) (src_x + src_w) ||
937                         src.y2 > (int) (src_y + src_h));
938
939                 /*
940                  * Hardware doesn't handle subpixel coordinates.
941                  * Adjust to (macro)pixel boundary, but be careful not to
942                  * increase the source viewport size, because that could
943                  * push the downscaling factor out of bounds.
944                  */
945                 src_x = src.x1 >> 16;
946                 src_w = drm_rect_width(&src) >> 16;
947                 src_y = src.y1 >> 16;
948                 src_h = drm_rect_height(&src) >> 16;
949
950                 if (format_is_yuv(fb->pixel_format)) {
951                         src_x &= ~1;
952                         src_w &= ~1;
953
954                         /*
955                          * Must keep src and dst the
956                          * same if we can't scale.
957                          */
958                         if (!intel_plane->can_scale)
959                                 crtc_w &= ~1;
960
961                         if (crtc_w == 0)
962                                 visible = false;
963                 }
964         }
965
966         /* Check size restrictions when scaling */
967         if (visible && (src_w != crtc_w || src_h != crtc_h)) {
968                 unsigned int width_bytes;
969
970                 WARN_ON(!intel_plane->can_scale);
971
972                 /* FIXME interlacing min height is 6 */
973
974                 if (crtc_w < 3 || crtc_h < 3)
975                         visible = false;
976
977                 if (src_w < 3 || src_h < 3)
978                         visible = false;
979
980                 width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size;
981
982                 if (src_w > 2048 || src_h > 2048 ||
983                     width_bytes > 4096 || fb->pitches[0] > 4096) {
984                         DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
985                         return -EINVAL;
986                 }
987         }
988
989         dst.x1 = crtc_x;
990         dst.x2 = crtc_x + crtc_w;
991         dst.y1 = crtc_y;
992         dst.y2 = crtc_y + crtc_h;
993
994         /*
995          * If the sprite is completely covering the primary plane,
996          * we can disable the primary and save power.
997          */
998         primary_enabled = !drm_rect_equals(&dst, &clip) || colorkey_enabled(intel_plane);
999         WARN_ON(!primary_enabled && !visible && intel_crtc->active);
1000
1001         mutex_lock(&dev->struct_mutex);
1002
1003         /* Note that this will apply the VT-d workaround for scanouts,
1004          * which is more restrictive than required for sprites. (The
1005          * primary plane requires 256KiB alignment with 64 PTE padding,
1006          * the sprite planes only require 128KiB alignment and 32 PTE padding.
1007          */
1008         ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
1009
1010         i915_gem_track_fb(old_obj, obj,
1011                           INTEL_FRONTBUFFER_SPRITE(pipe));
1012         mutex_unlock(&dev->struct_mutex);
1013
1014         if (ret)
1015                 return ret;
1016
1017         intel_plane->crtc_x = orig.crtc_x;
1018         intel_plane->crtc_y = orig.crtc_y;
1019         intel_plane->crtc_w = orig.crtc_w;
1020         intel_plane->crtc_h = orig.crtc_h;
1021         intel_plane->src_x = orig.src_x;
1022         intel_plane->src_y = orig.src_y;
1023         intel_plane->src_w = orig.src_w;
1024         intel_plane->src_h = orig.src_h;
1025         intel_plane->obj = obj;
1026
1027         if (intel_crtc->active) {
1028                 bool primary_was_enabled = intel_crtc->primary_enabled;
1029
1030                 intel_crtc->primary_enabled = primary_enabled;
1031
1032                 if (primary_was_enabled != primary_enabled)
1033                         intel_crtc_wait_for_pending_flips(crtc);
1034
1035                 if (primary_was_enabled && !primary_enabled)
1036                         intel_pre_disable_primary(crtc);
1037
1038                 if (visible)
1039                         intel_plane->update_plane(plane, crtc, fb, obj,
1040                                                   crtc_x, crtc_y, crtc_w, crtc_h,
1041                                                   src_x, src_y, src_w, src_h);
1042                 else
1043                         intel_plane->disable_plane(plane, crtc);
1044
1045                 intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
1046
1047                 if (!primary_was_enabled && primary_enabled)
1048                         intel_post_enable_primary(crtc);
1049         }
1050
1051         /* Unpin old obj after new one is active to avoid ugliness */
1052         if (old_obj) {
1053                 /*
1054                  * It's fairly common to simply update the position of
1055                  * an existing object.  In that case, we don't need to
1056                  * wait for vblank to avoid ugliness, we only need to
1057                  * do the pin & ref bookkeeping.
1058                  */
1059                 if (old_obj != obj && intel_crtc->active)
1060                         intel_wait_for_vblank(dev, intel_crtc->pipe);
1061
1062                 mutex_lock(&dev->struct_mutex);
1063                 intel_unpin_fb_obj(old_obj);
1064                 mutex_unlock(&dev->struct_mutex);
1065         }
1066
1067         return 0;
1068 }
1069
1070 static int
1071 intel_disable_plane(struct drm_plane *plane)
1072 {
1073         struct drm_device *dev = plane->dev;
1074         struct intel_plane *intel_plane = to_intel_plane(plane);
1075         struct intel_crtc *intel_crtc;
1076         enum pipe pipe;
1077
1078         if (!plane->fb)
1079                 return 0;
1080
1081         if (WARN_ON(!plane->crtc))
1082                 return -EINVAL;
1083
1084         intel_crtc = to_intel_crtc(plane->crtc);
1085         pipe = intel_crtc->pipe;
1086
1087         if (intel_crtc->active) {
1088                 bool primary_was_enabled = intel_crtc->primary_enabled;
1089
1090                 intel_crtc->primary_enabled = true;
1091
1092                 intel_plane->disable_plane(plane, plane->crtc);
1093
1094                 if (!primary_was_enabled && intel_crtc->primary_enabled)
1095                         intel_post_enable_primary(plane->crtc);
1096         }
1097
1098         if (intel_plane->obj) {
1099                 if (intel_crtc->active)
1100                         intel_wait_for_vblank(dev, intel_plane->pipe);
1101
1102                 mutex_lock(&dev->struct_mutex);
1103                 intel_unpin_fb_obj(intel_plane->obj);
1104                 i915_gem_track_fb(intel_plane->obj, NULL,
1105                                   INTEL_FRONTBUFFER_SPRITE(pipe));
1106                 mutex_unlock(&dev->struct_mutex);
1107
1108                 intel_plane->obj = NULL;
1109         }
1110
1111         return 0;
1112 }
1113
1114 static void intel_destroy_plane(struct drm_plane *plane)
1115 {
1116         struct intel_plane *intel_plane = to_intel_plane(plane);
1117         intel_disable_plane(plane);
1118         drm_plane_cleanup(plane);
1119         kfree(intel_plane);
1120 }
1121
1122 int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
1123                               struct drm_file *file_priv)
1124 {
1125         struct drm_intel_sprite_colorkey *set = data;
1126         struct drm_mode_object *obj;
1127         struct drm_plane *plane;
1128         struct intel_plane *intel_plane;
1129         int ret = 0;
1130
1131         if (!drm_core_check_feature(dev, DRIVER_MODESET))
1132                 return -ENODEV;
1133
1134         /* Make sure we don't try to enable both src & dest simultaneously */
1135         if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1136                 return -EINVAL;
1137
1138         drm_modeset_lock_all(dev);
1139
1140         obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
1141         if (!obj) {
1142                 ret = -ENOENT;
1143                 goto out_unlock;
1144         }
1145
1146         plane = obj_to_plane(obj);
1147         intel_plane = to_intel_plane(plane);
1148         ret = intel_plane->update_colorkey(plane, set);
1149
1150 out_unlock:
1151         drm_modeset_unlock_all(dev);
1152         return ret;
1153 }
1154
1155 int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
1156                               struct drm_file *file_priv)
1157 {
1158         struct drm_intel_sprite_colorkey *get = data;
1159         struct drm_mode_object *obj;
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         obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
1170         if (!obj) {
1171                 ret = -ENOENT;
1172                 goto out_unlock;
1173         }
1174
1175         plane = obj_to_plane(obj);
1176         intel_plane = to_intel_plane(plane);
1177         intel_plane->get_colorkey(plane, get);
1178
1179 out_unlock:
1180         drm_modeset_unlock_all(dev);
1181         return ret;
1182 }
1183
1184 void intel_plane_restore(struct drm_plane *plane)
1185 {
1186         struct intel_plane *intel_plane = to_intel_plane(plane);
1187
1188         if (!plane->crtc || !plane->fb)
1189                 return;
1190
1191         intel_update_plane(plane, plane->crtc, plane->fb,
1192                            intel_plane->crtc_x, intel_plane->crtc_y,
1193                            intel_plane->crtc_w, intel_plane->crtc_h,
1194                            intel_plane->src_x, intel_plane->src_y,
1195                            intel_plane->src_w, intel_plane->src_h);
1196 }
1197
1198 void intel_plane_disable(struct drm_plane *plane)
1199 {
1200         if (!plane->crtc || !plane->fb)
1201                 return;
1202
1203         intel_disable_plane(plane);
1204 }
1205
1206 static const struct drm_plane_funcs intel_plane_funcs = {
1207         .update_plane = intel_update_plane,
1208         .disable_plane = intel_disable_plane,
1209         .destroy = intel_destroy_plane,
1210 };
1211
1212 static uint32_t ilk_plane_formats[] = {
1213         DRM_FORMAT_XRGB8888,
1214         DRM_FORMAT_YUYV,
1215         DRM_FORMAT_YVYU,
1216         DRM_FORMAT_UYVY,
1217         DRM_FORMAT_VYUY,
1218 };
1219
1220 static uint32_t snb_plane_formats[] = {
1221         DRM_FORMAT_XBGR8888,
1222         DRM_FORMAT_XRGB8888,
1223         DRM_FORMAT_YUYV,
1224         DRM_FORMAT_YVYU,
1225         DRM_FORMAT_UYVY,
1226         DRM_FORMAT_VYUY,
1227 };
1228
1229 static uint32_t vlv_plane_formats[] = {
1230         DRM_FORMAT_RGB565,
1231         DRM_FORMAT_ABGR8888,
1232         DRM_FORMAT_ARGB8888,
1233         DRM_FORMAT_XBGR8888,
1234         DRM_FORMAT_XRGB8888,
1235         DRM_FORMAT_XBGR2101010,
1236         DRM_FORMAT_ABGR2101010,
1237         DRM_FORMAT_YUYV,
1238         DRM_FORMAT_YVYU,
1239         DRM_FORMAT_UYVY,
1240         DRM_FORMAT_VYUY,
1241 };
1242
1243 int
1244 intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
1245 {
1246         struct intel_plane *intel_plane;
1247         unsigned long possible_crtcs;
1248         const uint32_t *plane_formats;
1249         int num_plane_formats;
1250         int ret;
1251
1252         if (INTEL_INFO(dev)->gen < 5)
1253                 return -ENODEV;
1254
1255         intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1256         if (!intel_plane)
1257                 return -ENOMEM;
1258
1259         switch (INTEL_INFO(dev)->gen) {
1260         case 5:
1261         case 6:
1262                 intel_plane->can_scale = true;
1263                 intel_plane->max_downscale = 16;
1264                 intel_plane->update_plane = ilk_update_plane;
1265                 intel_plane->disable_plane = ilk_disable_plane;
1266                 intel_plane->update_colorkey = ilk_update_colorkey;
1267                 intel_plane->get_colorkey = ilk_get_colorkey;
1268
1269                 if (IS_GEN6(dev)) {
1270                         plane_formats = snb_plane_formats;
1271                         num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1272                 } else {
1273                         plane_formats = ilk_plane_formats;
1274                         num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1275                 }
1276                 break;
1277
1278         case 7:
1279         case 8:
1280                 if (IS_IVYBRIDGE(dev)) {
1281                         intel_plane->can_scale = true;
1282                         intel_plane->max_downscale = 2;
1283                 } else {
1284                         intel_plane->can_scale = false;
1285                         intel_plane->max_downscale = 1;
1286                 }
1287
1288                 if (IS_VALLEYVIEW(dev)) {
1289                         intel_plane->update_plane = vlv_update_plane;
1290                         intel_plane->disable_plane = vlv_disable_plane;
1291                         intel_plane->update_colorkey = vlv_update_colorkey;
1292                         intel_plane->get_colorkey = vlv_get_colorkey;
1293
1294                         plane_formats = vlv_plane_formats;
1295                         num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1296                 } else {
1297                         intel_plane->update_plane = ivb_update_plane;
1298                         intel_plane->disable_plane = ivb_disable_plane;
1299                         intel_plane->update_colorkey = ivb_update_colorkey;
1300                         intel_plane->get_colorkey = ivb_get_colorkey;
1301
1302                         plane_formats = snb_plane_formats;
1303                         num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1304                 }
1305                 break;
1306
1307         default:
1308                 kfree(intel_plane);
1309                 return -ENODEV;
1310         }
1311
1312         intel_plane->pipe = pipe;
1313         intel_plane->plane = plane;
1314         possible_crtcs = (1 << pipe);
1315         ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
1316                              &intel_plane_funcs,
1317                              plane_formats, num_plane_formats,
1318                              false);
1319         if (ret)
1320                 kfree(intel_plane);
1321
1322         return ret;
1323 }