drm/i915: Check the framebuffer offset
[linux-block.git] / drivers / gpu / drm / i915 / intel_sprite.c
CommitLineData
b840d907
JB
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 */
760285e7
DH
32#include <drm/drmP.h>
33#include <drm/drm_crtc.h>
34#include <drm/drm_fourcc.h>
b840d907 35#include "intel_drv.h"
760285e7 36#include <drm/i915_drm.h>
b840d907
JB
37#include "i915_drv.h"
38
39static void
40ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
41 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
42 unsigned int crtc_w, unsigned int crtc_h,
43 uint32_t x, uint32_t y,
44 uint32_t src_w, uint32_t src_h)
45{
46 struct drm_device *dev = plane->dev;
47 struct drm_i915_private *dev_priv = dev->dev_private;
48 struct intel_plane *intel_plane = to_intel_plane(plane);
49 int pipe = intel_plane->pipe;
50 u32 sprctl, sprscale = 0;
51 int pixel_size;
5a35e99e 52 unsigned long sprsurf_offset, linear_offset;
b840d907
JB
53
54 sprctl = I915_READ(SPRCTL(pipe));
55
56 /* Mask out pixel format bits in case we change it */
57 sprctl &= ~SPRITE_PIXFORMAT_MASK;
58 sprctl &= ~SPRITE_RGB_ORDER_RGBX;
59 sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
e86fe0d3 60 sprctl &= ~SPRITE_TILED;
b840d907
JB
61
62 switch (fb->pixel_format) {
63 case DRM_FORMAT_XBGR8888:
5ee36913 64 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
b840d907
JB
65 pixel_size = 4;
66 break;
67 case DRM_FORMAT_XRGB8888:
5ee36913 68 sprctl |= SPRITE_FORMAT_RGBX888;
b840d907
JB
69 pixel_size = 4;
70 break;
71 case DRM_FORMAT_YUYV:
72 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
73 pixel_size = 2;
74 break;
75 case DRM_FORMAT_YVYU:
76 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
77 pixel_size = 2;
78 break;
79 case DRM_FORMAT_UYVY:
80 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
81 pixel_size = 2;
82 break;
83 case DRM_FORMAT_VYUY:
84 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
85 pixel_size = 2;
86 break;
87 default:
88 DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
f4d71056 89 sprctl |= SPRITE_FORMAT_RGBX888;
b840d907
JB
90 pixel_size = 4;
91 break;
92 }
93
94 if (obj->tiling_mode != I915_TILING_NONE)
95 sprctl |= SPRITE_TILED;
96
97 /* must disable */
98 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
99 sprctl |= SPRITE_ENABLE;
100
101 /* Sizes are 0 based */
102 src_w--;
103 src_h--;
104 crtc_w--;
105 crtc_h--;
106
107 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
108
109 /*
110 * IVB workaround: must disable low power watermarks for at least
111 * one frame before enabling scaling. LP watermarks can be re-enabled
112 * when scaling is disabled.
113 */
114 if (crtc_w != src_w || crtc_h != src_h) {
828ed3e1
CW
115 if (!dev_priv->sprite_scaling_enabled) {
116 dev_priv->sprite_scaling_enabled = true;
117 intel_update_watermarks(dev);
118 intel_wait_for_vblank(dev, pipe);
119 }
b840d907
JB
120 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
121 } else {
828ed3e1
CW
122 if (dev_priv->sprite_scaling_enabled) {
123 dev_priv->sprite_scaling_enabled = false;
124 /* potentially re-enable LP watermarks */
125 intel_update_watermarks(dev);
126 }
b840d907
JB
127 }
128
129 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
130 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
c54173a8 131
5a35e99e
DL
132 linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
133 sprsurf_offset =
134 intel_gen4_compute_offset_xtiled(&x, &y,
135 fb->bits_per_pixel / 8,
136 fb->pitches[0]);
137 linear_offset -= sprsurf_offset;
138
139 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
140 * register */
141 if (IS_HASWELL(dev))
c54173a8 142 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
5a35e99e 143 else if (obj->tiling_mode != I915_TILING_NONE)
b840d907 144 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
5a35e99e
DL
145 else
146 I915_WRITE(SPRLINOFF(pipe), linear_offset);
c54173a8 147
b840d907 148 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
2d354c34
DL
149 if (intel_plane->can_scale)
150 I915_WRITE(SPRSCALE(pipe), sprscale);
b840d907 151 I915_WRITE(SPRCTL(pipe), sprctl);
5a35e99e 152 I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
b840d907
JB
153 POSTING_READ(SPRSURF(pipe));
154}
155
156static void
157ivb_disable_plane(struct drm_plane *plane)
158{
159 struct drm_device *dev = plane->dev;
160 struct drm_i915_private *dev_priv = dev->dev_private;
161 struct intel_plane *intel_plane = to_intel_plane(plane);
162 int pipe = intel_plane->pipe;
163
164 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
165 /* Can't leave the scaler enabled... */
2d354c34
DL
166 if (intel_plane->can_scale)
167 I915_WRITE(SPRSCALE(pipe), 0);
b840d907 168 /* Activate double buffered register update */
446f2545 169 I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
b840d907 170 POSTING_READ(SPRSURF(pipe));
828ed3e1
CW
171
172 dev_priv->sprite_scaling_enabled = false;
173 intel_update_watermarks(dev);
b840d907
JB
174}
175
8ea30864
JB
176static int
177ivb_update_colorkey(struct drm_plane *plane,
178 struct drm_intel_sprite_colorkey *key)
179{
180 struct drm_device *dev = plane->dev;
181 struct drm_i915_private *dev_priv = dev->dev_private;
182 struct intel_plane *intel_plane;
183 u32 sprctl;
184 int ret = 0;
185
186 intel_plane = to_intel_plane(plane);
187
188 I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
189 I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
190 I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
191
192 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
193 sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
194 if (key->flags & I915_SET_COLORKEY_DESTINATION)
195 sprctl |= SPRITE_DEST_KEY;
196 else if (key->flags & I915_SET_COLORKEY_SOURCE)
197 sprctl |= SPRITE_SOURCE_KEY;
198 I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
199
200 POSTING_READ(SPRKEYMSK(intel_plane->pipe));
201
202 return ret;
203}
204
205static void
206ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
207{
208 struct drm_device *dev = plane->dev;
209 struct drm_i915_private *dev_priv = dev->dev_private;
210 struct intel_plane *intel_plane;
211 u32 sprctl;
212
213 intel_plane = to_intel_plane(plane);
214
215 key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
216 key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
217 key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
218 key->flags = 0;
219
220 sprctl = I915_READ(SPRCTL(intel_plane->pipe));
221
222 if (sprctl & SPRITE_DEST_KEY)
223 key->flags = I915_SET_COLORKEY_DESTINATION;
224 else if (sprctl & SPRITE_SOURCE_KEY)
225 key->flags = I915_SET_COLORKEY_SOURCE;
226 else
227 key->flags = I915_SET_COLORKEY_NONE;
228}
229
b840d907 230static void
d1686ae3 231ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
b840d907
JB
232 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
233 unsigned int crtc_w, unsigned int crtc_h,
234 uint32_t x, uint32_t y,
235 uint32_t src_w, uint32_t src_h)
236{
237 struct drm_device *dev = plane->dev;
238 struct drm_i915_private *dev_priv = dev->dev_private;
239 struct intel_plane *intel_plane = to_intel_plane(plane);
240 int pipe = intel_plane->pipe, pixel_size;
5a35e99e 241 unsigned long dvssurf_offset, linear_offset;
8aaa81a1 242 u32 dvscntr, dvsscale;
b840d907
JB
243
244 dvscntr = I915_READ(DVSCNTR(pipe));
245
246 /* Mask out pixel format bits in case we change it */
247 dvscntr &= ~DVS_PIXFORMAT_MASK;
ab2f9df1 248 dvscntr &= ~DVS_RGB_ORDER_XBGR;
b840d907 249 dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
79626523 250 dvscntr &= ~DVS_TILED;
b840d907
JB
251
252 switch (fb->pixel_format) {
253 case DRM_FORMAT_XBGR8888:
ab2f9df1 254 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
b840d907
JB
255 pixel_size = 4;
256 break;
257 case DRM_FORMAT_XRGB8888:
ab2f9df1 258 dvscntr |= DVS_FORMAT_RGBX888;
b840d907
JB
259 pixel_size = 4;
260 break;
261 case DRM_FORMAT_YUYV:
262 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
263 pixel_size = 2;
264 break;
265 case DRM_FORMAT_YVYU:
266 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
267 pixel_size = 2;
268 break;
269 case DRM_FORMAT_UYVY:
270 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
271 pixel_size = 2;
272 break;
273 case DRM_FORMAT_VYUY:
274 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
275 pixel_size = 2;
276 break;
277 default:
278 DRM_DEBUG_DRIVER("bad pixel format, assuming RGBX888\n");
279 dvscntr |= DVS_FORMAT_RGBX888;
280 pixel_size = 4;
281 break;
282 }
283
284 if (obj->tiling_mode != I915_TILING_NONE)
285 dvscntr |= DVS_TILED;
286
d1686ae3
CW
287 if (IS_GEN6(dev))
288 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
b840d907
JB
289 dvscntr |= DVS_ENABLE;
290
291 /* Sizes are 0 based */
292 src_w--;
293 src_h--;
294 crtc_w--;
295 crtc_h--;
296
297 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
298
8aaa81a1
CW
299 dvsscale = 0;
300 if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
b840d907
JB
301 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
302
303 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
304 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
5a35e99e
DL
305
306 linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
307 dvssurf_offset =
308 intel_gen4_compute_offset_xtiled(&x, &y,
309 fb->bits_per_pixel / 8,
310 fb->pitches[0]);
311 linear_offset -= dvssurf_offset;
312
313 if (obj->tiling_mode != I915_TILING_NONE)
b840d907 314 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
5a35e99e
DL
315 else
316 I915_WRITE(DVSLINOFF(pipe), linear_offset);
b840d907 317
b840d907
JB
318 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
319 I915_WRITE(DVSSCALE(pipe), dvsscale);
320 I915_WRITE(DVSCNTR(pipe), dvscntr);
5a35e99e 321 I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
b840d907
JB
322 POSTING_READ(DVSSURF(pipe));
323}
324
325static void
d1686ae3 326ilk_disable_plane(struct drm_plane *plane)
b840d907
JB
327{
328 struct drm_device *dev = plane->dev;
329 struct drm_i915_private *dev_priv = dev->dev_private;
330 struct intel_plane *intel_plane = to_intel_plane(plane);
331 int pipe = intel_plane->pipe;
332
333 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
334 /* Disable the scaler */
335 I915_WRITE(DVSSCALE(pipe), 0);
336 /* Flush double buffered register updates */
446f2545 337 I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
b840d907
JB
338 POSTING_READ(DVSSURF(pipe));
339}
340
175bd420
JB
341static void
342intel_enable_primary(struct drm_crtc *crtc)
343{
344 struct drm_device *dev = crtc->dev;
345 struct drm_i915_private *dev_priv = dev->dev_private;
346 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
347 int reg = DSPCNTR(intel_crtc->plane);
348
93314b5b
CW
349 if (!intel_crtc->primary_disabled)
350 return;
351
352 intel_crtc->primary_disabled = false;
353 intel_update_fbc(dev);
354
175bd420
JB
355 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
356}
357
358static void
359intel_disable_primary(struct drm_crtc *crtc)
360{
361 struct drm_device *dev = crtc->dev;
362 struct drm_i915_private *dev_priv = dev->dev_private;
363 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
364 int reg = DSPCNTR(intel_crtc->plane);
365
93314b5b
CW
366 if (intel_crtc->primary_disabled)
367 return;
368
175bd420 369 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
93314b5b
CW
370
371 intel_crtc->primary_disabled = true;
372 intel_update_fbc(dev);
175bd420
JB
373}
374
8ea30864 375static int
d1686ae3 376ilk_update_colorkey(struct drm_plane *plane,
8ea30864
JB
377 struct drm_intel_sprite_colorkey *key)
378{
379 struct drm_device *dev = plane->dev;
380 struct drm_i915_private *dev_priv = dev->dev_private;
381 struct intel_plane *intel_plane;
382 u32 dvscntr;
383 int ret = 0;
384
385 intel_plane = to_intel_plane(plane);
386
387 I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
388 I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
389 I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
390
391 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
392 dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
393 if (key->flags & I915_SET_COLORKEY_DESTINATION)
394 dvscntr |= DVS_DEST_KEY;
395 else if (key->flags & I915_SET_COLORKEY_SOURCE)
396 dvscntr |= DVS_SOURCE_KEY;
397 I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
398
399 POSTING_READ(DVSKEYMSK(intel_plane->pipe));
400
401 return ret;
402}
403
404static void
d1686ae3 405ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
8ea30864
JB
406{
407 struct drm_device *dev = plane->dev;
408 struct drm_i915_private *dev_priv = dev->dev_private;
409 struct intel_plane *intel_plane;
410 u32 dvscntr;
411
412 intel_plane = to_intel_plane(plane);
413
414 key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
415 key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
416 key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
417 key->flags = 0;
418
419 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
420
421 if (dvscntr & DVS_DEST_KEY)
422 key->flags = I915_SET_COLORKEY_DESTINATION;
423 else if (dvscntr & DVS_SOURCE_KEY)
424 key->flags = I915_SET_COLORKEY_SOURCE;
425 else
426 key->flags = I915_SET_COLORKEY_NONE;
427}
428
b840d907
JB
429static int
430intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
431 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
432 unsigned int crtc_w, unsigned int crtc_h,
433 uint32_t src_x, uint32_t src_y,
434 uint32_t src_w, uint32_t src_h)
435{
436 struct drm_device *dev = plane->dev;
437 struct drm_i915_private *dev_priv = dev->dev_private;
438 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
439 struct intel_plane *intel_plane = to_intel_plane(plane);
440 struct intel_framebuffer *intel_fb;
441 struct drm_i915_gem_object *obj, *old_obj;
442 int pipe = intel_plane->pipe;
702e7a56
PZ
443 enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
444 pipe);
b840d907
JB
445 int ret = 0;
446 int x = src_x >> 16, y = src_y >> 16;
447 int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
448 bool disable_primary = false;
449
450 intel_fb = to_intel_framebuffer(fb);
451 obj = intel_fb->obj;
452
453 old_obj = intel_plane->obj;
454
b4db1e35
JB
455 src_w = src_w >> 16;
456 src_h = src_h >> 16;
457
b840d907 458 /* Pipe must be running... */
702e7a56 459 if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE))
b840d907
JB
460 return -EINVAL;
461
462 if (crtc_x >= primary_w || crtc_y >= primary_h)
463 return -EINVAL;
464
465 /* Don't modify another pipe's plane */
466 if (intel_plane->pipe != intel_crtc->pipe)
467 return -EINVAL;
468
94c6419e
DL
469 /* Sprite planes can be linear or x-tiled surfaces */
470 switch (obj->tiling_mode) {
471 case I915_TILING_NONE:
472 case I915_TILING_X:
473 break;
474 default:
475 return -EINVAL;
476 }
477
b840d907
JB
478 /*
479 * Clamp the width & height into the visible area. Note we don't
480 * try to scale the source if part of the visible region is offscreen.
481 * The caller must handle that by adjusting source offset and size.
482 */
483 if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
484 crtc_w += crtc_x;
485 crtc_x = 0;
486 }
487 if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
488 goto out;
489 if ((crtc_x + crtc_w) > primary_w)
490 crtc_w = primary_w - crtc_x;
491
492 if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
493 crtc_h += crtc_y;
494 crtc_y = 0;
495 }
496 if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
497 goto out;
498 if (crtc_y + crtc_h > primary_h)
499 crtc_h = primary_h - crtc_y;
500
501 if (!crtc_w || !crtc_h) /* Again, nothing to display */
502 goto out;
503
2d354c34
DL
504 /*
505 * We may not have a scaler, eg. HSW does not have it any more
506 */
507 if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h))
508 return -EINVAL;
509
b840d907
JB
510 /*
511 * We can take a larger source and scale it down, but
512 * only so much... 16x is the max on SNB.
513 */
514 if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
515 return -EINVAL;
516
517 /*
518 * If the sprite is completely covering the primary plane,
519 * we can disable the primary and save power.
520 */
521 if ((crtc_x == 0) && (crtc_y == 0) &&
522 (crtc_w == primary_w) && (crtc_h == primary_h))
523 disable_primary = true;
524
525 mutex_lock(&dev->struct_mutex);
526
527 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
00c2064b 528 if (ret)
b840d907 529 goto out_unlock;
b840d907
JB
530
531 intel_plane->obj = obj;
532
175bd420
JB
533 /*
534 * Be sure to re-enable the primary before the sprite is no longer
535 * covering it fully.
536 */
93314b5b 537 if (!disable_primary)
175bd420 538 intel_enable_primary(crtc);
175bd420 539
b840d907
JB
540 intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
541 crtc_w, crtc_h, x, y, src_w, src_h);
542
93314b5b 543 if (disable_primary)
175bd420 544 intel_disable_primary(crtc);
175bd420 545
b840d907
JB
546 /* Unpin old obj after new one is active to avoid ugliness */
547 if (old_obj) {
548 /*
549 * It's fairly common to simply update the position of
550 * an existing object. In that case, we don't need to
551 * wait for vblank to avoid ugliness, we only need to
552 * do the pin & ref bookkeeping.
553 */
554 if (old_obj != obj) {
555 mutex_unlock(&dev->struct_mutex);
556 intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
557 mutex_lock(&dev->struct_mutex);
558 }
1690e1eb 559 intel_unpin_fb_obj(old_obj);
b840d907
JB
560 }
561
562out_unlock:
563 mutex_unlock(&dev->struct_mutex);
564out:
565 return ret;
566}
567
568static int
569intel_disable_plane(struct drm_plane *plane)
570{
571 struct drm_device *dev = plane->dev;
572 struct intel_plane *intel_plane = to_intel_plane(plane);
573 int ret = 0;
574
93314b5b 575 if (plane->crtc)
175bd420 576 intel_enable_primary(plane->crtc);
b840d907
JB
577 intel_plane->disable_plane(plane);
578
579 if (!intel_plane->obj)
580 goto out;
581
582 mutex_lock(&dev->struct_mutex);
1690e1eb 583 intel_unpin_fb_obj(intel_plane->obj);
b840d907
JB
584 intel_plane->obj = NULL;
585 mutex_unlock(&dev->struct_mutex);
586out:
587
588 return ret;
589}
590
591static void intel_destroy_plane(struct drm_plane *plane)
592{
593 struct intel_plane *intel_plane = to_intel_plane(plane);
594 intel_disable_plane(plane);
595 drm_plane_cleanup(plane);
596 kfree(intel_plane);
597}
598
8ea30864
JB
599int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
600 struct drm_file *file_priv)
601{
602 struct drm_intel_sprite_colorkey *set = data;
8ea30864
JB
603 struct drm_mode_object *obj;
604 struct drm_plane *plane;
605 struct intel_plane *intel_plane;
606 int ret = 0;
607
1cff8f6b
DV
608 if (!drm_core_check_feature(dev, DRIVER_MODESET))
609 return -ENODEV;
8ea30864
JB
610
611 /* Make sure we don't try to enable both src & dest simultaneously */
612 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
613 return -EINVAL;
614
615 mutex_lock(&dev->mode_config.mutex);
616
617 obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
618 if (!obj) {
619 ret = -EINVAL;
620 goto out_unlock;
621 }
622
623 plane = obj_to_plane(obj);
624 intel_plane = to_intel_plane(plane);
625 ret = intel_plane->update_colorkey(plane, set);
626
627out_unlock:
628 mutex_unlock(&dev->mode_config.mutex);
629 return ret;
630}
631
632int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
633 struct drm_file *file_priv)
634{
635 struct drm_intel_sprite_colorkey *get = data;
8ea30864
JB
636 struct drm_mode_object *obj;
637 struct drm_plane *plane;
638 struct intel_plane *intel_plane;
639 int ret = 0;
640
1cff8f6b
DV
641 if (!drm_core_check_feature(dev, DRIVER_MODESET))
642 return -ENODEV;
8ea30864
JB
643
644 mutex_lock(&dev->mode_config.mutex);
645
646 obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
647 if (!obj) {
648 ret = -EINVAL;
649 goto out_unlock;
650 }
651
652 plane = obj_to_plane(obj);
653 intel_plane = to_intel_plane(plane);
654 intel_plane->get_colorkey(plane, get);
655
656out_unlock:
657 mutex_unlock(&dev->mode_config.mutex);
658 return ret;
659}
660
b840d907
JB
661static const struct drm_plane_funcs intel_plane_funcs = {
662 .update_plane = intel_update_plane,
663 .disable_plane = intel_disable_plane,
664 .destroy = intel_destroy_plane,
665};
666
d1686ae3
CW
667static uint32_t ilk_plane_formats[] = {
668 DRM_FORMAT_XRGB8888,
669 DRM_FORMAT_YUYV,
670 DRM_FORMAT_YVYU,
671 DRM_FORMAT_UYVY,
672 DRM_FORMAT_VYUY,
673};
674
b840d907
JB
675static uint32_t snb_plane_formats[] = {
676 DRM_FORMAT_XBGR8888,
677 DRM_FORMAT_XRGB8888,
678 DRM_FORMAT_YUYV,
679 DRM_FORMAT_YVYU,
680 DRM_FORMAT_UYVY,
681 DRM_FORMAT_VYUY,
682};
683
684int
685intel_plane_init(struct drm_device *dev, enum pipe pipe)
686{
687 struct intel_plane *intel_plane;
688 unsigned long possible_crtcs;
d1686ae3
CW
689 const uint32_t *plane_formats;
690 int num_plane_formats;
b840d907
JB
691 int ret;
692
d1686ae3 693 if (INTEL_INFO(dev)->gen < 5)
b840d907 694 return -ENODEV;
b840d907
JB
695
696 intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
697 if (!intel_plane)
698 return -ENOMEM;
699
d1686ae3
CW
700 switch (INTEL_INFO(dev)->gen) {
701 case 5:
702 case 6:
2d354c34 703 intel_plane->can_scale = true;
b840d907 704 intel_plane->max_downscale = 16;
d1686ae3
CW
705 intel_plane->update_plane = ilk_update_plane;
706 intel_plane->disable_plane = ilk_disable_plane;
707 intel_plane->update_colorkey = ilk_update_colorkey;
708 intel_plane->get_colorkey = ilk_get_colorkey;
709
710 if (IS_GEN6(dev)) {
711 plane_formats = snb_plane_formats;
712 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
713 } else {
714 plane_formats = ilk_plane_formats;
715 num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
716 }
717 break;
718
719 case 7:
4d8d71b5 720 if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev))
2d354c34
DL
721 intel_plane->can_scale = false;
722 else
723 intel_plane->can_scale = true;
b840d907
JB
724 intel_plane->max_downscale = 2;
725 intel_plane->update_plane = ivb_update_plane;
726 intel_plane->disable_plane = ivb_disable_plane;
8ea30864
JB
727 intel_plane->update_colorkey = ivb_update_colorkey;
728 intel_plane->get_colorkey = ivb_get_colorkey;
d1686ae3
CW
729
730 plane_formats = snb_plane_formats;
731 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
732 break;
733
734 default:
a8b0bbab 735 kfree(intel_plane);
d1686ae3 736 return -ENODEV;
b840d907
JB
737 }
738
739 intel_plane->pipe = pipe;
740 possible_crtcs = (1 << pipe);
741 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
d1686ae3
CW
742 &intel_plane_funcs,
743 plane_formats, num_plane_formats,
744 false);
b840d907
JB
745 if (ret)
746 kfree(intel_plane);
747
748 return ret;
749}