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.h>
34 #include <drm/drm_atomic_helper.h>
35 #include <drm/drm_color_mgmt.h>
36 #include <drm/drm_crtc.h>
37 #include <drm/drm_fourcc.h>
38 #include <drm/drm_plane_helper.h>
39 #include <drm/drm_rect.h>
40 #include <drm/i915_drm.h>
43 #include "i915_trace.h"
44 #include "intel_atomic_plane.h"
45 #include "intel_display_types.h"
46 #include "intel_frontbuffer.h"
48 #include "intel_psr.h"
49 #include "intel_sprite.h"
51 bool is_planar_yuv_format(u32 pixelformat)
53 switch (pixelformat) {
64 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
68 if (!adjusted_mode->crtc_htotal)
71 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
72 1000 * adjusted_mode->crtc_htotal);
75 /* FIXME: We should instead only take spinlocks once for the entire update
76 * instead of once per mmio. */
77 #if IS_ENABLED(CONFIG_PROVE_LOCKING)
78 #define VBLANK_EVASION_TIME_US 250
80 #define VBLANK_EVASION_TIME_US 100
84 * intel_pipe_update_start() - start update of a set of display registers
85 * @new_crtc_state: the new crtc state
87 * Mark the start of an update to pipe registers that should be updated
88 * atomically regarding vblank. If the next vblank will happens within
89 * the next 100 us, this function waits until the vblank passes.
91 * After a successful call to this function, interrupts will be disabled
92 * until a subsequent call to intel_pipe_update_end(). That is done to
93 * avoid random delays.
95 void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
97 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
98 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
99 const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
100 long timeout = msecs_to_jiffies_timeout(1);
101 int scanline, min, max, vblank_start;
102 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
103 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
104 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
108 vblank_start = adjusted_mode->crtc_vblank_start;
109 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
110 vblank_start = DIV_ROUND_UP(vblank_start, 2);
112 /* FIXME needs to be calibrated sensibly */
113 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
114 VBLANK_EVASION_TIME_US);
115 max = vblank_start - 1;
117 if (min <= 0 || max <= 0)
120 if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
124 * Wait for psr to idle out after enabling the VBL interrupts
125 * VBL interrupts will start the PSR exit and prevent a PSR
128 if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
129 DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
134 crtc->debug.min_vbl = min;
135 crtc->debug.max_vbl = max;
136 trace_i915_pipe_update_start(crtc);
140 * prepare_to_wait() has a memory barrier, which guarantees
141 * other CPUs can see the task state update by the time we
144 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
146 scanline = intel_get_crtc_scanline(crtc);
147 if (scanline < min || scanline > max)
151 DRM_ERROR("Potential atomic update failure on pipe %c\n",
152 pipe_name(crtc->pipe));
158 timeout = schedule_timeout(timeout);
163 finish_wait(wq, &wait);
165 drm_crtc_vblank_put(&crtc->base);
168 * On VLV/CHV DSI the scanline counter would appear to
169 * increment approx. 1/3 of a scanline before start of vblank.
170 * The registers still get latched at start of vblank however.
171 * This means we must not write any registers on the first
172 * line of vblank (since not the whole line is actually in
173 * vblank). And unfortunately we can't use the interrupt to
174 * wait here since it will fire too soon. We could use the
175 * frame start interrupt instead since it will fire after the
176 * critical scanline, but that would require more changes
177 * in the interrupt code. So for now we'll just do the nasty
178 * thing and poll for the bad scanline to pass us by.
180 * FIXME figure out if BXT+ DSI suffers from this as well
182 while (need_vlv_dsi_wa && scanline == vblank_start)
183 scanline = intel_get_crtc_scanline(crtc);
185 crtc->debug.scanline_start = scanline;
186 crtc->debug.start_vbl_time = ktime_get();
187 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
189 trace_i915_pipe_update_vblank_evaded(crtc);
197 * intel_pipe_update_end() - end update of a set of display registers
198 * @new_crtc_state: the new crtc state
200 * Mark the end of an update started with intel_pipe_update_start(). This
201 * re-enables interrupts and verifies the update was actually completed
204 void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
206 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
207 enum pipe pipe = crtc->pipe;
208 int scanline_end = intel_get_crtc_scanline(crtc);
209 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
210 ktime_t end_vbl_time = ktime_get();
211 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
213 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
215 /* We're still in the vblank-evade critical section, this can't race.
216 * Would be slightly nice to just grab the vblank count and arm the
217 * event outside of the critical section - the spinlock might spin for a
219 if (new_crtc_state->base.event) {
220 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
222 spin_lock(&crtc->base.dev->event_lock);
223 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
224 spin_unlock(&crtc->base.dev->event_lock);
226 new_crtc_state->base.event = NULL;
231 if (intel_vgpu_active(dev_priv))
234 if (crtc->debug.start_vbl_count &&
235 crtc->debug.start_vbl_count != end_vbl_count) {
236 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",
237 pipe_name(pipe), crtc->debug.start_vbl_count,
239 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
240 crtc->debug.min_vbl, crtc->debug.max_vbl,
241 crtc->debug.scanline_start, scanline_end);
243 #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
244 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
245 VBLANK_EVASION_TIME_US)
246 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
248 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
249 VBLANK_EVASION_TIME_US);
253 int intel_plane_check_stride(const struct intel_plane_state *plane_state)
255 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
256 const struct drm_framebuffer *fb = plane_state->base.fb;
257 unsigned int rotation = plane_state->base.rotation;
258 u32 stride, max_stride;
261 * We ignore stride for all invisible planes that
262 * can be remapped. Otherwise we could end up
263 * with a false positive when the remapping didn't
264 * kick in due the plane being invisible.
266 if (intel_plane_can_remap(plane_state) &&
267 !plane_state->base.visible)
270 /* FIXME other color planes? */
271 stride = plane_state->color_plane[0].stride;
272 max_stride = plane->max_stride(plane, fb->format->format,
273 fb->modifier, rotation);
275 if (stride > max_stride) {
276 DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
278 plane->base.base.id, plane->base.name, max_stride);
285 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
287 const struct drm_framebuffer *fb = plane_state->base.fb;
288 struct drm_rect *src = &plane_state->base.src;
289 u32 src_x, src_y, src_w, src_h, hsub, vsub;
290 bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
293 * Hardware doesn't handle subpixel coordinates.
294 * Adjust to (macro)pixel boundary, but be careful not to
295 * increase the source viewport size, because that could
296 * push the downscaling factor out of bounds.
298 src_x = src->x1 >> 16;
299 src_w = drm_rect_width(src) >> 16;
300 src_y = src->y1 >> 16;
301 src_h = drm_rect_height(src) >> 16;
303 src->x1 = src_x << 16;
304 src->x2 = (src_x + src_w) << 16;
305 src->y1 = src_y << 16;
306 src->y2 = (src_y + src_h) << 16;
308 if (!fb->format->is_yuv)
311 /* YUV specific checks */
313 hsub = fb->format->hsub;
314 vsub = fb->format->vsub;
316 hsub = vsub = max(fb->format->hsub, fb->format->vsub);
319 if (src_x % hsub || src_w % hsub) {
320 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
321 src_x, src_w, hsub, rotated ? "rotated " : "");
325 if (src_y % vsub || src_h % vsub) {
326 DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
327 src_y, src_h, vsub, rotated ? "rotated " : "");
334 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
336 return INTEL_GEN(dev_priv) >= 11 &&
337 icl_hdr_plane_mask() & BIT(plane_id);
341 skl_plane_max_stride(struct intel_plane *plane,
342 u32 pixel_format, u64 modifier,
343 unsigned int rotation)
345 const struct drm_format_info *info = drm_format_info(pixel_format);
346 int cpp = info->cpp[0];
349 * "The stride in bytes must not exceed the
350 * of the size of 8K pixels and 32K bytes."
352 if (drm_rotation_90_or_270(rotation))
353 return min(8192, 32768 / cpp);
355 return min(8192 * cpp, 32768);
359 skl_program_scaler(struct intel_plane *plane,
360 const struct intel_crtc_state *crtc_state,
361 const struct intel_plane_state *plane_state)
363 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
364 enum pipe pipe = plane->pipe;
365 int scaler_id = plane_state->scaler_id;
366 const struct intel_scaler *scaler =
367 &crtc_state->scaler_state.scalers[scaler_id];
368 int crtc_x = plane_state->base.dst.x1;
369 int crtc_y = plane_state->base.dst.y1;
370 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
371 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
372 u16 y_hphase, uv_rgb_hphase;
373 u16 y_vphase, uv_rgb_vphase;
376 hscale = drm_rect_calc_hscale(&plane_state->base.src,
377 &plane_state->base.dst,
379 vscale = drm_rect_calc_vscale(&plane_state->base.src,
380 &plane_state->base.dst,
383 /* TODO: handle sub-pixel coordinates */
384 if (is_planar_yuv_format(plane_state->base.fb->format->format) &&
385 !icl_is_hdr_plane(dev_priv, plane->id)) {
386 y_hphase = skl_scaler_calc_phase(1, hscale, false);
387 y_vphase = skl_scaler_calc_phase(1, vscale, false);
389 /* MPEG2 chroma siting convention */
390 uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
391 uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
397 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
398 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
401 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
402 PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
403 I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
404 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
405 I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
406 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
407 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
408 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
411 /* Preoffset values for YUV to RGB Conversion */
412 #define PREOFF_YUV_TO_RGB_HI 0x1800
413 #define PREOFF_YUV_TO_RGB_ME 0x1F00
414 #define PREOFF_YUV_TO_RGB_LO 0x1800
416 #define ROFF(x) (((x) & 0xffff) << 16)
417 #define GOFF(x) (((x) & 0xffff) << 0)
418 #define BOFF(x) (((x) & 0xffff) << 16)
421 icl_program_input_csc(struct intel_plane *plane,
422 const struct intel_crtc_state *crtc_state,
423 const struct intel_plane_state *plane_state)
425 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
426 enum pipe pipe = plane->pipe;
427 enum plane_id plane_id = plane->id;
429 static const u16 input_csc_matrix[][9] = {
431 * BT.601 full range YCbCr -> full range RGB
432 * The matrix required is :
433 * [1.000, 0.000, 1.371,
434 * 1.000, -0.336, -0.698,
435 * 1.000, 1.732, 0.0000]
437 [DRM_COLOR_YCBCR_BT601] = {
439 0x8B28, 0x7800, 0x9AC0,
443 * BT.709 full range YCbCr -> full range RGB
444 * The matrix required is :
445 * [1.000, 0.000, 1.574,
446 * 1.000, -0.187, -0.468,
447 * 1.000, 1.855, 0.0000]
449 [DRM_COLOR_YCBCR_BT709] = {
451 0x9EF8, 0x7800, 0xAC00,
455 * BT.2020 full range YCbCr -> full range RGB
456 * The matrix required is :
457 * [1.000, 0.000, 1.474,
458 * 1.000, -0.1645, -0.5713,
459 * 1.000, 1.8814, 0.0000]
461 [DRM_COLOR_YCBCR_BT2020] = {
463 0x8928, 0x7800, 0xAA88,
468 /* Matrix for Limited Range to Full Range Conversion */
469 static const u16 input_csc_matrix_lr[][9] = {
471 * BT.601 Limted range YCbCr -> full range RGB
472 * The matrix required is :
473 * [1.164384, 0.000, 1.596027,
474 * 1.164384, -0.39175, -0.812813,
475 * 1.164384, 2.017232, 0.0000]
477 [DRM_COLOR_YCBCR_BT601] = {
479 0x8D00, 0x7950, 0x9C88,
483 * BT.709 Limited range YCbCr -> full range RGB
484 * The matrix required is :
485 * [1.164384, 0.000, 1.792741,
486 * 1.164384, -0.213249, -0.532909,
487 * 1.164384, 2.112402, 0.0000]
489 [DRM_COLOR_YCBCR_BT709] = {
491 0x8888, 0x7950, 0xADA8,
495 * BT.2020 Limited range YCbCr -> full range RGB
496 * The matrix required is :
497 * [1.164, 0.000, 1.678,
498 * 1.164, -0.1873, -0.6504,
499 * 1.164, 2.1417, 0.0000]
501 [DRM_COLOR_YCBCR_BT2020] = {
503 0x8A68, 0x7950, 0xAC00,
509 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
510 csc = input_csc_matrix[plane_state->base.color_encoding];
512 csc = input_csc_matrix_lr[plane_state->base.color_encoding];
514 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
516 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
517 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
519 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
520 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
522 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));
524 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
525 PREOFF_YUV_TO_RGB_HI);
526 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
527 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 0);
529 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
530 PREOFF_YUV_TO_RGB_ME);
531 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
532 PREOFF_YUV_TO_RGB_LO);
533 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
534 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
535 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
539 skl_program_plane(struct intel_plane *plane,
540 const struct intel_crtc_state *crtc_state,
541 const struct intel_plane_state *plane_state,
542 int color_plane, bool slave, u32 plane_ctl)
544 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
545 enum plane_id plane_id = plane->id;
546 enum pipe pipe = plane->pipe;
547 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
548 u32 surf_addr = plane_state->color_plane[color_plane].offset;
549 u32 stride = skl_plane_stride(plane_state, color_plane);
550 u32 aux_stride = skl_plane_stride(plane_state, 1);
551 int crtc_x = plane_state->base.dst.x1;
552 int crtc_y = plane_state->base.dst.y1;
553 u32 x = plane_state->color_plane[color_plane].x;
554 u32 y = plane_state->color_plane[color_plane].y;
555 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
556 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
557 struct intel_plane *linked = plane_state->linked_plane;
558 const struct drm_framebuffer *fb = plane_state->base.fb;
559 u8 alpha = plane_state->base.alpha >> 8;
560 u32 plane_color_ctl = 0;
561 unsigned long irqflags;
564 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
566 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
567 plane_color_ctl = plane_state->color_ctl |
568 glk_plane_color_ctl_crtc(crtc_state);
570 /* Sizes are 0 based */
574 keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
576 keymsk = key->channel_mask & 0x7ffffff;
578 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
580 /* The scaler will handle the output position */
581 if (plane_state->scaler_id >= 0) {
586 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
588 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
589 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
590 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
591 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
592 (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
594 if (icl_is_hdr_plane(dev_priv, plane_id)) {
598 /* Enable and use MPEG-2 chroma siting */
599 cus_ctl = PLANE_CUS_ENABLE |
601 PLANE_CUS_VPHASE_SIGN_NEGATIVE |
602 PLANE_CUS_VPHASE_0_25;
604 if (linked->id == PLANE_SPRITE5)
605 cus_ctl |= PLANE_CUS_PLANE_7;
606 else if (linked->id == PLANE_SPRITE4)
607 cus_ctl |= PLANE_CUS_PLANE_6;
609 MISSING_CASE(linked->id);
612 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), cus_ctl);
615 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
616 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
618 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
619 icl_program_input_csc(plane, crtc_state, plane_state);
621 skl_write_plane_wm(plane, crtc_state);
623 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
624 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
625 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
627 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
629 if (INTEL_GEN(dev_priv) < 11)
630 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
631 (plane_state->color_plane[1].y << 16) |
632 plane_state->color_plane[1].x);
635 * The control register self-arms if the plane was previously
636 * disabled. Try to make the plane enable atomic by writing
637 * the control register just before the surface register.
639 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
640 I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
641 intel_plane_ggtt_offset(plane_state) + surf_addr);
643 if (!slave && plane_state->scaler_id >= 0)
644 skl_program_scaler(plane, crtc_state, plane_state);
646 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
650 skl_update_plane(struct intel_plane *plane,
651 const struct intel_crtc_state *crtc_state,
652 const struct intel_plane_state *plane_state)
656 if (plane_state->linked_plane) {
657 /* Program the UV plane */
661 skl_program_plane(plane, crtc_state, plane_state,
662 color_plane, false, plane_state->ctl);
666 icl_update_slave(struct intel_plane *plane,
667 const struct intel_crtc_state *crtc_state,
668 const struct intel_plane_state *plane_state)
670 skl_program_plane(plane, crtc_state, plane_state, 0, true,
671 plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);
675 skl_disable_plane(struct intel_plane *plane,
676 const struct intel_crtc_state *crtc_state)
678 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
679 enum plane_id plane_id = plane->id;
680 enum pipe pipe = plane->pipe;
681 unsigned long irqflags;
683 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
685 if (icl_is_hdr_plane(dev_priv, plane_id))
686 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);
688 skl_write_plane_wm(plane, crtc_state);
690 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
691 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
693 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
697 skl_plane_get_hw_state(struct intel_plane *plane,
700 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
701 enum intel_display_power_domain power_domain;
702 enum plane_id plane_id = plane->id;
703 intel_wakeref_t wakeref;
706 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
707 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
711 ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
715 intel_display_power_put(dev_priv, power_domain, wakeref);
720 static void i9xx_plane_linear_gamma(u16 gamma[8])
722 /* The points are not evenly spaced. */
723 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
726 for (i = 0; i < 8; i++)
727 gamma[i] = (in[i] << 8) / 32;
731 chv_update_csc(const struct intel_plane_state *plane_state)
733 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
734 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
735 const struct drm_framebuffer *fb = plane_state->base.fb;
736 enum plane_id plane_id = plane->id;
738 * |r| | c0 c1 c2 | |cr|
739 * |g| = | c3 c4 c5 | x |y |
740 * |b| | c6 c7 c8 | |cb|
742 * Coefficients are s3.12.
744 * Cb and Cr apparently come in as signed already, and
745 * we always get full range data in on account of CLRC0/1.
747 static const s16 csc_matrix[][9] = {
748 /* BT.601 full range YCbCr -> full range RGB */
749 [DRM_COLOR_YCBCR_BT601] = {
754 /* BT.709 full range YCbCr -> full range RGB */
755 [DRM_COLOR_YCBCR_BT709] = {
761 const s16 *csc = csc_matrix[plane_state->base.color_encoding];
763 /* Seems RGB data bypasses the CSC always */
764 if (!fb->format->is_yuv)
767 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
768 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
769 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
771 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
772 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
773 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
774 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
775 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
777 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
778 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
779 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
781 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
782 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
783 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
790 vlv_update_clrc(const struct intel_plane_state *plane_state)
792 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
793 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
794 const struct drm_framebuffer *fb = plane_state->base.fb;
795 enum pipe pipe = plane->pipe;
796 enum plane_id plane_id = plane->id;
797 int contrast, brightness, sh_scale, sh_sin, sh_cos;
799 if (fb->format->is_yuv &&
800 plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
802 * Expand limited range to full range:
803 * Contrast is applied first and is used to expand Y range.
804 * Brightness is applied second and is used to remove the
805 * offset from Y. Saturation/hue is used to expand CbCr range.
807 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
808 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
809 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
810 sh_sin = SIN_0 * sh_scale;
811 sh_cos = COS_0 * sh_scale;
813 /* Pass-through everything. */
817 sh_sin = SIN_0 * sh_scale;
818 sh_cos = COS_0 * sh_scale;
821 /* FIXME these register are single buffered :( */
822 I915_WRITE_FW(SPCLRC0(pipe, plane_id),
823 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
824 I915_WRITE_FW(SPCLRC1(pipe, plane_id),
825 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
828 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
832 if (crtc_state->gamma_enable)
833 sprctl |= SP_GAMMA_ENABLE;
838 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
839 const struct intel_plane_state *plane_state)
841 const struct drm_framebuffer *fb = plane_state->base.fb;
842 unsigned int rotation = plane_state->base.rotation;
843 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
848 switch (fb->format->format) {
849 case DRM_FORMAT_YUYV:
850 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
852 case DRM_FORMAT_YVYU:
853 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
855 case DRM_FORMAT_UYVY:
856 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
858 case DRM_FORMAT_VYUY:
859 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
861 case DRM_FORMAT_RGB565:
862 sprctl |= SP_FORMAT_BGR565;
864 case DRM_FORMAT_XRGB8888:
865 sprctl |= SP_FORMAT_BGRX8888;
867 case DRM_FORMAT_ARGB8888:
868 sprctl |= SP_FORMAT_BGRA8888;
870 case DRM_FORMAT_XBGR2101010:
871 sprctl |= SP_FORMAT_RGBX1010102;
873 case DRM_FORMAT_ABGR2101010:
874 sprctl |= SP_FORMAT_RGBA1010102;
876 case DRM_FORMAT_XBGR8888:
877 sprctl |= SP_FORMAT_RGBX8888;
879 case DRM_FORMAT_ABGR8888:
880 sprctl |= SP_FORMAT_RGBA8888;
883 MISSING_CASE(fb->format->format);
887 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
888 sprctl |= SP_YUV_FORMAT_BT709;
890 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
893 if (rotation & DRM_MODE_ROTATE_180)
894 sprctl |= SP_ROTATE_180;
896 if (rotation & DRM_MODE_REFLECT_X)
899 if (key->flags & I915_SET_COLORKEY_SOURCE)
900 sprctl |= SP_SOURCE_KEY;
905 static void vlv_update_gamma(const struct intel_plane_state *plane_state)
907 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
908 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
909 const struct drm_framebuffer *fb = plane_state->base.fb;
910 enum pipe pipe = plane->pipe;
911 enum plane_id plane_id = plane->id;
915 /* Seems RGB data bypasses the gamma always */
916 if (!fb->format->is_yuv)
919 i9xx_plane_linear_gamma(gamma);
921 /* FIXME these register are single buffered :( */
922 /* The two end points are implicit (0.0 and 1.0) */
923 for (i = 1; i < 8 - 1; i++)
924 I915_WRITE_FW(SPGAMC(pipe, plane_id, i - 1),
931 vlv_update_plane(struct intel_plane *plane,
932 const struct intel_crtc_state *crtc_state,
933 const struct intel_plane_state *plane_state)
935 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
936 enum pipe pipe = plane->pipe;
937 enum plane_id plane_id = plane->id;
938 u32 sprsurf_offset = plane_state->color_plane[0].offset;
940 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
941 int crtc_x = plane_state->base.dst.x1;
942 int crtc_y = plane_state->base.dst.y1;
943 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
944 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
945 u32 x = plane_state->color_plane[0].x;
946 u32 y = plane_state->color_plane[0].y;
947 unsigned long irqflags;
950 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
952 /* Sizes are 0 based */
956 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
958 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
960 I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
961 plane_state->color_plane[0].stride);
962 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
963 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
964 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
966 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
967 chv_update_csc(plane_state);
970 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
971 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
972 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
975 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
976 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
979 * The control register self-arms if the plane was previously
980 * disabled. Try to make the plane enable atomic by writing
981 * the control register just before the surface register.
983 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
984 I915_WRITE_FW(SPSURF(pipe, plane_id),
985 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
987 vlv_update_clrc(plane_state);
988 vlv_update_gamma(plane_state);
990 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
994 vlv_disable_plane(struct intel_plane *plane,
995 const struct intel_crtc_state *crtc_state)
997 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
998 enum pipe pipe = plane->pipe;
999 enum plane_id plane_id = plane->id;
1000 unsigned long irqflags;
1002 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1004 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
1005 I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
1007 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1011 vlv_plane_get_hw_state(struct intel_plane *plane,
1014 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1015 enum intel_display_power_domain power_domain;
1016 enum plane_id plane_id = plane->id;
1017 intel_wakeref_t wakeref;
1020 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1021 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1025 ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
1027 *pipe = plane->pipe;
1029 intel_display_power_put(dev_priv, power_domain, wakeref);
1034 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1038 if (crtc_state->gamma_enable)
1039 sprctl |= SPRITE_GAMMA_ENABLE;
1041 if (crtc_state->csc_enable)
1042 sprctl |= SPRITE_PIPE_CSC_ENABLE;
1047 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
1048 const struct intel_plane_state *plane_state)
1050 struct drm_i915_private *dev_priv =
1051 to_i915(plane_state->base.plane->dev);
1052 const struct drm_framebuffer *fb = plane_state->base.fb;
1053 unsigned int rotation = plane_state->base.rotation;
1054 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1057 sprctl = SPRITE_ENABLE;
1059 if (IS_IVYBRIDGE(dev_priv))
1060 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
1062 switch (fb->format->format) {
1063 case DRM_FORMAT_XBGR8888:
1064 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1066 case DRM_FORMAT_XRGB8888:
1067 sprctl |= SPRITE_FORMAT_RGBX888;
1069 case DRM_FORMAT_YUYV:
1070 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
1072 case DRM_FORMAT_YVYU:
1073 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
1075 case DRM_FORMAT_UYVY:
1076 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
1078 case DRM_FORMAT_VYUY:
1079 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
1082 MISSING_CASE(fb->format->format);
1086 sprctl |= SPRITE_INT_GAMMA_DISABLE;
1088 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1089 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1091 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1092 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1094 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1095 sprctl |= SPRITE_TILED;
1097 if (rotation & DRM_MODE_ROTATE_180)
1098 sprctl |= SPRITE_ROTATE_180;
1100 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1101 sprctl |= SPRITE_DEST_KEY;
1102 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1103 sprctl |= SPRITE_SOURCE_KEY;
1108 static void ivb_sprite_linear_gamma(u16 gamma[18])
1112 for (i = 0; i < 17; i++)
1113 gamma[i] = (i << 10) / 16;
1119 static void ivb_update_gamma(const struct intel_plane_state *plane_state)
1121 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1122 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1123 enum pipe pipe = plane->pipe;
1127 ivb_sprite_linear_gamma(gamma);
1129 /* FIXME these register are single buffered :( */
1130 for (i = 0; i < 16; i++)
1131 I915_WRITE_FW(SPRGAMC(pipe, i),
1136 I915_WRITE_FW(SPRGAMC16(pipe, 0), gamma[i]);
1137 I915_WRITE_FW(SPRGAMC16(pipe, 1), gamma[i]);
1138 I915_WRITE_FW(SPRGAMC16(pipe, 2), gamma[i]);
1141 I915_WRITE_FW(SPRGAMC17(pipe, 0), gamma[i]);
1142 I915_WRITE_FW(SPRGAMC17(pipe, 1), gamma[i]);
1143 I915_WRITE_FW(SPRGAMC17(pipe, 2), gamma[i]);
1148 ivb_update_plane(struct intel_plane *plane,
1149 const struct intel_crtc_state *crtc_state,
1150 const struct intel_plane_state *plane_state)
1152 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1153 enum pipe pipe = plane->pipe;
1154 u32 sprsurf_offset = plane_state->color_plane[0].offset;
1156 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1157 int crtc_x = plane_state->base.dst.x1;
1158 int crtc_y = plane_state->base.dst.y1;
1159 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1160 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1161 u32 x = plane_state->color_plane[0].x;
1162 u32 y = plane_state->color_plane[0].y;
1163 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1164 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1165 u32 sprctl, sprscale = 0;
1166 unsigned long irqflags;
1168 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1170 /* Sizes are 0 based */
1176 if (crtc_w != src_w || crtc_h != src_h)
1177 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1179 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1181 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1183 I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
1184 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1185 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1186 if (IS_IVYBRIDGE(dev_priv))
1187 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
1190 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
1191 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1192 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1195 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1197 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1198 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1200 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1201 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1205 * The control register self-arms if the plane was previously
1206 * disabled. Try to make the plane enable atomic by writing
1207 * the control register just before the surface register.
1209 I915_WRITE_FW(SPRCTL(pipe), sprctl);
1210 I915_WRITE_FW(SPRSURF(pipe),
1211 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1213 ivb_update_gamma(plane_state);
1215 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1219 ivb_disable_plane(struct intel_plane *plane,
1220 const struct intel_crtc_state *crtc_state)
1222 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1223 enum pipe pipe = plane->pipe;
1224 unsigned long irqflags;
1226 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1228 I915_WRITE_FW(SPRCTL(pipe), 0);
1229 /* Disable the scaler */
1230 if (IS_IVYBRIDGE(dev_priv))
1231 I915_WRITE_FW(SPRSCALE(pipe), 0);
1232 I915_WRITE_FW(SPRSURF(pipe), 0);
1234 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1238 ivb_plane_get_hw_state(struct intel_plane *plane,
1241 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1242 enum intel_display_power_domain power_domain;
1243 intel_wakeref_t wakeref;
1246 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1247 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1251 ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1253 *pipe = plane->pipe;
1255 intel_display_power_put(dev_priv, power_domain, wakeref);
1261 g4x_sprite_max_stride(struct intel_plane *plane,
1262 u32 pixel_format, u64 modifier,
1263 unsigned int rotation)
1268 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1272 if (crtc_state->gamma_enable)
1273 dvscntr |= DVS_GAMMA_ENABLE;
1275 if (crtc_state->csc_enable)
1276 dvscntr |= DVS_PIPE_CSC_ENABLE;
1281 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1282 const struct intel_plane_state *plane_state)
1284 struct drm_i915_private *dev_priv =
1285 to_i915(plane_state->base.plane->dev);
1286 const struct drm_framebuffer *fb = plane_state->base.fb;
1287 unsigned int rotation = plane_state->base.rotation;
1288 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1291 dvscntr = DVS_ENABLE;
1293 if (IS_GEN(dev_priv, 6))
1294 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1296 switch (fb->format->format) {
1297 case DRM_FORMAT_XBGR8888:
1298 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1300 case DRM_FORMAT_XRGB8888:
1301 dvscntr |= DVS_FORMAT_RGBX888;
1303 case DRM_FORMAT_YUYV:
1304 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1306 case DRM_FORMAT_YVYU:
1307 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1309 case DRM_FORMAT_UYVY:
1310 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1312 case DRM_FORMAT_VYUY:
1313 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1316 MISSING_CASE(fb->format->format);
1320 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1321 dvscntr |= DVS_YUV_FORMAT_BT709;
1323 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1324 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1326 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1327 dvscntr |= DVS_TILED;
1329 if (rotation & DRM_MODE_ROTATE_180)
1330 dvscntr |= DVS_ROTATE_180;
1332 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1333 dvscntr |= DVS_DEST_KEY;
1334 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1335 dvscntr |= DVS_SOURCE_KEY;
1340 static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1342 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1343 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1344 const struct drm_framebuffer *fb = plane_state->base.fb;
1345 enum pipe pipe = plane->pipe;
1349 /* Seems RGB data bypasses the gamma always */
1350 if (!fb->format->is_yuv)
1353 i9xx_plane_linear_gamma(gamma);
1355 /* FIXME these register are single buffered :( */
1356 /* The two end points are implicit (0.0 and 1.0) */
1357 for (i = 1; i < 8 - 1; i++)
1358 I915_WRITE_FW(DVSGAMC_G4X(pipe, i - 1),
1364 static void ilk_sprite_linear_gamma(u16 gamma[17])
1368 for (i = 0; i < 17; i++)
1369 gamma[i] = (i << 10) / 16;
1372 static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1374 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1375 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1376 const struct drm_framebuffer *fb = plane_state->base.fb;
1377 enum pipe pipe = plane->pipe;
1381 /* Seems RGB data bypasses the gamma always */
1382 if (!fb->format->is_yuv)
1385 ilk_sprite_linear_gamma(gamma);
1387 /* FIXME these register are single buffered :( */
1388 for (i = 0; i < 16; i++)
1389 I915_WRITE_FW(DVSGAMC_ILK(pipe, i),
1394 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1395 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1396 I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1401 g4x_update_plane(struct intel_plane *plane,
1402 const struct intel_crtc_state *crtc_state,
1403 const struct intel_plane_state *plane_state)
1405 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1406 enum pipe pipe = plane->pipe;
1407 u32 dvssurf_offset = plane_state->color_plane[0].offset;
1409 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1410 int crtc_x = plane_state->base.dst.x1;
1411 int crtc_y = plane_state->base.dst.y1;
1412 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1413 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1414 u32 x = plane_state->color_plane[0].x;
1415 u32 y = plane_state->color_plane[0].y;
1416 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1417 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1418 u32 dvscntr, dvsscale = 0;
1419 unsigned long irqflags;
1421 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1423 /* Sizes are 0 based */
1429 if (crtc_w != src_w || crtc_h != src_h)
1430 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1432 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1434 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1436 I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
1437 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1438 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1439 I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
1442 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
1443 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1444 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1447 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1448 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1451 * The control register self-arms if the plane was previously
1452 * disabled. Try to make the plane enable atomic by writing
1453 * the control register just before the surface register.
1455 I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
1456 I915_WRITE_FW(DVSSURF(pipe),
1457 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1459 if (IS_G4X(dev_priv))
1460 g4x_update_gamma(plane_state);
1462 ilk_update_gamma(plane_state);
1464 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1468 g4x_disable_plane(struct intel_plane *plane,
1469 const struct intel_crtc_state *crtc_state)
1471 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1472 enum pipe pipe = plane->pipe;
1473 unsigned long irqflags;
1475 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1477 I915_WRITE_FW(DVSCNTR(pipe), 0);
1478 /* Disable the scaler */
1479 I915_WRITE_FW(DVSSCALE(pipe), 0);
1480 I915_WRITE_FW(DVSSURF(pipe), 0);
1482 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1486 g4x_plane_get_hw_state(struct intel_plane *plane,
1489 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1490 enum intel_display_power_domain power_domain;
1491 intel_wakeref_t wakeref;
1494 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1495 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1499 ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1501 *pipe = plane->pipe;
1503 intel_display_power_put(dev_priv, power_domain, wakeref);
1508 static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1513 switch (fb->format->format) {
1522 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1523 struct intel_plane_state *plane_state)
1525 const struct drm_framebuffer *fb = plane_state->base.fb;
1526 const struct drm_rect *src = &plane_state->base.src;
1527 const struct drm_rect *dst = &plane_state->base.dst;
1528 int src_x, src_w, src_h, crtc_w, crtc_h;
1529 const struct drm_display_mode *adjusted_mode =
1530 &crtc_state->base.adjusted_mode;
1531 unsigned int stride = plane_state->color_plane[0].stride;
1532 unsigned int cpp = fb->format->cpp[0];
1533 unsigned int width_bytes;
1534 int min_width, min_height;
1536 crtc_w = drm_rect_width(dst);
1537 crtc_h = drm_rect_height(dst);
1539 src_x = src->x1 >> 16;
1540 src_w = drm_rect_width(src) >> 16;
1541 src_h = drm_rect_height(src) >> 16;
1543 if (src_w == crtc_w && src_h == crtc_h)
1548 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1550 DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1558 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1560 if (src_w < min_width || src_h < min_height ||
1561 src_w > 2048 || src_h > 2048) {
1562 DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1563 src_w, src_h, min_width, min_height, 2048, 2048);
1567 if (width_bytes > 4096) {
1568 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1573 if (stride > 4096) {
1574 DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1583 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1584 struct intel_plane_state *plane_state)
1586 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1587 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1588 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1589 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1592 if (intel_fb_scalable(plane_state->base.fb)) {
1593 if (INTEL_GEN(dev_priv) < 7) {
1595 max_scale = 16 << 16;
1596 } else if (IS_IVYBRIDGE(dev_priv)) {
1598 max_scale = 2 << 16;
1602 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1604 min_scale, max_scale,
1609 ret = i9xx_check_plane_surface(plane_state);
1613 if (!plane_state->base.visible)
1616 ret = intel_plane_check_src_coordinates(plane_state);
1620 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1624 if (INTEL_GEN(dev_priv) >= 7)
1625 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1627 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1632 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1634 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1635 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1636 unsigned int rotation = plane_state->base.rotation;
1638 /* CHV ignores the mirror bit when the rotate bit is set :( */
1639 if (IS_CHERRYVIEW(dev_priv) &&
1640 rotation & DRM_MODE_ROTATE_180 &&
1641 rotation & DRM_MODE_REFLECT_X) {
1642 DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
1650 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1651 struct intel_plane_state *plane_state)
1655 ret = chv_plane_check_rotation(plane_state);
1659 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1661 DRM_PLANE_HELPER_NO_SCALING,
1662 DRM_PLANE_HELPER_NO_SCALING,
1667 ret = i9xx_check_plane_surface(plane_state);
1671 if (!plane_state->base.visible)
1674 ret = intel_plane_check_src_coordinates(plane_state);
1678 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1683 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1684 const struct intel_plane_state *plane_state)
1686 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1687 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1688 const struct drm_framebuffer *fb = plane_state->base.fb;
1689 unsigned int rotation = plane_state->base.rotation;
1690 struct drm_format_name_buf format_name;
1695 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1696 is_ccs_modifier(fb->modifier)) {
1697 DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
1702 if (rotation & DRM_MODE_REFLECT_X &&
1703 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1704 DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
1708 if (drm_rotation_90_or_270(rotation)) {
1709 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
1710 fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
1711 DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
1716 * 90/270 is not allowed with RGB64 16:16:16:16 and
1717 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1719 switch (fb->format->format) {
1720 case DRM_FORMAT_RGB565:
1721 if (INTEL_GEN(dev_priv) >= 11)
1725 case DRM_FORMAT_XRGB16161616F:
1726 case DRM_FORMAT_XBGR16161616F:
1727 case DRM_FORMAT_ARGB16161616F:
1728 case DRM_FORMAT_ABGR16161616F:
1729 case DRM_FORMAT_Y210:
1730 case DRM_FORMAT_Y212:
1731 case DRM_FORMAT_Y216:
1732 case DRM_FORMAT_XVYU12_16161616:
1733 case DRM_FORMAT_XVYU16161616:
1734 DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
1735 drm_get_format_name(fb->format->format,
1743 /* Y-tiling is not supported in IF-ID Interlace mode */
1744 if (crtc_state->base.enable &&
1745 crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1746 (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1747 fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1748 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1749 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) {
1750 DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
1757 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1758 const struct intel_plane_state *plane_state)
1760 struct drm_i915_private *dev_priv =
1761 to_i915(plane_state->base.plane->dev);
1762 int crtc_x = plane_state->base.dst.x1;
1763 int crtc_w = drm_rect_width(&plane_state->base.dst);
1764 int pipe_src_w = crtc_state->pipe_src_w;
1767 * Display WA #1175: cnl,glk
1768 * Planes other than the cursor may cause FIFO underflow and display
1769 * corruption if starting less than 4 pixels from the right edge of
1771 * Besides the above WA fix the similar problem, where planes other
1772 * than the cursor ending less than 4 pixels from the left edge of the
1773 * screen may cause FIFO underflow and display corruption.
1775 if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
1776 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1777 DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
1778 crtc_x + crtc_w < 4 ? "end" : "start",
1779 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1787 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1789 const struct drm_framebuffer *fb = plane_state->base.fb;
1790 unsigned int rotation = plane_state->base.rotation;
1791 int src_w = drm_rect_width(&plane_state->base.src) >> 16;
1793 /* Display WA #1106 */
1794 if (is_planar_yuv_format(fb->format->format) && src_w & 3 &&
1795 (rotation == DRM_MODE_ROTATE_270 ||
1796 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1797 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1804 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1805 struct intel_plane_state *plane_state)
1807 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1808 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1809 const struct drm_framebuffer *fb = plane_state->base.fb;
1810 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1811 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1814 ret = skl_plane_check_fb(crtc_state, plane_state);
1818 /* use scaler when colorkey is not required */
1819 if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
1821 max_scale = skl_max_scale(crtc_state, fb->format->format);
1824 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1826 min_scale, max_scale,
1831 ret = skl_check_plane_surface(plane_state);
1835 if (!plane_state->base.visible)
1838 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1842 ret = intel_plane_check_src_coordinates(plane_state);
1846 ret = skl_plane_check_nv12_rotation(plane_state);
1850 /* HW only has 8 bits pixel precision, disable plane if invisible */
1851 if (!(plane_state->base.alpha >> 8))
1852 plane_state->base.visible = false;
1854 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1856 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1857 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1863 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1865 return INTEL_GEN(dev_priv) >= 9;
1868 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1869 const struct drm_intel_sprite_colorkey *set)
1871 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1872 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1873 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1878 * We want src key enabled on the
1879 * sprite and not on the primary.
1881 if (plane->id == PLANE_PRIMARY &&
1882 set->flags & I915_SET_COLORKEY_SOURCE)
1886 * On SKL+ we want dst key enabled on
1887 * the primary and not on the sprite.
1889 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1890 set->flags & I915_SET_COLORKEY_DESTINATION)
1894 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1895 struct drm_file *file_priv)
1897 struct drm_i915_private *dev_priv = to_i915(dev);
1898 struct drm_intel_sprite_colorkey *set = data;
1899 struct drm_plane *plane;
1900 struct drm_plane_state *plane_state;
1901 struct drm_atomic_state *state;
1902 struct drm_modeset_acquire_ctx ctx;
1905 /* ignore the pointless "none" flag */
1906 set->flags &= ~I915_SET_COLORKEY_NONE;
1908 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1911 /* Make sure we don't try to enable both src & dest simultaneously */
1912 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1915 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1916 set->flags & I915_SET_COLORKEY_DESTINATION)
1919 plane = drm_plane_find(dev, file_priv, set->plane_id);
1920 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1924 * SKL+ only plane 2 can do destination keying against plane 1.
1925 * Also multiple planes can't do destination keying on the same
1926 * pipe simultaneously.
1928 if (INTEL_GEN(dev_priv) >= 9 &&
1929 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1930 set->flags & I915_SET_COLORKEY_DESTINATION)
1933 drm_modeset_acquire_init(&ctx, 0);
1935 state = drm_atomic_state_alloc(plane->dev);
1940 state->acquire_ctx = &ctx;
1943 plane_state = drm_atomic_get_plane_state(state, plane);
1944 ret = PTR_ERR_OR_ZERO(plane_state);
1946 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1949 * On some platforms we have to configure
1950 * the dst colorkey on the primary plane.
1952 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1953 struct intel_crtc *crtc =
1954 intel_get_crtc_for_pipe(dev_priv,
1955 to_intel_plane(plane)->pipe);
1957 plane_state = drm_atomic_get_plane_state(state,
1958 crtc->base.primary);
1959 ret = PTR_ERR_OR_ZERO(plane_state);
1961 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1965 ret = drm_atomic_commit(state);
1967 if (ret != -EDEADLK)
1970 drm_atomic_state_clear(state);
1971 drm_modeset_backoff(&ctx);
1974 drm_atomic_state_put(state);
1976 drm_modeset_drop_locks(&ctx);
1977 drm_modeset_acquire_fini(&ctx);
1981 static const u32 g4x_plane_formats[] = {
1982 DRM_FORMAT_XRGB8888,
1989 static const u64 i9xx_plane_format_modifiers[] = {
1990 I915_FORMAT_MOD_X_TILED,
1991 DRM_FORMAT_MOD_LINEAR,
1992 DRM_FORMAT_MOD_INVALID
1995 static const u32 snb_plane_formats[] = {
1996 DRM_FORMAT_XBGR8888,
1997 DRM_FORMAT_XRGB8888,
2004 static const u32 vlv_plane_formats[] = {
2006 DRM_FORMAT_ABGR8888,
2007 DRM_FORMAT_ARGB8888,
2008 DRM_FORMAT_XBGR8888,
2009 DRM_FORMAT_XRGB8888,
2010 DRM_FORMAT_XBGR2101010,
2011 DRM_FORMAT_ABGR2101010,
2018 static const u32 skl_plane_formats[] = {
2021 DRM_FORMAT_XRGB8888,
2022 DRM_FORMAT_XBGR8888,
2023 DRM_FORMAT_ARGB8888,
2024 DRM_FORMAT_ABGR8888,
2025 DRM_FORMAT_XRGB2101010,
2026 DRM_FORMAT_XBGR2101010,
2033 static const u32 skl_planar_formats[] = {
2036 DRM_FORMAT_XRGB8888,
2037 DRM_FORMAT_XBGR8888,
2038 DRM_FORMAT_ARGB8888,
2039 DRM_FORMAT_ABGR8888,
2040 DRM_FORMAT_XRGB2101010,
2041 DRM_FORMAT_XBGR2101010,
2049 static const u32 glk_planar_formats[] = {
2052 DRM_FORMAT_XRGB8888,
2053 DRM_FORMAT_XBGR8888,
2054 DRM_FORMAT_ARGB8888,
2055 DRM_FORMAT_ABGR8888,
2056 DRM_FORMAT_XRGB2101010,
2057 DRM_FORMAT_XBGR2101010,
2068 static const u32 icl_sdr_y_plane_formats[] = {
2071 DRM_FORMAT_XRGB8888,
2072 DRM_FORMAT_XBGR8888,
2073 DRM_FORMAT_ARGB8888,
2074 DRM_FORMAT_ABGR8888,
2075 DRM_FORMAT_XRGB2101010,
2076 DRM_FORMAT_XBGR2101010,
2084 DRM_FORMAT_XVYU2101010,
2085 DRM_FORMAT_XVYU12_16161616,
2086 DRM_FORMAT_XVYU16161616,
2089 static const u32 icl_sdr_uv_plane_formats[] = {
2092 DRM_FORMAT_XRGB8888,
2093 DRM_FORMAT_XBGR8888,
2094 DRM_FORMAT_ARGB8888,
2095 DRM_FORMAT_ABGR8888,
2096 DRM_FORMAT_XRGB2101010,
2097 DRM_FORMAT_XBGR2101010,
2109 DRM_FORMAT_XVYU2101010,
2110 DRM_FORMAT_XVYU12_16161616,
2111 DRM_FORMAT_XVYU16161616,
2114 static const u32 icl_hdr_plane_formats[] = {
2117 DRM_FORMAT_XRGB8888,
2118 DRM_FORMAT_XBGR8888,
2119 DRM_FORMAT_ARGB8888,
2120 DRM_FORMAT_ABGR8888,
2121 DRM_FORMAT_XRGB2101010,
2122 DRM_FORMAT_XBGR2101010,
2123 DRM_FORMAT_XRGB16161616F,
2124 DRM_FORMAT_XBGR16161616F,
2125 DRM_FORMAT_ARGB16161616F,
2126 DRM_FORMAT_ABGR16161616F,
2138 DRM_FORMAT_XVYU2101010,
2139 DRM_FORMAT_XVYU12_16161616,
2140 DRM_FORMAT_XVYU16161616,
2143 static const u64 skl_plane_format_modifiers_noccs[] = {
2144 I915_FORMAT_MOD_Yf_TILED,
2145 I915_FORMAT_MOD_Y_TILED,
2146 I915_FORMAT_MOD_X_TILED,
2147 DRM_FORMAT_MOD_LINEAR,
2148 DRM_FORMAT_MOD_INVALID
2151 static const u64 skl_plane_format_modifiers_ccs[] = {
2152 I915_FORMAT_MOD_Yf_TILED_CCS,
2153 I915_FORMAT_MOD_Y_TILED_CCS,
2154 I915_FORMAT_MOD_Yf_TILED,
2155 I915_FORMAT_MOD_Y_TILED,
2156 I915_FORMAT_MOD_X_TILED,
2157 DRM_FORMAT_MOD_LINEAR,
2158 DRM_FORMAT_MOD_INVALID
2161 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
2162 u32 format, u64 modifier)
2165 case DRM_FORMAT_MOD_LINEAR:
2166 case I915_FORMAT_MOD_X_TILED:
2173 case DRM_FORMAT_XRGB8888:
2174 case DRM_FORMAT_YUYV:
2175 case DRM_FORMAT_YVYU:
2176 case DRM_FORMAT_UYVY:
2177 case DRM_FORMAT_VYUY:
2178 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2179 modifier == I915_FORMAT_MOD_X_TILED)
2187 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2188 u32 format, u64 modifier)
2191 case DRM_FORMAT_MOD_LINEAR:
2192 case I915_FORMAT_MOD_X_TILED:
2199 case DRM_FORMAT_XRGB8888:
2200 case DRM_FORMAT_XBGR8888:
2201 case DRM_FORMAT_YUYV:
2202 case DRM_FORMAT_YVYU:
2203 case DRM_FORMAT_UYVY:
2204 case DRM_FORMAT_VYUY:
2205 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2206 modifier == I915_FORMAT_MOD_X_TILED)
2214 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2215 u32 format, u64 modifier)
2218 case DRM_FORMAT_MOD_LINEAR:
2219 case I915_FORMAT_MOD_X_TILED:
2226 case DRM_FORMAT_RGB565:
2227 case DRM_FORMAT_ABGR8888:
2228 case DRM_FORMAT_ARGB8888:
2229 case DRM_FORMAT_XBGR8888:
2230 case DRM_FORMAT_XRGB8888:
2231 case DRM_FORMAT_XBGR2101010:
2232 case DRM_FORMAT_ABGR2101010:
2233 case DRM_FORMAT_YUYV:
2234 case DRM_FORMAT_YVYU:
2235 case DRM_FORMAT_UYVY:
2236 case DRM_FORMAT_VYUY:
2237 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2238 modifier == I915_FORMAT_MOD_X_TILED)
2246 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2247 u32 format, u64 modifier)
2249 struct intel_plane *plane = to_intel_plane(_plane);
2252 case DRM_FORMAT_MOD_LINEAR:
2253 case I915_FORMAT_MOD_X_TILED:
2254 case I915_FORMAT_MOD_Y_TILED:
2255 case I915_FORMAT_MOD_Yf_TILED:
2257 case I915_FORMAT_MOD_Y_TILED_CCS:
2258 case I915_FORMAT_MOD_Yf_TILED_CCS:
2259 if (!plane->has_ccs)
2267 case DRM_FORMAT_XRGB8888:
2268 case DRM_FORMAT_XBGR8888:
2269 case DRM_FORMAT_ARGB8888:
2270 case DRM_FORMAT_ABGR8888:
2271 if (is_ccs_modifier(modifier))
2274 case DRM_FORMAT_RGB565:
2275 case DRM_FORMAT_XRGB2101010:
2276 case DRM_FORMAT_XBGR2101010:
2277 case DRM_FORMAT_YUYV:
2278 case DRM_FORMAT_YVYU:
2279 case DRM_FORMAT_UYVY:
2280 case DRM_FORMAT_VYUY:
2281 case DRM_FORMAT_NV12:
2282 case DRM_FORMAT_P010:
2283 case DRM_FORMAT_P012:
2284 case DRM_FORMAT_P016:
2285 case DRM_FORMAT_XVYU2101010:
2286 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2290 case DRM_FORMAT_XBGR16161616F:
2291 case DRM_FORMAT_ABGR16161616F:
2292 case DRM_FORMAT_XRGB16161616F:
2293 case DRM_FORMAT_ARGB16161616F:
2294 case DRM_FORMAT_Y210:
2295 case DRM_FORMAT_Y212:
2296 case DRM_FORMAT_Y216:
2297 case DRM_FORMAT_XVYU12_16161616:
2298 case DRM_FORMAT_XVYU16161616:
2299 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2300 modifier == I915_FORMAT_MOD_X_TILED ||
2301 modifier == I915_FORMAT_MOD_Y_TILED)
2309 static const struct drm_plane_funcs g4x_sprite_funcs = {
2310 .update_plane = drm_atomic_helper_update_plane,
2311 .disable_plane = drm_atomic_helper_disable_plane,
2312 .destroy = intel_plane_destroy,
2313 .atomic_duplicate_state = intel_plane_duplicate_state,
2314 .atomic_destroy_state = intel_plane_destroy_state,
2315 .format_mod_supported = g4x_sprite_format_mod_supported,
2318 static const struct drm_plane_funcs snb_sprite_funcs = {
2319 .update_plane = drm_atomic_helper_update_plane,
2320 .disable_plane = drm_atomic_helper_disable_plane,
2321 .destroy = intel_plane_destroy,
2322 .atomic_duplicate_state = intel_plane_duplicate_state,
2323 .atomic_destroy_state = intel_plane_destroy_state,
2324 .format_mod_supported = snb_sprite_format_mod_supported,
2327 static const struct drm_plane_funcs vlv_sprite_funcs = {
2328 .update_plane = drm_atomic_helper_update_plane,
2329 .disable_plane = drm_atomic_helper_disable_plane,
2330 .destroy = intel_plane_destroy,
2331 .atomic_duplicate_state = intel_plane_duplicate_state,
2332 .atomic_destroy_state = intel_plane_destroy_state,
2333 .format_mod_supported = vlv_sprite_format_mod_supported,
2336 static const struct drm_plane_funcs skl_plane_funcs = {
2337 .update_plane = drm_atomic_helper_update_plane,
2338 .disable_plane = drm_atomic_helper_disable_plane,
2339 .destroy = intel_plane_destroy,
2340 .atomic_duplicate_state = intel_plane_duplicate_state,
2341 .atomic_destroy_state = intel_plane_destroy_state,
2342 .format_mod_supported = skl_plane_format_mod_supported,
2345 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2346 enum pipe pipe, enum plane_id plane_id)
2348 if (!HAS_FBC(dev_priv))
2351 return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2354 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2355 enum pipe pipe, enum plane_id plane_id)
2357 /* Display WA #0870: skl, bxt */
2358 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2361 if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2364 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2370 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2371 enum pipe pipe, enum plane_id plane_id,
2374 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2375 *num_formats = ARRAY_SIZE(skl_planar_formats);
2376 return skl_planar_formats;
2378 *num_formats = ARRAY_SIZE(skl_plane_formats);
2379 return skl_plane_formats;
2383 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
2384 enum pipe pipe, enum plane_id plane_id,
2387 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2388 *num_formats = ARRAY_SIZE(glk_planar_formats);
2389 return glk_planar_formats;
2391 *num_formats = ARRAY_SIZE(skl_plane_formats);
2392 return skl_plane_formats;
2396 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
2397 enum pipe pipe, enum plane_id plane_id,
2400 if (icl_is_hdr_plane(dev_priv, plane_id)) {
2401 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2402 return icl_hdr_plane_formats;
2403 } else if (icl_is_nv12_y_plane(plane_id)) {
2404 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2405 return icl_sdr_y_plane_formats;
2407 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2408 return icl_sdr_uv_plane_formats;
2412 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
2413 enum pipe pipe, enum plane_id plane_id)
2415 if (plane_id == PLANE_CURSOR)
2418 if (INTEL_GEN(dev_priv) >= 10)
2421 if (IS_GEMINILAKE(dev_priv))
2422 return pipe != PIPE_C;
2424 return pipe != PIPE_C &&
2425 (plane_id == PLANE_PRIMARY ||
2426 plane_id == PLANE_SPRITE0);
2429 struct intel_plane *
2430 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2431 enum pipe pipe, enum plane_id plane_id)
2433 struct intel_plane *plane;
2434 enum drm_plane_type plane_type;
2435 unsigned int supported_rotations;
2436 unsigned int possible_crtcs;
2437 const u64 *modifiers;
2442 plane = intel_plane_alloc();
2447 plane->id = plane_id;
2448 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2450 plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2451 if (plane->has_fbc) {
2452 struct intel_fbc *fbc = &dev_priv->fbc;
2454 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2457 plane->max_stride = skl_plane_max_stride;
2458 plane->update_plane = skl_update_plane;
2459 plane->disable_plane = skl_disable_plane;
2460 plane->get_hw_state = skl_plane_get_hw_state;
2461 plane->check_plane = skl_plane_check;
2462 if (icl_is_nv12_y_plane(plane_id))
2463 plane->update_slave = icl_update_slave;
2465 if (INTEL_GEN(dev_priv) >= 11)
2466 formats = icl_get_plane_formats(dev_priv, pipe,
2467 plane_id, &num_formats);
2468 else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2469 formats = glk_get_plane_formats(dev_priv, pipe,
2470 plane_id, &num_formats);
2472 formats = skl_get_plane_formats(dev_priv, pipe,
2473 plane_id, &num_formats);
2475 plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2477 modifiers = skl_plane_format_modifiers_ccs;
2479 modifiers = skl_plane_format_modifiers_noccs;
2481 if (plane_id == PLANE_PRIMARY)
2482 plane_type = DRM_PLANE_TYPE_PRIMARY;
2484 plane_type = DRM_PLANE_TYPE_OVERLAY;
2486 possible_crtcs = BIT(pipe);
2488 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2489 possible_crtcs, &skl_plane_funcs,
2490 formats, num_formats, modifiers,
2492 "plane %d%c", plane_id + 1,
2497 supported_rotations =
2498 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2499 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2501 if (INTEL_GEN(dev_priv) >= 10)
2502 supported_rotations |= DRM_MODE_REFLECT_X;
2504 drm_plane_create_rotation_property(&plane->base,
2506 supported_rotations);
2508 drm_plane_create_color_properties(&plane->base,
2509 BIT(DRM_COLOR_YCBCR_BT601) |
2510 BIT(DRM_COLOR_YCBCR_BT709),
2511 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2512 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2513 DRM_COLOR_YCBCR_BT709,
2514 DRM_COLOR_YCBCR_LIMITED_RANGE);
2516 drm_plane_create_alpha_property(&plane->base);
2517 drm_plane_create_blend_mode_property(&plane->base,
2518 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2519 BIT(DRM_MODE_BLEND_PREMULTI) |
2520 BIT(DRM_MODE_BLEND_COVERAGE));
2522 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2527 intel_plane_free(plane);
2529 return ERR_PTR(ret);
2532 struct intel_plane *
2533 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
2534 enum pipe pipe, int sprite)
2536 struct intel_plane *plane;
2537 const struct drm_plane_funcs *plane_funcs;
2538 unsigned long possible_crtcs;
2539 unsigned int supported_rotations;
2540 const u64 *modifiers;
2545 if (INTEL_GEN(dev_priv) >= 9)
2546 return skl_universal_plane_create(dev_priv, pipe,
2547 PLANE_SPRITE0 + sprite);
2549 plane = intel_plane_alloc();
2553 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
2554 plane->max_stride = i9xx_plane_max_stride;
2555 plane->update_plane = vlv_update_plane;
2556 plane->disable_plane = vlv_disable_plane;
2557 plane->get_hw_state = vlv_plane_get_hw_state;
2558 plane->check_plane = vlv_sprite_check;
2560 formats = vlv_plane_formats;
2561 num_formats = ARRAY_SIZE(vlv_plane_formats);
2562 modifiers = i9xx_plane_format_modifiers;
2564 plane_funcs = &vlv_sprite_funcs;
2565 } else if (INTEL_GEN(dev_priv) >= 7) {
2566 plane->max_stride = g4x_sprite_max_stride;
2567 plane->update_plane = ivb_update_plane;
2568 plane->disable_plane = ivb_disable_plane;
2569 plane->get_hw_state = ivb_plane_get_hw_state;
2570 plane->check_plane = g4x_sprite_check;
2572 formats = snb_plane_formats;
2573 num_formats = ARRAY_SIZE(snb_plane_formats);
2574 modifiers = i9xx_plane_format_modifiers;
2576 plane_funcs = &snb_sprite_funcs;
2578 plane->max_stride = g4x_sprite_max_stride;
2579 plane->update_plane = g4x_update_plane;
2580 plane->disable_plane = g4x_disable_plane;
2581 plane->get_hw_state = g4x_plane_get_hw_state;
2582 plane->check_plane = g4x_sprite_check;
2584 modifiers = i9xx_plane_format_modifiers;
2585 if (IS_GEN(dev_priv, 6)) {
2586 formats = snb_plane_formats;
2587 num_formats = ARRAY_SIZE(snb_plane_formats);
2589 plane_funcs = &snb_sprite_funcs;
2591 formats = g4x_plane_formats;
2592 num_formats = ARRAY_SIZE(g4x_plane_formats);
2594 plane_funcs = &g4x_sprite_funcs;
2598 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
2599 supported_rotations =
2600 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
2603 supported_rotations =
2604 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2608 plane->id = PLANE_SPRITE0 + sprite;
2609 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
2611 possible_crtcs = BIT(pipe);
2613 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2614 possible_crtcs, plane_funcs,
2615 formats, num_formats, modifiers,
2616 DRM_PLANE_TYPE_OVERLAY,
2617 "sprite %c", sprite_name(pipe, sprite));
2621 drm_plane_create_rotation_property(&plane->base,
2623 supported_rotations);
2625 drm_plane_create_color_properties(&plane->base,
2626 BIT(DRM_COLOR_YCBCR_BT601) |
2627 BIT(DRM_COLOR_YCBCR_BT709),
2628 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2629 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2630 DRM_COLOR_YCBCR_BT709,
2631 DRM_COLOR_YCBCR_LIMITED_RANGE);
2633 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2638 intel_plane_free(plane);
2640 return ERR_PTR(ret);