Merge tag 'v3.13-rc3' into drm-intel-next-queued
[platform/adaptation/renesas_rcar/renesas_kernel.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 void
41 vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
42                  struct drm_framebuffer *fb,
43                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
44                  unsigned int crtc_w, unsigned int crtc_h,
45                  uint32_t x, uint32_t y,
46                  uint32_t src_w, uint32_t src_h)
47 {
48         struct drm_device *dev = dplane->dev;
49         struct drm_i915_private *dev_priv = dev->dev_private;
50         struct intel_plane *intel_plane = to_intel_plane(dplane);
51         int pipe = intel_plane->pipe;
52         int plane = intel_plane->plane;
53         u32 sprctl;
54         unsigned long sprsurf_offset, linear_offset;
55         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
56
57         sprctl = I915_READ(SPCNTR(pipe, plane));
58
59         /* Mask out pixel format bits in case we change it */
60         sprctl &= ~SP_PIXFORMAT_MASK;
61         sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
62         sprctl &= ~SP_TILED;
63
64         switch (fb->pixel_format) {
65         case DRM_FORMAT_YUYV:
66                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
67                 break;
68         case DRM_FORMAT_YVYU:
69                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
70                 break;
71         case DRM_FORMAT_UYVY:
72                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
73                 break;
74         case DRM_FORMAT_VYUY:
75                 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
76                 break;
77         case DRM_FORMAT_RGB565:
78                 sprctl |= SP_FORMAT_BGR565;
79                 break;
80         case DRM_FORMAT_XRGB8888:
81                 sprctl |= SP_FORMAT_BGRX8888;
82                 break;
83         case DRM_FORMAT_ARGB8888:
84                 sprctl |= SP_FORMAT_BGRA8888;
85                 break;
86         case DRM_FORMAT_XBGR2101010:
87                 sprctl |= SP_FORMAT_RGBX1010102;
88                 break;
89         case DRM_FORMAT_ABGR2101010:
90                 sprctl |= SP_FORMAT_RGBA1010102;
91                 break;
92         case DRM_FORMAT_XBGR8888:
93                 sprctl |= SP_FORMAT_RGBX8888;
94                 break;
95         case DRM_FORMAT_ABGR8888:
96                 sprctl |= SP_FORMAT_RGBA8888;
97                 break;
98         default:
99                 /*
100                  * If we get here one of the upper layers failed to filter
101                  * out the unsupported plane formats
102                  */
103                 BUG();
104                 break;
105         }
106
107         /*
108          * Enable gamma to match primary/cursor plane behaviour.
109          * FIXME should be user controllable via propertiesa.
110          */
111         sprctl |= SP_GAMMA_ENABLE;
112
113         if (obj->tiling_mode != I915_TILING_NONE)
114                 sprctl |= SP_TILED;
115
116         sprctl |= SP_ENABLE;
117
118         intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
119                                        src_w != crtc_w || src_h != crtc_h);
120
121         /* Sizes are 0 based */
122         src_w--;
123         src_h--;
124         crtc_w--;
125         crtc_h--;
126
127         I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
128         I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
129
130         linear_offset = y * fb->pitches[0] + x * pixel_size;
131         sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
132                                                         obj->tiling_mode,
133                                                         pixel_size,
134                                                         fb->pitches[0]);
135         linear_offset -= sprsurf_offset;
136
137         if (obj->tiling_mode != I915_TILING_NONE)
138                 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
139         else
140                 I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
141
142         I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
143         I915_WRITE(SPCNTR(pipe, plane), sprctl);
144         I915_MODIFY_DISPBASE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
145                              sprsurf_offset);
146         POSTING_READ(SPSURF(pipe, plane));
147 }
148
149 static void
150 vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
151 {
152         struct drm_device *dev = dplane->dev;
153         struct drm_i915_private *dev_priv = dev->dev_private;
154         struct intel_plane *intel_plane = to_intel_plane(dplane);
155         int pipe = intel_plane->pipe;
156         int plane = intel_plane->plane;
157
158         I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
159                    ~SP_ENABLE);
160         /* Activate double buffered register update */
161         I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
162         POSTING_READ(SPSURF(pipe, plane));
163
164         intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
165 }
166
167 static int
168 vlv_update_colorkey(struct drm_plane *dplane,
169                     struct drm_intel_sprite_colorkey *key)
170 {
171         struct drm_device *dev = dplane->dev;
172         struct drm_i915_private *dev_priv = dev->dev_private;
173         struct intel_plane *intel_plane = to_intel_plane(dplane);
174         int pipe = intel_plane->pipe;
175         int plane = intel_plane->plane;
176         u32 sprctl;
177
178         if (key->flags & I915_SET_COLORKEY_DESTINATION)
179                 return -EINVAL;
180
181         I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
182         I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
183         I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
184
185         sprctl = I915_READ(SPCNTR(pipe, plane));
186         sprctl &= ~SP_SOURCE_KEY;
187         if (key->flags & I915_SET_COLORKEY_SOURCE)
188                 sprctl |= SP_SOURCE_KEY;
189         I915_WRITE(SPCNTR(pipe, plane), sprctl);
190
191         POSTING_READ(SPKEYMSK(pipe, plane));
192
193         return 0;
194 }
195
196 static void
197 vlv_get_colorkey(struct drm_plane *dplane,
198                  struct drm_intel_sprite_colorkey *key)
199 {
200         struct drm_device *dev = dplane->dev;
201         struct drm_i915_private *dev_priv = dev->dev_private;
202         struct intel_plane *intel_plane = to_intel_plane(dplane);
203         int pipe = intel_plane->pipe;
204         int plane = intel_plane->plane;
205         u32 sprctl;
206
207         key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
208         key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
209         key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
210
211         sprctl = I915_READ(SPCNTR(pipe, plane));
212         if (sprctl & SP_SOURCE_KEY)
213                 key->flags = I915_SET_COLORKEY_SOURCE;
214         else
215                 key->flags = I915_SET_COLORKEY_NONE;
216 }
217
218 static void
219 ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
220                  struct drm_framebuffer *fb,
221                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
222                  unsigned int crtc_w, unsigned int crtc_h,
223                  uint32_t x, uint32_t y,
224                  uint32_t src_w, uint32_t src_h)
225 {
226         struct drm_device *dev = plane->dev;
227         struct drm_i915_private *dev_priv = dev->dev_private;
228         struct intel_plane *intel_plane = to_intel_plane(plane);
229         int pipe = intel_plane->pipe;
230         u32 sprctl, sprscale = 0;
231         unsigned long sprsurf_offset, linear_offset;
232         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
233         bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
234
235         sprctl = I915_READ(SPRCTL(pipe));
236
237         /* Mask out pixel format bits in case we change it */
238         sprctl &= ~SPRITE_PIXFORMAT_MASK;
239         sprctl &= ~SPRITE_RGB_ORDER_RGBX;
240         sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
241         sprctl &= ~SPRITE_TILED;
242
243         switch (fb->pixel_format) {
244         case DRM_FORMAT_XBGR8888:
245                 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
246                 break;
247         case DRM_FORMAT_XRGB8888:
248                 sprctl |= SPRITE_FORMAT_RGBX888;
249                 break;
250         case DRM_FORMAT_YUYV:
251                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
252                 break;
253         case DRM_FORMAT_YVYU:
254                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
255                 break;
256         case DRM_FORMAT_UYVY:
257                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
258                 break;
259         case DRM_FORMAT_VYUY:
260                 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
261                 break;
262         default:
263                 BUG();
264         }
265
266         /*
267          * Enable gamma to match primary/cursor plane behaviour.
268          * FIXME should be user controllable via propertiesa.
269          */
270         sprctl |= SPRITE_GAMMA_ENABLE;
271
272         if (obj->tiling_mode != I915_TILING_NONE)
273                 sprctl |= SPRITE_TILED;
274
275         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
276                 sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
277         else
278                 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
279
280         sprctl |= SPRITE_ENABLE;
281
282         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
283                 sprctl |= SPRITE_PIPE_CSC_ENABLE;
284
285         intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
286                                        src_w != crtc_w || src_h != crtc_h);
287
288         /* Sizes are 0 based */
289         src_w--;
290         src_h--;
291         crtc_w--;
292         crtc_h--;
293
294         /*
295          * IVB workaround: must disable low power watermarks for at least
296          * one frame before enabling scaling.  LP watermarks can be re-enabled
297          * when scaling is disabled.
298          */
299         if (crtc_w != src_w || crtc_h != src_h) {
300                 dev_priv->sprite_scaling_enabled |= 1 << pipe;
301
302                 if (!scaling_was_enabled) {
303                         intel_update_watermarks(crtc);
304                         intel_wait_for_vblank(dev, pipe);
305                 }
306                 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
307         } else
308                 dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
309
310         I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
311         I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
312
313         linear_offset = y * fb->pitches[0] + x * pixel_size;
314         sprsurf_offset =
315                 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
316                                                pixel_size, fb->pitches[0]);
317         linear_offset -= sprsurf_offset;
318
319         /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
320          * register */
321         if (IS_HASWELL(dev) || IS_BROADWELL(dev))
322                 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
323         else if (obj->tiling_mode != I915_TILING_NONE)
324                 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
325         else
326                 I915_WRITE(SPRLINOFF(pipe), linear_offset);
327
328         I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
329         if (intel_plane->can_scale)
330                 I915_WRITE(SPRSCALE(pipe), sprscale);
331         I915_WRITE(SPRCTL(pipe), sprctl);
332         I915_MODIFY_DISPBASE(SPRSURF(pipe),
333                              i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
334         POSTING_READ(SPRSURF(pipe));
335
336         /* potentially re-enable LP watermarks */
337         if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
338                 intel_update_watermarks(crtc);
339 }
340
341 static void
342 ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
343 {
344         struct drm_device *dev = plane->dev;
345         struct drm_i915_private *dev_priv = dev->dev_private;
346         struct intel_plane *intel_plane = to_intel_plane(plane);
347         int pipe = intel_plane->pipe;
348         bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
349
350         I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
351         /* Can't leave the scaler enabled... */
352         if (intel_plane->can_scale)
353                 I915_WRITE(SPRSCALE(pipe), 0);
354         /* Activate double buffered register update */
355         I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
356         POSTING_READ(SPRSURF(pipe));
357
358         dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
359
360         intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
361
362         /* potentially re-enable LP watermarks */
363         if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
364                 intel_update_watermarks(crtc);
365 }
366
367 static int
368 ivb_update_colorkey(struct drm_plane *plane,
369                     struct drm_intel_sprite_colorkey *key)
370 {
371         struct drm_device *dev = plane->dev;
372         struct drm_i915_private *dev_priv = dev->dev_private;
373         struct intel_plane *intel_plane;
374         u32 sprctl;
375         int ret = 0;
376
377         intel_plane = to_intel_plane(plane);
378
379         I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
380         I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
381         I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
382
383         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
384         sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
385         if (key->flags & I915_SET_COLORKEY_DESTINATION)
386                 sprctl |= SPRITE_DEST_KEY;
387         else if (key->flags & I915_SET_COLORKEY_SOURCE)
388                 sprctl |= SPRITE_SOURCE_KEY;
389         I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
390
391         POSTING_READ(SPRKEYMSK(intel_plane->pipe));
392
393         return ret;
394 }
395
396 static void
397 ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
398 {
399         struct drm_device *dev = plane->dev;
400         struct drm_i915_private *dev_priv = dev->dev_private;
401         struct intel_plane *intel_plane;
402         u32 sprctl;
403
404         intel_plane = to_intel_plane(plane);
405
406         key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
407         key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
408         key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
409         key->flags = 0;
410
411         sprctl = I915_READ(SPRCTL(intel_plane->pipe));
412
413         if (sprctl & SPRITE_DEST_KEY)
414                 key->flags = I915_SET_COLORKEY_DESTINATION;
415         else if (sprctl & SPRITE_SOURCE_KEY)
416                 key->flags = I915_SET_COLORKEY_SOURCE;
417         else
418                 key->flags = I915_SET_COLORKEY_NONE;
419 }
420
421 static void
422 ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
423                  struct drm_framebuffer *fb,
424                  struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
425                  unsigned int crtc_w, unsigned int crtc_h,
426                  uint32_t x, uint32_t y,
427                  uint32_t src_w, uint32_t src_h)
428 {
429         struct drm_device *dev = plane->dev;
430         struct drm_i915_private *dev_priv = dev->dev_private;
431         struct intel_plane *intel_plane = to_intel_plane(plane);
432         int pipe = intel_plane->pipe;
433         unsigned long dvssurf_offset, linear_offset;
434         u32 dvscntr, dvsscale;
435         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
436
437         dvscntr = I915_READ(DVSCNTR(pipe));
438
439         /* Mask out pixel format bits in case we change it */
440         dvscntr &= ~DVS_PIXFORMAT_MASK;
441         dvscntr &= ~DVS_RGB_ORDER_XBGR;
442         dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
443         dvscntr &= ~DVS_TILED;
444
445         switch (fb->pixel_format) {
446         case DRM_FORMAT_XBGR8888:
447                 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
448                 break;
449         case DRM_FORMAT_XRGB8888:
450                 dvscntr |= DVS_FORMAT_RGBX888;
451                 break;
452         case DRM_FORMAT_YUYV:
453                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
454                 break;
455         case DRM_FORMAT_YVYU:
456                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
457                 break;
458         case DRM_FORMAT_UYVY:
459                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
460                 break;
461         case DRM_FORMAT_VYUY:
462                 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
463                 break;
464         default:
465                 BUG();
466         }
467
468         /*
469          * Enable gamma to match primary/cursor plane behaviour.
470          * FIXME should be user controllable via propertiesa.
471          */
472         dvscntr |= DVS_GAMMA_ENABLE;
473
474         if (obj->tiling_mode != I915_TILING_NONE)
475                 dvscntr |= DVS_TILED;
476
477         if (IS_GEN6(dev))
478                 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
479         dvscntr |= DVS_ENABLE;
480
481         intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
482                                        src_w != crtc_w || src_h != crtc_h);
483
484         /* Sizes are 0 based */
485         src_w--;
486         src_h--;
487         crtc_w--;
488         crtc_h--;
489
490         dvsscale = 0;
491         if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
492                 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
493
494         I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
495         I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
496
497         linear_offset = y * fb->pitches[0] + x * pixel_size;
498         dvssurf_offset =
499                 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
500                                                pixel_size, fb->pitches[0]);
501         linear_offset -= dvssurf_offset;
502
503         if (obj->tiling_mode != I915_TILING_NONE)
504                 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
505         else
506                 I915_WRITE(DVSLINOFF(pipe), linear_offset);
507
508         I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
509         I915_WRITE(DVSSCALE(pipe), dvsscale);
510         I915_WRITE(DVSCNTR(pipe), dvscntr);
511         I915_MODIFY_DISPBASE(DVSSURF(pipe),
512                              i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
513         POSTING_READ(DVSSURF(pipe));
514 }
515
516 static void
517 ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
518 {
519         struct drm_device *dev = plane->dev;
520         struct drm_i915_private *dev_priv = dev->dev_private;
521         struct intel_plane *intel_plane = to_intel_plane(plane);
522         int pipe = intel_plane->pipe;
523
524         I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
525         /* Disable the scaler */
526         I915_WRITE(DVSSCALE(pipe), 0);
527         /* Flush double buffered register updates */
528         I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
529         POSTING_READ(DVSSURF(pipe));
530
531         intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
532 }
533
534 static void
535 intel_enable_primary(struct drm_crtc *crtc)
536 {
537         struct drm_device *dev = crtc->dev;
538         struct drm_i915_private *dev_priv = dev->dev_private;
539         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
540         int reg = DSPCNTR(intel_crtc->plane);
541
542         if (intel_crtc->primary_enabled)
543                 return;
544
545         intel_crtc->primary_enabled = true;
546
547         I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
548         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
549
550         /*
551          * FIXME IPS should be fine as long as one plane is
552          * enabled, but in practice it seems to have problems
553          * when going from primary only to sprite only and vice
554          * versa.
555          */
556         if (intel_crtc->config.ips_enabled) {
557                 intel_wait_for_vblank(dev, intel_crtc->pipe);
558                 hsw_enable_ips(intel_crtc);
559         }
560
561         mutex_lock(&dev->struct_mutex);
562         intel_update_fbc(dev);
563         mutex_unlock(&dev->struct_mutex);
564 }
565
566 static void
567 intel_disable_primary(struct drm_crtc *crtc)
568 {
569         struct drm_device *dev = crtc->dev;
570         struct drm_i915_private *dev_priv = dev->dev_private;
571         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
572         int reg = DSPCNTR(intel_crtc->plane);
573
574         if (!intel_crtc->primary_enabled)
575                 return;
576
577         intel_crtc->primary_enabled = false;
578
579         mutex_lock(&dev->struct_mutex);
580         if (dev_priv->fbc.plane == intel_crtc->plane)
581                 intel_disable_fbc(dev);
582         mutex_unlock(&dev->struct_mutex);
583
584         /*
585          * FIXME IPS should be fine as long as one plane is
586          * enabled, but in practice it seems to have problems
587          * when going from primary only to sprite only and vice
588          * versa.
589          */
590         hsw_disable_ips(intel_crtc);
591
592         I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
593         intel_flush_primary_plane(dev_priv, intel_crtc->plane);
594 }
595
596 static int
597 ilk_update_colorkey(struct drm_plane *plane,
598                     struct drm_intel_sprite_colorkey *key)
599 {
600         struct drm_device *dev = plane->dev;
601         struct drm_i915_private *dev_priv = dev->dev_private;
602         struct intel_plane *intel_plane;
603         u32 dvscntr;
604         int ret = 0;
605
606         intel_plane = to_intel_plane(plane);
607
608         I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
609         I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
610         I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
611
612         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
613         dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
614         if (key->flags & I915_SET_COLORKEY_DESTINATION)
615                 dvscntr |= DVS_DEST_KEY;
616         else if (key->flags & I915_SET_COLORKEY_SOURCE)
617                 dvscntr |= DVS_SOURCE_KEY;
618         I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
619
620         POSTING_READ(DVSKEYMSK(intel_plane->pipe));
621
622         return ret;
623 }
624
625 static void
626 ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
627 {
628         struct drm_device *dev = plane->dev;
629         struct drm_i915_private *dev_priv = dev->dev_private;
630         struct intel_plane *intel_plane;
631         u32 dvscntr;
632
633         intel_plane = to_intel_plane(plane);
634
635         key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
636         key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
637         key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
638         key->flags = 0;
639
640         dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
641
642         if (dvscntr & DVS_DEST_KEY)
643                 key->flags = I915_SET_COLORKEY_DESTINATION;
644         else if (dvscntr & DVS_SOURCE_KEY)
645                 key->flags = I915_SET_COLORKEY_SOURCE;
646         else
647                 key->flags = I915_SET_COLORKEY_NONE;
648 }
649
650 static bool
651 format_is_yuv(uint32_t format)
652 {
653         switch (format) {
654         case DRM_FORMAT_YUYV:
655         case DRM_FORMAT_UYVY:
656         case DRM_FORMAT_VYUY:
657         case DRM_FORMAT_YVYU:
658                 return true;
659         default:
660                 return false;
661         }
662 }
663
664 static int
665 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
666                    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
667                    unsigned int crtc_w, unsigned int crtc_h,
668                    uint32_t src_x, uint32_t src_y,
669                    uint32_t src_w, uint32_t src_h)
670 {
671         struct drm_device *dev = plane->dev;
672         struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
673         struct intel_plane *intel_plane = to_intel_plane(plane);
674         struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
675         struct drm_i915_gem_object *obj = intel_fb->obj;
676         struct drm_i915_gem_object *old_obj = intel_plane->obj;
677         int ret;
678         bool disable_primary = false;
679         bool visible;
680         int hscale, vscale;
681         int max_scale, min_scale;
682         int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
683         struct drm_rect src = {
684                 /* sample coordinates in 16.16 fixed point */
685                 .x1 = src_x,
686                 .x2 = src_x + src_w,
687                 .y1 = src_y,
688                 .y2 = src_y + src_h,
689         };
690         struct drm_rect dst = {
691                 /* integer pixels */
692                 .x1 = crtc_x,
693                 .x2 = crtc_x + crtc_w,
694                 .y1 = crtc_y,
695                 .y2 = crtc_y + crtc_h,
696         };
697         const struct drm_rect clip = {
698                 .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
699                 .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
700         };
701         const struct {
702                 int crtc_x, crtc_y;
703                 unsigned int crtc_w, crtc_h;
704                 uint32_t src_x, src_y, src_w, src_h;
705         } orig = {
706                 .crtc_x = crtc_x,
707                 .crtc_y = crtc_y,
708                 .crtc_w = crtc_w,
709                 .crtc_h = crtc_h,
710                 .src_x = src_x,
711                 .src_y = src_y,
712                 .src_w = src_w,
713                 .src_h = src_h,
714         };
715
716         /* Don't modify another pipe's plane */
717         if (intel_plane->pipe != intel_crtc->pipe) {
718                 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
719                 return -EINVAL;
720         }
721
722         /* FIXME check all gen limits */
723         if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
724                 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
725                 return -EINVAL;
726         }
727
728         /* Sprite planes can be linear or x-tiled surfaces */
729         switch (obj->tiling_mode) {
730                 case I915_TILING_NONE:
731                 case I915_TILING_X:
732                         break;
733                 default:
734                         DRM_DEBUG_KMS("Unsupported tiling mode\n");
735                         return -EINVAL;
736         }
737
738         /*
739          * FIXME the following code does a bunch of fuzzy adjustments to the
740          * coordinates and sizes. We probably need some way to decide whether
741          * more strict checking should be done instead.
742          */
743         max_scale = intel_plane->max_downscale << 16;
744         min_scale = intel_plane->can_scale ? 1 : (1 << 16);
745
746         hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale);
747         BUG_ON(hscale < 0);
748
749         vscale = drm_rect_calc_vscale_relaxed(&src, &dst, min_scale, max_scale);
750         BUG_ON(vscale < 0);
751
752         visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale);
753
754         crtc_x = dst.x1;
755         crtc_y = dst.y1;
756         crtc_w = drm_rect_width(&dst);
757         crtc_h = drm_rect_height(&dst);
758
759         if (visible) {
760                 /* check again in case clipping clamped the results */
761                 hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale);
762                 if (hscale < 0) {
763                         DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
764                         drm_rect_debug_print(&src, true);
765                         drm_rect_debug_print(&dst, false);
766
767                         return hscale;
768                 }
769
770                 vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale);
771                 if (vscale < 0) {
772                         DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
773                         drm_rect_debug_print(&src, true);
774                         drm_rect_debug_print(&dst, false);
775
776                         return vscale;
777                 }
778
779                 /* Make the source viewport size an exact multiple of the scaling factors. */
780                 drm_rect_adjust_size(&src,
781                                      drm_rect_width(&dst) * hscale - drm_rect_width(&src),
782                                      drm_rect_height(&dst) * vscale - drm_rect_height(&src));
783
784                 /* sanity check to make sure the src viewport wasn't enlarged */
785                 WARN_ON(src.x1 < (int) src_x ||
786                         src.y1 < (int) src_y ||
787                         src.x2 > (int) (src_x + src_w) ||
788                         src.y2 > (int) (src_y + src_h));
789
790                 /*
791                  * Hardware doesn't handle subpixel coordinates.
792                  * Adjust to (macro)pixel boundary, but be careful not to
793                  * increase the source viewport size, because that could
794                  * push the downscaling factor out of bounds.
795                  */
796                 src_x = src.x1 >> 16;
797                 src_w = drm_rect_width(&src) >> 16;
798                 src_y = src.y1 >> 16;
799                 src_h = drm_rect_height(&src) >> 16;
800
801                 if (format_is_yuv(fb->pixel_format)) {
802                         src_x &= ~1;
803                         src_w &= ~1;
804
805                         /*
806                          * Must keep src and dst the
807                          * same if we can't scale.
808                          */
809                         if (!intel_plane->can_scale)
810                                 crtc_w &= ~1;
811
812                         if (crtc_w == 0)
813                                 visible = false;
814                 }
815         }
816
817         /* Check size restrictions when scaling */
818         if (visible && (src_w != crtc_w || src_h != crtc_h)) {
819                 unsigned int width_bytes;
820
821                 WARN_ON(!intel_plane->can_scale);
822
823                 /* FIXME interlacing min height is 6 */
824
825                 if (crtc_w < 3 || crtc_h < 3)
826                         visible = false;
827
828                 if (src_w < 3 || src_h < 3)
829                         visible = false;
830
831                 width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size;
832
833                 if (src_w > 2048 || src_h > 2048 ||
834                     width_bytes > 4096 || fb->pitches[0] > 4096) {
835                         DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
836                         return -EINVAL;
837                 }
838         }
839
840         dst.x1 = crtc_x;
841         dst.x2 = crtc_x + crtc_w;
842         dst.y1 = crtc_y;
843         dst.y2 = crtc_y + crtc_h;
844
845         /*
846          * If the sprite is completely covering the primary plane,
847          * we can disable the primary and save power.
848          */
849         disable_primary = drm_rect_equals(&dst, &clip);
850         WARN_ON(disable_primary && !visible && intel_crtc->active);
851
852         mutex_lock(&dev->struct_mutex);
853
854         /* Note that this will apply the VT-d workaround for scanouts,
855          * which is more restrictive than required for sprites. (The
856          * primary plane requires 256KiB alignment with 64 PTE padding,
857          * the sprite planes only require 128KiB alignment and 32 PTE padding.
858          */
859         ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
860
861         mutex_unlock(&dev->struct_mutex);
862
863         if (ret)
864                 return ret;
865
866         intel_plane->crtc_x = orig.crtc_x;
867         intel_plane->crtc_y = orig.crtc_y;
868         intel_plane->crtc_w = orig.crtc_w;
869         intel_plane->crtc_h = orig.crtc_h;
870         intel_plane->src_x = orig.src_x;
871         intel_plane->src_y = orig.src_y;
872         intel_plane->src_w = orig.src_w;
873         intel_plane->src_h = orig.src_h;
874         intel_plane->obj = obj;
875
876         if (intel_crtc->active) {
877                 /*
878                  * Be sure to re-enable the primary before the sprite is no longer
879                  * covering it fully.
880                  */
881                 if (!disable_primary)
882                         intel_enable_primary(crtc);
883
884                 if (visible)
885                         intel_plane->update_plane(plane, crtc, fb, obj,
886                                                   crtc_x, crtc_y, crtc_w, crtc_h,
887                                                   src_x, src_y, src_w, src_h);
888                 else
889                         intel_plane->disable_plane(plane, crtc);
890
891                 if (disable_primary)
892                         intel_disable_primary(crtc);
893         }
894
895         /* Unpin old obj after new one is active to avoid ugliness */
896         if (old_obj) {
897                 /*
898                  * It's fairly common to simply update the position of
899                  * an existing object.  In that case, we don't need to
900                  * wait for vblank to avoid ugliness, we only need to
901                  * do the pin & ref bookkeeping.
902                  */
903                 if (old_obj != obj && intel_crtc->active)
904                         intel_wait_for_vblank(dev, intel_crtc->pipe);
905
906                 mutex_lock(&dev->struct_mutex);
907                 intel_unpin_fb_obj(old_obj);
908                 mutex_unlock(&dev->struct_mutex);
909         }
910
911         return 0;
912 }
913
914 static int
915 intel_disable_plane(struct drm_plane *plane)
916 {
917         struct drm_device *dev = plane->dev;
918         struct intel_plane *intel_plane = to_intel_plane(plane);
919         struct intel_crtc *intel_crtc;
920
921         if (!plane->fb)
922                 return 0;
923
924         if (WARN_ON(!plane->crtc))
925                 return -EINVAL;
926
927         intel_crtc = to_intel_crtc(plane->crtc);
928
929         if (intel_crtc->active) {
930                 intel_enable_primary(plane->crtc);
931                 intel_plane->disable_plane(plane, plane->crtc);
932         }
933
934         if (intel_plane->obj) {
935                 if (intel_crtc->active)
936                         intel_wait_for_vblank(dev, intel_plane->pipe);
937
938                 mutex_lock(&dev->struct_mutex);
939                 intel_unpin_fb_obj(intel_plane->obj);
940                 mutex_unlock(&dev->struct_mutex);
941
942                 intel_plane->obj = NULL;
943         }
944
945         return 0;
946 }
947
948 static void intel_destroy_plane(struct drm_plane *plane)
949 {
950         struct intel_plane *intel_plane = to_intel_plane(plane);
951         intel_disable_plane(plane);
952         drm_plane_cleanup(plane);
953         kfree(intel_plane);
954 }
955
956 int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
957                               struct drm_file *file_priv)
958 {
959         struct drm_intel_sprite_colorkey *set = data;
960         struct drm_mode_object *obj;
961         struct drm_plane *plane;
962         struct intel_plane *intel_plane;
963         int ret = 0;
964
965         if (!drm_core_check_feature(dev, DRIVER_MODESET))
966                 return -ENODEV;
967
968         /* Make sure we don't try to enable both src & dest simultaneously */
969         if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
970                 return -EINVAL;
971
972         drm_modeset_lock_all(dev);
973
974         obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
975         if (!obj) {
976                 ret = -ENOENT;
977                 goto out_unlock;
978         }
979
980         plane = obj_to_plane(obj);
981         intel_plane = to_intel_plane(plane);
982         ret = intel_plane->update_colorkey(plane, set);
983
984 out_unlock:
985         drm_modeset_unlock_all(dev);
986         return ret;
987 }
988
989 int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
990                               struct drm_file *file_priv)
991 {
992         struct drm_intel_sprite_colorkey *get = data;
993         struct drm_mode_object *obj;
994         struct drm_plane *plane;
995         struct intel_plane *intel_plane;
996         int ret = 0;
997
998         if (!drm_core_check_feature(dev, DRIVER_MODESET))
999                 return -ENODEV;
1000
1001         drm_modeset_lock_all(dev);
1002
1003         obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
1004         if (!obj) {
1005                 ret = -ENOENT;
1006                 goto out_unlock;
1007         }
1008
1009         plane = obj_to_plane(obj);
1010         intel_plane = to_intel_plane(plane);
1011         intel_plane->get_colorkey(plane, get);
1012
1013 out_unlock:
1014         drm_modeset_unlock_all(dev);
1015         return ret;
1016 }
1017
1018 void intel_plane_restore(struct drm_plane *plane)
1019 {
1020         struct intel_plane *intel_plane = to_intel_plane(plane);
1021
1022         if (!plane->crtc || !plane->fb)
1023                 return;
1024
1025         intel_update_plane(plane, plane->crtc, plane->fb,
1026                            intel_plane->crtc_x, intel_plane->crtc_y,
1027                            intel_plane->crtc_w, intel_plane->crtc_h,
1028                            intel_plane->src_x, intel_plane->src_y,
1029                            intel_plane->src_w, intel_plane->src_h);
1030 }
1031
1032 void intel_plane_disable(struct drm_plane *plane)
1033 {
1034         if (!plane->crtc || !plane->fb)
1035                 return;
1036
1037         intel_disable_plane(plane);
1038 }
1039
1040 static const struct drm_plane_funcs intel_plane_funcs = {
1041         .update_plane = intel_update_plane,
1042         .disable_plane = intel_disable_plane,
1043         .destroy = intel_destroy_plane,
1044 };
1045
1046 static uint32_t ilk_plane_formats[] = {
1047         DRM_FORMAT_XRGB8888,
1048         DRM_FORMAT_YUYV,
1049         DRM_FORMAT_YVYU,
1050         DRM_FORMAT_UYVY,
1051         DRM_FORMAT_VYUY,
1052 };
1053
1054 static uint32_t snb_plane_formats[] = {
1055         DRM_FORMAT_XBGR8888,
1056         DRM_FORMAT_XRGB8888,
1057         DRM_FORMAT_YUYV,
1058         DRM_FORMAT_YVYU,
1059         DRM_FORMAT_UYVY,
1060         DRM_FORMAT_VYUY,
1061 };
1062
1063 static uint32_t vlv_plane_formats[] = {
1064         DRM_FORMAT_RGB565,
1065         DRM_FORMAT_ABGR8888,
1066         DRM_FORMAT_ARGB8888,
1067         DRM_FORMAT_XBGR8888,
1068         DRM_FORMAT_XRGB8888,
1069         DRM_FORMAT_XBGR2101010,
1070         DRM_FORMAT_ABGR2101010,
1071         DRM_FORMAT_YUYV,
1072         DRM_FORMAT_YVYU,
1073         DRM_FORMAT_UYVY,
1074         DRM_FORMAT_VYUY,
1075 };
1076
1077 int
1078 intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
1079 {
1080         struct intel_plane *intel_plane;
1081         unsigned long possible_crtcs;
1082         const uint32_t *plane_formats;
1083         int num_plane_formats;
1084         int ret;
1085
1086         if (INTEL_INFO(dev)->gen < 5)
1087                 return -ENODEV;
1088
1089         intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1090         if (!intel_plane)
1091                 return -ENOMEM;
1092
1093         switch (INTEL_INFO(dev)->gen) {
1094         case 5:
1095         case 6:
1096                 intel_plane->can_scale = true;
1097                 intel_plane->max_downscale = 16;
1098                 intel_plane->update_plane = ilk_update_plane;
1099                 intel_plane->disable_plane = ilk_disable_plane;
1100                 intel_plane->update_colorkey = ilk_update_colorkey;
1101                 intel_plane->get_colorkey = ilk_get_colorkey;
1102
1103                 if (IS_GEN6(dev)) {
1104                         plane_formats = snb_plane_formats;
1105                         num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1106                 } else {
1107                         plane_formats = ilk_plane_formats;
1108                         num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1109                 }
1110                 break;
1111
1112         case 7:
1113         case 8:
1114                 if (IS_IVYBRIDGE(dev)) {
1115                         intel_plane->can_scale = true;
1116                         intel_plane->max_downscale = 2;
1117                 } else {
1118                         intel_plane->can_scale = false;
1119                         intel_plane->max_downscale = 1;
1120                 }
1121
1122                 if (IS_VALLEYVIEW(dev)) {
1123                         intel_plane->update_plane = vlv_update_plane;
1124                         intel_plane->disable_plane = vlv_disable_plane;
1125                         intel_plane->update_colorkey = vlv_update_colorkey;
1126                         intel_plane->get_colorkey = vlv_get_colorkey;
1127
1128                         plane_formats = vlv_plane_formats;
1129                         num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1130                 } else {
1131                         intel_plane->update_plane = ivb_update_plane;
1132                         intel_plane->disable_plane = ivb_disable_plane;
1133                         intel_plane->update_colorkey = ivb_update_colorkey;
1134                         intel_plane->get_colorkey = ivb_get_colorkey;
1135
1136                         plane_formats = snb_plane_formats;
1137                         num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1138                 }
1139                 break;
1140
1141         default:
1142                 kfree(intel_plane);
1143                 return -ENODEV;
1144         }
1145
1146         intel_plane->pipe = pipe;
1147         intel_plane->plane = plane;
1148         possible_crtcs = (1 << pipe);
1149         ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
1150                              &intel_plane_funcs,
1151                              plane_formats, num_plane_formats,
1152                              false);
1153         if (ret)
1154                 kfree(intel_plane);
1155
1156         return ret;
1157 }