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;
275 * Hardware doesn't handle subpixel coordinates.
276 * Adjust to (macro)pixel boundary, but be careful not to
277 * increase the source viewport size, because that could
278 * push the downscaling factor out of bounds.
280 src_x = src->x1 >> 16;
281 src_w = drm_rect_width(src) >> 16;
282 src_y = src->y1 >> 16;
283 src_h = drm_rect_height(src) >> 16;
285 src->x1 = src_x << 16;
286 src->x2 = (src_x + src_w) << 16;
287 src->y1 = src_y << 16;
288 src->y2 = (src_y + src_h) << 16;
290 if (fb->format->is_yuv &&
291 (src_x & 1 || src_w & 1)) {
292 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
297 if (fb->format->is_yuv &&
298 fb->format->num_planes > 1 &&
299 (src_y & 1 || src_h & 1)) {
300 DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of 2 for planar YUV planes\n",
309 skl_plane_max_stride(struct intel_plane *plane,
310 u32 pixel_format, u64 modifier,
311 unsigned int rotation)
313 int cpp = drm_format_plane_cpp(pixel_format, 0);
316 * "The stride in bytes must not exceed the
317 * of the size of 8K pixels and 32K bytes."
319 if (drm_rotation_90_or_270(rotation))
320 return min(8192, 32768 / cpp);
322 return min(8192 * cpp, 32768);
326 skl_program_scaler(struct intel_plane *plane,
327 const struct intel_crtc_state *crtc_state,
328 const struct intel_plane_state *plane_state)
330 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
331 enum pipe pipe = plane->pipe;
332 int scaler_id = plane_state->scaler_id;
333 const struct intel_scaler *scaler =
334 &crtc_state->scaler_state.scalers[scaler_id];
335 int crtc_x = plane_state->base.dst.x1;
336 int crtc_y = plane_state->base.dst.y1;
337 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
338 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
339 u16 y_hphase, uv_rgb_hphase;
340 u16 y_vphase, uv_rgb_vphase;
343 hscale = drm_rect_calc_hscale(&plane_state->base.src,
344 &plane_state->base.dst,
346 vscale = drm_rect_calc_vscale(&plane_state->base.src,
347 &plane_state->base.dst,
350 /* TODO: handle sub-pixel coordinates */
351 if (is_planar_yuv_format(plane_state->base.fb->format->format) &&
352 !icl_is_hdr_plane(dev_priv, plane->id)) {
353 y_hphase = skl_scaler_calc_phase(1, hscale, false);
354 y_vphase = skl_scaler_calc_phase(1, vscale, false);
356 /* MPEG2 chroma siting convention */
357 uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
358 uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
364 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
365 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
368 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
369 PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
370 I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
371 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
372 I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
373 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
374 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
375 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
378 /* Preoffset values for YUV to RGB Conversion */
379 #define PREOFF_YUV_TO_RGB_HI 0x1800
380 #define PREOFF_YUV_TO_RGB_ME 0x1F00
381 #define PREOFF_YUV_TO_RGB_LO 0x1800
383 #define ROFF(x) (((x) & 0xffff) << 16)
384 #define GOFF(x) (((x) & 0xffff) << 0)
385 #define BOFF(x) (((x) & 0xffff) << 16)
388 icl_program_input_csc(struct intel_plane *plane,
389 const struct intel_crtc_state *crtc_state,
390 const struct intel_plane_state *plane_state)
392 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
393 enum pipe pipe = plane->pipe;
394 enum plane_id plane_id = plane->id;
396 static const u16 input_csc_matrix[][9] = {
398 * BT.601 full range YCbCr -> full range RGB
399 * The matrix required is :
400 * [1.000, 0.000, 1.371,
401 * 1.000, -0.336, -0.698,
402 * 1.000, 1.732, 0.0000]
404 [DRM_COLOR_YCBCR_BT601] = {
406 0x8B28, 0x7800, 0x9AC0,
410 * BT.709 full range YCbCr -> full range RGB
411 * The matrix required is :
412 * [1.000, 0.000, 1.574,
413 * 1.000, -0.187, -0.468,
414 * 1.000, 1.855, 0.0000]
416 [DRM_COLOR_YCBCR_BT709] = {
418 0x9EF8, 0x7800, 0xABF8,
423 /* Matrix for Limited Range to Full Range Conversion */
424 static const u16 input_csc_matrix_lr[][9] = {
426 * BT.601 Limted range YCbCr -> full range RGB
427 * The matrix required is :
428 * [1.164384, 0.000, 1.596370,
429 * 1.138393, -0.382500, -0.794598,
430 * 1.138393, 1.971696, 0.0000]
432 [DRM_COLOR_YCBCR_BT601] = {
434 0x8CB8, 0x7918, 0x9C40,
438 * BT.709 Limited range YCbCr -> full range RGB
439 * The matrix required is :
440 * [1.164, 0.000, 1.833671,
441 * 1.138393, -0.213249, -0.532909,
442 * 1.138393, 2.112402, 0.0000]
444 [DRM_COLOR_YCBCR_BT709] = {
446 0x8888, 0x7918, 0xADA8,
452 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
453 csc = input_csc_matrix[plane_state->base.color_encoding];
455 csc = input_csc_matrix_lr[plane_state->base.color_encoding];
457 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
459 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
460 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
462 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
463 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
465 I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));
467 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
468 PREOFF_YUV_TO_RGB_HI);
469 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
470 PREOFF_YUV_TO_RGB_ME);
471 I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
472 PREOFF_YUV_TO_RGB_LO);
473 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
474 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
475 I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
479 skl_program_plane(struct intel_plane *plane,
480 const struct intel_crtc_state *crtc_state,
481 const struct intel_plane_state *plane_state,
482 int color_plane, bool slave, u32 plane_ctl)
484 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
485 enum plane_id plane_id = plane->id;
486 enum pipe pipe = plane->pipe;
487 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
488 u32 surf_addr = plane_state->color_plane[color_plane].offset;
489 u32 stride = skl_plane_stride(plane_state, color_plane);
490 u32 aux_stride = skl_plane_stride(plane_state, 1);
491 int crtc_x = plane_state->base.dst.x1;
492 int crtc_y = plane_state->base.dst.y1;
493 u32 x = plane_state->color_plane[color_plane].x;
494 u32 y = plane_state->color_plane[color_plane].y;
495 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
496 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
497 struct intel_plane *linked = plane_state->linked_plane;
498 const struct drm_framebuffer *fb = plane_state->base.fb;
499 u8 alpha = plane_state->base.alpha >> 8;
500 u32 plane_color_ctl = 0;
501 unsigned long irqflags;
504 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
506 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
507 plane_color_ctl = plane_state->color_ctl |
508 glk_plane_color_ctl_crtc(crtc_state);
510 /* Sizes are 0 based */
514 keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
516 keymsk = key->channel_mask & 0x7ffffff;
518 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
520 /* The scaler will handle the output position */
521 if (plane_state->scaler_id >= 0) {
526 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
528 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
529 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
530 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
531 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
532 (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
534 if (icl_is_hdr_plane(dev_priv, plane_id)) {
538 /* Enable and use MPEG-2 chroma siting */
539 cus_ctl = PLANE_CUS_ENABLE |
541 PLANE_CUS_VPHASE_SIGN_NEGATIVE |
542 PLANE_CUS_VPHASE_0_25;
544 if (linked->id == PLANE_SPRITE5)
545 cus_ctl |= PLANE_CUS_PLANE_7;
546 else if (linked->id == PLANE_SPRITE4)
547 cus_ctl |= PLANE_CUS_PLANE_6;
549 MISSING_CASE(linked->id);
552 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), cus_ctl);
555 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
556 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
558 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
559 icl_program_input_csc(plane, crtc_state, plane_state);
561 skl_write_plane_wm(plane, crtc_state);
563 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
564 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
565 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
567 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
569 if (INTEL_GEN(dev_priv) < 11)
570 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
571 (plane_state->color_plane[1].y << 16) |
572 plane_state->color_plane[1].x);
575 * The control register self-arms if the plane was previously
576 * disabled. Try to make the plane enable atomic by writing
577 * the control register just before the surface register.
579 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
580 I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
581 intel_plane_ggtt_offset(plane_state) + surf_addr);
583 if (!slave && plane_state->scaler_id >= 0)
584 skl_program_scaler(plane, crtc_state, plane_state);
586 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
590 skl_update_plane(struct intel_plane *plane,
591 const struct intel_crtc_state *crtc_state,
592 const struct intel_plane_state *plane_state)
596 if (plane_state->linked_plane) {
597 /* Program the UV plane */
601 skl_program_plane(plane, crtc_state, plane_state,
602 color_plane, false, plane_state->ctl);
606 icl_update_slave(struct intel_plane *plane,
607 const struct intel_crtc_state *crtc_state,
608 const struct intel_plane_state *plane_state)
610 skl_program_plane(plane, crtc_state, plane_state, 0, true,
611 plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE);
615 skl_disable_plane(struct intel_plane *plane,
616 const struct intel_crtc_state *crtc_state)
618 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
619 enum plane_id plane_id = plane->id;
620 enum pipe pipe = plane->pipe;
621 unsigned long irqflags;
623 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
625 if (icl_is_hdr_plane(dev_priv, plane_id))
626 I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);
628 skl_write_plane_wm(plane, crtc_state);
630 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
631 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
633 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
637 skl_plane_get_hw_state(struct intel_plane *plane,
640 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
641 enum intel_display_power_domain power_domain;
642 enum plane_id plane_id = plane->id;
643 intel_wakeref_t wakeref;
646 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
647 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
651 ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
655 intel_display_power_put(dev_priv, power_domain, wakeref);
661 chv_update_csc(const struct intel_plane_state *plane_state)
663 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
664 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
665 const struct drm_framebuffer *fb = plane_state->base.fb;
666 enum plane_id plane_id = plane->id;
668 * |r| | c0 c1 c2 | |cr|
669 * |g| = | c3 c4 c5 | x |y |
670 * |b| | c6 c7 c8 | |cb|
672 * Coefficients are s3.12.
674 * Cb and Cr apparently come in as signed already, and
675 * we always get full range data in on account of CLRC0/1.
677 static const s16 csc_matrix[][9] = {
678 /* BT.601 full range YCbCr -> full range RGB */
679 [DRM_COLOR_YCBCR_BT601] = {
684 /* BT.709 full range YCbCr -> full range RGB */
685 [DRM_COLOR_YCBCR_BT709] = {
691 const s16 *csc = csc_matrix[plane_state->base.color_encoding];
693 /* Seems RGB data bypasses the CSC always */
694 if (!fb->format->is_yuv)
697 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
698 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
699 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
701 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
702 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
703 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
704 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
705 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
707 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
708 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
709 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
711 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
712 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
713 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
720 vlv_update_clrc(const struct intel_plane_state *plane_state)
722 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
723 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
724 const struct drm_framebuffer *fb = plane_state->base.fb;
725 enum pipe pipe = plane->pipe;
726 enum plane_id plane_id = plane->id;
727 int contrast, brightness, sh_scale, sh_sin, sh_cos;
729 if (fb->format->is_yuv &&
730 plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
732 * Expand limited range to full range:
733 * Contrast is applied first and is used to expand Y range.
734 * Brightness is applied second and is used to remove the
735 * offset from Y. Saturation/hue is used to expand CbCr range.
737 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
738 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
739 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
740 sh_sin = SIN_0 * sh_scale;
741 sh_cos = COS_0 * sh_scale;
743 /* Pass-through everything. */
747 sh_sin = SIN_0 * sh_scale;
748 sh_cos = COS_0 * sh_scale;
751 /* FIXME these register are single buffered :( */
752 I915_WRITE_FW(SPCLRC0(pipe, plane_id),
753 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
754 I915_WRITE_FW(SPCLRC1(pipe, plane_id),
755 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
758 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
762 if (crtc_state->gamma_enable)
763 sprctl |= SP_GAMMA_ENABLE;
768 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
769 const struct intel_plane_state *plane_state)
771 const struct drm_framebuffer *fb = plane_state->base.fb;
772 unsigned int rotation = plane_state->base.rotation;
773 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
778 switch (fb->format->format) {
779 case DRM_FORMAT_YUYV:
780 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
782 case DRM_FORMAT_YVYU:
783 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
785 case DRM_FORMAT_UYVY:
786 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
788 case DRM_FORMAT_VYUY:
789 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
791 case DRM_FORMAT_RGB565:
792 sprctl |= SP_FORMAT_BGR565;
794 case DRM_FORMAT_XRGB8888:
795 sprctl |= SP_FORMAT_BGRX8888;
797 case DRM_FORMAT_ARGB8888:
798 sprctl |= SP_FORMAT_BGRA8888;
800 case DRM_FORMAT_XBGR2101010:
801 sprctl |= SP_FORMAT_RGBX1010102;
803 case DRM_FORMAT_ABGR2101010:
804 sprctl |= SP_FORMAT_RGBA1010102;
806 case DRM_FORMAT_XBGR8888:
807 sprctl |= SP_FORMAT_RGBX8888;
809 case DRM_FORMAT_ABGR8888:
810 sprctl |= SP_FORMAT_RGBA8888;
813 MISSING_CASE(fb->format->format);
817 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
818 sprctl |= SP_YUV_FORMAT_BT709;
820 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
823 if (rotation & DRM_MODE_ROTATE_180)
824 sprctl |= SP_ROTATE_180;
826 if (rotation & DRM_MODE_REFLECT_X)
829 if (key->flags & I915_SET_COLORKEY_SOURCE)
830 sprctl |= SP_SOURCE_KEY;
836 vlv_update_plane(struct intel_plane *plane,
837 const struct intel_crtc_state *crtc_state,
838 const struct intel_plane_state *plane_state)
840 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
841 enum pipe pipe = plane->pipe;
842 enum plane_id plane_id = plane->id;
843 u32 sprsurf_offset = plane_state->color_plane[0].offset;
845 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
846 int crtc_x = plane_state->base.dst.x1;
847 int crtc_y = plane_state->base.dst.y1;
848 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
849 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
850 u32 x = plane_state->color_plane[0].x;
851 u32 y = plane_state->color_plane[0].y;
852 unsigned long irqflags;
855 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
857 /* Sizes are 0 based */
861 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
863 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
865 I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
866 plane_state->color_plane[0].stride);
867 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
868 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
869 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
871 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
872 chv_update_csc(plane_state);
875 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
876 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
877 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
880 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
881 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
884 * The control register self-arms if the plane was previously
885 * disabled. Try to make the plane enable atomic by writing
886 * the control register just before the surface register.
888 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
889 I915_WRITE_FW(SPSURF(pipe, plane_id),
890 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
892 vlv_update_clrc(plane_state);
894 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
898 vlv_disable_plane(struct intel_plane *plane,
899 const struct intel_crtc_state *crtc_state)
901 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
902 enum pipe pipe = plane->pipe;
903 enum plane_id plane_id = plane->id;
904 unsigned long irqflags;
906 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
908 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
909 I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
911 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
915 vlv_plane_get_hw_state(struct intel_plane *plane,
918 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
919 enum intel_display_power_domain power_domain;
920 enum plane_id plane_id = plane->id;
921 intel_wakeref_t wakeref;
924 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
925 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
929 ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
933 intel_display_power_put(dev_priv, power_domain, wakeref);
938 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
942 if (crtc_state->gamma_enable)
943 sprctl |= SPRITE_GAMMA_ENABLE;
945 if (crtc_state->csc_enable)
946 sprctl |= SPRITE_PIPE_CSC_ENABLE;
951 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
952 const struct intel_plane_state *plane_state)
954 struct drm_i915_private *dev_priv =
955 to_i915(plane_state->base.plane->dev);
956 const struct drm_framebuffer *fb = plane_state->base.fb;
957 unsigned int rotation = plane_state->base.rotation;
958 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
961 sprctl = SPRITE_ENABLE;
963 if (IS_IVYBRIDGE(dev_priv))
964 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
966 switch (fb->format->format) {
967 case DRM_FORMAT_XBGR8888:
968 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
970 case DRM_FORMAT_XRGB8888:
971 sprctl |= SPRITE_FORMAT_RGBX888;
973 case DRM_FORMAT_YUYV:
974 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
976 case DRM_FORMAT_YVYU:
977 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
979 case DRM_FORMAT_UYVY:
980 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
982 case DRM_FORMAT_VYUY:
983 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
986 MISSING_CASE(fb->format->format);
990 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
991 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
993 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
994 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
996 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
997 sprctl |= SPRITE_TILED;
999 if (rotation & DRM_MODE_ROTATE_180)
1000 sprctl |= SPRITE_ROTATE_180;
1002 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1003 sprctl |= SPRITE_DEST_KEY;
1004 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1005 sprctl |= SPRITE_SOURCE_KEY;
1011 ivb_update_plane(struct intel_plane *plane,
1012 const struct intel_crtc_state *crtc_state,
1013 const struct intel_plane_state *plane_state)
1015 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1016 enum pipe pipe = plane->pipe;
1017 u32 sprsurf_offset = plane_state->color_plane[0].offset;
1019 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1020 int crtc_x = plane_state->base.dst.x1;
1021 int crtc_y = plane_state->base.dst.y1;
1022 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1023 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1024 u32 x = plane_state->color_plane[0].x;
1025 u32 y = plane_state->color_plane[0].y;
1026 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1027 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1028 u32 sprctl, sprscale = 0;
1029 unsigned long irqflags;
1031 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1033 /* Sizes are 0 based */
1039 if (crtc_w != src_w || crtc_h != src_h)
1040 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1042 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1044 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1046 I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
1047 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1048 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1049 if (IS_IVYBRIDGE(dev_priv))
1050 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
1053 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
1054 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1055 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1058 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1060 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1061 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1063 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1064 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1068 * The control register self-arms if the plane was previously
1069 * disabled. Try to make the plane enable atomic by writing
1070 * the control register just before the surface register.
1072 I915_WRITE_FW(SPRCTL(pipe), sprctl);
1073 I915_WRITE_FW(SPRSURF(pipe),
1074 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1076 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1080 ivb_disable_plane(struct intel_plane *plane,
1081 const struct intel_crtc_state *crtc_state)
1083 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1084 enum pipe pipe = plane->pipe;
1085 unsigned long irqflags;
1087 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1089 I915_WRITE_FW(SPRCTL(pipe), 0);
1090 /* Disable the scaler */
1091 if (IS_IVYBRIDGE(dev_priv))
1092 I915_WRITE_FW(SPRSCALE(pipe), 0);
1093 I915_WRITE_FW(SPRSURF(pipe), 0);
1095 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1099 ivb_plane_get_hw_state(struct intel_plane *plane,
1102 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1103 enum intel_display_power_domain power_domain;
1104 intel_wakeref_t wakeref;
1107 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1108 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1112 ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1114 *pipe = plane->pipe;
1116 intel_display_power_put(dev_priv, power_domain, wakeref);
1122 g4x_sprite_max_stride(struct intel_plane *plane,
1123 u32 pixel_format, u64 modifier,
1124 unsigned int rotation)
1129 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1133 if (crtc_state->gamma_enable)
1134 dvscntr |= DVS_GAMMA_ENABLE;
1136 if (crtc_state->csc_enable)
1137 dvscntr |= DVS_PIPE_CSC_ENABLE;
1142 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1143 const struct intel_plane_state *plane_state)
1145 struct drm_i915_private *dev_priv =
1146 to_i915(plane_state->base.plane->dev);
1147 const struct drm_framebuffer *fb = plane_state->base.fb;
1148 unsigned int rotation = plane_state->base.rotation;
1149 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1152 dvscntr = DVS_ENABLE;
1154 if (IS_GEN(dev_priv, 6))
1155 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1157 switch (fb->format->format) {
1158 case DRM_FORMAT_XBGR8888:
1159 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1161 case DRM_FORMAT_XRGB8888:
1162 dvscntr |= DVS_FORMAT_RGBX888;
1164 case DRM_FORMAT_YUYV:
1165 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1167 case DRM_FORMAT_YVYU:
1168 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1170 case DRM_FORMAT_UYVY:
1171 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1173 case DRM_FORMAT_VYUY:
1174 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1177 MISSING_CASE(fb->format->format);
1181 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
1182 dvscntr |= DVS_YUV_FORMAT_BT709;
1184 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1185 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1187 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1188 dvscntr |= DVS_TILED;
1190 if (rotation & DRM_MODE_ROTATE_180)
1191 dvscntr |= DVS_ROTATE_180;
1193 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1194 dvscntr |= DVS_DEST_KEY;
1195 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1196 dvscntr |= DVS_SOURCE_KEY;
1202 g4x_update_plane(struct intel_plane *plane,
1203 const struct intel_crtc_state *crtc_state,
1204 const struct intel_plane_state *plane_state)
1206 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1207 enum pipe pipe = plane->pipe;
1208 u32 dvssurf_offset = plane_state->color_plane[0].offset;
1210 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1211 int crtc_x = plane_state->base.dst.x1;
1212 int crtc_y = plane_state->base.dst.y1;
1213 u32 crtc_w = drm_rect_width(&plane_state->base.dst);
1214 u32 crtc_h = drm_rect_height(&plane_state->base.dst);
1215 u32 x = plane_state->color_plane[0].x;
1216 u32 y = plane_state->color_plane[0].y;
1217 u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
1218 u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
1219 u32 dvscntr, dvsscale = 0;
1220 unsigned long irqflags;
1222 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1224 /* Sizes are 0 based */
1230 if (crtc_w != src_w || crtc_h != src_h)
1231 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1233 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1235 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1237 I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
1238 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1239 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1240 I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
1243 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
1244 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1245 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1248 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1249 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1252 * The control register self-arms if the plane was previously
1253 * disabled. Try to make the plane enable atomic by writing
1254 * the control register just before the surface register.
1256 I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
1257 I915_WRITE_FW(DVSSURF(pipe),
1258 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1260 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1264 g4x_disable_plane(struct intel_plane *plane,
1265 const struct intel_crtc_state *crtc_state)
1267 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1268 enum pipe pipe = plane->pipe;
1269 unsigned long irqflags;
1271 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1273 I915_WRITE_FW(DVSCNTR(pipe), 0);
1274 /* Disable the scaler */
1275 I915_WRITE_FW(DVSSCALE(pipe), 0);
1276 I915_WRITE_FW(DVSSURF(pipe), 0);
1278 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1282 g4x_plane_get_hw_state(struct intel_plane *plane,
1285 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1286 enum intel_display_power_domain power_domain;
1287 intel_wakeref_t wakeref;
1290 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1291 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1295 ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1297 *pipe = plane->pipe;
1299 intel_display_power_put(dev_priv, power_domain, wakeref);
1304 static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1309 switch (fb->format->format) {
1318 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1319 struct intel_plane_state *plane_state)
1321 const struct drm_framebuffer *fb = plane_state->base.fb;
1322 const struct drm_rect *src = &plane_state->base.src;
1323 const struct drm_rect *dst = &plane_state->base.dst;
1324 int src_x, src_y, src_w, src_h, crtc_w, crtc_h;
1325 const struct drm_display_mode *adjusted_mode =
1326 &crtc_state->base.adjusted_mode;
1327 unsigned int cpp = fb->format->cpp[0];
1328 unsigned int width_bytes;
1329 int min_width, min_height;
1331 crtc_w = drm_rect_width(dst);
1332 crtc_h = drm_rect_height(dst);
1334 src_x = src->x1 >> 16;
1335 src_y = src->y1 >> 16;
1336 src_w = drm_rect_width(src) >> 16;
1337 src_h = drm_rect_height(src) >> 16;
1339 if (src_w == crtc_w && src_h == crtc_h)
1344 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1346 DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1354 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1356 if (src_w < min_width || src_h < min_height ||
1357 src_w > 2048 || src_h > 2048) {
1358 DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1359 src_w, src_h, min_width, min_height, 2048, 2048);
1363 if (width_bytes > 4096) {
1364 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1369 if (width_bytes > 4096 || fb->pitches[0] > 4096) {
1370 DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1371 fb->pitches[0], 4096);
1379 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1380 struct intel_plane_state *plane_state)
1382 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1383 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1384 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1385 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1388 if (intel_fb_scalable(plane_state->base.fb)) {
1389 if (INTEL_GEN(dev_priv) < 7) {
1391 max_scale = 16 << 16;
1392 } else if (IS_IVYBRIDGE(dev_priv)) {
1394 max_scale = 2 << 16;
1398 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1400 min_scale, max_scale,
1405 if (!plane_state->base.visible)
1408 ret = intel_plane_check_src_coordinates(plane_state);
1412 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1416 ret = i9xx_check_plane_surface(plane_state);
1420 if (INTEL_GEN(dev_priv) >= 7)
1421 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1423 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1428 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1430 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1431 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1432 unsigned int rotation = plane_state->base.rotation;
1434 /* CHV ignores the mirror bit when the rotate bit is set :( */
1435 if (IS_CHERRYVIEW(dev_priv) &&
1436 rotation & DRM_MODE_ROTATE_180 &&
1437 rotation & DRM_MODE_REFLECT_X) {
1438 DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
1446 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1447 struct intel_plane_state *plane_state)
1451 ret = chv_plane_check_rotation(plane_state);
1455 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1457 DRM_PLANE_HELPER_NO_SCALING,
1458 DRM_PLANE_HELPER_NO_SCALING,
1463 if (!plane_state->base.visible)
1466 ret = intel_plane_check_src_coordinates(plane_state);
1470 ret = i9xx_check_plane_surface(plane_state);
1474 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1479 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1480 const struct intel_plane_state *plane_state)
1482 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1483 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1484 const struct drm_framebuffer *fb = plane_state->base.fb;
1485 unsigned int rotation = plane_state->base.rotation;
1486 struct drm_format_name_buf format_name;
1491 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1492 is_ccs_modifier(fb->modifier)) {
1493 DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
1498 if (rotation & DRM_MODE_REFLECT_X &&
1499 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1500 DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
1504 if (drm_rotation_90_or_270(rotation)) {
1505 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
1506 fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
1507 DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
1512 * 90/270 is not allowed with RGB64 16:16:16:16 and
1513 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1515 switch (fb->format->format) {
1516 case DRM_FORMAT_RGB565:
1517 if (INTEL_GEN(dev_priv) >= 11)
1521 case DRM_FORMAT_XRGB16161616F:
1522 case DRM_FORMAT_XBGR16161616F:
1523 case DRM_FORMAT_ARGB16161616F:
1524 case DRM_FORMAT_ABGR16161616F:
1525 DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
1526 drm_get_format_name(fb->format->format,
1534 /* Y-tiling is not supported in IF-ID Interlace mode */
1535 if (crtc_state->base.enable &&
1536 crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1537 (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1538 fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1539 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1540 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) {
1541 DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
1548 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1549 const struct intel_plane_state *plane_state)
1551 struct drm_i915_private *dev_priv =
1552 to_i915(plane_state->base.plane->dev);
1553 int crtc_x = plane_state->base.dst.x1;
1554 int crtc_w = drm_rect_width(&plane_state->base.dst);
1555 int pipe_src_w = crtc_state->pipe_src_w;
1558 * Display WA #1175: cnl,glk
1559 * Planes other than the cursor may cause FIFO underflow and display
1560 * corruption if starting less than 4 pixels from the right edge of
1562 * Besides the above WA fix the similar problem, where planes other
1563 * than the cursor ending less than 4 pixels from the left edge of the
1564 * screen may cause FIFO underflow and display corruption.
1566 if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
1567 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1568 DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
1569 crtc_x + crtc_w < 4 ? "end" : "start",
1570 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1578 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1580 const struct drm_framebuffer *fb = plane_state->base.fb;
1581 unsigned int rotation = plane_state->base.rotation;
1582 int src_w = drm_rect_width(&plane_state->base.src) >> 16;
1584 /* Display WA #1106 */
1585 if (is_planar_yuv_format(fb->format->format) && src_w & 3 &&
1586 (rotation == DRM_MODE_ROTATE_270 ||
1587 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1588 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1595 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1596 struct intel_plane_state *plane_state)
1598 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1599 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1600 const struct drm_framebuffer *fb = plane_state->base.fb;
1601 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1602 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1605 ret = skl_plane_check_fb(crtc_state, plane_state);
1609 /* use scaler when colorkey is not required */
1610 if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
1612 max_scale = skl_max_scale(crtc_state, fb->format->format);
1615 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1617 min_scale, max_scale,
1622 if (!plane_state->base.visible)
1625 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1629 ret = intel_plane_check_src_coordinates(plane_state);
1633 ret = skl_plane_check_nv12_rotation(plane_state);
1637 ret = skl_check_plane_surface(plane_state);
1641 /* HW only has 8 bits pixel precision, disable plane if invisible */
1642 if (!(plane_state->base.alpha >> 8))
1643 plane_state->base.visible = false;
1645 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1647 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1648 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1654 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1656 return INTEL_GEN(dev_priv) >= 9;
1659 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1660 const struct drm_intel_sprite_colorkey *set)
1662 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1663 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1664 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1669 * We want src key enabled on the
1670 * sprite and not on the primary.
1672 if (plane->id == PLANE_PRIMARY &&
1673 set->flags & I915_SET_COLORKEY_SOURCE)
1677 * On SKL+ we want dst key enabled on
1678 * the primary and not on the sprite.
1680 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1681 set->flags & I915_SET_COLORKEY_DESTINATION)
1685 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1686 struct drm_file *file_priv)
1688 struct drm_i915_private *dev_priv = to_i915(dev);
1689 struct drm_intel_sprite_colorkey *set = data;
1690 struct drm_plane *plane;
1691 struct drm_plane_state *plane_state;
1692 struct drm_atomic_state *state;
1693 struct drm_modeset_acquire_ctx ctx;
1696 /* ignore the pointless "none" flag */
1697 set->flags &= ~I915_SET_COLORKEY_NONE;
1699 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1702 /* Make sure we don't try to enable both src & dest simultaneously */
1703 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1706 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1707 set->flags & I915_SET_COLORKEY_DESTINATION)
1710 plane = drm_plane_find(dev, file_priv, set->plane_id);
1711 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1715 * SKL+ only plane 2 can do destination keying against plane 1.
1716 * Also multiple planes can't do destination keying on the same
1717 * pipe simultaneously.
1719 if (INTEL_GEN(dev_priv) >= 9 &&
1720 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1721 set->flags & I915_SET_COLORKEY_DESTINATION)
1724 drm_modeset_acquire_init(&ctx, 0);
1726 state = drm_atomic_state_alloc(plane->dev);
1731 state->acquire_ctx = &ctx;
1734 plane_state = drm_atomic_get_plane_state(state, plane);
1735 ret = PTR_ERR_OR_ZERO(plane_state);
1737 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1740 * On some platforms we have to configure
1741 * the dst colorkey on the primary plane.
1743 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1744 struct intel_crtc *crtc =
1745 intel_get_crtc_for_pipe(dev_priv,
1746 to_intel_plane(plane)->pipe);
1748 plane_state = drm_atomic_get_plane_state(state,
1749 crtc->base.primary);
1750 ret = PTR_ERR_OR_ZERO(plane_state);
1752 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1756 ret = drm_atomic_commit(state);
1758 if (ret != -EDEADLK)
1761 drm_atomic_state_clear(state);
1762 drm_modeset_backoff(&ctx);
1765 drm_atomic_state_put(state);
1767 drm_modeset_drop_locks(&ctx);
1768 drm_modeset_acquire_fini(&ctx);
1772 static const u32 g4x_plane_formats[] = {
1773 DRM_FORMAT_XRGB8888,
1780 static const u64 i9xx_plane_format_modifiers[] = {
1781 I915_FORMAT_MOD_X_TILED,
1782 DRM_FORMAT_MOD_LINEAR,
1783 DRM_FORMAT_MOD_INVALID
1786 static const u32 snb_plane_formats[] = {
1787 DRM_FORMAT_XBGR8888,
1788 DRM_FORMAT_XRGB8888,
1795 static const u32 vlv_plane_formats[] = {
1797 DRM_FORMAT_ABGR8888,
1798 DRM_FORMAT_ARGB8888,
1799 DRM_FORMAT_XBGR8888,
1800 DRM_FORMAT_XRGB8888,
1801 DRM_FORMAT_XBGR2101010,
1802 DRM_FORMAT_ABGR2101010,
1809 static const u32 skl_plane_formats[] = {
1812 DRM_FORMAT_XRGB8888,
1813 DRM_FORMAT_XBGR8888,
1814 DRM_FORMAT_ARGB8888,
1815 DRM_FORMAT_ABGR8888,
1816 DRM_FORMAT_XRGB2101010,
1817 DRM_FORMAT_XBGR2101010,
1824 static const uint32_t icl_plane_formats[] = {
1827 DRM_FORMAT_XRGB8888,
1828 DRM_FORMAT_XBGR8888,
1829 DRM_FORMAT_ARGB8888,
1830 DRM_FORMAT_ABGR8888,
1831 DRM_FORMAT_XRGB2101010,
1832 DRM_FORMAT_XBGR2101010,
1845 static const uint32_t icl_hdr_plane_formats[] = {
1848 DRM_FORMAT_XRGB8888,
1849 DRM_FORMAT_XBGR8888,
1850 DRM_FORMAT_ARGB8888,
1851 DRM_FORMAT_ABGR8888,
1852 DRM_FORMAT_XRGB2101010,
1853 DRM_FORMAT_XBGR2101010,
1854 DRM_FORMAT_XRGB16161616F,
1855 DRM_FORMAT_XBGR16161616F,
1856 DRM_FORMAT_ARGB16161616F,
1857 DRM_FORMAT_ABGR16161616F,
1870 static const u32 skl_planar_formats[] = {
1873 DRM_FORMAT_XRGB8888,
1874 DRM_FORMAT_XBGR8888,
1875 DRM_FORMAT_ARGB8888,
1876 DRM_FORMAT_ABGR8888,
1877 DRM_FORMAT_XRGB2101010,
1878 DRM_FORMAT_XBGR2101010,
1886 static const uint32_t glk_planar_formats[] = {
1889 DRM_FORMAT_XRGB8888,
1890 DRM_FORMAT_XBGR8888,
1891 DRM_FORMAT_ARGB8888,
1892 DRM_FORMAT_ABGR8888,
1893 DRM_FORMAT_XRGB2101010,
1894 DRM_FORMAT_XBGR2101010,
1905 static const uint32_t icl_planar_formats[] = {
1908 DRM_FORMAT_XRGB8888,
1909 DRM_FORMAT_XBGR8888,
1910 DRM_FORMAT_ARGB8888,
1911 DRM_FORMAT_ABGR8888,
1912 DRM_FORMAT_XRGB2101010,
1913 DRM_FORMAT_XBGR2101010,
1930 static const uint32_t icl_hdr_planar_formats[] = {
1933 DRM_FORMAT_XRGB8888,
1934 DRM_FORMAT_XBGR8888,
1935 DRM_FORMAT_ARGB8888,
1936 DRM_FORMAT_ABGR8888,
1937 DRM_FORMAT_XRGB2101010,
1938 DRM_FORMAT_XBGR2101010,
1939 DRM_FORMAT_XRGB16161616F,
1940 DRM_FORMAT_XBGR16161616F,
1941 DRM_FORMAT_ARGB16161616F,
1942 DRM_FORMAT_ABGR16161616F,
1959 static const u64 skl_plane_format_modifiers_noccs[] = {
1960 I915_FORMAT_MOD_Yf_TILED,
1961 I915_FORMAT_MOD_Y_TILED,
1962 I915_FORMAT_MOD_X_TILED,
1963 DRM_FORMAT_MOD_LINEAR,
1964 DRM_FORMAT_MOD_INVALID
1967 static const u64 skl_plane_format_modifiers_ccs[] = {
1968 I915_FORMAT_MOD_Yf_TILED_CCS,
1969 I915_FORMAT_MOD_Y_TILED_CCS,
1970 I915_FORMAT_MOD_Yf_TILED,
1971 I915_FORMAT_MOD_Y_TILED,
1972 I915_FORMAT_MOD_X_TILED,
1973 DRM_FORMAT_MOD_LINEAR,
1974 DRM_FORMAT_MOD_INVALID
1977 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1978 u32 format, u64 modifier)
1981 case DRM_FORMAT_MOD_LINEAR:
1982 case I915_FORMAT_MOD_X_TILED:
1989 case DRM_FORMAT_XRGB8888:
1990 case DRM_FORMAT_YUYV:
1991 case DRM_FORMAT_YVYU:
1992 case DRM_FORMAT_UYVY:
1993 case DRM_FORMAT_VYUY:
1994 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1995 modifier == I915_FORMAT_MOD_X_TILED)
2003 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2004 u32 format, u64 modifier)
2007 case DRM_FORMAT_MOD_LINEAR:
2008 case I915_FORMAT_MOD_X_TILED:
2015 case DRM_FORMAT_XRGB8888:
2016 case DRM_FORMAT_XBGR8888:
2017 case DRM_FORMAT_YUYV:
2018 case DRM_FORMAT_YVYU:
2019 case DRM_FORMAT_UYVY:
2020 case DRM_FORMAT_VYUY:
2021 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2022 modifier == I915_FORMAT_MOD_X_TILED)
2030 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2031 u32 format, u64 modifier)
2034 case DRM_FORMAT_MOD_LINEAR:
2035 case I915_FORMAT_MOD_X_TILED:
2042 case DRM_FORMAT_RGB565:
2043 case DRM_FORMAT_ABGR8888:
2044 case DRM_FORMAT_ARGB8888:
2045 case DRM_FORMAT_XBGR8888:
2046 case DRM_FORMAT_XRGB8888:
2047 case DRM_FORMAT_XBGR2101010:
2048 case DRM_FORMAT_ABGR2101010:
2049 case DRM_FORMAT_YUYV:
2050 case DRM_FORMAT_YVYU:
2051 case DRM_FORMAT_UYVY:
2052 case DRM_FORMAT_VYUY:
2053 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2054 modifier == I915_FORMAT_MOD_X_TILED)
2062 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2063 u32 format, u64 modifier)
2065 struct intel_plane *plane = to_intel_plane(_plane);
2068 case DRM_FORMAT_MOD_LINEAR:
2069 case I915_FORMAT_MOD_X_TILED:
2070 case I915_FORMAT_MOD_Y_TILED:
2071 case I915_FORMAT_MOD_Yf_TILED:
2073 case I915_FORMAT_MOD_Y_TILED_CCS:
2074 case I915_FORMAT_MOD_Yf_TILED_CCS:
2075 if (!plane->has_ccs)
2083 case DRM_FORMAT_XRGB8888:
2084 case DRM_FORMAT_XBGR8888:
2085 case DRM_FORMAT_ARGB8888:
2086 case DRM_FORMAT_ABGR8888:
2087 if (is_ccs_modifier(modifier))
2090 case DRM_FORMAT_RGB565:
2091 case DRM_FORMAT_XRGB2101010:
2092 case DRM_FORMAT_XBGR2101010:
2093 case DRM_FORMAT_YUYV:
2094 case DRM_FORMAT_YVYU:
2095 case DRM_FORMAT_UYVY:
2096 case DRM_FORMAT_VYUY:
2097 case DRM_FORMAT_NV12:
2098 case DRM_FORMAT_P010:
2099 case DRM_FORMAT_P012:
2100 case DRM_FORMAT_P016:
2101 case DRM_FORMAT_Y210:
2102 case DRM_FORMAT_Y212:
2103 case DRM_FORMAT_Y216:
2104 case DRM_FORMAT_Y410:
2105 case DRM_FORMAT_Y412:
2106 case DRM_FORMAT_Y416:
2107 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2111 case DRM_FORMAT_XBGR16161616F:
2112 case DRM_FORMAT_ABGR16161616F:
2113 case DRM_FORMAT_XRGB16161616F:
2114 case DRM_FORMAT_ARGB16161616F:
2115 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2116 modifier == I915_FORMAT_MOD_X_TILED ||
2117 modifier == I915_FORMAT_MOD_Y_TILED)
2125 static const struct drm_plane_funcs g4x_sprite_funcs = {
2126 .update_plane = drm_atomic_helper_update_plane,
2127 .disable_plane = drm_atomic_helper_disable_plane,
2128 .destroy = intel_plane_destroy,
2129 .atomic_get_property = intel_plane_atomic_get_property,
2130 .atomic_set_property = intel_plane_atomic_set_property,
2131 .atomic_duplicate_state = intel_plane_duplicate_state,
2132 .atomic_destroy_state = intel_plane_destroy_state,
2133 .format_mod_supported = g4x_sprite_format_mod_supported,
2136 static const struct drm_plane_funcs snb_sprite_funcs = {
2137 .update_plane = drm_atomic_helper_update_plane,
2138 .disable_plane = drm_atomic_helper_disable_plane,
2139 .destroy = intel_plane_destroy,
2140 .atomic_get_property = intel_plane_atomic_get_property,
2141 .atomic_set_property = intel_plane_atomic_set_property,
2142 .atomic_duplicate_state = intel_plane_duplicate_state,
2143 .atomic_destroy_state = intel_plane_destroy_state,
2144 .format_mod_supported = snb_sprite_format_mod_supported,
2147 static const struct drm_plane_funcs vlv_sprite_funcs = {
2148 .update_plane = drm_atomic_helper_update_plane,
2149 .disable_plane = drm_atomic_helper_disable_plane,
2150 .destroy = intel_plane_destroy,
2151 .atomic_get_property = intel_plane_atomic_get_property,
2152 .atomic_set_property = intel_plane_atomic_set_property,
2153 .atomic_duplicate_state = intel_plane_duplicate_state,
2154 .atomic_destroy_state = intel_plane_destroy_state,
2155 .format_mod_supported = vlv_sprite_format_mod_supported,
2158 static const struct drm_plane_funcs skl_plane_funcs = {
2159 .update_plane = drm_atomic_helper_update_plane,
2160 .disable_plane = drm_atomic_helper_disable_plane,
2161 .destroy = intel_plane_destroy,
2162 .atomic_get_property = intel_plane_atomic_get_property,
2163 .atomic_set_property = intel_plane_atomic_set_property,
2164 .atomic_duplicate_state = intel_plane_duplicate_state,
2165 .atomic_destroy_state = intel_plane_destroy_state,
2166 .format_mod_supported = skl_plane_format_mod_supported,
2169 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2170 enum pipe pipe, enum plane_id plane_id)
2172 if (!HAS_FBC(dev_priv))
2175 return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2178 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2179 enum pipe pipe, enum plane_id plane_id)
2181 if (INTEL_GEN(dev_priv) >= 11)
2182 return plane_id <= PLANE_SPRITE3;
2184 /* Display WA #0870: skl, bxt */
2185 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2188 if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2191 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2197 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
2198 enum pipe pipe, enum plane_id plane_id)
2200 if (plane_id == PLANE_CURSOR)
2203 if (INTEL_GEN(dev_priv) >= 10)
2206 if (IS_GEMINILAKE(dev_priv))
2207 return pipe != PIPE_C;
2209 return pipe != PIPE_C &&
2210 (plane_id == PLANE_PRIMARY ||
2211 plane_id == PLANE_SPRITE0);
2214 struct intel_plane *
2215 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2216 enum pipe pipe, enum plane_id plane_id)
2218 struct intel_plane *plane;
2219 enum drm_plane_type plane_type;
2220 unsigned int supported_rotations;
2221 unsigned int possible_crtcs;
2222 const u64 *modifiers;
2227 plane = intel_plane_alloc();
2232 plane->id = plane_id;
2233 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2235 plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2236 if (plane->has_fbc) {
2237 struct intel_fbc *fbc = &dev_priv->fbc;
2239 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2242 plane->max_stride = skl_plane_max_stride;
2243 plane->update_plane = skl_update_plane;
2244 plane->disable_plane = skl_disable_plane;
2245 plane->get_hw_state = skl_plane_get_hw_state;
2246 plane->check_plane = skl_plane_check;
2247 if (icl_is_nv12_y_plane(plane_id))
2248 plane->update_slave = icl_update_slave;
2250 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2251 if (icl_is_hdr_plane(dev_priv, plane_id)) {
2252 formats = icl_hdr_planar_formats;
2253 num_formats = ARRAY_SIZE(icl_hdr_planar_formats);
2254 } else if (INTEL_GEN(dev_priv) >= 11) {
2255 formats = icl_planar_formats;
2256 num_formats = ARRAY_SIZE(icl_planar_formats);
2257 } else if (INTEL_GEN(dev_priv) == 10 || IS_GEMINILAKE(dev_priv)) {
2258 formats = glk_planar_formats;
2259 num_formats = ARRAY_SIZE(glk_planar_formats);
2261 formats = skl_planar_formats;
2262 num_formats = ARRAY_SIZE(skl_planar_formats);
2264 } else if (icl_is_hdr_plane(dev_priv, plane_id)) {
2265 formats = icl_hdr_plane_formats;
2266 num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2267 } else if (INTEL_GEN(dev_priv) >= 11) {
2268 formats = icl_plane_formats;
2269 num_formats = ARRAY_SIZE(icl_plane_formats);
2271 formats = skl_plane_formats;
2272 num_formats = ARRAY_SIZE(skl_plane_formats);
2275 plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2277 modifiers = skl_plane_format_modifiers_ccs;
2279 modifiers = skl_plane_format_modifiers_noccs;
2281 if (plane_id == PLANE_PRIMARY)
2282 plane_type = DRM_PLANE_TYPE_PRIMARY;
2284 plane_type = DRM_PLANE_TYPE_OVERLAY;
2286 possible_crtcs = BIT(pipe);
2288 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2289 possible_crtcs, &skl_plane_funcs,
2290 formats, num_formats, modifiers,
2292 "plane %d%c", plane_id + 1,
2297 supported_rotations =
2298 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2299 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2301 if (INTEL_GEN(dev_priv) >= 10)
2302 supported_rotations |= DRM_MODE_REFLECT_X;
2304 drm_plane_create_rotation_property(&plane->base,
2306 supported_rotations);
2308 drm_plane_create_color_properties(&plane->base,
2309 BIT(DRM_COLOR_YCBCR_BT601) |
2310 BIT(DRM_COLOR_YCBCR_BT709),
2311 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2312 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2313 DRM_COLOR_YCBCR_BT709,
2314 DRM_COLOR_YCBCR_LIMITED_RANGE);
2316 drm_plane_create_alpha_property(&plane->base);
2317 drm_plane_create_blend_mode_property(&plane->base,
2318 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2319 BIT(DRM_MODE_BLEND_PREMULTI) |
2320 BIT(DRM_MODE_BLEND_COVERAGE));
2322 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2327 intel_plane_free(plane);
2329 return ERR_PTR(ret);
2332 struct intel_plane *
2333 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
2334 enum pipe pipe, int sprite)
2336 struct intel_plane *plane;
2337 const struct drm_plane_funcs *plane_funcs;
2338 unsigned long possible_crtcs;
2339 unsigned int supported_rotations;
2340 const u64 *modifiers;
2345 if (INTEL_GEN(dev_priv) >= 9)
2346 return skl_universal_plane_create(dev_priv, pipe,
2347 PLANE_SPRITE0 + sprite);
2349 plane = intel_plane_alloc();
2353 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
2354 plane->max_stride = i9xx_plane_max_stride;
2355 plane->update_plane = vlv_update_plane;
2356 plane->disable_plane = vlv_disable_plane;
2357 plane->get_hw_state = vlv_plane_get_hw_state;
2358 plane->check_plane = vlv_sprite_check;
2360 formats = vlv_plane_formats;
2361 num_formats = ARRAY_SIZE(vlv_plane_formats);
2362 modifiers = i9xx_plane_format_modifiers;
2364 plane_funcs = &vlv_sprite_funcs;
2365 } else if (INTEL_GEN(dev_priv) >= 7) {
2366 plane->max_stride = g4x_sprite_max_stride;
2367 plane->update_plane = ivb_update_plane;
2368 plane->disable_plane = ivb_disable_plane;
2369 plane->get_hw_state = ivb_plane_get_hw_state;
2370 plane->check_plane = g4x_sprite_check;
2372 formats = snb_plane_formats;
2373 num_formats = ARRAY_SIZE(snb_plane_formats);
2374 modifiers = i9xx_plane_format_modifiers;
2376 plane_funcs = &snb_sprite_funcs;
2378 plane->max_stride = g4x_sprite_max_stride;
2379 plane->update_plane = g4x_update_plane;
2380 plane->disable_plane = g4x_disable_plane;
2381 plane->get_hw_state = g4x_plane_get_hw_state;
2382 plane->check_plane = g4x_sprite_check;
2384 modifiers = i9xx_plane_format_modifiers;
2385 if (IS_GEN(dev_priv, 6)) {
2386 formats = snb_plane_formats;
2387 num_formats = ARRAY_SIZE(snb_plane_formats);
2389 plane_funcs = &snb_sprite_funcs;
2391 formats = g4x_plane_formats;
2392 num_formats = ARRAY_SIZE(g4x_plane_formats);
2394 plane_funcs = &g4x_sprite_funcs;
2398 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
2399 supported_rotations =
2400 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
2403 supported_rotations =
2404 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2408 plane->id = PLANE_SPRITE0 + sprite;
2409 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
2411 possible_crtcs = BIT(pipe);
2413 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2414 possible_crtcs, plane_funcs,
2415 formats, num_formats, modifiers,
2416 DRM_PLANE_TYPE_OVERLAY,
2417 "sprite %c", sprite_name(pipe, sprite));
2421 drm_plane_create_rotation_property(&plane->base,
2423 supported_rotations);
2425 drm_plane_create_color_properties(&plane->base,
2426 BIT(DRM_COLOR_YCBCR_BT601) |
2427 BIT(DRM_COLOR_YCBCR_BT709),
2428 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2429 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2430 DRM_COLOR_YCBCR_BT709,
2431 DRM_COLOR_YCBCR_LIMITED_RANGE);
2433 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2438 intel_plane_free(plane);
2440 return ERR_PTR(ret);