vt: vt_ioctl: fix VT_DISALLOCATE freeing in-use virtual console
[linux/fpc-iii.git] / drivers / gpu / drm / i915 / intel_sprite.c
blobf7026e887fa9bd65d996c1afa851a92be28e6e6a
1 /*
2 * Copyright © 2011 Intel Corporation
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:
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.
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.
23 * Authors:
24 * Jesse Barnes <jbarnes@virtuousgeek.org>
26 * New plane/sprite handling.
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.
32 #include <drm/drmP.h>
33 #include <drm/drm_atomic_helper.h>
34 #include <drm/drm_crtc.h>
35 #include <drm/drm_fourcc.h>
36 #include <drm/drm_rect.h>
37 #include <drm/drm_atomic.h>
38 #include <drm/drm_plane_helper.h>
39 #include "intel_drv.h"
40 #include "intel_frontbuffer.h"
41 #include <drm/i915_drm.h>
42 #include "i915_drv.h"
44 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
45 int usecs)
47 /* paranoia */
48 if (!adjusted_mode->crtc_htotal)
49 return 1;
51 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
52 1000 * adjusted_mode->crtc_htotal);
55 /* FIXME: We should instead only take spinlocks once for the entire update
56 * instead of once per mmio. */
57 #if IS_ENABLED(CONFIG_PROVE_LOCKING)
58 #define VBLANK_EVASION_TIME_US 250
59 #else
60 #define VBLANK_EVASION_TIME_US 100
61 #endif
63 /**
64 * intel_pipe_update_start() - start update of a set of display registers
65 * @new_crtc_state: the new crtc state
67 * Mark the start of an update to pipe registers that should be updated
68 * atomically regarding vblank. If the next vblank will happens within
69 * the next 100 us, this function waits until the vblank passes.
71 * After a successful call to this function, interrupts will be disabled
72 * until a subsequent call to intel_pipe_update_end(). That is done to
73 * avoid random delays.
75 void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
77 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
78 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
79 const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
80 long timeout = msecs_to_jiffies_timeout(1);
81 int scanline, min, max, vblank_start;
82 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
83 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
84 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
85 DEFINE_WAIT(wait);
87 vblank_start = adjusted_mode->crtc_vblank_start;
88 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
89 vblank_start = DIV_ROUND_UP(vblank_start, 2);
91 /* FIXME needs to be calibrated sensibly */
92 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
93 VBLANK_EVASION_TIME_US);
94 max = vblank_start - 1;
96 if (min <= 0 || max <= 0)
97 goto irq_disable;
99 if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
100 goto irq_disable;
103 * Wait for psr to idle out after enabling the VBL interrupts
104 * VBL interrupts will start the PSR exit and prevent a PSR
105 * re-entry as well.
107 if (intel_psr_wait_for_idle(new_crtc_state))
108 DRM_ERROR("PSR idle timed out, atomic update may fail\n");
110 local_irq_disable();
112 crtc->debug.min_vbl = min;
113 crtc->debug.max_vbl = max;
114 trace_i915_pipe_update_start(crtc);
116 for (;;) {
118 * prepare_to_wait() has a memory barrier, which guarantees
119 * other CPUs can see the task state update by the time we
120 * read the scanline.
122 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
124 scanline = intel_get_crtc_scanline(crtc);
125 if (scanline < min || scanline > max)
126 break;
128 if (!timeout) {
129 DRM_ERROR("Potential atomic update failure on pipe %c\n",
130 pipe_name(crtc->pipe));
131 break;
134 local_irq_enable();
136 timeout = schedule_timeout(timeout);
138 local_irq_disable();
141 finish_wait(wq, &wait);
143 drm_crtc_vblank_put(&crtc->base);
146 * On VLV/CHV DSI the scanline counter would appear to
147 * increment approx. 1/3 of a scanline before start of vblank.
148 * The registers still get latched at start of vblank however.
149 * This means we must not write any registers on the first
150 * line of vblank (since not the whole line is actually in
151 * vblank). And unfortunately we can't use the interrupt to
152 * wait here since it will fire too soon. We could use the
153 * frame start interrupt instead since it will fire after the
154 * critical scanline, but that would require more changes
155 * in the interrupt code. So for now we'll just do the nasty
156 * thing and poll for the bad scanline to pass us by.
158 * FIXME figure out if BXT+ DSI suffers from this as well
160 while (need_vlv_dsi_wa && scanline == vblank_start)
161 scanline = intel_get_crtc_scanline(crtc);
163 crtc->debug.scanline_start = scanline;
164 crtc->debug.start_vbl_time = ktime_get();
165 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
167 trace_i915_pipe_update_vblank_evaded(crtc);
168 return;
170 irq_disable:
171 local_irq_disable();
175 * intel_pipe_update_end() - end update of a set of display registers
176 * @new_crtc_state: the new crtc state
178 * Mark the end of an update started with intel_pipe_update_start(). This
179 * re-enables interrupts and verifies the update was actually completed
180 * before a vblank.
182 void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
184 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
185 enum pipe pipe = crtc->pipe;
186 int scanline_end = intel_get_crtc_scanline(crtc);
187 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
188 ktime_t end_vbl_time = ktime_get();
189 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
191 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
193 /* We're still in the vblank-evade critical section, this can't race.
194 * Would be slightly nice to just grab the vblank count and arm the
195 * event outside of the critical section - the spinlock might spin for a
196 * while ... */
197 if (new_crtc_state->base.event) {
198 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
200 spin_lock(&crtc->base.dev->event_lock);
201 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
202 spin_unlock(&crtc->base.dev->event_lock);
204 new_crtc_state->base.event = NULL;
207 local_irq_enable();
209 if (intel_vgpu_active(dev_priv))
210 return;
212 if (crtc->debug.start_vbl_count &&
213 crtc->debug.start_vbl_count != end_vbl_count) {
214 DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
215 pipe_name(pipe), crtc->debug.start_vbl_count,
216 end_vbl_count,
217 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
218 crtc->debug.min_vbl, crtc->debug.max_vbl,
219 crtc->debug.scanline_start, scanline_end);
221 #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
222 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
223 VBLANK_EVASION_TIME_US)
224 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
225 pipe_name(pipe),
226 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
227 VBLANK_EVASION_TIME_US);
228 #endif
231 void
232 skl_update_plane(struct intel_plane *plane,
233 const struct intel_crtc_state *crtc_state,
234 const struct intel_plane_state *plane_state)
236 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
237 const struct drm_framebuffer *fb = plane_state->base.fb;
238 enum plane_id plane_id = plane->id;
239 enum pipe pipe = plane->pipe;
240 u32 plane_ctl = plane_state->ctl;
241 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
242 u32 surf_addr = plane_state->main.offset;
243 unsigned int rotation = plane_state->base.rotation;
244 u32 stride = skl_plane_stride(fb, 0, rotation);
245 u32 aux_stride = skl_plane_stride(fb, 1, rotation);
246 int crtc_x = plane_state->base.dst.x1;
247 int crtc_y = plane_state->base.dst.y1;
248 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
249 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
250 uint32_t x = plane_state->main.x;
251 uint32_t y = plane_state->main.y;
252 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
253 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
254 unsigned long irqflags;
256 /* Sizes are 0 based */
257 src_w--;
258 src_h--;
259 crtc_w--;
260 crtc_h--;
262 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
264 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
265 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
266 plane_state->color_ctl);
268 if (key->flags) {
269 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
270 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value);
271 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
274 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
275 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
276 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
277 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
278 (plane_state->aux.offset - surf_addr) | aux_stride);
279 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
280 (plane_state->aux.y << 16) | plane_state->aux.x);
282 /* program plane scaler */
283 if (plane_state->scaler_id >= 0) {
284 int scaler_id = plane_state->scaler_id;
285 const struct intel_scaler *scaler =
286 &crtc_state->scaler_state.scalers[scaler_id];
287 u16 y_hphase, uv_rgb_hphase;
288 u16 y_vphase, uv_rgb_vphase;
290 /* TODO: handle sub-pixel coordinates */
291 if (fb->format->format == DRM_FORMAT_NV12) {
292 y_hphase = skl_scaler_calc_phase(1, false);
293 y_vphase = skl_scaler_calc_phase(1, false);
295 /* MPEG2 chroma siting convention */
296 uv_rgb_hphase = skl_scaler_calc_phase(2, true);
297 uv_rgb_vphase = skl_scaler_calc_phase(2, false);
298 } else {
299 /* not used */
300 y_hphase = 0;
301 y_vphase = 0;
303 uv_rgb_hphase = skl_scaler_calc_phase(1, false);
304 uv_rgb_vphase = skl_scaler_calc_phase(1, false);
307 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
308 PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
309 I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
310 I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
311 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
312 I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
313 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
314 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
315 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id),
316 ((crtc_w + 1) << 16)|(crtc_h + 1));
318 I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
319 } else {
320 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
323 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
324 I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
325 intel_plane_ggtt_offset(plane_state) + surf_addr);
326 POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
328 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
331 void
332 skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
334 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
335 enum plane_id plane_id = plane->id;
336 enum pipe pipe = plane->pipe;
337 unsigned long irqflags;
339 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
341 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
343 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
344 POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
346 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
349 bool
350 skl_plane_get_hw_state(struct intel_plane *plane,
351 enum pipe *pipe)
353 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
354 enum intel_display_power_domain power_domain;
355 enum plane_id plane_id = plane->id;
356 bool ret;
358 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
359 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
360 return false;
362 ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
364 *pipe = plane->pipe;
366 intel_display_power_put(dev_priv, power_domain);
368 return ret;
371 static void
372 chv_update_csc(const struct intel_plane_state *plane_state)
374 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
375 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
376 const struct drm_framebuffer *fb = plane_state->base.fb;
377 enum plane_id plane_id = plane->id;
379 * |r| | c0 c1 c2 | |cr|
380 * |g| = | c3 c4 c5 | x |y |
381 * |b| | c6 c7 c8 | |cb|
383 * Coefficients are s3.12.
385 * Cb and Cr apparently come in as signed already, and
386 * we always get full range data in on account of CLRC0/1.
388 static const s16 csc_matrix[][9] = {
389 /* BT.601 full range YCbCr -> full range RGB */
390 [DRM_COLOR_YCBCR_BT601] = {
391 5743, 4096, 0,
392 -2925, 4096, -1410,
393 0, 4096, 7258,
395 /* BT.709 full range YCbCr -> full range RGB */
396 [DRM_COLOR_YCBCR_BT709] = {
397 6450, 4096, 0,
398 -1917, 4096, -767,
399 0, 4096, 7601,
402 const s16 *csc = csc_matrix[plane_state->base.color_encoding];
404 /* Seems RGB data bypasses the CSC always */
405 if (!fb->format->is_yuv)
406 return;
408 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
409 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
410 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
412 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
413 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
414 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
415 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
416 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
418 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
419 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
420 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
422 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
423 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
424 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
427 #define SIN_0 0
428 #define COS_0 1
430 static void
431 vlv_update_clrc(const struct intel_plane_state *plane_state)
433 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
434 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
435 const struct drm_framebuffer *fb = plane_state->base.fb;
436 enum pipe pipe = plane->pipe;
437 enum plane_id plane_id = plane->id;
438 int contrast, brightness, sh_scale, sh_sin, sh_cos;
440 if (fb->format->is_yuv &&
441 plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
443 * Expand limited range to full range:
444 * Contrast is applied first and is used to expand Y range.
445 * Brightness is applied second and is used to remove the
446 * offset from Y. Saturation/hue is used to expand CbCr range.
448 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
449 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
450 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
451 sh_sin = SIN_0 * sh_scale;
452 sh_cos = COS_0 * sh_scale;
453 } else {
454 /* Pass-through everything. */
455 contrast = 1 << 6;
456 brightness = 0;
457 sh_scale = 1 << 7;
458 sh_sin = SIN_0 * sh_scale;
459 sh_cos = COS_0 * sh_scale;
462 /* FIXME these register are single buffered :( */
463 I915_WRITE_FW(SPCLRC0(pipe, plane_id),
464 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
465 I915_WRITE_FW(SPCLRC1(pipe, plane_id),
466 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
469 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
470 const struct intel_plane_state *plane_state)
472 const struct drm_framebuffer *fb = plane_state->base.fb;
473 unsigned int rotation = plane_state->base.rotation;
474 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
475 u32 sprctl;
477 sprctl = SP_ENABLE | SP_GAMMA_ENABLE;
479 switch (fb->format->format) {
480 case DRM_FORMAT_YUYV:
481 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
482 break;
483 case DRM_FORMAT_YVYU:
484 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
485 break;
486 case DRM_FORMAT_UYVY:
487 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
488 break;
489 case DRM_FORMAT_VYUY:
490 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
491 break;
492 case DRM_FORMAT_RGB565:
493 sprctl |= SP_FORMAT_BGR565;
494 break;
495 case DRM_FORMAT_XRGB8888:
496 sprctl |= SP_FORMAT_BGRX8888;
497 break;
498 case DRM_FORMAT_ARGB8888:
499 sprctl |= SP_FORMAT_BGRA8888;
500 break;
501 case DRM_FORMAT_XBGR2101010:
502 sprctl |= SP_FORMAT_RGBX1010102;
503 break;
504 case DRM_FORMAT_ABGR2101010:
505 sprctl |= SP_FORMAT_RGBA1010102;
506 break;
507 case DRM_FORMAT_XBGR8888:
508 sprctl |= SP_FORMAT_RGBX8888;
509 break;
510 case DRM_FORMAT_ABGR8888:
511 sprctl |= SP_FORMAT_RGBA8888;
512 break;
513 default:
514 MISSING_CASE(fb->format->format);
515 return 0;
518 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
519 sprctl |= SP_YUV_FORMAT_BT709;
521 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
522 sprctl |= SP_TILED;
524 if (rotation & DRM_MODE_ROTATE_180)
525 sprctl |= SP_ROTATE_180;
527 if (rotation & DRM_MODE_REFLECT_X)
528 sprctl |= SP_MIRROR;
530 if (key->flags & I915_SET_COLORKEY_SOURCE)
531 sprctl |= SP_SOURCE_KEY;
533 return sprctl;
536 static void
537 vlv_update_plane(struct intel_plane *plane,
538 const struct intel_crtc_state *crtc_state,
539 const struct intel_plane_state *plane_state)
541 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
542 const struct drm_framebuffer *fb = plane_state->base.fb;
543 enum pipe pipe = plane->pipe;
544 enum plane_id plane_id = plane->id;
545 u32 sprctl = plane_state->ctl;
546 u32 sprsurf_offset = plane_state->main.offset;
547 u32 linear_offset;
548 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
549 int crtc_x = plane_state->base.dst.x1;
550 int crtc_y = plane_state->base.dst.y1;
551 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
552 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
553 uint32_t x = plane_state->main.x;
554 uint32_t y = plane_state->main.y;
555 unsigned long irqflags;
557 /* Sizes are 0 based */
558 crtc_w--;
559 crtc_h--;
561 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
563 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
565 vlv_update_clrc(plane_state);
567 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
568 chv_update_csc(plane_state);
570 if (key->flags) {
571 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
572 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
573 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
575 I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]);
576 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
578 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
579 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
580 else
581 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
583 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
585 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
586 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
587 I915_WRITE_FW(SPSURF(pipe, plane_id),
588 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
589 POSTING_READ_FW(SPSURF(pipe, plane_id));
591 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
594 static void
595 vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
597 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
598 enum pipe pipe = plane->pipe;
599 enum plane_id plane_id = plane->id;
600 unsigned long irqflags;
602 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
604 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
606 I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
607 POSTING_READ_FW(SPSURF(pipe, plane_id));
609 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
612 static bool
613 vlv_plane_get_hw_state(struct intel_plane *plane,
614 enum pipe *pipe)
616 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
617 enum intel_display_power_domain power_domain;
618 enum plane_id plane_id = plane->id;
619 bool ret;
621 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
622 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
623 return false;
625 ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
627 *pipe = plane->pipe;
629 intel_display_power_put(dev_priv, power_domain);
631 return ret;
634 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
635 const struct intel_plane_state *plane_state)
637 struct drm_i915_private *dev_priv =
638 to_i915(plane_state->base.plane->dev);
639 const struct drm_framebuffer *fb = plane_state->base.fb;
640 unsigned int rotation = plane_state->base.rotation;
641 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
642 u32 sprctl;
644 sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE;
646 if (IS_IVYBRIDGE(dev_priv))
647 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
649 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
650 sprctl |= SPRITE_PIPE_CSC_ENABLE;
652 switch (fb->format->format) {
653 case DRM_FORMAT_XBGR8888:
654 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
655 break;
656 case DRM_FORMAT_XRGB8888:
657 sprctl |= SPRITE_FORMAT_RGBX888;
658 break;
659 case DRM_FORMAT_YUYV:
660 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
661 break;
662 case DRM_FORMAT_YVYU:
663 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
664 break;
665 case DRM_FORMAT_UYVY:
666 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
667 break;
668 case DRM_FORMAT_VYUY:
669 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
670 break;
671 default:
672 MISSING_CASE(fb->format->format);
673 return 0;
676 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
677 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
679 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
680 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
682 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
683 sprctl |= SPRITE_TILED;
685 if (rotation & DRM_MODE_ROTATE_180)
686 sprctl |= SPRITE_ROTATE_180;
688 if (key->flags & I915_SET_COLORKEY_DESTINATION)
689 sprctl |= SPRITE_DEST_KEY;
690 else if (key->flags & I915_SET_COLORKEY_SOURCE)
691 sprctl |= SPRITE_SOURCE_KEY;
693 return sprctl;
696 static void
697 ivb_update_plane(struct intel_plane *plane,
698 const struct intel_crtc_state *crtc_state,
699 const struct intel_plane_state *plane_state)
701 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
702 const struct drm_framebuffer *fb = plane_state->base.fb;
703 enum pipe pipe = plane->pipe;
704 u32 sprctl = plane_state->ctl, sprscale = 0;
705 u32 sprsurf_offset = plane_state->main.offset;
706 u32 linear_offset;
707 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
708 int crtc_x = plane_state->base.dst.x1;
709 int crtc_y = plane_state->base.dst.y1;
710 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
711 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
712 uint32_t x = plane_state->main.x;
713 uint32_t y = plane_state->main.y;
714 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
715 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
716 unsigned long irqflags;
718 /* Sizes are 0 based */
719 src_w--;
720 src_h--;
721 crtc_w--;
722 crtc_h--;
724 if (crtc_w != src_w || crtc_h != src_h)
725 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
727 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
729 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
731 if (key->flags) {
732 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
733 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
734 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
737 I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]);
738 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
740 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
741 * register */
742 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
743 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
744 else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
745 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
746 else
747 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
749 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
750 if (plane->can_scale)
751 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
752 I915_WRITE_FW(SPRCTL(pipe), sprctl);
753 I915_WRITE_FW(SPRSURF(pipe),
754 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
755 POSTING_READ_FW(SPRSURF(pipe));
757 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
760 static void
761 ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
763 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
764 enum pipe pipe = plane->pipe;
765 unsigned long irqflags;
767 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
769 I915_WRITE_FW(SPRCTL(pipe), 0);
770 /* Can't leave the scaler enabled... */
771 if (plane->can_scale)
772 I915_WRITE_FW(SPRSCALE(pipe), 0);
774 I915_WRITE_FW(SPRSURF(pipe), 0);
775 POSTING_READ_FW(SPRSURF(pipe));
777 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
780 static bool
781 ivb_plane_get_hw_state(struct intel_plane *plane,
782 enum pipe *pipe)
784 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
785 enum intel_display_power_domain power_domain;
786 bool ret;
788 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
789 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
790 return false;
792 ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
794 *pipe = plane->pipe;
796 intel_display_power_put(dev_priv, power_domain);
798 return ret;
801 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
802 const struct intel_plane_state *plane_state)
804 struct drm_i915_private *dev_priv =
805 to_i915(plane_state->base.plane->dev);
806 const struct drm_framebuffer *fb = plane_state->base.fb;
807 unsigned int rotation = plane_state->base.rotation;
808 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
809 u32 dvscntr;
811 dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
813 if (IS_GEN6(dev_priv))
814 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
816 switch (fb->format->format) {
817 case DRM_FORMAT_XBGR8888:
818 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
819 break;
820 case DRM_FORMAT_XRGB8888:
821 dvscntr |= DVS_FORMAT_RGBX888;
822 break;
823 case DRM_FORMAT_YUYV:
824 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
825 break;
826 case DRM_FORMAT_YVYU:
827 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
828 break;
829 case DRM_FORMAT_UYVY:
830 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
831 break;
832 case DRM_FORMAT_VYUY:
833 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
834 break;
835 default:
836 MISSING_CASE(fb->format->format);
837 return 0;
840 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
841 dvscntr |= DVS_YUV_FORMAT_BT709;
843 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
844 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
846 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
847 dvscntr |= DVS_TILED;
849 if (rotation & DRM_MODE_ROTATE_180)
850 dvscntr |= DVS_ROTATE_180;
852 if (key->flags & I915_SET_COLORKEY_DESTINATION)
853 dvscntr |= DVS_DEST_KEY;
854 else if (key->flags & I915_SET_COLORKEY_SOURCE)
855 dvscntr |= DVS_SOURCE_KEY;
857 return dvscntr;
860 static void
861 g4x_update_plane(struct intel_plane *plane,
862 const struct intel_crtc_state *crtc_state,
863 const struct intel_plane_state *plane_state)
865 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
866 const struct drm_framebuffer *fb = plane_state->base.fb;
867 enum pipe pipe = plane->pipe;
868 u32 dvscntr = plane_state->ctl, dvsscale = 0;
869 u32 dvssurf_offset = plane_state->main.offset;
870 u32 linear_offset;
871 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
872 int crtc_x = plane_state->base.dst.x1;
873 int crtc_y = plane_state->base.dst.y1;
874 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
875 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
876 uint32_t x = plane_state->main.x;
877 uint32_t y = plane_state->main.y;
878 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
879 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
880 unsigned long irqflags;
882 /* Sizes are 0 based */
883 src_w--;
884 src_h--;
885 crtc_w--;
886 crtc_h--;
888 if (crtc_w != src_w || crtc_h != src_h)
889 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
891 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
893 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
895 if (key->flags) {
896 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
897 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
898 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
901 I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]);
902 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
904 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
905 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
906 else
907 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
909 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
910 I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
911 I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
912 I915_WRITE_FW(DVSSURF(pipe),
913 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
914 POSTING_READ_FW(DVSSURF(pipe));
916 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
919 static void
920 g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
922 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
923 enum pipe pipe = plane->pipe;
924 unsigned long irqflags;
926 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
928 I915_WRITE_FW(DVSCNTR(pipe), 0);
929 /* Disable the scaler */
930 I915_WRITE_FW(DVSSCALE(pipe), 0);
932 I915_WRITE_FW(DVSSURF(pipe), 0);
933 POSTING_READ_FW(DVSSURF(pipe));
935 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
938 static bool
939 g4x_plane_get_hw_state(struct intel_plane *plane,
940 enum pipe *pipe)
942 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
943 enum intel_display_power_domain power_domain;
944 bool ret;
946 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
947 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
948 return false;
950 ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
952 *pipe = plane->pipe;
954 intel_display_power_put(dev_priv, power_domain);
956 return ret;
959 static int
960 intel_check_sprite_plane(struct intel_plane *plane,
961 struct intel_crtc_state *crtc_state,
962 struct intel_plane_state *state)
964 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
965 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
966 struct drm_framebuffer *fb = state->base.fb;
967 int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
968 int max_scale, min_scale;
969 bool can_scale;
970 int ret;
971 uint32_t pixel_format = 0;
973 if (!fb) {
974 state->base.visible = false;
975 return 0;
978 /* Don't modify another pipe's plane */
979 if (plane->pipe != crtc->pipe) {
980 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
981 return -EINVAL;
984 /* FIXME check all gen limits */
985 if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > max_stride) {
986 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
987 return -EINVAL;
990 /* setup can_scale, min_scale, max_scale */
991 if (INTEL_GEN(dev_priv) >= 9) {
992 if (state->base.fb)
993 pixel_format = state->base.fb->format->format;
994 /* use scaler when colorkey is not required */
995 if (!state->ckey.flags) {
996 can_scale = 1;
997 min_scale = 1;
998 max_scale =
999 skl_max_scale(crtc, crtc_state, pixel_format);
1000 } else {
1001 can_scale = 0;
1002 min_scale = DRM_PLANE_HELPER_NO_SCALING;
1003 max_scale = DRM_PLANE_HELPER_NO_SCALING;
1005 } else {
1006 can_scale = plane->can_scale;
1007 max_scale = plane->max_downscale << 16;
1008 min_scale = plane->can_scale ? 1 : (1 << 16);
1011 ret = drm_atomic_helper_check_plane_state(&state->base,
1012 &crtc_state->base,
1013 min_scale, max_scale,
1014 true, true);
1015 if (ret)
1016 return ret;
1018 if (state->base.visible) {
1019 struct drm_rect *src = &state->base.src;
1020 struct drm_rect *dst = &state->base.dst;
1021 unsigned int crtc_w = drm_rect_width(dst);
1022 unsigned int crtc_h = drm_rect_height(dst);
1023 uint32_t src_x, src_y, src_w, src_h;
1026 * Hardware doesn't handle subpixel coordinates.
1027 * Adjust to (macro)pixel boundary, but be careful not to
1028 * increase the source viewport size, because that could
1029 * push the downscaling factor out of bounds.
1031 src_x = src->x1 >> 16;
1032 src_w = drm_rect_width(src) >> 16;
1033 src_y = src->y1 >> 16;
1034 src_h = drm_rect_height(src) >> 16;
1036 src->x1 = src_x << 16;
1037 src->x2 = (src_x + src_w) << 16;
1038 src->y1 = src_y << 16;
1039 src->y2 = (src_y + src_h) << 16;
1041 if (fb->format->is_yuv &&
1042 fb->format->format != DRM_FORMAT_NV12 &&
1043 (src_x % 2 || src_w % 2)) {
1044 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
1045 src_x, src_w);
1046 return -EINVAL;
1049 /* Check size restrictions when scaling */
1050 if (src_w != crtc_w || src_h != crtc_h) {
1051 unsigned int width_bytes;
1052 int cpp = fb->format->cpp[0];
1054 WARN_ON(!can_scale);
1056 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1058 /* FIXME interlacing min height is 6 */
1059 if (INTEL_GEN(dev_priv) < 9 && (
1060 src_w < 3 || src_h < 3 ||
1061 src_w > 2048 || src_h > 2048 ||
1062 crtc_w < 3 || crtc_h < 3 ||
1063 width_bytes > 4096 || fb->pitches[0] > 4096)) {
1064 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
1065 return -EINVAL;
1070 if (INTEL_GEN(dev_priv) >= 9) {
1071 ret = skl_check_plane_surface(crtc_state, state);
1072 if (ret)
1073 return ret;
1075 state->ctl = skl_plane_ctl(crtc_state, state);
1076 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1077 ret = i9xx_check_plane_surface(state);
1078 if (ret)
1079 return ret;
1081 state->ctl = vlv_sprite_ctl(crtc_state, state);
1082 } else if (INTEL_GEN(dev_priv) >= 7) {
1083 ret = i9xx_check_plane_surface(state);
1084 if (ret)
1085 return ret;
1087 state->ctl = ivb_sprite_ctl(crtc_state, state);
1088 } else {
1089 ret = i9xx_check_plane_surface(state);
1090 if (ret)
1091 return ret;
1093 state->ctl = g4x_sprite_ctl(crtc_state, state);
1096 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1097 state->color_ctl = glk_plane_color_ctl(crtc_state, state);
1099 return 0;
1102 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1104 return INTEL_GEN(dev_priv) >= 9;
1107 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1108 const struct drm_intel_sprite_colorkey *set)
1110 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1111 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1112 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1114 *key = *set;
1117 * We want src key enabled on the
1118 * sprite and not on the primary.
1120 if (plane->id == PLANE_PRIMARY &&
1121 set->flags & I915_SET_COLORKEY_SOURCE)
1122 key->flags = 0;
1125 * On SKL+ we want dst key enabled on
1126 * the primary and not on the sprite.
1128 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1129 set->flags & I915_SET_COLORKEY_DESTINATION)
1130 key->flags = 0;
1133 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1134 struct drm_file *file_priv)
1136 struct drm_i915_private *dev_priv = to_i915(dev);
1137 struct drm_intel_sprite_colorkey *set = data;
1138 struct drm_plane *plane;
1139 struct drm_plane_state *plane_state;
1140 struct drm_atomic_state *state;
1141 struct drm_modeset_acquire_ctx ctx;
1142 int ret = 0;
1144 /* ignore the pointless "none" flag */
1145 set->flags &= ~I915_SET_COLORKEY_NONE;
1147 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1148 return -EINVAL;
1150 /* Make sure we don't try to enable both src & dest simultaneously */
1151 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1152 return -EINVAL;
1154 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1155 set->flags & I915_SET_COLORKEY_DESTINATION)
1156 return -EINVAL;
1158 plane = drm_plane_find(dev, file_priv, set->plane_id);
1159 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1160 return -ENOENT;
1163 * SKL+ only plane 2 can do destination keying against plane 1.
1164 * Also multiple planes can't do destination keying on the same
1165 * pipe simultaneously.
1167 if (INTEL_GEN(dev_priv) >= 9 &&
1168 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1169 set->flags & I915_SET_COLORKEY_DESTINATION)
1170 return -EINVAL;
1172 drm_modeset_acquire_init(&ctx, 0);
1174 state = drm_atomic_state_alloc(plane->dev);
1175 if (!state) {
1176 ret = -ENOMEM;
1177 goto out;
1179 state->acquire_ctx = &ctx;
1181 while (1) {
1182 plane_state = drm_atomic_get_plane_state(state, plane);
1183 ret = PTR_ERR_OR_ZERO(plane_state);
1184 if (!ret)
1185 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1188 * On some platforms we have to configure
1189 * the dst colorkey on the primary plane.
1191 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1192 struct intel_crtc *crtc =
1193 intel_get_crtc_for_pipe(dev_priv,
1194 to_intel_plane(plane)->pipe);
1196 plane_state = drm_atomic_get_plane_state(state,
1197 crtc->base.primary);
1198 ret = PTR_ERR_OR_ZERO(plane_state);
1199 if (!ret)
1200 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1203 if (!ret)
1204 ret = drm_atomic_commit(state);
1206 if (ret != -EDEADLK)
1207 break;
1209 drm_atomic_state_clear(state);
1210 drm_modeset_backoff(&ctx);
1213 drm_atomic_state_put(state);
1214 out:
1215 drm_modeset_drop_locks(&ctx);
1216 drm_modeset_acquire_fini(&ctx);
1217 return ret;
1220 static const uint32_t g4x_plane_formats[] = {
1221 DRM_FORMAT_XRGB8888,
1222 DRM_FORMAT_YUYV,
1223 DRM_FORMAT_YVYU,
1224 DRM_FORMAT_UYVY,
1225 DRM_FORMAT_VYUY,
1228 static const uint64_t i9xx_plane_format_modifiers[] = {
1229 I915_FORMAT_MOD_X_TILED,
1230 DRM_FORMAT_MOD_LINEAR,
1231 DRM_FORMAT_MOD_INVALID
1234 static const uint32_t snb_plane_formats[] = {
1235 DRM_FORMAT_XBGR8888,
1236 DRM_FORMAT_XRGB8888,
1237 DRM_FORMAT_YUYV,
1238 DRM_FORMAT_YVYU,
1239 DRM_FORMAT_UYVY,
1240 DRM_FORMAT_VYUY,
1243 static const uint32_t vlv_plane_formats[] = {
1244 DRM_FORMAT_RGB565,
1245 DRM_FORMAT_ABGR8888,
1246 DRM_FORMAT_ARGB8888,
1247 DRM_FORMAT_XBGR8888,
1248 DRM_FORMAT_XRGB8888,
1249 DRM_FORMAT_XBGR2101010,
1250 DRM_FORMAT_ABGR2101010,
1251 DRM_FORMAT_YUYV,
1252 DRM_FORMAT_YVYU,
1253 DRM_FORMAT_UYVY,
1254 DRM_FORMAT_VYUY,
1257 static uint32_t skl_plane_formats[] = {
1258 DRM_FORMAT_RGB565,
1259 DRM_FORMAT_ABGR8888,
1260 DRM_FORMAT_ARGB8888,
1261 DRM_FORMAT_XBGR8888,
1262 DRM_FORMAT_XRGB8888,
1263 DRM_FORMAT_YUYV,
1264 DRM_FORMAT_YVYU,
1265 DRM_FORMAT_UYVY,
1266 DRM_FORMAT_VYUY,
1269 static uint32_t skl_planar_formats[] = {
1270 DRM_FORMAT_RGB565,
1271 DRM_FORMAT_ABGR8888,
1272 DRM_FORMAT_ARGB8888,
1273 DRM_FORMAT_XBGR8888,
1274 DRM_FORMAT_XRGB8888,
1275 DRM_FORMAT_YUYV,
1276 DRM_FORMAT_YVYU,
1277 DRM_FORMAT_UYVY,
1278 DRM_FORMAT_VYUY,
1279 DRM_FORMAT_NV12,
1282 static const uint64_t skl_plane_format_modifiers_noccs[] = {
1283 I915_FORMAT_MOD_Yf_TILED,
1284 I915_FORMAT_MOD_Y_TILED,
1285 I915_FORMAT_MOD_X_TILED,
1286 DRM_FORMAT_MOD_LINEAR,
1287 DRM_FORMAT_MOD_INVALID
1290 static const uint64_t skl_plane_format_modifiers_ccs[] = {
1291 I915_FORMAT_MOD_Yf_TILED_CCS,
1292 I915_FORMAT_MOD_Y_TILED_CCS,
1293 I915_FORMAT_MOD_Yf_TILED,
1294 I915_FORMAT_MOD_Y_TILED,
1295 I915_FORMAT_MOD_X_TILED,
1296 DRM_FORMAT_MOD_LINEAR,
1297 DRM_FORMAT_MOD_INVALID
1300 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1301 u32 format, u64 modifier)
1303 switch (modifier) {
1304 case DRM_FORMAT_MOD_LINEAR:
1305 case I915_FORMAT_MOD_X_TILED:
1306 break;
1307 default:
1308 return false;
1311 switch (format) {
1312 case DRM_FORMAT_XRGB8888:
1313 case DRM_FORMAT_YUYV:
1314 case DRM_FORMAT_YVYU:
1315 case DRM_FORMAT_UYVY:
1316 case DRM_FORMAT_VYUY:
1317 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1318 modifier == I915_FORMAT_MOD_X_TILED)
1319 return true;
1320 /* fall through */
1321 default:
1322 return false;
1326 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1327 u32 format, u64 modifier)
1329 switch (modifier) {
1330 case DRM_FORMAT_MOD_LINEAR:
1331 case I915_FORMAT_MOD_X_TILED:
1332 break;
1333 default:
1334 return false;
1337 switch (format) {
1338 case DRM_FORMAT_XRGB8888:
1339 case DRM_FORMAT_XBGR8888:
1340 case DRM_FORMAT_YUYV:
1341 case DRM_FORMAT_YVYU:
1342 case DRM_FORMAT_UYVY:
1343 case DRM_FORMAT_VYUY:
1344 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1345 modifier == I915_FORMAT_MOD_X_TILED)
1346 return true;
1347 /* fall through */
1348 default:
1349 return false;
1353 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1354 u32 format, u64 modifier)
1356 switch (modifier) {
1357 case DRM_FORMAT_MOD_LINEAR:
1358 case I915_FORMAT_MOD_X_TILED:
1359 break;
1360 default:
1361 return false;
1364 switch (format) {
1365 case DRM_FORMAT_RGB565:
1366 case DRM_FORMAT_ABGR8888:
1367 case DRM_FORMAT_ARGB8888:
1368 case DRM_FORMAT_XBGR8888:
1369 case DRM_FORMAT_XRGB8888:
1370 case DRM_FORMAT_XBGR2101010:
1371 case DRM_FORMAT_ABGR2101010:
1372 case DRM_FORMAT_YUYV:
1373 case DRM_FORMAT_YVYU:
1374 case DRM_FORMAT_UYVY:
1375 case DRM_FORMAT_VYUY:
1376 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1377 modifier == I915_FORMAT_MOD_X_TILED)
1378 return true;
1379 /* fall through */
1380 default:
1381 return false;
1385 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1386 u32 format, u64 modifier)
1388 struct intel_plane *plane = to_intel_plane(_plane);
1390 switch (modifier) {
1391 case DRM_FORMAT_MOD_LINEAR:
1392 case I915_FORMAT_MOD_X_TILED:
1393 case I915_FORMAT_MOD_Y_TILED:
1394 case I915_FORMAT_MOD_Yf_TILED:
1395 break;
1396 case I915_FORMAT_MOD_Y_TILED_CCS:
1397 case I915_FORMAT_MOD_Yf_TILED_CCS:
1398 if (!plane->has_ccs)
1399 return false;
1400 break;
1401 default:
1402 return false;
1405 switch (format) {
1406 case DRM_FORMAT_XRGB8888:
1407 case DRM_FORMAT_XBGR8888:
1408 case DRM_FORMAT_ARGB8888:
1409 case DRM_FORMAT_ABGR8888:
1410 if (modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
1411 modifier == I915_FORMAT_MOD_Y_TILED_CCS)
1412 return true;
1413 /* fall through */
1414 case DRM_FORMAT_RGB565:
1415 case DRM_FORMAT_XRGB2101010:
1416 case DRM_FORMAT_XBGR2101010:
1417 case DRM_FORMAT_YUYV:
1418 case DRM_FORMAT_YVYU:
1419 case DRM_FORMAT_UYVY:
1420 case DRM_FORMAT_VYUY:
1421 case DRM_FORMAT_NV12:
1422 if (modifier == I915_FORMAT_MOD_Yf_TILED)
1423 return true;
1424 /* fall through */
1425 case DRM_FORMAT_C8:
1426 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1427 modifier == I915_FORMAT_MOD_X_TILED ||
1428 modifier == I915_FORMAT_MOD_Y_TILED)
1429 return true;
1430 /* fall through */
1431 default:
1432 return false;
1436 static const struct drm_plane_funcs g4x_sprite_funcs = {
1437 .update_plane = drm_atomic_helper_update_plane,
1438 .disable_plane = drm_atomic_helper_disable_plane,
1439 .destroy = intel_plane_destroy,
1440 .atomic_get_property = intel_plane_atomic_get_property,
1441 .atomic_set_property = intel_plane_atomic_set_property,
1442 .atomic_duplicate_state = intel_plane_duplicate_state,
1443 .atomic_destroy_state = intel_plane_destroy_state,
1444 .format_mod_supported = g4x_sprite_format_mod_supported,
1447 static const struct drm_plane_funcs snb_sprite_funcs = {
1448 .update_plane = drm_atomic_helper_update_plane,
1449 .disable_plane = drm_atomic_helper_disable_plane,
1450 .destroy = intel_plane_destroy,
1451 .atomic_get_property = intel_plane_atomic_get_property,
1452 .atomic_set_property = intel_plane_atomic_set_property,
1453 .atomic_duplicate_state = intel_plane_duplicate_state,
1454 .atomic_destroy_state = intel_plane_destroy_state,
1455 .format_mod_supported = snb_sprite_format_mod_supported,
1458 static const struct drm_plane_funcs vlv_sprite_funcs = {
1459 .update_plane = drm_atomic_helper_update_plane,
1460 .disable_plane = drm_atomic_helper_disable_plane,
1461 .destroy = intel_plane_destroy,
1462 .atomic_get_property = intel_plane_atomic_get_property,
1463 .atomic_set_property = intel_plane_atomic_set_property,
1464 .atomic_duplicate_state = intel_plane_duplicate_state,
1465 .atomic_destroy_state = intel_plane_destroy_state,
1466 .format_mod_supported = vlv_sprite_format_mod_supported,
1469 static const struct drm_plane_funcs skl_plane_funcs = {
1470 .update_plane = drm_atomic_helper_update_plane,
1471 .disable_plane = drm_atomic_helper_disable_plane,
1472 .destroy = intel_plane_destroy,
1473 .atomic_get_property = intel_plane_atomic_get_property,
1474 .atomic_set_property = intel_plane_atomic_set_property,
1475 .atomic_duplicate_state = intel_plane_duplicate_state,
1476 .atomic_destroy_state = intel_plane_destroy_state,
1477 .format_mod_supported = skl_plane_format_mod_supported,
1480 bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1481 enum pipe pipe, enum plane_id plane_id)
1483 if (plane_id == PLANE_CURSOR)
1484 return false;
1486 if (INTEL_GEN(dev_priv) >= 10)
1487 return true;
1489 if (IS_GEMINILAKE(dev_priv))
1490 return pipe != PIPE_C;
1492 return pipe != PIPE_C &&
1493 (plane_id == PLANE_PRIMARY ||
1494 plane_id == PLANE_SPRITE0);
1497 struct intel_plane *
1498 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1499 enum pipe pipe, int plane)
1501 struct intel_plane *intel_plane = NULL;
1502 struct intel_plane_state *state = NULL;
1503 const struct drm_plane_funcs *plane_funcs;
1504 unsigned long possible_crtcs;
1505 const uint32_t *plane_formats;
1506 const uint64_t *modifiers;
1507 unsigned int supported_rotations;
1508 int num_plane_formats;
1509 int ret;
1511 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1512 if (!intel_plane) {
1513 ret = -ENOMEM;
1514 goto fail;
1517 state = intel_create_plane_state(&intel_plane->base);
1518 if (!state) {
1519 ret = -ENOMEM;
1520 goto fail;
1522 intel_plane->base.state = &state->base;
1524 if (INTEL_GEN(dev_priv) >= 9) {
1525 intel_plane->can_scale = true;
1526 state->scaler_id = -1;
1528 intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
1529 PLANE_SPRITE0 + plane);
1531 intel_plane->update_plane = skl_update_plane;
1532 intel_plane->disable_plane = skl_disable_plane;
1533 intel_plane->get_hw_state = skl_plane_get_hw_state;
1535 if (skl_plane_has_planar(dev_priv, pipe,
1536 PLANE_SPRITE0 + plane)) {
1537 plane_formats = skl_planar_formats;
1538 num_plane_formats = ARRAY_SIZE(skl_planar_formats);
1539 } else {
1540 plane_formats = skl_plane_formats;
1541 num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1544 if (intel_plane->has_ccs)
1545 modifiers = skl_plane_format_modifiers_ccs;
1546 else
1547 modifiers = skl_plane_format_modifiers_noccs;
1549 plane_funcs = &skl_plane_funcs;
1550 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1551 intel_plane->can_scale = false;
1552 intel_plane->max_downscale = 1;
1554 intel_plane->update_plane = vlv_update_plane;
1555 intel_plane->disable_plane = vlv_disable_plane;
1556 intel_plane->get_hw_state = vlv_plane_get_hw_state;
1558 plane_formats = vlv_plane_formats;
1559 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1560 modifiers = i9xx_plane_format_modifiers;
1562 plane_funcs = &vlv_sprite_funcs;
1563 } else if (INTEL_GEN(dev_priv) >= 7) {
1564 if (IS_IVYBRIDGE(dev_priv)) {
1565 intel_plane->can_scale = true;
1566 intel_plane->max_downscale = 2;
1567 } else {
1568 intel_plane->can_scale = false;
1569 intel_plane->max_downscale = 1;
1572 intel_plane->update_plane = ivb_update_plane;
1573 intel_plane->disable_plane = ivb_disable_plane;
1574 intel_plane->get_hw_state = ivb_plane_get_hw_state;
1576 plane_formats = snb_plane_formats;
1577 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1578 modifiers = i9xx_plane_format_modifiers;
1580 plane_funcs = &snb_sprite_funcs;
1581 } else {
1582 intel_plane->can_scale = true;
1583 intel_plane->max_downscale = 16;
1585 intel_plane->update_plane = g4x_update_plane;
1586 intel_plane->disable_plane = g4x_disable_plane;
1587 intel_plane->get_hw_state = g4x_plane_get_hw_state;
1589 modifiers = i9xx_plane_format_modifiers;
1590 if (IS_GEN6(dev_priv)) {
1591 plane_formats = snb_plane_formats;
1592 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1594 plane_funcs = &snb_sprite_funcs;
1595 } else {
1596 plane_formats = g4x_plane_formats;
1597 num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
1599 plane_funcs = &g4x_sprite_funcs;
1603 if (INTEL_GEN(dev_priv) >= 9) {
1604 supported_rotations =
1605 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
1606 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
1607 } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1608 supported_rotations =
1609 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1610 DRM_MODE_REFLECT_X;
1611 } else {
1612 supported_rotations =
1613 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1616 intel_plane->pipe = pipe;
1617 intel_plane->i9xx_plane = plane;
1618 intel_plane->id = PLANE_SPRITE0 + plane;
1619 intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id);
1620 intel_plane->check_plane = intel_check_sprite_plane;
1622 possible_crtcs = (1 << pipe);
1624 if (INTEL_GEN(dev_priv) >= 9)
1625 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1626 possible_crtcs, plane_funcs,
1627 plane_formats, num_plane_formats,
1628 modifiers,
1629 DRM_PLANE_TYPE_OVERLAY,
1630 "plane %d%c", plane + 2, pipe_name(pipe));
1631 else
1632 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1633 possible_crtcs, plane_funcs,
1634 plane_formats, num_plane_formats,
1635 modifiers,
1636 DRM_PLANE_TYPE_OVERLAY,
1637 "sprite %c", sprite_name(pipe, plane));
1638 if (ret)
1639 goto fail;
1641 drm_plane_create_rotation_property(&intel_plane->base,
1642 DRM_MODE_ROTATE_0,
1643 supported_rotations);
1645 drm_plane_create_color_properties(&intel_plane->base,
1646 BIT(DRM_COLOR_YCBCR_BT601) |
1647 BIT(DRM_COLOR_YCBCR_BT709),
1648 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1649 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1650 DRM_COLOR_YCBCR_BT709,
1651 DRM_COLOR_YCBCR_LIMITED_RANGE);
1653 drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
1655 return intel_plane;
1657 fail:
1658 kfree(state);
1659 kfree(intel_plane);
1661 return ERR_PTR(ret);