drm/i915: Turn HAS_FPGA_DBG_UNCLAIMED into a device_info flag
[deliverable/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 "intel_drv.h"
36 #include <drm/i915_drm.h>
37 #include "i915_drv.h"
38
39 static void
40 vlv_update_plane(struct drm_plane *dplane, 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 = dplane->dev;
47 struct drm_i915_private *dev_priv = dev->dev_private;
48 struct intel_plane *intel_plane = to_intel_plane(dplane);
49 int pipe = intel_plane->pipe;
50 int plane = intel_plane->plane;
51 u32 sprctl;
52 unsigned long sprsurf_offset, linear_offset;
53 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
54
55 sprctl = I915_READ(SPCNTR(pipe, plane));
56
57 /* Mask out pixel format bits in case we change it */
58 sprctl &= ~SP_PIXFORMAT_MASK;
59 sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
60 sprctl &= ~SP_TILED;
61
62 switch (fb->pixel_format) {
63 case DRM_FORMAT_YUYV:
64 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
65 break;
66 case DRM_FORMAT_YVYU:
67 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
68 break;
69 case DRM_FORMAT_UYVY:
70 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
71 break;
72 case DRM_FORMAT_VYUY:
73 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
74 break;
75 case DRM_FORMAT_RGB565:
76 sprctl |= SP_FORMAT_BGR565;
77 break;
78 case DRM_FORMAT_XRGB8888:
79 sprctl |= SP_FORMAT_BGRX8888;
80 break;
81 case DRM_FORMAT_ARGB8888:
82 sprctl |= SP_FORMAT_BGRA8888;
83 break;
84 case DRM_FORMAT_XBGR2101010:
85 sprctl |= SP_FORMAT_RGBX1010102;
86 break;
87 case DRM_FORMAT_ABGR2101010:
88 sprctl |= SP_FORMAT_RGBA1010102;
89 break;
90 case DRM_FORMAT_XBGR8888:
91 sprctl |= SP_FORMAT_RGBX8888;
92 break;
93 case DRM_FORMAT_ABGR8888:
94 sprctl |= SP_FORMAT_RGBA8888;
95 break;
96 default:
97 /*
98 * If we get here one of the upper layers failed to filter
99 * out the unsupported plane formats
100 */
101 BUG();
102 break;
103 }
104
105 if (obj->tiling_mode != I915_TILING_NONE)
106 sprctl |= SP_TILED;
107
108 sprctl |= SP_ENABLE;
109
110 /* Sizes are 0 based */
111 src_w--;
112 src_h--;
113 crtc_w--;
114 crtc_h--;
115
116 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
117
118 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
119 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
120
121 linear_offset = y * fb->pitches[0] + x * pixel_size;
122 sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
123 obj->tiling_mode,
124 pixel_size,
125 fb->pitches[0]);
126 linear_offset -= sprsurf_offset;
127
128 if (obj->tiling_mode != I915_TILING_NONE)
129 I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
130 else
131 I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
132
133 I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
134 I915_WRITE(SPCNTR(pipe, plane), sprctl);
135 I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset +
136 sprsurf_offset);
137 POSTING_READ(SPSURF(pipe, plane));
138 }
139
140 static void
141 vlv_disable_plane(struct drm_plane *dplane)
142 {
143 struct drm_device *dev = dplane->dev;
144 struct drm_i915_private *dev_priv = dev->dev_private;
145 struct intel_plane *intel_plane = to_intel_plane(dplane);
146 int pipe = intel_plane->pipe;
147 int plane = intel_plane->plane;
148
149 I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
150 ~SP_ENABLE);
151 /* Activate double buffered register update */
152 I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
153 POSTING_READ(SPSURF(pipe, plane));
154 }
155
156 static int
157 vlv_update_colorkey(struct drm_plane *dplane,
158 struct drm_intel_sprite_colorkey *key)
159 {
160 struct drm_device *dev = dplane->dev;
161 struct drm_i915_private *dev_priv = dev->dev_private;
162 struct intel_plane *intel_plane = to_intel_plane(dplane);
163 int pipe = intel_plane->pipe;
164 int plane = intel_plane->plane;
165 u32 sprctl;
166
167 if (key->flags & I915_SET_COLORKEY_DESTINATION)
168 return -EINVAL;
169
170 I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
171 I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
172 I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
173
174 sprctl = I915_READ(SPCNTR(pipe, plane));
175 sprctl &= ~SP_SOURCE_KEY;
176 if (key->flags & I915_SET_COLORKEY_SOURCE)
177 sprctl |= SP_SOURCE_KEY;
178 I915_WRITE(SPCNTR(pipe, plane), sprctl);
179
180 POSTING_READ(SPKEYMSK(pipe, plane));
181
182 return 0;
183 }
184
185 static void
186 vlv_get_colorkey(struct drm_plane *dplane,
187 struct drm_intel_sprite_colorkey *key)
188 {
189 struct drm_device *dev = dplane->dev;
190 struct drm_i915_private *dev_priv = dev->dev_private;
191 struct intel_plane *intel_plane = to_intel_plane(dplane);
192 int pipe = intel_plane->pipe;
193 int plane = intel_plane->plane;
194 u32 sprctl;
195
196 key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
197 key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
198 key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
199
200 sprctl = I915_READ(SPCNTR(pipe, plane));
201 if (sprctl & SP_SOURCE_KEY)
202 key->flags = I915_SET_COLORKEY_SOURCE;
203 else
204 key->flags = I915_SET_COLORKEY_NONE;
205 }
206
207 static void
208 ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
209 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
210 unsigned int crtc_w, unsigned int crtc_h,
211 uint32_t x, uint32_t y,
212 uint32_t src_w, uint32_t src_h)
213 {
214 struct drm_device *dev = plane->dev;
215 struct drm_i915_private *dev_priv = dev->dev_private;
216 struct intel_plane *intel_plane = to_intel_plane(plane);
217 int pipe = intel_plane->pipe;
218 u32 sprctl, sprscale = 0;
219 unsigned long sprsurf_offset, linear_offset;
220 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
221 bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
222
223 sprctl = I915_READ(SPRCTL(pipe));
224
225 /* Mask out pixel format bits in case we change it */
226 sprctl &= ~SPRITE_PIXFORMAT_MASK;
227 sprctl &= ~SPRITE_RGB_ORDER_RGBX;
228 sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
229 sprctl &= ~SPRITE_TILED;
230
231 switch (fb->pixel_format) {
232 case DRM_FORMAT_XBGR8888:
233 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
234 break;
235 case DRM_FORMAT_XRGB8888:
236 sprctl |= SPRITE_FORMAT_RGBX888;
237 break;
238 case DRM_FORMAT_YUYV:
239 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
240 break;
241 case DRM_FORMAT_YVYU:
242 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
243 break;
244 case DRM_FORMAT_UYVY:
245 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
246 break;
247 case DRM_FORMAT_VYUY:
248 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
249 break;
250 default:
251 BUG();
252 }
253
254 if (obj->tiling_mode != I915_TILING_NONE)
255 sprctl |= SPRITE_TILED;
256
257 /* must disable */
258 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
259 sprctl |= SPRITE_ENABLE;
260
261 if (IS_HASWELL(dev))
262 sprctl |= SPRITE_PIPE_CSC_ENABLE;
263
264 /* Sizes are 0 based */
265 src_w--;
266 src_h--;
267 crtc_w--;
268 crtc_h--;
269
270 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
271
272 /*
273 * IVB workaround: must disable low power watermarks for at least
274 * one frame before enabling scaling. LP watermarks can be re-enabled
275 * when scaling is disabled.
276 */
277 if (crtc_w != src_w || crtc_h != src_h) {
278 dev_priv->sprite_scaling_enabled |= 1 << pipe;
279
280 if (!scaling_was_enabled) {
281 intel_update_watermarks(dev);
282 intel_wait_for_vblank(dev, pipe);
283 }
284 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
285 } else
286 dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
287
288 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
289 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
290
291 linear_offset = y * fb->pitches[0] + x * pixel_size;
292 sprsurf_offset =
293 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
294 pixel_size, fb->pitches[0]);
295 linear_offset -= sprsurf_offset;
296
297 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
298 * register */
299 if (IS_HASWELL(dev))
300 I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
301 else if (obj->tiling_mode != I915_TILING_NONE)
302 I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
303 else
304 I915_WRITE(SPRLINOFF(pipe), linear_offset);
305
306 I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
307 if (intel_plane->can_scale)
308 I915_WRITE(SPRSCALE(pipe), sprscale);
309 I915_WRITE(SPRCTL(pipe), sprctl);
310 I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
311 POSTING_READ(SPRSURF(pipe));
312
313 /* potentially re-enable LP watermarks */
314 if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
315 intel_update_watermarks(dev);
316 }
317
318 static void
319 ivb_disable_plane(struct drm_plane *plane)
320 {
321 struct drm_device *dev = plane->dev;
322 struct drm_i915_private *dev_priv = dev->dev_private;
323 struct intel_plane *intel_plane = to_intel_plane(plane);
324 int pipe = intel_plane->pipe;
325 bool scaling_was_enabled = dev_priv->sprite_scaling_enabled;
326
327 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
328 /* Can't leave the scaler enabled... */
329 if (intel_plane->can_scale)
330 I915_WRITE(SPRSCALE(pipe), 0);
331 /* Activate double buffered register update */
332 I915_MODIFY_DISPBASE(SPRSURF(pipe), 0);
333 POSTING_READ(SPRSURF(pipe));
334
335 dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
336
337 /* potentially re-enable LP watermarks */
338 if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
339 intel_update_watermarks(dev);
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_framebuffer *fb,
398 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
399 unsigned int crtc_w, unsigned int crtc_h,
400 uint32_t x, uint32_t y,
401 uint32_t src_w, uint32_t src_h)
402 {
403 struct drm_device *dev = plane->dev;
404 struct drm_i915_private *dev_priv = dev->dev_private;
405 struct intel_plane *intel_plane = to_intel_plane(plane);
406 int pipe = intel_plane->pipe;
407 unsigned long dvssurf_offset, linear_offset;
408 u32 dvscntr, dvsscale;
409 int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
410
411 dvscntr = I915_READ(DVSCNTR(pipe));
412
413 /* Mask out pixel format bits in case we change it */
414 dvscntr &= ~DVS_PIXFORMAT_MASK;
415 dvscntr &= ~DVS_RGB_ORDER_XBGR;
416 dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
417 dvscntr &= ~DVS_TILED;
418
419 switch (fb->pixel_format) {
420 case DRM_FORMAT_XBGR8888:
421 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
422 break;
423 case DRM_FORMAT_XRGB8888:
424 dvscntr |= DVS_FORMAT_RGBX888;
425 break;
426 case DRM_FORMAT_YUYV:
427 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
428 break;
429 case DRM_FORMAT_YVYU:
430 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
431 break;
432 case DRM_FORMAT_UYVY:
433 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
434 break;
435 case DRM_FORMAT_VYUY:
436 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
437 break;
438 default:
439 BUG();
440 }
441
442 if (obj->tiling_mode != I915_TILING_NONE)
443 dvscntr |= DVS_TILED;
444
445 if (IS_GEN6(dev))
446 dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
447 dvscntr |= DVS_ENABLE;
448
449 /* Sizes are 0 based */
450 src_w--;
451 src_h--;
452 crtc_w--;
453 crtc_h--;
454
455 intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size);
456
457 dvsscale = 0;
458 if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
459 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
460
461 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
462 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
463
464 linear_offset = y * fb->pitches[0] + x * pixel_size;
465 dvssurf_offset =
466 intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
467 pixel_size, fb->pitches[0]);
468 linear_offset -= dvssurf_offset;
469
470 if (obj->tiling_mode != I915_TILING_NONE)
471 I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
472 else
473 I915_WRITE(DVSLINOFF(pipe), linear_offset);
474
475 I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
476 I915_WRITE(DVSSCALE(pipe), dvsscale);
477 I915_WRITE(DVSCNTR(pipe), dvscntr);
478 I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
479 POSTING_READ(DVSSURF(pipe));
480 }
481
482 static void
483 ilk_disable_plane(struct drm_plane *plane)
484 {
485 struct drm_device *dev = plane->dev;
486 struct drm_i915_private *dev_priv = dev->dev_private;
487 struct intel_plane *intel_plane = to_intel_plane(plane);
488 int pipe = intel_plane->pipe;
489
490 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
491 /* Disable the scaler */
492 I915_WRITE(DVSSCALE(pipe), 0);
493 /* Flush double buffered register updates */
494 I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
495 POSTING_READ(DVSSURF(pipe));
496 }
497
498 static void
499 intel_enable_primary(struct drm_crtc *crtc)
500 {
501 struct drm_device *dev = crtc->dev;
502 struct drm_i915_private *dev_priv = dev->dev_private;
503 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
504 int reg = DSPCNTR(intel_crtc->plane);
505
506 if (!intel_crtc->primary_disabled)
507 return;
508
509 intel_crtc->primary_disabled = false;
510 intel_update_fbc(dev);
511
512 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
513 }
514
515 static void
516 intel_disable_primary(struct drm_crtc *crtc)
517 {
518 struct drm_device *dev = crtc->dev;
519 struct drm_i915_private *dev_priv = dev->dev_private;
520 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
521 int reg = DSPCNTR(intel_crtc->plane);
522
523 if (intel_crtc->primary_disabled)
524 return;
525
526 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
527
528 intel_crtc->primary_disabled = true;
529 intel_update_fbc(dev);
530 }
531
532 static int
533 ilk_update_colorkey(struct drm_plane *plane,
534 struct drm_intel_sprite_colorkey *key)
535 {
536 struct drm_device *dev = plane->dev;
537 struct drm_i915_private *dev_priv = dev->dev_private;
538 struct intel_plane *intel_plane;
539 u32 dvscntr;
540 int ret = 0;
541
542 intel_plane = to_intel_plane(plane);
543
544 I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
545 I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
546 I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
547
548 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
549 dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
550 if (key->flags & I915_SET_COLORKEY_DESTINATION)
551 dvscntr |= DVS_DEST_KEY;
552 else if (key->flags & I915_SET_COLORKEY_SOURCE)
553 dvscntr |= DVS_SOURCE_KEY;
554 I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
555
556 POSTING_READ(DVSKEYMSK(intel_plane->pipe));
557
558 return ret;
559 }
560
561 static void
562 ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
563 {
564 struct drm_device *dev = plane->dev;
565 struct drm_i915_private *dev_priv = dev->dev_private;
566 struct intel_plane *intel_plane;
567 u32 dvscntr;
568
569 intel_plane = to_intel_plane(plane);
570
571 key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
572 key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
573 key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
574 key->flags = 0;
575
576 dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
577
578 if (dvscntr & DVS_DEST_KEY)
579 key->flags = I915_SET_COLORKEY_DESTINATION;
580 else if (dvscntr & DVS_SOURCE_KEY)
581 key->flags = I915_SET_COLORKEY_SOURCE;
582 else
583 key->flags = I915_SET_COLORKEY_NONE;
584 }
585
586 static int
587 intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
588 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
589 unsigned int crtc_w, unsigned int crtc_h,
590 uint32_t src_x, uint32_t src_y,
591 uint32_t src_w, uint32_t src_h)
592 {
593 struct drm_device *dev = plane->dev;
594 struct drm_i915_private *dev_priv = dev->dev_private;
595 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
596 struct intel_plane *intel_plane = to_intel_plane(plane);
597 struct intel_framebuffer *intel_fb;
598 struct drm_i915_gem_object *obj, *old_obj;
599 int pipe = intel_plane->pipe;
600 enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
601 pipe);
602 int ret = 0;
603 int x = src_x >> 16, y = src_y >> 16;
604 int primary_w = crtc->mode.hdisplay, primary_h = crtc->mode.vdisplay;
605 bool disable_primary = false;
606
607 intel_fb = to_intel_framebuffer(fb);
608 obj = intel_fb->obj;
609
610 old_obj = intel_plane->obj;
611
612 intel_plane->crtc_x = crtc_x;
613 intel_plane->crtc_y = crtc_y;
614 intel_plane->crtc_w = crtc_w;
615 intel_plane->crtc_h = crtc_h;
616 intel_plane->src_x = src_x;
617 intel_plane->src_y = src_y;
618 intel_plane->src_w = src_w;
619 intel_plane->src_h = src_h;
620
621 src_w = src_w >> 16;
622 src_h = src_h >> 16;
623
624 /* Pipe must be running... */
625 if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE))
626 return -EINVAL;
627
628 if (crtc_x >= primary_w || crtc_y >= primary_h)
629 return -EINVAL;
630
631 /* Don't modify another pipe's plane */
632 if (intel_plane->pipe != intel_crtc->pipe)
633 return -EINVAL;
634
635 /* Sprite planes can be linear or x-tiled surfaces */
636 switch (obj->tiling_mode) {
637 case I915_TILING_NONE:
638 case I915_TILING_X:
639 break;
640 default:
641 return -EINVAL;
642 }
643
644 /*
645 * Clamp the width & height into the visible area. Note we don't
646 * try to scale the source if part of the visible region is offscreen.
647 * The caller must handle that by adjusting source offset and size.
648 */
649 if ((crtc_x < 0) && ((crtc_x + crtc_w) > 0)) {
650 crtc_w += crtc_x;
651 crtc_x = 0;
652 }
653 if ((crtc_x + crtc_w) <= 0) /* Nothing to display */
654 goto out;
655 if ((crtc_x + crtc_w) > primary_w)
656 crtc_w = primary_w - crtc_x;
657
658 if ((crtc_y < 0) && ((crtc_y + crtc_h) > 0)) {
659 crtc_h += crtc_y;
660 crtc_y = 0;
661 }
662 if ((crtc_y + crtc_h) <= 0) /* Nothing to display */
663 goto out;
664 if (crtc_y + crtc_h > primary_h)
665 crtc_h = primary_h - crtc_y;
666
667 if (!crtc_w || !crtc_h) /* Again, nothing to display */
668 goto out;
669
670 /*
671 * We may not have a scaler, eg. HSW does not have it any more
672 */
673 if (!intel_plane->can_scale && (crtc_w != src_w || crtc_h != src_h))
674 return -EINVAL;
675
676 /*
677 * We can take a larger source and scale it down, but
678 * only so much... 16x is the max on SNB.
679 */
680 if (((src_w * src_h) / (crtc_w * crtc_h)) > intel_plane->max_downscale)
681 return -EINVAL;
682
683 /*
684 * If the sprite is completely covering the primary plane,
685 * we can disable the primary and save power.
686 */
687 if ((crtc_x == 0) && (crtc_y == 0) &&
688 (crtc_w == primary_w) && (crtc_h == primary_h))
689 disable_primary = true;
690
691 mutex_lock(&dev->struct_mutex);
692
693 /* Note that this will apply the VT-d workaround for scanouts,
694 * which is more restrictive than required for sprites. (The
695 * primary plane requires 256KiB alignment with 64 PTE padding,
696 * the sprite planes only require 128KiB alignment and 32 PTE padding.
697 */
698 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
699 if (ret)
700 goto out_unlock;
701
702 intel_plane->obj = obj;
703
704 /*
705 * Be sure to re-enable the primary before the sprite is no longer
706 * covering it fully.
707 */
708 if (!disable_primary)
709 intel_enable_primary(crtc);
710
711 intel_plane->update_plane(plane, fb, obj, crtc_x, crtc_y,
712 crtc_w, crtc_h, x, y, src_w, src_h);
713
714 if (disable_primary)
715 intel_disable_primary(crtc);
716
717 /* Unpin old obj after new one is active to avoid ugliness */
718 if (old_obj) {
719 /*
720 * It's fairly common to simply update the position of
721 * an existing object. In that case, we don't need to
722 * wait for vblank to avoid ugliness, we only need to
723 * do the pin & ref bookkeeping.
724 */
725 if (old_obj != obj) {
726 mutex_unlock(&dev->struct_mutex);
727 intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
728 mutex_lock(&dev->struct_mutex);
729 }
730 intel_unpin_fb_obj(old_obj);
731 }
732
733 out_unlock:
734 mutex_unlock(&dev->struct_mutex);
735 out:
736 return ret;
737 }
738
739 static int
740 intel_disable_plane(struct drm_plane *plane)
741 {
742 struct drm_device *dev = plane->dev;
743 struct intel_plane *intel_plane = to_intel_plane(plane);
744 int ret = 0;
745
746 if (plane->crtc)
747 intel_enable_primary(plane->crtc);
748 intel_plane->disable_plane(plane);
749
750 if (!intel_plane->obj)
751 goto out;
752
753 intel_wait_for_vblank(dev, intel_plane->pipe);
754
755 mutex_lock(&dev->struct_mutex);
756 intel_unpin_fb_obj(intel_plane->obj);
757 intel_plane->obj = NULL;
758 mutex_unlock(&dev->struct_mutex);
759 out:
760
761 return ret;
762 }
763
764 static void intel_destroy_plane(struct drm_plane *plane)
765 {
766 struct intel_plane *intel_plane = to_intel_plane(plane);
767 intel_disable_plane(plane);
768 drm_plane_cleanup(plane);
769 kfree(intel_plane);
770 }
771
772 int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
773 struct drm_file *file_priv)
774 {
775 struct drm_intel_sprite_colorkey *set = data;
776 struct drm_mode_object *obj;
777 struct drm_plane *plane;
778 struct intel_plane *intel_plane;
779 int ret = 0;
780
781 if (!drm_core_check_feature(dev, DRIVER_MODESET))
782 return -ENODEV;
783
784 /* Make sure we don't try to enable both src & dest simultaneously */
785 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
786 return -EINVAL;
787
788 drm_modeset_lock_all(dev);
789
790 obj = drm_mode_object_find(dev, set->plane_id, DRM_MODE_OBJECT_PLANE);
791 if (!obj) {
792 ret = -EINVAL;
793 goto out_unlock;
794 }
795
796 plane = obj_to_plane(obj);
797 intel_plane = to_intel_plane(plane);
798 ret = intel_plane->update_colorkey(plane, set);
799
800 out_unlock:
801 drm_modeset_unlock_all(dev);
802 return ret;
803 }
804
805 int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
806 struct drm_file *file_priv)
807 {
808 struct drm_intel_sprite_colorkey *get = data;
809 struct drm_mode_object *obj;
810 struct drm_plane *plane;
811 struct intel_plane *intel_plane;
812 int ret = 0;
813
814 if (!drm_core_check_feature(dev, DRIVER_MODESET))
815 return -ENODEV;
816
817 drm_modeset_lock_all(dev);
818
819 obj = drm_mode_object_find(dev, get->plane_id, DRM_MODE_OBJECT_PLANE);
820 if (!obj) {
821 ret = -EINVAL;
822 goto out_unlock;
823 }
824
825 plane = obj_to_plane(obj);
826 intel_plane = to_intel_plane(plane);
827 intel_plane->get_colorkey(plane, get);
828
829 out_unlock:
830 drm_modeset_unlock_all(dev);
831 return ret;
832 }
833
834 void intel_plane_restore(struct drm_plane *plane)
835 {
836 struct intel_plane *intel_plane = to_intel_plane(plane);
837
838 if (!plane->crtc || !plane->fb)
839 return;
840
841 intel_update_plane(plane, plane->crtc, plane->fb,
842 intel_plane->crtc_x, intel_plane->crtc_y,
843 intel_plane->crtc_w, intel_plane->crtc_h,
844 intel_plane->src_x, intel_plane->src_y,
845 intel_plane->src_w, intel_plane->src_h);
846 }
847
848 static const struct drm_plane_funcs intel_plane_funcs = {
849 .update_plane = intel_update_plane,
850 .disable_plane = intel_disable_plane,
851 .destroy = intel_destroy_plane,
852 };
853
854 static uint32_t ilk_plane_formats[] = {
855 DRM_FORMAT_XRGB8888,
856 DRM_FORMAT_YUYV,
857 DRM_FORMAT_YVYU,
858 DRM_FORMAT_UYVY,
859 DRM_FORMAT_VYUY,
860 };
861
862 static uint32_t snb_plane_formats[] = {
863 DRM_FORMAT_XBGR8888,
864 DRM_FORMAT_XRGB8888,
865 DRM_FORMAT_YUYV,
866 DRM_FORMAT_YVYU,
867 DRM_FORMAT_UYVY,
868 DRM_FORMAT_VYUY,
869 };
870
871 static uint32_t vlv_plane_formats[] = {
872 DRM_FORMAT_RGB565,
873 DRM_FORMAT_ABGR8888,
874 DRM_FORMAT_ARGB8888,
875 DRM_FORMAT_XBGR8888,
876 DRM_FORMAT_XRGB8888,
877 DRM_FORMAT_XBGR2101010,
878 DRM_FORMAT_ABGR2101010,
879 DRM_FORMAT_YUYV,
880 DRM_FORMAT_YVYU,
881 DRM_FORMAT_UYVY,
882 DRM_FORMAT_VYUY,
883 };
884
885 int
886 intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
887 {
888 struct intel_plane *intel_plane;
889 unsigned long possible_crtcs;
890 const uint32_t *plane_formats;
891 int num_plane_formats;
892 int ret;
893
894 if (INTEL_INFO(dev)->gen < 5)
895 return -ENODEV;
896
897 intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
898 if (!intel_plane)
899 return -ENOMEM;
900
901 switch (INTEL_INFO(dev)->gen) {
902 case 5:
903 case 6:
904 intel_plane->can_scale = true;
905 intel_plane->max_downscale = 16;
906 intel_plane->update_plane = ilk_update_plane;
907 intel_plane->disable_plane = ilk_disable_plane;
908 intel_plane->update_colorkey = ilk_update_colorkey;
909 intel_plane->get_colorkey = ilk_get_colorkey;
910
911 if (IS_GEN6(dev)) {
912 plane_formats = snb_plane_formats;
913 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
914 } else {
915 plane_formats = ilk_plane_formats;
916 num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
917 }
918 break;
919
920 case 7:
921 if (IS_HASWELL(dev) || IS_VALLEYVIEW(dev))
922 intel_plane->can_scale = false;
923 else
924 intel_plane->can_scale = true;
925
926 if (IS_VALLEYVIEW(dev)) {
927 intel_plane->max_downscale = 1;
928 intel_plane->update_plane = vlv_update_plane;
929 intel_plane->disable_plane = vlv_disable_plane;
930 intel_plane->update_colorkey = vlv_update_colorkey;
931 intel_plane->get_colorkey = vlv_get_colorkey;
932
933 plane_formats = vlv_plane_formats;
934 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
935 } else {
936 intel_plane->max_downscale = 2;
937 intel_plane->update_plane = ivb_update_plane;
938 intel_plane->disable_plane = ivb_disable_plane;
939 intel_plane->update_colorkey = ivb_update_colorkey;
940 intel_plane->get_colorkey = ivb_get_colorkey;
941
942 plane_formats = snb_plane_formats;
943 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
944 }
945 break;
946
947 default:
948 kfree(intel_plane);
949 return -ENODEV;
950 }
951
952 intel_plane->pipe = pipe;
953 intel_plane->plane = plane;
954 possible_crtcs = (1 << pipe);
955 ret = drm_plane_init(dev, &intel_plane->base, possible_crtcs,
956 &intel_plane_funcs,
957 plane_formats, num_plane_formats,
958 false);
959 if (ret)
960 kfree(intel_plane);
961
962 return ret;
963 }
This page took 0.052436 seconds and 5 git commands to generate.