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
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
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
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>
44 int intel_usecs_to_scanlines(const struct drm_display_mode
*adjusted_mode
,
48 if (!adjusted_mode
->crtc_htotal
)
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
60 #define VBLANK_EVASION_TIME_US 100
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
);
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)
99 if (WARN_ON(drm_crtc_vblank_get(&crtc
->base
)))
103 * Wait for psr to idle out after enabling the VBL interrupts
104 * VBL interrupts will start the PSR exit and prevent a PSR
107 if (intel_psr_wait_for_idle(new_crtc_state
))
108 DRM_ERROR("PSR idle timed out, atomic update may fail\n");
112 crtc
->debug
.min_vbl
= min
;
113 crtc
->debug
.max_vbl
= max
;
114 trace_i915_pipe_update_start(crtc
);
118 * prepare_to_wait() has a memory barrier, which guarantees
119 * other CPUs can see the task state update by the time we
122 prepare_to_wait(wq
, &wait
, TASK_UNINTERRUPTIBLE
);
124 scanline
= intel_get_crtc_scanline(crtc
);
125 if (scanline
< min
|| scanline
> max
)
129 DRM_ERROR("Potential atomic update failure on pipe %c\n",
130 pipe_name(crtc
->pipe
));
136 timeout
= schedule_timeout(timeout
);
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
);
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
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
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
;
209 if (intel_vgpu_active(dev_priv
))
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
,
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",
226 ktime_us_delta(end_vbl_time
, crtc
->debug
.start_vbl_time
),
227 VBLANK_EVASION_TIME_US
);
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 */
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
);
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);
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);
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
);
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
);
350 skl_plane_get_hw_state(struct intel_plane
*plane
,
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
;
358 power_domain
= POWER_DOMAIN_PIPE(plane
->pipe
);
359 if (!intel_display_power_get_if_enabled(dev_priv
, power_domain
))
362 ret
= I915_READ(PLANE_CTL(plane
->pipe
, plane_id
)) & PLANE_CTL_ENABLE
;
366 intel_display_power_put(dev_priv
, power_domain
);
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
] = {
395 /* BT.709 full range YCbCr -> full range RGB */
396 [DRM_COLOR_YCBCR_BT709
] = {
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
)
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));
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
;
454 /* Pass-through everything. */
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
;
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
;
483 case DRM_FORMAT_YVYU
:
484 sprctl
|= SP_FORMAT_YUV422
| SP_YUV_ORDER_YVYU
;
486 case DRM_FORMAT_UYVY
:
487 sprctl
|= SP_FORMAT_YUV422
| SP_YUV_ORDER_UYVY
;
489 case DRM_FORMAT_VYUY
:
490 sprctl
|= SP_FORMAT_YUV422
| SP_YUV_ORDER_VYUY
;
492 case DRM_FORMAT_RGB565
:
493 sprctl
|= SP_FORMAT_BGR565
;
495 case DRM_FORMAT_XRGB8888
:
496 sprctl
|= SP_FORMAT_BGRX8888
;
498 case DRM_FORMAT_ARGB8888
:
499 sprctl
|= SP_FORMAT_BGRA8888
;
501 case DRM_FORMAT_XBGR2101010
:
502 sprctl
|= SP_FORMAT_RGBX1010102
;
504 case DRM_FORMAT_ABGR2101010
:
505 sprctl
|= SP_FORMAT_RGBA1010102
;
507 case DRM_FORMAT_XBGR8888
:
508 sprctl
|= SP_FORMAT_RGBX8888
;
510 case DRM_FORMAT_ABGR8888
:
511 sprctl
|= SP_FORMAT_RGBA8888
;
514 MISSING_CASE(fb
->format
->format
);
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
)
524 if (rotation
& DRM_MODE_ROTATE_180
)
525 sprctl
|= SP_ROTATE_180
;
527 if (rotation
& DRM_MODE_REFLECT_X
)
530 if (key
->flags
& I915_SET_COLORKEY_SOURCE
)
531 sprctl
|= SP_SOURCE_KEY
;
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
;
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 */
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
);
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
);
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
);
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
);
613 vlv_plane_get_hw_state(struct intel_plane
*plane
,
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
;
621 power_domain
= POWER_DOMAIN_PIPE(plane
->pipe
);
622 if (!intel_display_power_get_if_enabled(dev_priv
, power_domain
))
625 ret
= I915_READ(SPCNTR(plane
->pipe
, plane_id
)) & SP_ENABLE
;
629 intel_display_power_put(dev_priv
, power_domain
);
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
;
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
;
656 case DRM_FORMAT_XRGB8888
:
657 sprctl
|= SPRITE_FORMAT_RGBX888
;
659 case DRM_FORMAT_YUYV
:
660 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_YUYV
;
662 case DRM_FORMAT_YVYU
:
663 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_YVYU
;
665 case DRM_FORMAT_UYVY
:
666 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_UYVY
;
668 case DRM_FORMAT_VYUY
:
669 sprctl
|= SPRITE_FORMAT_YUV422
| SPRITE_YUV_ORDER_VYUY
;
672 MISSING_CASE(fb
->format
->format
);
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
;
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
;
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 */
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
);
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
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
);
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
);
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
);
781 ivb_plane_get_hw_state(struct intel_plane
*plane
,
784 struct drm_i915_private
*dev_priv
= to_i915(plane
->base
.dev
);
785 enum intel_display_power_domain power_domain
;
788 power_domain
= POWER_DOMAIN_PIPE(plane
->pipe
);
789 if (!intel_display_power_get_if_enabled(dev_priv
, power_domain
))
792 ret
= I915_READ(SPRCTL(plane
->pipe
)) & SPRITE_ENABLE
;
796 intel_display_power_put(dev_priv
, power_domain
);
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
;
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
;
820 case DRM_FORMAT_XRGB8888
:
821 dvscntr
|= DVS_FORMAT_RGBX888
;
823 case DRM_FORMAT_YUYV
:
824 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_YUYV
;
826 case DRM_FORMAT_YVYU
:
827 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_YVYU
;
829 case DRM_FORMAT_UYVY
:
830 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_UYVY
;
832 case DRM_FORMAT_VYUY
:
833 dvscntr
|= DVS_FORMAT_YUV422
| DVS_YUV_ORDER_VYUY
;
836 MISSING_CASE(fb
->format
->format
);
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
;
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
;
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 */
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
);
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
);
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
);
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
);
939 g4x_plane_get_hw_state(struct intel_plane
*plane
,
942 struct drm_i915_private
*dev_priv
= to_i915(plane
->base
.dev
);
943 enum intel_display_power_domain power_domain
;
946 power_domain
= POWER_DOMAIN_PIPE(plane
->pipe
);
947 if (!intel_display_power_get_if_enabled(dev_priv
, power_domain
))
950 ret
= I915_READ(DVSCNTR(plane
->pipe
)) & DVS_ENABLE
;
954 intel_display_power_put(dev_priv
, power_domain
);
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
;
971 uint32_t pixel_format
= 0;
974 state
->base
.visible
= false;
978 /* Don't modify another pipe's plane */
979 if (plane
->pipe
!= crtc
->pipe
) {
980 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
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");
990 /* setup can_scale, min_scale, max_scale */
991 if (INTEL_GEN(dev_priv
) >= 9) {
993 pixel_format
= state
->base
.fb
->format
->format
;
994 /* use scaler when colorkey is not required */
995 if (!state
->ckey
.flags
) {
999 skl_max_scale(crtc
, crtc_state
, pixel_format
);
1002 min_scale
= DRM_PLANE_HELPER_NO_SCALING
;
1003 max_scale
= DRM_PLANE_HELPER_NO_SCALING
;
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
,
1013 min_scale
, max_scale
,
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",
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");
1070 if (INTEL_GEN(dev_priv
) >= 9) {
1071 ret
= skl_check_plane_surface(crtc_state
, state
);
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
);
1081 state
->ctl
= vlv_sprite_ctl(crtc_state
, state
);
1082 } else if (INTEL_GEN(dev_priv
) >= 7) {
1083 ret
= i9xx_check_plane_surface(state
);
1087 state
->ctl
= ivb_sprite_ctl(crtc_state
, state
);
1089 ret
= i9xx_check_plane_surface(state
);
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
);
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
;
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
)
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
)
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
;
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
))
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
))
1154 if ((IS_VALLEYVIEW(dev_priv
) || IS_CHERRYVIEW(dev_priv
)) &&
1155 set
->flags
& I915_SET_COLORKEY_DESTINATION
)
1158 plane
= drm_plane_find(dev
, file_priv
, set
->plane_id
);
1159 if (!plane
|| plane
->type
!= DRM_PLANE_TYPE_OVERLAY
)
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
)
1172 drm_modeset_acquire_init(&ctx
, 0);
1174 state
= drm_atomic_state_alloc(plane
->dev
);
1179 state
->acquire_ctx
= &ctx
;
1182 plane_state
= drm_atomic_get_plane_state(state
, plane
);
1183 ret
= PTR_ERR_OR_ZERO(plane_state
);
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
);
1200 intel_plane_set_ckey(to_intel_plane_state(plane_state
), set
);
1204 ret
= drm_atomic_commit(state
);
1206 if (ret
!= -EDEADLK
)
1209 drm_atomic_state_clear(state
);
1210 drm_modeset_backoff(&ctx
);
1213 drm_atomic_state_put(state
);
1215 drm_modeset_drop_locks(&ctx
);
1216 drm_modeset_acquire_fini(&ctx
);
1220 static const uint32_t g4x_plane_formats
[] = {
1221 DRM_FORMAT_XRGB8888
,
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
,
1243 static const uint32_t vlv_plane_formats
[] = {
1245 DRM_FORMAT_ABGR8888
,
1246 DRM_FORMAT_ARGB8888
,
1247 DRM_FORMAT_XBGR8888
,
1248 DRM_FORMAT_XRGB8888
,
1249 DRM_FORMAT_XBGR2101010
,
1250 DRM_FORMAT_ABGR2101010
,
1257 static uint32_t skl_plane_formats
[] = {
1259 DRM_FORMAT_ABGR8888
,
1260 DRM_FORMAT_ARGB8888
,
1261 DRM_FORMAT_XBGR8888
,
1262 DRM_FORMAT_XRGB8888
,
1269 static uint32_t skl_planar_formats
[] = {
1271 DRM_FORMAT_ABGR8888
,
1272 DRM_FORMAT_ARGB8888
,
1273 DRM_FORMAT_XBGR8888
,
1274 DRM_FORMAT_XRGB8888
,
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
)
1304 case DRM_FORMAT_MOD_LINEAR
:
1305 case I915_FORMAT_MOD_X_TILED
:
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
)
1326 static bool snb_sprite_format_mod_supported(struct drm_plane
*_plane
,
1327 u32 format
, u64 modifier
)
1330 case DRM_FORMAT_MOD_LINEAR
:
1331 case I915_FORMAT_MOD_X_TILED
:
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
)
1353 static bool vlv_sprite_format_mod_supported(struct drm_plane
*_plane
,
1354 u32 format
, u64 modifier
)
1357 case DRM_FORMAT_MOD_LINEAR
:
1358 case I915_FORMAT_MOD_X_TILED
:
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
)
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
);
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
:
1396 case I915_FORMAT_MOD_Y_TILED_CCS
:
1397 case I915_FORMAT_MOD_Yf_TILED_CCS
:
1398 if (!plane
->has_ccs
)
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
)
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
)
1426 if (modifier
== DRM_FORMAT_MOD_LINEAR
||
1427 modifier
== I915_FORMAT_MOD_X_TILED
||
1428 modifier
== I915_FORMAT_MOD_Y_TILED
)
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
)
1486 if (INTEL_GEN(dev_priv
) >= 10)
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
;
1511 intel_plane
= kzalloc(sizeof(*intel_plane
), GFP_KERNEL
);
1517 state
= intel_create_plane_state(&intel_plane
->base
);
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
);
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
;
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;
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
;
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
;
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
|
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
,
1629 DRM_PLANE_TYPE_OVERLAY
,
1630 "plane %d%c", plane
+ 2, pipe_name(pipe
));
1632 ret
= drm_universal_plane_init(&dev_priv
->drm
, &intel_plane
->base
,
1633 possible_crtcs
, plane_funcs
,
1634 plane_formats
, num_plane_formats
,
1636 DRM_PLANE_TYPE_OVERLAY
,
1637 "sprite %c", sprite_name(pipe
, plane
));
1641 drm_plane_create_rotation_property(&intel_plane
->base
,
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
);
1661 return ERR_PTR(ret
);