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
32 #include <drm/drm_atomic_helper.h>
33 #include <drm/drm_crtc.h>
34 #include <drm/drm_fourcc.h>
35 #include <drm/drm_rect.h>
36 #include <drm/drm_atomic.h>
37 #include <drm/drm_plane_helper.h>
38 #include "intel_drv.h"
39 #include "intel_frontbuffer.h"
40 #include <drm/i915_drm.h>
42 #include <drm/drm_color_mgmt.h>
44 bool is_planar_yuv_format(u32 pixelformat)
46 switch (pixelformat) {
57 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
61 if (!adjusted_mode->crtc_htotal)
64 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
65 1000 * adjusted_mode->crtc_htotal);
68 /* FIXME: We should instead only take spinlocks once for the entire update
69 * instead of once per mmio. */
70 #if IS_ENABLED(CONFIG_PROVE_LOCKING)
71 #define VBLANK_EVASION_TIME_US 250
73 #define VBLANK_EVASION_TIME_US 100
77 * intel_pipe_update_start() - start update of a set of display registers
78 * @new_crtc_state: the new crtc state
80 * Mark the start of an update to pipe registers that should be updated
81 * atomically regarding vblank. If the next vblank will happens within
82 * the next 100 us, this function waits until the vblank passes.
84 * After a successful call to this function, interrupts will be disabled
85 * until a subsequent call to intel_pipe_update_end(). That is done to
86 * avoid random delays.
88 void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
90 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
91 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
92 const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
93 long timeout = msecs_to_jiffies_timeout(1);
94 int scanline, min, max, vblank_start;
95 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
96 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
97 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
101 vblank_start = adjusted_mode->crtc_vblank_start;
102 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
103 vblank_start = DIV_ROUND_UP(vblank_start, 2);
105 /* FIXME needs to be calibrated sensibly */
106 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
107 VBLANK_EVASION_TIME_US);
108 max = vblank_start - 1;
110 if (min <= 0 || max <= 0)
113 if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
117 * Wait for psr to idle out after enabling the VBL interrupts
118 * VBL interrupts will start the PSR exit and prevent a PSR
121 if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
122 DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
127 crtc->debug.min_vbl = min;
128 crtc->debug.max_vbl = max;
129 trace_i915_pipe_update_start(crtc);
133 * prepare_to_wait() has a memory barrier, which guarantees
134 * other CPUs can see the task state update by the time we
137 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
139 scanline = intel_get_crtc_scanline(crtc);
140 if (scanline < min || scanline > max)
144 DRM_ERROR("Potential atomic update failure on pipe %c\n",
145 pipe_name(crtc->pipe));
151 timeout = schedule_timeout(timeout);
156 finish_wait(wq, &wait);
158 drm_crtc_vblank_put(&crtc->base);
161 * On VLV/CHV DSI the scanline counter would appear to
162 * increment approx. 1/3 of a scanline before start of vblank.
163 * The registers still get latched at start of vblank however.
164 * This means we must not write any registers on the first
165 * line of vblank (since not the whole line is actually in
166 * vblank). And unfortunately we can't use the interrupt to
167 * wait here since it will fire too soon. We could use the
168 * frame start interrupt instead since it will fire after the
169 * critical scanline, but that would require more changes
170 * in the interrupt code. So for now we'll just do the nasty
171 * thing and poll for the bad scanline to pass us by.
173 * FIXME figure out if BXT+ DSI suffers from this as well
175 while (need_vlv_dsi_wa && scanline == vblank_start)
176 scanline = intel_get_crtc_scanline(crtc);
178 crtc->debug.scanline_start = scanline;
179 crtc->debug.start_vbl_time = ktime_get();
180 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
182 trace_i915_pipe_update_vblank_evaded(crtc);
190 * intel_pipe_update_end() - end update of a set of display registers
191 * @new_crtc_state: the new crtc state
193 * Mark the end of an update started with intel_pipe_update_start(). This
194 * re-enables interrupts and verifies the update was actually completed
197 void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
199 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
200 enum pipe pipe = crtc->pipe;
201 int scanline_end = intel_get_crtc_scanline(crtc);
202 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
203 ktime_t end_vbl_time = ktime_get();
204 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
206 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
208 /* We're still in the vblank-evade critical section, this can't race.
209 * Would be slightly nice to just grab the vblank count and arm the
210 * event outside of the critical section - the spinlock might spin for a
212 if (new_crtc_state->base.event) {
213 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
215 spin_lock(&crtc->base.dev->event_lock);
216 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
217 spin_unlock(&crtc->base.dev->event_lock);
219 new_crtc_state->base.event = NULL;
224 if (intel_vgpu_active(dev_priv))
227 if (crtc->debug.start_vbl_count &&
228 crtc->debug.start_vbl_count != end_vbl_count) {
229 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",
230 pipe_name(pipe), crtc->debug.start_vbl_count,
232 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
233 crtc->debug.min_vbl, crtc->debug.max_vbl,
234 crtc->debug.scanline_start, scanline_end);
236 #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
237 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
238 VBLANK_EVASION_TIME_US)
239 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
241 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
242 VBLANK_EVASION_TIME_US);
246 int intel_plane_check_stride(const struct intel_plane_state *plane_state)
248 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
249 const struct drm_framebuffer *fb = plane_state->base.fb;
250 unsigned int rotation = plane_state->base.rotation;
251 u32 stride, max_stride;
253 /* FIXME other color planes? */
254 stride = plane_state->color_plane[0].stride;
255 max_stride = plane->max_stride(plane, fb->format->format,
256 fb->modifier, rotation);
258 if (stride > max_stride) {
259 DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
261 plane->base.base.id, plane->base.name, max_stride);
268 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
270 const struct drm_framebuffer *fb = plane_state->base.fb;
271 struct drm_rect *src = &plane_state->base.src;
272 u32 src_x, src_y, src_w, src_h, hsub, vsub;
273 bool rotated = drm_rotation_90_or_270(plane_state->base.rotation);
276 * Hardware doesn't handle subpixel coordinates.
277 * Adjust to (macro)pixel boundary, but be careful not to
278 * increase the source viewport size, because that could
279 * push the downscaling factor out of bounds.
281 src_x = src->x1 >> 16;
282 src_w = drm_rect_width(src) >> 16;
283 src_y = src->y1 >> 16;
284 src_h = drm_rect_height(src) >> 16;
286 src->x1 = src_x << 16;
287 src->x2 = (src_x + src_w) << 16;
288 src->y1 = src_y << 16;
289 src->y2 = (src_y + src_h) << 16;
291 if (!fb->format->is_yuv)
294 /* YUV specific checks */
296 hsub = fb->format->hsub;
297 vsub = fb->format->vsub;
299 hsub = vsub = max(fb->format->hsub, fb->format->vsub);
302 if (src_x % hsub || src_w % hsub) {
303 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
304 src_x, src_w, hsub, rotated ? "rotated " : "");
308 if (src_y % vsub || src_h % vsub) {
309 DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
310 src_y, src_h, vsub, rotated ? "rotated " : "");
318 skl_plane_max_stride(struct intel_plane *plane,
319 u32 pixel_format, u64 modifier,
320 unsigned int rotation)
322 int cpp = drm_format_plane_cpp(pixel_format, 0);
325 * "The stride in bytes must not exceed the
326 * of the size of 8K pixels and 32K bytes."
328 if (drm_rotation_90_or_270(rotation))
329 return min(8192, 32768 / cpp);
331 return min(8192 * cpp, 32768);
335 skl_program_scaler(struct intel_plane *plane,
336 const struct intel_crtc_state *crtc_state,
337 const struct intel_plane_state *plane_state)
339 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
340 enum pipe pipe = plane->pipe;
341 int scaler_id = plane_state->scaler_id;
342 const struct intel_scaler *scaler =
343 &crtc_state->scaler_state.scalers[scaler_id];
344 int crtc_x = plane_state->base.dst.x1;
345 int crtc_y = plane_state->base.dst.y1;
346 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
347 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
348 u16 y_hphase, uv_rgb_hphase;
349 u16 y_vphase, uv_rgb_vphase;
352 hscale = drm_rect_calc_hscale(&plane_state->base.src,
353 &plane_state->base.dst,
355 vscale = drm_rect_calc_vscale(&plane_state->base.src,
356 &plane_state->base.dst,
359 /* TODO: handle sub-pixel coordinates */
360 if (is_planar_yuv_format(plane_state->base.fb->format->format) &&
361 !icl_is_hdr_plane(dev_priv, plane->id)) {
362 y_hphase = skl_scaler_calc_phase(1, hscale, false);
363 y_vphase = skl_scaler_calc_phase(1, vscale, false);
365 /* MPEG2 chroma siting convention */
366 uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
367 uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
373 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
374 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
377 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
378 PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
379 I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
380 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
381 I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
382 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
383 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
384 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
387 /* Preoffset values for YUV to RGB Conversion */
388 #define PREOFF_YUV_TO_RGB_HI 0x1800
389 #define PREOFF_YUV_TO_RGB_ME 0x1F00
390 #define PREOFF_YUV_TO_RGB_LO 0x1800
392 #define ROFF(x) (((x) & 0xffff) << 16)
393 #define GOFF(x) (((x) & 0xffff) << 0)
394 #define BOFF(x) (((x) & 0xffff) << 16)
397 icl_program_input_csc(struct intel_plane *plane,
398 const struct intel_crtc_state *crtc_state,
399 const struct intel_plane_state *plane_state)
401 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
402 enum pipe pipe = plane->pipe;
403 enum plane_id plane_id = plane->id;
405 static const u16 input_csc_matrix[][9] = {
407 * BT.601 full range YCbCr -> full range RGB
408 * The matrix required is :
409 * [1.000, 0.000, 1.371,
410 * 1.000, -0.336, -0.698,
411 * 1.000, 1.732, 0.0000]
413 [DRM_COLOR_YCBCR_BT601] = {
415 0x8B28, 0x7800, 0x9AC0,
419 * BT.709 full range YCbCr -> full range RGB
420 * The matrix required is :
421 * [1.000, 0.000, 1.574,
422 * 1.000, -0.187, -0.468,
423 * 1.000, 1.855, 0.0000]
425 [DRM_COLOR_YCBCR_BT709] = {
427 0x9EF8, 0x7800, 0xABF8,
432 /* Matrix for Limited Range to Full Range Conversion */
433 static const u16 input_csc_matrix_lr[][9] = {
435 * BT.601 Limted range YCbCr -> full range RGB
436 * The matrix required is :
437 * [1.164384, 0.000, 1.596370,
438 * 1.138393, -0.382500, -0.794598,
439 * 1.138393, 1.971696, 0.0000]
441 [DRM_COLOR_YCBCR_BT601] = {
443 0x8CB8, 0x7918, 0x9C40,
447 * BT.709 Limited range YCbCr -> full range RGB
448 * The matrix required is :
449 * [1.164, 0.000, 1.833671,
450 * 1.138393, -0.213249, -0.532909,
451 * 1.138393, 2.112402, 0.0000]
453 [DRM_COLOR_YCBCR_BT709] = {
455 0x8888, 0x7918, 0xADA8,
461 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
462 csc = input_csc_matrix[plane_state->base.color_encoding];
464 csc = input_csc_matrix_lr[plane_state->base.color_encoding];
466 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
468 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
469 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
471 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
472 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
474 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));
476 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
477 PREOFF_YUV_TO_RGB_HI);
478 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
479 PREOFF_YUV_TO_RGB_ME);
480 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
481 PREOFF_YUV_TO_RGB_LO);
482 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
483 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
484 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
488 skl_program_plane(struct intel_plane *plane,
489 const struct intel_crtc_state *crtc_state,
490 const struct intel_plane_state *plane_state,
491 int color_plane, bool slave, u32 plane_ctl)
493 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
494 enum plane_id plane_id = plane->id;
495 enum pipe pipe = plane->pipe;
496 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
497 u32 surf_addr = plane_state->color_plane[color_plane].offset;
498 u32 stride = skl_plane_stride(plane_state, color_plane);
499 u32 aux_stride = skl_plane_stride(plane_state, 1);
500 int crtc_x = plane_state->base.dst.x1;
501 int crtc_y = plane_state->base.dst.y1;
502 u32 x = plane_state->color_plane[color_plane].x;
503 u32 y = plane_state->color_plane[color_plane].y;
504 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
505 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
506 struct intel_plane *linked = plane_state->linked_plane;
507 const struct drm_framebuffer *fb = plane_state->base.fb;
508 u8 alpha = plane_state->base.alpha >> 8;
509 u32 plane_color_ctl = 0;
510 unsigned long irqflags;
513 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
515 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
516 plane_color_ctl = plane_state->color_ctl |
517 glk_plane_color_ctl_crtc(crtc_state);
519 /* Sizes are 0 based */
523 keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
525 keymsk = key->channel_mask & 0x7ffffff;
527 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
529 /* The scaler will handle the output position */
530 if (plane_state->scaler_id >= 0) {
535 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
537 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
538 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
539 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
540 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
541 (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
543 if (icl_is_hdr_plane(dev_priv, plane_id)) {
547 /* Enable and use MPEG-2 chroma siting */
548 cus_ctl = PLANE_CUS_ENABLE |
550 PLANE_CUS_VPHASE_SIGN_NEGATIVE |
551 PLANE_CUS_VPHASE_0_25;
553 if (linked->id == PLANE_SPRITE5)
554 cus_ctl |= PLANE_CUS_PLANE_7;
555 else if (linked->id == PLANE_SPRITE4)
556 cus_ctl |= PLANE_CUS_PLANE_6;
558 MISSING_CASE(linked->id);
561 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), cus_ctl);
564 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
565 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
567 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
568 icl_program_input_csc(plane, crtc_state, plane_state);
570 skl_write_plane_wm(plane, crtc_state);
572 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
573 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
574 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
576 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
578 if (INTEL_GEN(dev_priv) < 11)
579 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
580 (plane_state->color_plane[1].y << 16) |
581 plane_state->color_plane[1].x);
584 * The control register self-arms if the plane was previously
585 * disabled. Try to make the plane enable atomic by writing
586 * the control register just before the surface register.
588 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
589 I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
590 intel_plane_ggtt_offset(plane_state) + surf_addr);
592 if (!slave && plane_state->scaler_id >= 0)
593 skl_program_scaler(plane, crtc_state, plane_state);
595 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
599 skl_update_plane(struct intel_plane *plane,
600 const struct intel_crtc_state *crtc_state,
601 const struct intel_plane_state *plane_state)
605 if (plane_state->linked_plane) {
606 /* Program the UV plane */
610 skl_program_plane(plane, crtc_state, plane_state,
611 color_plane, false, plane_state->ctl);
615 icl_update_slave(struct intel_plane *plane,
616 const struct intel_crtc_state *crtc_state,
617 const struct intel_plane_state *plane_state)
619 skl_program_plane(plane, crtc_state, plane_state, 0, true,
620 plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);
624 skl_disable_plane(struct intel_plane *plane,
625 const struct intel_crtc_state *crtc_state)
627 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
628 enum plane_id plane_id = plane->id;
629 enum pipe pipe = plane->pipe;
630 unsigned long irqflags;
632 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
634 if (icl_is_hdr_plane(dev_priv, plane_id))
635 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);
637 skl_write_plane_wm(plane, crtc_state);
639 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
640 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
642 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
646 skl_plane_get_hw_state(struct intel_plane *plane,
649 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
650 enum intel_display_power_domain power_domain;
651 enum plane_id plane_id = plane->id;
652 intel_wakeref_t wakeref;
655 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
656 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
660 ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
664 intel_display_power_put(dev_priv, power_domain, wakeref);
670 chv_update_csc(const struct intel_plane_state *plane_state)
672 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
673 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
674 const struct drm_framebuffer *fb = plane_state->base.fb;
675 enum plane_id plane_id = plane->id;
677 * |r| | c0 c1 c2 | |cr|
678 * |g| = | c3 c4 c5 | x |y |
679 * |b| | c6 c7 c8 | |cb|
681 * Coefficients are s3.12.
683 * Cb and Cr apparently come in as signed already, and
684 * we always get full range data in on account of CLRC0/1.
686 static const s16 csc_matrix[][9] = {
687 /* BT.601 full range YCbCr -> full range RGB */
688 [DRM_COLOR_YCBCR_BT601] = {
693 /* BT.709 full range YCbCr -> full range RGB */
694 [DRM_COLOR_YCBCR_BT709] = {
700 const s16 *csc = csc_matrix[plane_state->base.color_encoding];
702 /* Seems RGB data bypasses the CSC always */
703 if (!fb->format->is_yuv)
706 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
707 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
708 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
710 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
711 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
712 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
713 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
714 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
716 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
717 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
718 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
720 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
721 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
722 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
729 vlv_update_clrc(const struct intel_plane_state *plane_state)
731 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
732 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
733 const struct drm_framebuffer *fb = plane_state->base.fb;
734 enum pipe pipe = plane->pipe;
735 enum plane_id plane_id = plane->id;
736 int contrast, brightness, sh_scale, sh_sin, sh_cos;
738 if (fb->format->is_yuv &&
739 plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
741 * Expand limited range to full range:
742 * Contrast is applied first and is used to expand Y range.
743 * Brightness is applied second and is used to remove the
744 * offset from Y. Saturation/hue is used to expand CbCr range.
746 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
747 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
748 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
749 sh_sin = SIN_0 * sh_scale;
750 sh_cos = COS_0 * sh_scale;
752 /* Pass-through everything. */
756 sh_sin = SIN_0 * sh_scale;
757 sh_cos = COS_0 * sh_scale;
760 /* FIXME these register are single buffered :( */
761 I915_WRITE_FW(SPCLRC0(pipe, plane_id),
762 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
763 I915_WRITE_FW(SPCLRC1(pipe, plane_id),
764 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
767 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
771 if (crtc_state->gamma_enable)
772 sprctl |= SP_GAMMA_ENABLE;
777 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
778 const struct intel_plane_state *plane_state)
780 const struct drm_framebuffer *fb = plane_state->base.fb;
781 unsigned int rotation = plane_state->base.rotation;
782 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
787 switch (fb->format->format) {
788 case DRM_FORMAT_YUYV:
789 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
791 case DRM_FORMAT_YVYU:
792 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
794 case DRM_FORMAT_UYVY:
795 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
797 case DRM_FORMAT_VYUY:
798 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
800 case DRM_FORMAT_RGB565:
801 sprctl |= SP_FORMAT_BGR565;
803 case DRM_FORMAT_XRGB8888:
804 sprctl |= SP_FORMAT_BGRX8888;
806 case DRM_FORMAT_ARGB8888:
807 sprctl |= SP_FORMAT_BGRA8888;
809 case DRM_FORMAT_XBGR2101010:
810 sprctl |= SP_FORMAT_RGBX1010102;
812 case DRM_FORMAT_ABGR2101010:
813 sprctl |= SP_FORMAT_RGBA1010102;
815 case DRM_FORMAT_XBGR8888:
816 sprctl |= SP_FORMAT_RGBX8888;
818 case DRM_FORMAT_ABGR8888:
819 sprctl |= SP_FORMAT_RGBA8888;
822 MISSING_CASE(fb->format->format);
826 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
827 sprctl |= SP_YUV_FORMAT_BT709;
829 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
832 if (rotation & DRM_MODE_ROTATE_180)
833 sprctl |= SP_ROTATE_180;
835 if (rotation & DRM_MODE_REFLECT_X)
838 if (key->flags & I915_SET_COLORKEY_SOURCE)
839 sprctl |= SP_SOURCE_KEY;
845 vlv_update_plane(struct intel_plane *plane,
846 const struct intel_crtc_state *crtc_state,
847 const struct intel_plane_state *plane_state)
849 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
850 enum pipe pipe = plane->pipe;
851 enum plane_id plane_id = plane->id;
852 u32 sprsurf_offset = plane_state->color_plane[0].offset;
854 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
855 int crtc_x = plane_state->base.dst.x1;
856 int crtc_y = plane_state->base.dst.y1;
857 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
858 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
859 u32 x = plane_state->color_plane[0].x;
860 u32 y = plane_state->color_plane[0].y;
861 unsigned long irqflags;
864 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
866 /* Sizes are 0 based */
870 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
872 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
874 I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
875 plane_state->color_plane[0].stride);
876 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
877 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
878 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
880 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
881 chv_update_csc(plane_state);
884 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
885 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
886 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
889 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
890 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
893 * The control register self-arms if the plane was previously
894 * disabled. Try to make the plane enable atomic by writing
895 * the control register just before the surface register.
897 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
898 I915_WRITE_FW(SPSURF(pipe, plane_id),
899 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
901 vlv_update_clrc(plane_state);
903 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
907 vlv_disable_plane(struct intel_plane *plane,
908 const struct intel_crtc_state *crtc_state)
910 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
911 enum pipe pipe = plane->pipe;
912 enum plane_id plane_id = plane->id;
913 unsigned long irqflags;
915 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
917 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
918 I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
920 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
924 vlv_plane_get_hw_state(struct intel_plane *plane,
927 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
928 enum intel_display_power_domain power_domain;
929 enum plane_id plane_id = plane->id;
930 intel_wakeref_t wakeref;
933 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
934 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
938 ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
942 intel_display_power_put(dev_priv, power_domain, wakeref);
947 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
951 if (crtc_state->gamma_enable)
952 sprctl |= SPRITE_GAMMA_ENABLE;
954 if (crtc_state->csc_enable)
955 sprctl |= SPRITE_PIPE_CSC_ENABLE;
960 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
961 const struct intel_plane_state *plane_state)
963 struct drm_i915_private *dev_priv =
964 to_i915(plane_state->base.plane->dev);
965 const struct drm_framebuffer *fb = plane_state->base.fb;
966 unsigned int rotation = plane_state->base.rotation;
967 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
970 sprctl = SPRITE_ENABLE;
972 if (IS_IVYBRIDGE(dev_priv))
973 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
975 switch (fb->format->format) {
976 case DRM_FORMAT_XBGR8888:
977 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
979 case DRM_FORMAT_XRGB8888:
980 sprctl |= SPRITE_FORMAT_RGBX888;
982 case DRM_FORMAT_YUYV:
983 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
985 case DRM_FORMAT_YVYU:
986 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
988 case DRM_FORMAT_UYVY:
989 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
991 case DRM_FORMAT_VYUY:
992 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
995 MISSING_CASE(fb->format->format);
999 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1000 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1002 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1003 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1005 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1006 sprctl |= SPRITE_TILED;
1008 if (rotation & DRM_MODE_ROTATE_180)
1009 sprctl |= SPRITE_ROTATE_180;
1011 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1012 sprctl |= SPRITE_DEST_KEY;
1013 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1014 sprctl |= SPRITE_SOURCE_KEY;
1020 ivb_update_plane(struct intel_plane *plane,
1021 const struct intel_crtc_state *crtc_state,
1022 const struct intel_plane_state *plane_state)
1024 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1025 enum pipe pipe = plane->pipe;
1026 u32 sprsurf_offset = plane_state->color_plane[0].offset;
1028 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1029 int crtc_x = plane_state->base.dst.x1;
1030 int crtc_y = plane_state->base.dst.y1;
1031 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1032 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1033 u32 x = plane_state->color_plane[0].x;
1034 u32 y = plane_state->color_plane[0].y;
1035 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1036 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1037 u32 sprctl, sprscale = 0;
1038 unsigned long irqflags;
1040 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1042 /* Sizes are 0 based */
1048 if (crtc_w != src_w || crtc_h != src_h)
1049 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1051 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1053 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1055 I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
1056 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1057 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1058 if (IS_IVYBRIDGE(dev_priv))
1059 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
1062 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
1063 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1064 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1067 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1069 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1070 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1072 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1073 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1077 * The control register self-arms if the plane was previously
1078 * disabled. Try to make the plane enable atomic by writing
1079 * the control register just before the surface register.
1081 I915_WRITE_FW(SPRCTL(pipe), sprctl);
1082 I915_WRITE_FW(SPRSURF(pipe),
1083 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1085 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1089 ivb_disable_plane(struct intel_plane *plane,
1090 const struct intel_crtc_state *crtc_state)
1092 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1093 enum pipe pipe = plane->pipe;
1094 unsigned long irqflags;
1096 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1098 I915_WRITE_FW(SPRCTL(pipe), 0);
1099 /* Disable the scaler */
1100 if (IS_IVYBRIDGE(dev_priv))
1101 I915_WRITE_FW(SPRSCALE(pipe), 0);
1102 I915_WRITE_FW(SPRSURF(pipe), 0);
1104 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1108 ivb_plane_get_hw_state(struct intel_plane *plane,
1111 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1112 enum intel_display_power_domain power_domain;
1113 intel_wakeref_t wakeref;
1116 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1117 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1121 ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1123 *pipe = plane->pipe;
1125 intel_display_power_put(dev_priv, power_domain, wakeref);
1131 g4x_sprite_max_stride(struct intel_plane *plane,
1132 u32 pixel_format, u64 modifier,
1133 unsigned int rotation)
1138 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1142 if (crtc_state->gamma_enable)
1143 dvscntr |= DVS_GAMMA_ENABLE;
1145 if (crtc_state->csc_enable)
1146 dvscntr |= DVS_PIPE_CSC_ENABLE;
1151 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1152 const struct intel_plane_state *plane_state)
1154 struct drm_i915_private *dev_priv =
1155 to_i915(plane_state->base.plane->dev);
1156 const struct drm_framebuffer *fb = plane_state->base.fb;
1157 unsigned int rotation = plane_state->base.rotation;
1158 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1161 dvscntr = DVS_ENABLE;
1163 if (IS_GEN(dev_priv, 6))
1164 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1166 switch (fb->format->format) {
1167 case DRM_FORMAT_XBGR8888:
1168 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1170 case DRM_FORMAT_XRGB8888:
1171 dvscntr |= DVS_FORMAT_RGBX888;
1173 case DRM_FORMAT_YUYV:
1174 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1176 case DRM_FORMAT_YVYU:
1177 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1179 case DRM_FORMAT_UYVY:
1180 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1182 case DRM_FORMAT_VYUY:
1183 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1186 MISSING_CASE(fb->format->format);
1190 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1191 dvscntr |= DVS_YUV_FORMAT_BT709;
1193 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1194 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1196 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1197 dvscntr |= DVS_TILED;
1199 if (rotation & DRM_MODE_ROTATE_180)
1200 dvscntr |= DVS_ROTATE_180;
1202 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1203 dvscntr |= DVS_DEST_KEY;
1204 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1205 dvscntr |= DVS_SOURCE_KEY;
1211 g4x_update_plane(struct intel_plane *plane,
1212 const struct intel_crtc_state *crtc_state,
1213 const struct intel_plane_state *plane_state)
1215 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1216 enum pipe pipe = plane->pipe;
1217 u32 dvssurf_offset = plane_state->color_plane[0].offset;
1219 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1220 int crtc_x = plane_state->base.dst.x1;
1221 int crtc_y = plane_state->base.dst.y1;
1222 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1223 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1224 u32 x = plane_state->color_plane[0].x;
1225 u32 y = plane_state->color_plane[0].y;
1226 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1227 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1228 u32 dvscntr, dvsscale = 0;
1229 unsigned long irqflags;
1231 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1233 /* Sizes are 0 based */
1239 if (crtc_w != src_w || crtc_h != src_h)
1240 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1242 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1244 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1246 I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
1247 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1248 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1249 I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
1252 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
1253 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1254 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1257 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1258 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1261 * The control register self-arms if the plane was previously
1262 * disabled. Try to make the plane enable atomic by writing
1263 * the control register just before the surface register.
1265 I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
1266 I915_WRITE_FW(DVSSURF(pipe),
1267 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1269 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1273 g4x_disable_plane(struct intel_plane *plane,
1274 const struct intel_crtc_state *crtc_state)
1276 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1277 enum pipe pipe = plane->pipe;
1278 unsigned long irqflags;
1280 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1282 I915_WRITE_FW(DVSCNTR(pipe), 0);
1283 /* Disable the scaler */
1284 I915_WRITE_FW(DVSSCALE(pipe), 0);
1285 I915_WRITE_FW(DVSSURF(pipe), 0);
1287 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1291 g4x_plane_get_hw_state(struct intel_plane *plane,
1294 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1295 enum intel_display_power_domain power_domain;
1296 intel_wakeref_t wakeref;
1299 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1300 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1304 ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1306 *pipe = plane->pipe;
1308 intel_display_power_put(dev_priv, power_domain, wakeref);
1313 static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1318 switch (fb->format->format) {
1327 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1328 struct intel_plane_state *plane_state)
1330 const struct drm_framebuffer *fb = plane_state->base.fb;
1331 const struct drm_rect *src = &plane_state->base.src;
1332 const struct drm_rect *dst = &plane_state->base.dst;
1333 int src_x, src_y, src_w, src_h, crtc_w, crtc_h;
1334 const struct drm_display_mode *adjusted_mode =
1335 &crtc_state->base.adjusted_mode;
1336 unsigned int cpp = fb->format->cpp[0];
1337 unsigned int width_bytes;
1338 int min_width, min_height;
1340 crtc_w = drm_rect_width(dst);
1341 crtc_h = drm_rect_height(dst);
1343 src_x = src->x1 >> 16;
1344 src_y = src->y1 >> 16;
1345 src_w = drm_rect_width(src) >> 16;
1346 src_h = drm_rect_height(src) >> 16;
1348 if (src_w == crtc_w && src_h == crtc_h)
1353 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1355 DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1363 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1365 if (src_w < min_width || src_h < min_height ||
1366 src_w > 2048 || src_h > 2048) {
1367 DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1368 src_w, src_h, min_width, min_height, 2048, 2048);
1372 if (width_bytes > 4096) {
1373 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1378 if (width_bytes > 4096 || fb->pitches[0] > 4096) {
1379 DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1380 fb->pitches[0], 4096);
1388 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1389 struct intel_plane_state *plane_state)
1391 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1392 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1393 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1394 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1397 if (intel_fb_scalable(plane_state->base.fb)) {
1398 if (INTEL_GEN(dev_priv) < 7) {
1400 max_scale = 16 << 16;
1401 } else if (IS_IVYBRIDGE(dev_priv)) {
1403 max_scale = 2 << 16;
1407 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1409 min_scale, max_scale,
1414 if (!plane_state->base.visible)
1417 ret = intel_plane_check_src_coordinates(plane_state);
1421 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1425 ret = i9xx_check_plane_surface(plane_state);
1429 if (INTEL_GEN(dev_priv) >= 7)
1430 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1432 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1437 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1439 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1440 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1441 unsigned int rotation = plane_state->base.rotation;
1443 /* CHV ignores the mirror bit when the rotate bit is set :( */
1444 if (IS_CHERRYVIEW(dev_priv) &&
1445 rotation & DRM_MODE_ROTATE_180 &&
1446 rotation & DRM_MODE_REFLECT_X) {
1447 DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
1455 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1456 struct intel_plane_state *plane_state)
1460 ret = chv_plane_check_rotation(plane_state);
1464 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1466 DRM_PLANE_HELPER_NO_SCALING,
1467 DRM_PLANE_HELPER_NO_SCALING,
1472 if (!plane_state->base.visible)
1475 ret = intel_plane_check_src_coordinates(plane_state);
1479 ret = i9xx_check_plane_surface(plane_state);
1483 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1488 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1489 const struct intel_plane_state *plane_state)
1491 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1492 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1493 const struct drm_framebuffer *fb = plane_state->base.fb;
1494 unsigned int rotation = plane_state->base.rotation;
1495 struct drm_format_name_buf format_name;
1500 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1501 is_ccs_modifier(fb->modifier)) {
1502 DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
1507 if (rotation & DRM_MODE_REFLECT_X &&
1508 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1509 DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
1513 if (drm_rotation_90_or_270(rotation)) {
1514 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
1515 fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
1516 DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
1521 * 90/270 is not allowed with RGB64 16:16:16:16 and
1522 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1524 switch (fb->format->format) {
1525 case DRM_FORMAT_RGB565:
1526 if (INTEL_GEN(dev_priv) >= 11)
1530 case DRM_FORMAT_XRGB16161616F:
1531 case DRM_FORMAT_XBGR16161616F:
1532 case DRM_FORMAT_ARGB16161616F:
1533 case DRM_FORMAT_ABGR16161616F:
1534 case DRM_FORMAT_Y210:
1535 case DRM_FORMAT_Y212:
1536 case DRM_FORMAT_Y216:
1537 case DRM_FORMAT_XVYU12_16161616:
1538 case DRM_FORMAT_XVYU16161616:
1539 DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
1540 drm_get_format_name(fb->format->format,
1548 /* Y-tiling is not supported in IF-ID Interlace mode */
1549 if (crtc_state->base.enable &&
1550 crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1551 (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1552 fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1553 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1554 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) {
1555 DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
1562 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1563 const struct intel_plane_state *plane_state)
1565 struct drm_i915_private *dev_priv =
1566 to_i915(plane_state->base.plane->dev);
1567 int crtc_x = plane_state->base.dst.x1;
1568 int crtc_w = drm_rect_width(&plane_state->base.dst);
1569 int pipe_src_w = crtc_state->pipe_src_w;
1572 * Display WA #1175: cnl,glk
1573 * Planes other than the cursor may cause FIFO underflow and display
1574 * corruption if starting less than 4 pixels from the right edge of
1576 * Besides the above WA fix the similar problem, where planes other
1577 * than the cursor ending less than 4 pixels from the left edge of the
1578 * screen may cause FIFO underflow and display corruption.
1580 if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
1581 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1582 DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
1583 crtc_x + crtc_w < 4 ? "end" : "start",
1584 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1592 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1594 const struct drm_framebuffer *fb = plane_state->base.fb;
1595 unsigned int rotation = plane_state->base.rotation;
1596 int src_w = drm_rect_width(&plane_state->base.src) >> 16;
1598 /* Display WA #1106 */
1599 if (is_planar_yuv_format(fb->format->format) && src_w & 3 &&
1600 (rotation == DRM_MODE_ROTATE_270 ||
1601 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1602 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1609 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1610 struct intel_plane_state *plane_state)
1612 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1613 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1614 const struct drm_framebuffer *fb = plane_state->base.fb;
1615 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1616 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1619 ret = skl_plane_check_fb(crtc_state, plane_state);
1623 /* use scaler when colorkey is not required */
1624 if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
1626 max_scale = skl_max_scale(crtc_state, fb->format->format);
1629 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1631 min_scale, max_scale,
1636 if (!plane_state->base.visible)
1639 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1643 ret = intel_plane_check_src_coordinates(plane_state);
1647 ret = skl_plane_check_nv12_rotation(plane_state);
1651 ret = skl_check_plane_surface(plane_state);
1655 /* HW only has 8 bits pixel precision, disable plane if invisible */
1656 if (!(plane_state->base.alpha >> 8))
1657 plane_state->base.visible = false;
1659 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1661 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1662 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1668 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1670 return INTEL_GEN(dev_priv) >= 9;
1673 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1674 const struct drm_intel_sprite_colorkey *set)
1676 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1677 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1678 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1683 * We want src key enabled on the
1684 * sprite and not on the primary.
1686 if (plane->id == PLANE_PRIMARY &&
1687 set->flags & I915_SET_COLORKEY_SOURCE)
1691 * On SKL+ we want dst key enabled on
1692 * the primary and not on the sprite.
1694 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1695 set->flags & I915_SET_COLORKEY_DESTINATION)
1699 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1700 struct drm_file *file_priv)
1702 struct drm_i915_private *dev_priv = to_i915(dev);
1703 struct drm_intel_sprite_colorkey *set = data;
1704 struct drm_plane *plane;
1705 struct drm_plane_state *plane_state;
1706 struct drm_atomic_state *state;
1707 struct drm_modeset_acquire_ctx ctx;
1710 /* ignore the pointless "none" flag */
1711 set->flags &= ~I915_SET_COLORKEY_NONE;
1713 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1716 /* Make sure we don't try to enable both src & dest simultaneously */
1717 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1720 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1721 set->flags & I915_SET_COLORKEY_DESTINATION)
1724 plane = drm_plane_find(dev, file_priv, set->plane_id);
1725 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1729 * SKL+ only plane 2 can do destination keying against plane 1.
1730 * Also multiple planes can't do destination keying on the same
1731 * pipe simultaneously.
1733 if (INTEL_GEN(dev_priv) >= 9 &&
1734 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1735 set->flags & I915_SET_COLORKEY_DESTINATION)
1738 drm_modeset_acquire_init(&ctx, 0);
1740 state = drm_atomic_state_alloc(plane->dev);
1745 state->acquire_ctx = &ctx;
1748 plane_state = drm_atomic_get_plane_state(state, plane);
1749 ret = PTR_ERR_OR_ZERO(plane_state);
1751 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1754 * On some platforms we have to configure
1755 * the dst colorkey on the primary plane.
1757 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1758 struct intel_crtc *crtc =
1759 intel_get_crtc_for_pipe(dev_priv,
1760 to_intel_plane(plane)->pipe);
1762 plane_state = drm_atomic_get_plane_state(state,
1763 crtc->base.primary);
1764 ret = PTR_ERR_OR_ZERO(plane_state);
1766 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1770 ret = drm_atomic_commit(state);
1772 if (ret != -EDEADLK)
1775 drm_atomic_state_clear(state);
1776 drm_modeset_backoff(&ctx);
1779 drm_atomic_state_put(state);
1781 drm_modeset_drop_locks(&ctx);
1782 drm_modeset_acquire_fini(&ctx);
1786 static const u32 g4x_plane_formats[] = {
1787 DRM_FORMAT_XRGB8888,
1794 static const u64 i9xx_plane_format_modifiers[] = {
1795 I915_FORMAT_MOD_X_TILED,
1796 DRM_FORMAT_MOD_LINEAR,
1797 DRM_FORMAT_MOD_INVALID
1800 static const u32 snb_plane_formats[] = {
1801 DRM_FORMAT_XBGR8888,
1802 DRM_FORMAT_XRGB8888,
1809 static const u32 vlv_plane_formats[] = {
1811 DRM_FORMAT_ABGR8888,
1812 DRM_FORMAT_ARGB8888,
1813 DRM_FORMAT_XBGR8888,
1814 DRM_FORMAT_XRGB8888,
1815 DRM_FORMAT_XBGR2101010,
1816 DRM_FORMAT_ABGR2101010,
1823 static const u32 skl_plane_formats[] = {
1826 DRM_FORMAT_XRGB8888,
1827 DRM_FORMAT_XBGR8888,
1828 DRM_FORMAT_ARGB8888,
1829 DRM_FORMAT_ABGR8888,
1830 DRM_FORMAT_XRGB2101010,
1831 DRM_FORMAT_XBGR2101010,
1838 static const u32 icl_plane_formats[] = {
1841 DRM_FORMAT_XRGB8888,
1842 DRM_FORMAT_XBGR8888,
1843 DRM_FORMAT_ARGB8888,
1844 DRM_FORMAT_ABGR8888,
1845 DRM_FORMAT_XRGB2101010,
1846 DRM_FORMAT_XBGR2101010,
1854 DRM_FORMAT_XVYU2101010,
1855 DRM_FORMAT_XVYU12_16161616,
1856 DRM_FORMAT_XVYU16161616,
1859 static const u32 icl_hdr_plane_formats[] = {
1862 DRM_FORMAT_XRGB8888,
1863 DRM_FORMAT_XBGR8888,
1864 DRM_FORMAT_ARGB8888,
1865 DRM_FORMAT_ABGR8888,
1866 DRM_FORMAT_XRGB2101010,
1867 DRM_FORMAT_XBGR2101010,
1868 DRM_FORMAT_XRGB16161616F,
1869 DRM_FORMAT_XBGR16161616F,
1870 DRM_FORMAT_ARGB16161616F,
1871 DRM_FORMAT_ABGR16161616F,
1879 DRM_FORMAT_XVYU2101010,
1880 DRM_FORMAT_XVYU12_16161616,
1881 DRM_FORMAT_XVYU16161616,
1884 static const u32 skl_planar_formats[] = {
1887 DRM_FORMAT_XRGB8888,
1888 DRM_FORMAT_XBGR8888,
1889 DRM_FORMAT_ARGB8888,
1890 DRM_FORMAT_ABGR8888,
1891 DRM_FORMAT_XRGB2101010,
1892 DRM_FORMAT_XBGR2101010,
1900 static const u32 glk_planar_formats[] = {
1903 DRM_FORMAT_XRGB8888,
1904 DRM_FORMAT_XBGR8888,
1905 DRM_FORMAT_ARGB8888,
1906 DRM_FORMAT_ABGR8888,
1907 DRM_FORMAT_XRGB2101010,
1908 DRM_FORMAT_XBGR2101010,
1919 static const u32 icl_planar_formats[] = {
1922 DRM_FORMAT_XRGB8888,
1923 DRM_FORMAT_XBGR8888,
1924 DRM_FORMAT_ARGB8888,
1925 DRM_FORMAT_ABGR8888,
1926 DRM_FORMAT_XRGB2101010,
1927 DRM_FORMAT_XBGR2101010,
1939 DRM_FORMAT_XVYU2101010,
1940 DRM_FORMAT_XVYU12_16161616,
1941 DRM_FORMAT_XVYU16161616,
1944 static const u32 icl_hdr_planar_formats[] = {
1947 DRM_FORMAT_XRGB8888,
1948 DRM_FORMAT_XBGR8888,
1949 DRM_FORMAT_ARGB8888,
1950 DRM_FORMAT_ABGR8888,
1951 DRM_FORMAT_XRGB2101010,
1952 DRM_FORMAT_XBGR2101010,
1953 DRM_FORMAT_XRGB16161616F,
1954 DRM_FORMAT_XBGR16161616F,
1955 DRM_FORMAT_ARGB16161616F,
1956 DRM_FORMAT_ABGR16161616F,
1968 DRM_FORMAT_XVYU2101010,
1969 DRM_FORMAT_XVYU12_16161616,
1970 DRM_FORMAT_XVYU16161616,
1973 static const u64 skl_plane_format_modifiers_noccs[] = {
1974 I915_FORMAT_MOD_Yf_TILED,
1975 I915_FORMAT_MOD_Y_TILED,
1976 I915_FORMAT_MOD_X_TILED,
1977 DRM_FORMAT_MOD_LINEAR,
1978 DRM_FORMAT_MOD_INVALID
1981 static const u64 skl_plane_format_modifiers_ccs[] = {
1982 I915_FORMAT_MOD_Yf_TILED_CCS,
1983 I915_FORMAT_MOD_Y_TILED_CCS,
1984 I915_FORMAT_MOD_Yf_TILED,
1985 I915_FORMAT_MOD_Y_TILED,
1986 I915_FORMAT_MOD_X_TILED,
1987 DRM_FORMAT_MOD_LINEAR,
1988 DRM_FORMAT_MOD_INVALID
1991 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1992 u32 format, u64 modifier)
1995 case DRM_FORMAT_MOD_LINEAR:
1996 case I915_FORMAT_MOD_X_TILED:
2003 case DRM_FORMAT_XRGB8888:
2004 case DRM_FORMAT_YUYV:
2005 case DRM_FORMAT_YVYU:
2006 case DRM_FORMAT_UYVY:
2007 case DRM_FORMAT_VYUY:
2008 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2009 modifier == I915_FORMAT_MOD_X_TILED)
2017 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2018 u32 format, u64 modifier)
2021 case DRM_FORMAT_MOD_LINEAR:
2022 case I915_FORMAT_MOD_X_TILED:
2029 case DRM_FORMAT_XRGB8888:
2030 case DRM_FORMAT_XBGR8888:
2031 case DRM_FORMAT_YUYV:
2032 case DRM_FORMAT_YVYU:
2033 case DRM_FORMAT_UYVY:
2034 case DRM_FORMAT_VYUY:
2035 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2036 modifier == I915_FORMAT_MOD_X_TILED)
2044 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2045 u32 format, u64 modifier)
2048 case DRM_FORMAT_MOD_LINEAR:
2049 case I915_FORMAT_MOD_X_TILED:
2056 case DRM_FORMAT_RGB565:
2057 case DRM_FORMAT_ABGR8888:
2058 case DRM_FORMAT_ARGB8888:
2059 case DRM_FORMAT_XBGR8888:
2060 case DRM_FORMAT_XRGB8888:
2061 case DRM_FORMAT_XBGR2101010:
2062 case DRM_FORMAT_ABGR2101010:
2063 case DRM_FORMAT_YUYV:
2064 case DRM_FORMAT_YVYU:
2065 case DRM_FORMAT_UYVY:
2066 case DRM_FORMAT_VYUY:
2067 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2068 modifier == I915_FORMAT_MOD_X_TILED)
2076 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2077 u32 format, u64 modifier)
2079 struct intel_plane *plane = to_intel_plane(_plane);
2082 case DRM_FORMAT_MOD_LINEAR:
2083 case I915_FORMAT_MOD_X_TILED:
2084 case I915_FORMAT_MOD_Y_TILED:
2085 case I915_FORMAT_MOD_Yf_TILED:
2087 case I915_FORMAT_MOD_Y_TILED_CCS:
2088 case I915_FORMAT_MOD_Yf_TILED_CCS:
2089 if (!plane->has_ccs)
2097 case DRM_FORMAT_XRGB8888:
2098 case DRM_FORMAT_XBGR8888:
2099 case DRM_FORMAT_ARGB8888:
2100 case DRM_FORMAT_ABGR8888:
2101 if (is_ccs_modifier(modifier))
2104 case DRM_FORMAT_RGB565:
2105 case DRM_FORMAT_XRGB2101010:
2106 case DRM_FORMAT_XBGR2101010:
2107 case DRM_FORMAT_YUYV:
2108 case DRM_FORMAT_YVYU:
2109 case DRM_FORMAT_UYVY:
2110 case DRM_FORMAT_VYUY:
2111 case DRM_FORMAT_NV12:
2112 case DRM_FORMAT_P010:
2113 case DRM_FORMAT_P012:
2114 case DRM_FORMAT_P016:
2115 case DRM_FORMAT_XVYU2101010:
2116 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2120 case DRM_FORMAT_XBGR16161616F:
2121 case DRM_FORMAT_ABGR16161616F:
2122 case DRM_FORMAT_XRGB16161616F:
2123 case DRM_FORMAT_ARGB16161616F:
2124 case DRM_FORMAT_Y210:
2125 case DRM_FORMAT_Y212:
2126 case DRM_FORMAT_Y216:
2127 case DRM_FORMAT_XVYU12_16161616:
2128 case DRM_FORMAT_XVYU16161616:
2129 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2130 modifier == I915_FORMAT_MOD_X_TILED ||
2131 modifier == I915_FORMAT_MOD_Y_TILED)
2139 static const struct drm_plane_funcs g4x_sprite_funcs = {
2140 .update_plane = drm_atomic_helper_update_plane,
2141 .disable_plane = drm_atomic_helper_disable_plane,
2142 .destroy = intel_plane_destroy,
2143 .atomic_get_property = intel_plane_atomic_get_property,
2144 .atomic_set_property = intel_plane_atomic_set_property,
2145 .atomic_duplicate_state = intel_plane_duplicate_state,
2146 .atomic_destroy_state = intel_plane_destroy_state,
2147 .format_mod_supported = g4x_sprite_format_mod_supported,
2150 static const struct drm_plane_funcs snb_sprite_funcs = {
2151 .update_plane = drm_atomic_helper_update_plane,
2152 .disable_plane = drm_atomic_helper_disable_plane,
2153 .destroy = intel_plane_destroy,
2154 .atomic_get_property = intel_plane_atomic_get_property,
2155 .atomic_set_property = intel_plane_atomic_set_property,
2156 .atomic_duplicate_state = intel_plane_duplicate_state,
2157 .atomic_destroy_state = intel_plane_destroy_state,
2158 .format_mod_supported = snb_sprite_format_mod_supported,
2161 static const struct drm_plane_funcs vlv_sprite_funcs = {
2162 .update_plane = drm_atomic_helper_update_plane,
2163 .disable_plane = drm_atomic_helper_disable_plane,
2164 .destroy = intel_plane_destroy,
2165 .atomic_get_property = intel_plane_atomic_get_property,
2166 .atomic_set_property = intel_plane_atomic_set_property,
2167 .atomic_duplicate_state = intel_plane_duplicate_state,
2168 .atomic_destroy_state = intel_plane_destroy_state,
2169 .format_mod_supported = vlv_sprite_format_mod_supported,
2172 static const struct drm_plane_funcs skl_plane_funcs = {
2173 .update_plane = drm_atomic_helper_update_plane,
2174 .disable_plane = drm_atomic_helper_disable_plane,
2175 .destroy = intel_plane_destroy,
2176 .atomic_get_property = intel_plane_atomic_get_property,
2177 .atomic_set_property = intel_plane_atomic_set_property,
2178 .atomic_duplicate_state = intel_plane_duplicate_state,
2179 .atomic_destroy_state = intel_plane_destroy_state,
2180 .format_mod_supported = skl_plane_format_mod_supported,
2183 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2184 enum pipe pipe, enum plane_id plane_id)
2186 if (!HAS_FBC(dev_priv))
2189 return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2192 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2193 enum pipe pipe, enum plane_id plane_id)
2195 if (INTEL_GEN(dev_priv) >= 11)
2196 return plane_id <= PLANE_SPRITE3;
2198 /* Display WA #0870: skl, bxt */
2199 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2202 if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2205 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2211 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
2212 enum pipe pipe, enum plane_id plane_id)
2214 if (plane_id == PLANE_CURSOR)
2217 if (INTEL_GEN(dev_priv) >= 10)
2220 if (IS_GEMINILAKE(dev_priv))
2221 return pipe != PIPE_C;
2223 return pipe != PIPE_C &&
2224 (plane_id == PLANE_PRIMARY ||
2225 plane_id == PLANE_SPRITE0);
2228 struct intel_plane *
2229 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2230 enum pipe pipe, enum plane_id plane_id)
2232 struct intel_plane *plane;
2233 enum drm_plane_type plane_type;
2234 unsigned int supported_rotations;
2235 unsigned int possible_crtcs;
2236 const u64 *modifiers;
2241 plane = intel_plane_alloc();
2246 plane->id = plane_id;
2247 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2249 plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2250 if (plane->has_fbc) {
2251 struct intel_fbc *fbc = &dev_priv->fbc;
2253 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2256 plane->max_stride = skl_plane_max_stride;
2257 plane->update_plane = skl_update_plane;
2258 plane->disable_plane = skl_disable_plane;
2259 plane->get_hw_state = skl_plane_get_hw_state;
2260 plane->check_plane = skl_plane_check;
2261 if (icl_is_nv12_y_plane(plane_id))
2262 plane->update_slave = icl_update_slave;
2264 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2265 if (icl_is_hdr_plane(dev_priv, plane_id)) {
2266 formats = icl_hdr_planar_formats;
2267 num_formats = ARRAY_SIZE(icl_hdr_planar_formats);
2268 } else if (INTEL_GEN(dev_priv) >= 11) {
2269 formats = icl_planar_formats;
2270 num_formats = ARRAY_SIZE(icl_planar_formats);
2271 } else if (INTEL_GEN(dev_priv) == 10 || IS_GEMINILAKE(dev_priv)) {
2272 formats = glk_planar_formats;
2273 num_formats = ARRAY_SIZE(glk_planar_formats);
2275 formats = skl_planar_formats;
2276 num_formats = ARRAY_SIZE(skl_planar_formats);
2278 } else if (icl_is_hdr_plane(dev_priv, plane_id)) {
2279 formats = icl_hdr_plane_formats;
2280 num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2281 } else if (INTEL_GEN(dev_priv) >= 11) {
2282 formats = icl_plane_formats;
2283 num_formats = ARRAY_SIZE(icl_plane_formats);
2285 formats = skl_plane_formats;
2286 num_formats = ARRAY_SIZE(skl_plane_formats);
2289 plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2291 modifiers = skl_plane_format_modifiers_ccs;
2293 modifiers = skl_plane_format_modifiers_noccs;
2295 if (plane_id == PLANE_PRIMARY)
2296 plane_type = DRM_PLANE_TYPE_PRIMARY;
2298 plane_type = DRM_PLANE_TYPE_OVERLAY;
2300 possible_crtcs = BIT(pipe);
2302 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2303 possible_crtcs, &skl_plane_funcs,
2304 formats, num_formats, modifiers,
2306 "plane %d%c", plane_id + 1,
2311 supported_rotations =
2312 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2313 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2315 if (INTEL_GEN(dev_priv) >= 10)
2316 supported_rotations |= DRM_MODE_REFLECT_X;
2318 drm_plane_create_rotation_property(&plane->base,
2320 supported_rotations);
2322 drm_plane_create_color_properties(&plane->base,
2323 BIT(DRM_COLOR_YCBCR_BT601) |
2324 BIT(DRM_COLOR_YCBCR_BT709),
2325 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2326 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2327 DRM_COLOR_YCBCR_BT709,
2328 DRM_COLOR_YCBCR_LIMITED_RANGE);
2330 drm_plane_create_alpha_property(&plane->base);
2331 drm_plane_create_blend_mode_property(&plane->base,
2332 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2333 BIT(DRM_MODE_BLEND_PREMULTI) |
2334 BIT(DRM_MODE_BLEND_COVERAGE));
2336 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2341 intel_plane_free(plane);
2343 return ERR_PTR(ret);
2346 struct intel_plane *
2347 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
2348 enum pipe pipe, int sprite)
2350 struct intel_plane *plane;
2351 const struct drm_plane_funcs *plane_funcs;
2352 unsigned long possible_crtcs;
2353 unsigned int supported_rotations;
2354 const u64 *modifiers;
2359 if (INTEL_GEN(dev_priv) >= 9)
2360 return skl_universal_plane_create(dev_priv, pipe,
2361 PLANE_SPRITE0 + sprite);
2363 plane = intel_plane_alloc();
2367 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
2368 plane->max_stride = i9xx_plane_max_stride;
2369 plane->update_plane = vlv_update_plane;
2370 plane->disable_plane = vlv_disable_plane;
2371 plane->get_hw_state = vlv_plane_get_hw_state;
2372 plane->check_plane = vlv_sprite_check;
2374 formats = vlv_plane_formats;
2375 num_formats = ARRAY_SIZE(vlv_plane_formats);
2376 modifiers = i9xx_plane_format_modifiers;
2378 plane_funcs = &vlv_sprite_funcs;
2379 } else if (INTEL_GEN(dev_priv) >= 7) {
2380 plane->max_stride = g4x_sprite_max_stride;
2381 plane->update_plane = ivb_update_plane;
2382 plane->disable_plane = ivb_disable_plane;
2383 plane->get_hw_state = ivb_plane_get_hw_state;
2384 plane->check_plane = g4x_sprite_check;
2386 formats = snb_plane_formats;
2387 num_formats = ARRAY_SIZE(snb_plane_formats);
2388 modifiers = i9xx_plane_format_modifiers;
2390 plane_funcs = &snb_sprite_funcs;
2392 plane->max_stride = g4x_sprite_max_stride;
2393 plane->update_plane = g4x_update_plane;
2394 plane->disable_plane = g4x_disable_plane;
2395 plane->get_hw_state = g4x_plane_get_hw_state;
2396 plane->check_plane = g4x_sprite_check;
2398 modifiers = i9xx_plane_format_modifiers;
2399 if (IS_GEN(dev_priv, 6)) {
2400 formats = snb_plane_formats;
2401 num_formats = ARRAY_SIZE(snb_plane_formats);
2403 plane_funcs = &snb_sprite_funcs;
2405 formats = g4x_plane_formats;
2406 num_formats = ARRAY_SIZE(g4x_plane_formats);
2408 plane_funcs = &g4x_sprite_funcs;
2412 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
2413 supported_rotations =
2414 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
2417 supported_rotations =
2418 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2422 plane->id = PLANE_SPRITE0 + sprite;
2423 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
2425 possible_crtcs = BIT(pipe);
2427 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2428 possible_crtcs, plane_funcs,
2429 formats, num_formats, modifiers,
2430 DRM_PLANE_TYPE_OVERLAY,
2431 "sprite %c", sprite_name(pipe, sprite));
2435 drm_plane_create_rotation_property(&plane->base,
2437 supported_rotations);
2439 drm_plane_create_color_properties(&plane->base,
2440 BIT(DRM_COLOR_YCBCR_BT601) |
2441 BIT(DRM_COLOR_YCBCR_BT709),
2442 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2443 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2444 DRM_COLOR_YCBCR_BT709,
2445 DRM_COLOR_YCBCR_LIMITED_RANGE);
2447 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2452 intel_plane_free(plane);
2454 return ERR_PTR(ret);