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