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