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