Merge tag 'io_uring-5.11-2021-01-16' of git://git.kernel.dk/linux-block
[linux/fpc-iii.git] / drivers / gpu / drm / i915 / display / intel_sprite.c
blob019a2d6d807a6873fe7a184f12a52c6c6f62aeb8
1 /*
2 * Copyright © 2011 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
23 * Authors:
24 * Jesse Barnes <jbarnes@virtuousgeek.org>
26 * New plane/sprite handling.
28 * The older chips had a separate interface for programming plane related
29 * registers; newer ones are much simpler and we can use the new DRM plane
30 * support.
33 #include <drm/drm_atomic.h>
34 #include <drm/drm_atomic_helper.h>
35 #include <drm/drm_color_mgmt.h>
36 #include <drm/drm_crtc.h>
37 #include <drm/drm_damage_helper.h>
38 #include <drm/drm_fourcc.h>
39 #include <drm/drm_plane_helper.h>
40 #include <drm/drm_rect.h>
42 #include "i915_drv.h"
43 #include "i915_trace.h"
44 #include "i915_vgpu.h"
45 #include "intel_atomic_plane.h"
46 #include "intel_display_types.h"
47 #include "intel_frontbuffer.h"
48 #include "intel_pm.h"
49 #include "intel_psr.h"
50 #include "intel_dsi.h"
51 #include "intel_sprite.h"
53 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
54 int usecs)
56 /* paranoia */
57 if (!adjusted_mode->crtc_htotal)
58 return 1;
60 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
61 1000 * adjusted_mode->crtc_htotal);
64 /* FIXME: We should instead only take spinlocks once for the entire update
65 * instead of once per mmio. */
66 #if IS_ENABLED(CONFIG_PROVE_LOCKING)
67 #define VBLANK_EVASION_TIME_US 250
68 #else
69 #define VBLANK_EVASION_TIME_US 100
70 #endif
72 /**
73 * intel_pipe_update_start() - start update of a set of display registers
74 * @new_crtc_state: the new crtc state
76 * Mark the start of an update to pipe registers that should be updated
77 * atomically regarding vblank. If the next vblank will happens within
78 * the next 100 us, this function waits until the vblank passes.
80 * After a successful call to this function, interrupts will be disabled
81 * until a subsequent call to intel_pipe_update_end(). That is done to
82 * avoid random delays.
84 void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
86 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
87 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
88 const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode;
89 long timeout = msecs_to_jiffies_timeout(1);
90 int scanline, min, max, vblank_start;
91 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
92 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
93 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
94 DEFINE_WAIT(wait);
95 u32 psr_status;
97 if (new_crtc_state->uapi.async_flip)
98 return;
100 vblank_start = adjusted_mode->crtc_vblank_start;
101 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
102 vblank_start = DIV_ROUND_UP(vblank_start, 2);
104 /* FIXME needs to be calibrated sensibly */
105 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
106 VBLANK_EVASION_TIME_US);
107 max = vblank_start - 1;
109 if (min <= 0 || max <= 0)
110 goto irq_disable;
112 if (drm_WARN_ON(&dev_priv->drm, drm_crtc_vblank_get(&crtc->base)))
113 goto irq_disable;
116 * Wait for psr to idle out after enabling the VBL interrupts
117 * VBL interrupts will start the PSR exit and prevent a PSR
118 * re-entry as well.
120 if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
121 drm_err(&dev_priv->drm,
122 "PSR idle timed out 0x%x, atomic update may fail\n",
123 psr_status);
125 local_irq_disable();
127 crtc->debug.min_vbl = min;
128 crtc->debug.max_vbl = max;
129 trace_intel_pipe_update_start(crtc);
131 for (;;) {
133 * prepare_to_wait() has a memory barrier, which guarantees
134 * other CPUs can see the task state update by the time we
135 * read the scanline.
137 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
139 scanline = intel_get_crtc_scanline(crtc);
140 if (scanline < min || scanline > max)
141 break;
143 if (!timeout) {
144 drm_err(&dev_priv->drm,
145 "Potential atomic update failure on pipe %c\n",
146 pipe_name(crtc->pipe));
147 break;
150 local_irq_enable();
152 timeout = schedule_timeout(timeout);
154 local_irq_disable();
157 finish_wait(wq, &wait);
159 drm_crtc_vblank_put(&crtc->base);
162 * On VLV/CHV DSI the scanline counter would appear to
163 * increment approx. 1/3 of a scanline before start of vblank.
164 * The registers still get latched at start of vblank however.
165 * This means we must not write any registers on the first
166 * line of vblank (since not the whole line is actually in
167 * vblank). And unfortunately we can't use the interrupt to
168 * wait here since it will fire too soon. We could use the
169 * frame start interrupt instead since it will fire after the
170 * critical scanline, but that would require more changes
171 * in the interrupt code. So for now we'll just do the nasty
172 * thing and poll for the bad scanline to pass us by.
174 * FIXME figure out if BXT+ DSI suffers from this as well
176 while (need_vlv_dsi_wa && scanline == vblank_start)
177 scanline = intel_get_crtc_scanline(crtc);
179 crtc->debug.scanline_start = scanline;
180 crtc->debug.start_vbl_time = ktime_get();
181 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
183 trace_intel_pipe_update_vblank_evaded(crtc);
184 return;
186 irq_disable:
187 local_irq_disable();
191 * intel_pipe_update_end() - end update of a set of display registers
192 * @new_crtc_state: the new crtc state
194 * Mark the end of an update started with intel_pipe_update_start(). This
195 * re-enables interrupts and verifies the update was actually completed
196 * before a vblank.
198 void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
200 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
201 enum pipe pipe = crtc->pipe;
202 int scanline_end = intel_get_crtc_scanline(crtc);
203 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
204 ktime_t end_vbl_time = ktime_get();
205 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
207 if (new_crtc_state->uapi.async_flip)
208 return;
210 trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end);
213 * Incase of mipi dsi command mode, we need to set frame update
214 * request for every commit.
216 if (INTEL_GEN(dev_priv) >= 11 &&
217 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI))
218 icl_dsi_frame_update(new_crtc_state);
220 /* We're still in the vblank-evade critical section, this can't race.
221 * Would be slightly nice to just grab the vblank count and arm the
222 * event outside of the critical section - the spinlock might spin for a
223 * while ... */
224 if (new_crtc_state->uapi.event) {
225 drm_WARN_ON(&dev_priv->drm,
226 drm_crtc_vblank_get(&crtc->base) != 0);
228 spin_lock(&crtc->base.dev->event_lock);
229 drm_crtc_arm_vblank_event(&crtc->base,
230 new_crtc_state->uapi.event);
231 spin_unlock(&crtc->base.dev->event_lock);
233 new_crtc_state->uapi.event = NULL;
236 local_irq_enable();
238 if (intel_vgpu_active(dev_priv))
239 return;
241 if (crtc->debug.start_vbl_count &&
242 crtc->debug.start_vbl_count != end_vbl_count) {
243 drm_err(&dev_priv->drm,
244 "Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
245 pipe_name(pipe), crtc->debug.start_vbl_count,
246 end_vbl_count,
247 ktime_us_delta(end_vbl_time,
248 crtc->debug.start_vbl_time),
249 crtc->debug.min_vbl, crtc->debug.max_vbl,
250 crtc->debug.scanline_start, scanline_end);
252 #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
253 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
254 VBLANK_EVASION_TIME_US)
255 drm_warn(&dev_priv->drm,
256 "Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
257 pipe_name(pipe),
258 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
259 VBLANK_EVASION_TIME_US);
260 #endif
263 int intel_plane_check_stride(const struct intel_plane_state *plane_state)
265 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
266 const struct drm_framebuffer *fb = plane_state->hw.fb;
267 unsigned int rotation = plane_state->hw.rotation;
268 u32 stride, max_stride;
271 * We ignore stride for all invisible planes that
272 * can be remapped. Otherwise we could end up
273 * with a false positive when the remapping didn't
274 * kick in due the plane being invisible.
276 if (intel_plane_can_remap(plane_state) &&
277 !plane_state->uapi.visible)
278 return 0;
280 /* FIXME other color planes? */
281 stride = plane_state->color_plane[0].stride;
282 max_stride = plane->max_stride(plane, fb->format->format,
283 fb->modifier, rotation);
285 if (stride > max_stride) {
286 DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
287 fb->base.id, stride,
288 plane->base.base.id, plane->base.name, max_stride);
289 return -EINVAL;
292 return 0;
295 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
297 const struct drm_framebuffer *fb = plane_state->hw.fb;
298 struct drm_rect *src = &plane_state->uapi.src;
299 u32 src_x, src_y, src_w, src_h, hsub, vsub;
300 bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
303 * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
304 * abuses hsub/vsub so we can't use them here. But as they
305 * are limited to 32bpp RGB formats we don't actually need
306 * to check anything.
308 if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
309 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
310 return 0;
313 * Hardware doesn't handle subpixel coordinates.
314 * Adjust to (macro)pixel boundary, but be careful not to
315 * increase the source viewport size, because that could
316 * push the downscaling factor out of bounds.
318 src_x = src->x1 >> 16;
319 src_w = drm_rect_width(src) >> 16;
320 src_y = src->y1 >> 16;
321 src_h = drm_rect_height(src) >> 16;
323 drm_rect_init(src, src_x << 16, src_y << 16,
324 src_w << 16, src_h << 16);
326 if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
327 hsub = 2;
328 vsub = 2;
329 } else {
330 hsub = fb->format->hsub;
331 vsub = fb->format->vsub;
334 if (rotated)
335 hsub = vsub = max(hsub, vsub);
337 if (src_x % hsub || src_w % hsub) {
338 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
339 src_x, src_w, hsub, yesno(rotated));
340 return -EINVAL;
343 if (src_y % vsub || src_h % vsub) {
344 DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
345 src_y, src_h, vsub, yesno(rotated));
346 return -EINVAL;
349 return 0;
352 static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
354 if (IS_ROCKETLAKE(i915))
355 return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
356 else
357 return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
360 bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
361 enum plane_id plane_id)
363 return INTEL_GEN(dev_priv) >= 11 &&
364 icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
367 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
369 return INTEL_GEN(dev_priv) >= 11 &&
370 icl_hdr_plane_mask() & BIT(plane_id);
373 static void
374 skl_plane_ratio(const struct intel_crtc_state *crtc_state,
375 const struct intel_plane_state *plane_state,
376 unsigned int *num, unsigned int *den)
378 struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
379 const struct drm_framebuffer *fb = plane_state->hw.fb;
381 if (fb->format->cpp[0] == 8) {
382 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
383 *num = 10;
384 *den = 8;
385 } else {
386 *num = 9;
387 *den = 8;
389 } else {
390 *num = 1;
391 *den = 1;
395 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
396 const struct intel_plane_state *plane_state)
398 struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
399 unsigned int num, den;
400 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
402 skl_plane_ratio(crtc_state, plane_state, &num, &den);
404 /* two pixels per clock on glk+ */
405 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
406 den *= 2;
408 return DIV_ROUND_UP(pixel_rate * num, den);
411 static int skl_plane_max_width(const struct drm_framebuffer *fb,
412 int color_plane,
413 unsigned int rotation)
415 int cpp = fb->format->cpp[color_plane];
417 switch (fb->modifier) {
418 case DRM_FORMAT_MOD_LINEAR:
419 case I915_FORMAT_MOD_X_TILED:
421 * Validated limit is 4k, but has 5k should
422 * work apart from the following features:
423 * - Ytile (already limited to 4k)
424 * - FP16 (already limited to 4k)
425 * - render compression (already limited to 4k)
426 * - KVMR sprite and cursor (don't care)
427 * - horizontal panning (TODO verify this)
428 * - pipe and plane scaling (TODO verify this)
430 if (cpp == 8)
431 return 4096;
432 else
433 return 5120;
434 case I915_FORMAT_MOD_Y_TILED_CCS:
435 case I915_FORMAT_MOD_Yf_TILED_CCS:
436 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
437 /* FIXME AUX plane? */
438 case I915_FORMAT_MOD_Y_TILED:
439 case I915_FORMAT_MOD_Yf_TILED:
440 if (cpp == 8)
441 return 2048;
442 else
443 return 4096;
444 default:
445 MISSING_CASE(fb->modifier);
446 return 2048;
450 static int glk_plane_max_width(const struct drm_framebuffer *fb,
451 int color_plane,
452 unsigned int rotation)
454 int cpp = fb->format->cpp[color_plane];
456 switch (fb->modifier) {
457 case DRM_FORMAT_MOD_LINEAR:
458 case I915_FORMAT_MOD_X_TILED:
459 if (cpp == 8)
460 return 4096;
461 else
462 return 5120;
463 case I915_FORMAT_MOD_Y_TILED_CCS:
464 case I915_FORMAT_MOD_Yf_TILED_CCS:
465 /* FIXME AUX plane? */
466 case I915_FORMAT_MOD_Y_TILED:
467 case I915_FORMAT_MOD_Yf_TILED:
468 if (cpp == 8)
469 return 2048;
470 else
471 return 5120;
472 default:
473 MISSING_CASE(fb->modifier);
474 return 2048;
478 static int icl_plane_min_width(const struct drm_framebuffer *fb,
479 int color_plane,
480 unsigned int rotation)
482 /* Wa_14011264657, Wa_14011050563: gen11+ */
483 switch (fb->format->format) {
484 case DRM_FORMAT_C8:
485 return 18;
486 case DRM_FORMAT_RGB565:
487 return 10;
488 case DRM_FORMAT_XRGB8888:
489 case DRM_FORMAT_XBGR8888:
490 case DRM_FORMAT_ARGB8888:
491 case DRM_FORMAT_ABGR8888:
492 case DRM_FORMAT_XRGB2101010:
493 case DRM_FORMAT_XBGR2101010:
494 case DRM_FORMAT_ARGB2101010:
495 case DRM_FORMAT_ABGR2101010:
496 case DRM_FORMAT_XVYU2101010:
497 case DRM_FORMAT_Y212:
498 case DRM_FORMAT_Y216:
499 return 6;
500 case DRM_FORMAT_NV12:
501 return 20;
502 case DRM_FORMAT_P010:
503 case DRM_FORMAT_P012:
504 case DRM_FORMAT_P016:
505 return 12;
506 case DRM_FORMAT_XRGB16161616F:
507 case DRM_FORMAT_XBGR16161616F:
508 case DRM_FORMAT_ARGB16161616F:
509 case DRM_FORMAT_ABGR16161616F:
510 case DRM_FORMAT_XVYU12_16161616:
511 case DRM_FORMAT_XVYU16161616:
512 return 4;
513 default:
514 return 1;
518 static int icl_plane_max_width(const struct drm_framebuffer *fb,
519 int color_plane,
520 unsigned int rotation)
522 return 5120;
525 static int skl_plane_max_height(const struct drm_framebuffer *fb,
526 int color_plane,
527 unsigned int rotation)
529 return 4096;
532 static int icl_plane_max_height(const struct drm_framebuffer *fb,
533 int color_plane,
534 unsigned int rotation)
536 return 4320;
539 static unsigned int
540 skl_plane_max_stride(struct intel_plane *plane,
541 u32 pixel_format, u64 modifier,
542 unsigned int rotation)
544 const struct drm_format_info *info = drm_format_info(pixel_format);
545 int cpp = info->cpp[0];
548 * "The stride in bytes must not exceed the
549 * of the size of 8K pixels and 32K bytes."
551 if (drm_rotation_90_or_270(rotation))
552 return min(8192, 32768 / cpp);
553 else
554 return min(8192 * cpp, 32768);
557 static void
558 skl_program_scaler(struct intel_plane *plane,
559 const struct intel_crtc_state *crtc_state,
560 const struct intel_plane_state *plane_state)
562 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
563 const struct drm_framebuffer *fb = plane_state->hw.fb;
564 enum pipe pipe = plane->pipe;
565 int scaler_id = plane_state->scaler_id;
566 const struct intel_scaler *scaler =
567 &crtc_state->scaler_state.scalers[scaler_id];
568 int crtc_x = plane_state->uapi.dst.x1;
569 int crtc_y = plane_state->uapi.dst.y1;
570 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
571 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
572 u16 y_hphase, uv_rgb_hphase;
573 u16 y_vphase, uv_rgb_vphase;
574 int hscale, vscale;
575 u32 ps_ctrl;
577 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
578 &plane_state->uapi.dst,
579 0, INT_MAX);
580 vscale = drm_rect_calc_vscale(&plane_state->uapi.src,
581 &plane_state->uapi.dst,
582 0, INT_MAX);
584 /* TODO: handle sub-pixel coordinates */
585 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
586 !icl_is_hdr_plane(dev_priv, plane->id)) {
587 y_hphase = skl_scaler_calc_phase(1, hscale, false);
588 y_vphase = skl_scaler_calc_phase(1, vscale, false);
590 /* MPEG2 chroma siting convention */
591 uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
592 uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
593 } else {
594 /* not used */
595 y_hphase = 0;
596 y_vphase = 0;
598 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
599 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
602 ps_ctrl = skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0);
603 ps_ctrl |= PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode;
605 skl_scaler_setup_filter(dev_priv, pipe, scaler_id, 0,
606 plane_state->hw.scaling_filter);
608 intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
609 intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, scaler_id),
610 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
611 intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, scaler_id),
612 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
613 intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, scaler_id),
614 (crtc_x << 16) | crtc_y);
615 intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, scaler_id),
616 (crtc_w << 16) | crtc_h);
619 /* Preoffset values for YUV to RGB Conversion */
620 #define PREOFF_YUV_TO_RGB_HI 0x1800
621 #define PREOFF_YUV_TO_RGB_ME 0x1F00
622 #define PREOFF_YUV_TO_RGB_LO 0x1800
624 #define ROFF(x) (((x) & 0xffff) << 16)
625 #define GOFF(x) (((x) & 0xffff) << 0)
626 #define BOFF(x) (((x) & 0xffff) << 16)
628 static void
629 icl_program_input_csc(struct intel_plane *plane,
630 const struct intel_crtc_state *crtc_state,
631 const struct intel_plane_state *plane_state)
633 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
634 enum pipe pipe = plane->pipe;
635 enum plane_id plane_id = plane->id;
637 static const u16 input_csc_matrix[][9] = {
639 * BT.601 full range YCbCr -> full range RGB
640 * The matrix required is :
641 * [1.000, 0.000, 1.371,
642 * 1.000, -0.336, -0.698,
643 * 1.000, 1.732, 0.0000]
645 [DRM_COLOR_YCBCR_BT601] = {
646 0x7AF8, 0x7800, 0x0,
647 0x8B28, 0x7800, 0x9AC0,
648 0x0, 0x7800, 0x7DD8,
651 * BT.709 full range YCbCr -> full range RGB
652 * The matrix required is :
653 * [1.000, 0.000, 1.574,
654 * 1.000, -0.187, -0.468,
655 * 1.000, 1.855, 0.0000]
657 [DRM_COLOR_YCBCR_BT709] = {
658 0x7C98, 0x7800, 0x0,
659 0x9EF8, 0x7800, 0xAC00,
660 0x0, 0x7800, 0x7ED8,
663 * BT.2020 full range YCbCr -> full range RGB
664 * The matrix required is :
665 * [1.000, 0.000, 1.474,
666 * 1.000, -0.1645, -0.5713,
667 * 1.000, 1.8814, 0.0000]
669 [DRM_COLOR_YCBCR_BT2020] = {
670 0x7BC8, 0x7800, 0x0,
671 0x8928, 0x7800, 0xAA88,
672 0x0, 0x7800, 0x7F10,
676 /* Matrix for Limited Range to Full Range Conversion */
677 static const u16 input_csc_matrix_lr[][9] = {
679 * BT.601 Limted range YCbCr -> full range RGB
680 * The matrix required is :
681 * [1.164384, 0.000, 1.596027,
682 * 1.164384, -0.39175, -0.812813,
683 * 1.164384, 2.017232, 0.0000]
685 [DRM_COLOR_YCBCR_BT601] = {
686 0x7CC8, 0x7950, 0x0,
687 0x8D00, 0x7950, 0x9C88,
688 0x0, 0x7950, 0x6810,
691 * BT.709 Limited range YCbCr -> full range RGB
692 * The matrix required is :
693 * [1.164384, 0.000, 1.792741,
694 * 1.164384, -0.213249, -0.532909,
695 * 1.164384, 2.112402, 0.0000]
697 [DRM_COLOR_YCBCR_BT709] = {
698 0x7E58, 0x7950, 0x0,
699 0x8888, 0x7950, 0xADA8,
700 0x0, 0x7950, 0x6870,
703 * BT.2020 Limited range YCbCr -> full range RGB
704 * The matrix required is :
705 * [1.164, 0.000, 1.678,
706 * 1.164, -0.1873, -0.6504,
707 * 1.164, 2.1417, 0.0000]
709 [DRM_COLOR_YCBCR_BT2020] = {
710 0x7D70, 0x7950, 0x0,
711 0x8A68, 0x7950, 0xAC00,
712 0x0, 0x7950, 0x6890,
715 const u16 *csc;
717 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
718 csc = input_csc_matrix[plane_state->hw.color_encoding];
719 else
720 csc = input_csc_matrix_lr[plane_state->hw.color_encoding];
722 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
723 ROFF(csc[0]) | GOFF(csc[1]));
724 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
725 BOFF(csc[2]));
726 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
727 ROFF(csc[3]) | GOFF(csc[4]));
728 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
729 BOFF(csc[5]));
730 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
731 ROFF(csc[6]) | GOFF(csc[7]));
732 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
733 BOFF(csc[8]));
735 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
736 PREOFF_YUV_TO_RGB_HI);
737 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
738 intel_de_write_fw(dev_priv,
739 PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
741 else
742 intel_de_write_fw(dev_priv,
743 PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
744 PREOFF_YUV_TO_RGB_ME);
745 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
746 PREOFF_YUV_TO_RGB_LO);
747 intel_de_write_fw(dev_priv,
748 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
749 intel_de_write_fw(dev_priv,
750 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
751 intel_de_write_fw(dev_priv,
752 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
755 static void
756 skl_plane_async_flip(struct intel_plane *plane,
757 const struct intel_crtc_state *crtc_state,
758 const struct intel_plane_state *plane_state)
760 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
761 unsigned long irqflags;
762 enum plane_id plane_id = plane->id;
763 enum pipe pipe = plane->pipe;
764 u32 surf_addr = plane_state->color_plane[0].offset;
765 u32 plane_ctl = plane_state->ctl;
767 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
769 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
771 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
772 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
773 intel_plane_ggtt_offset(plane_state) + surf_addr);
775 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
778 static void
779 skl_program_plane(struct intel_plane *plane,
780 const struct intel_crtc_state *crtc_state,
781 const struct intel_plane_state *plane_state,
782 int color_plane)
784 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
785 enum plane_id plane_id = plane->id;
786 enum pipe pipe = plane->pipe;
787 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
788 u32 surf_addr = plane_state->color_plane[color_plane].offset;
789 u32 stride = skl_plane_stride(plane_state, color_plane);
790 const struct drm_framebuffer *fb = plane_state->hw.fb;
791 int aux_plane = intel_main_to_aux_plane(fb, color_plane);
792 int crtc_x = plane_state->uapi.dst.x1;
793 int crtc_y = plane_state->uapi.dst.y1;
794 u32 x = plane_state->color_plane[color_plane].x;
795 u32 y = plane_state->color_plane[color_plane].y;
796 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
797 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
798 u8 alpha = plane_state->hw.alpha >> 8;
799 u32 plane_color_ctl = 0, aux_dist = 0;
800 unsigned long irqflags;
801 u32 keymsk, keymax;
802 u32 plane_ctl = plane_state->ctl;
804 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
806 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
807 plane_color_ctl = plane_state->color_ctl |
808 glk_plane_color_ctl_crtc(crtc_state);
810 /* Sizes are 0 based */
811 src_w--;
812 src_h--;
814 keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
816 keymsk = key->channel_mask & 0x7ffffff;
817 if (alpha < 0xff)
818 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
820 /* The scaler will handle the output position */
821 if (plane_state->scaler_id >= 0) {
822 crtc_x = 0;
823 crtc_y = 0;
826 if (aux_plane) {
827 aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
829 if (INTEL_GEN(dev_priv) < 12)
830 aux_dist |= skl_plane_stride(plane_state, aux_plane);
833 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
835 intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
836 intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
837 (crtc_y << 16) | crtc_x);
838 intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
839 (src_h << 16) | src_w);
841 intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
843 if (icl_is_hdr_plane(dev_priv, plane_id))
844 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
845 plane_state->cus_ctl);
847 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
848 intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
849 plane_color_ctl);
851 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
852 icl_program_input_csc(plane, crtc_state, plane_state);
854 skl_write_plane_wm(plane, crtc_state);
856 intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
857 key->min_value);
858 intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
859 intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
861 intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
862 (y << 16) | x);
864 if (INTEL_GEN(dev_priv) < 11)
865 intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
866 (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x);
868 if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
869 intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
872 * The control register self-arms if the plane was previously
873 * disabled. Try to make the plane enable atomic by writing
874 * the control register just before the surface register.
876 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
877 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
878 intel_plane_ggtt_offset(plane_state) + surf_addr);
880 if (plane_state->scaler_id >= 0)
881 skl_program_scaler(plane, crtc_state, plane_state);
883 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
886 static void
887 skl_update_plane(struct intel_plane *plane,
888 const struct intel_crtc_state *crtc_state,
889 const struct intel_plane_state *plane_state)
891 int color_plane = 0;
893 if (plane_state->planar_linked_plane && !plane_state->planar_slave)
894 /* Program the UV plane on planar master */
895 color_plane = 1;
897 skl_program_plane(plane, crtc_state, plane_state, color_plane);
899 static void
900 skl_disable_plane(struct intel_plane *plane,
901 const struct intel_crtc_state *crtc_state)
903 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
904 enum plane_id plane_id = plane->id;
905 enum pipe pipe = plane->pipe;
906 unsigned long irqflags;
908 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
910 if (icl_is_hdr_plane(dev_priv, plane_id))
911 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
913 skl_write_plane_wm(plane, crtc_state);
915 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
916 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
918 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
921 static bool
922 skl_plane_get_hw_state(struct intel_plane *plane,
923 enum pipe *pipe)
925 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
926 enum intel_display_power_domain power_domain;
927 enum plane_id plane_id = plane->id;
928 intel_wakeref_t wakeref;
929 bool ret;
931 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
932 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
933 if (!wakeref)
934 return false;
936 ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
938 *pipe = plane->pipe;
940 intel_display_power_put(dev_priv, power_domain, wakeref);
942 return ret;
945 static void i9xx_plane_linear_gamma(u16 gamma[8])
947 /* The points are not evenly spaced. */
948 static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
949 int i;
951 for (i = 0; i < 8; i++)
952 gamma[i] = (in[i] << 8) / 32;
955 static void
956 chv_update_csc(const struct intel_plane_state *plane_state)
958 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
959 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
960 const struct drm_framebuffer *fb = plane_state->hw.fb;
961 enum plane_id plane_id = plane->id;
963 * |r| | c0 c1 c2 | |cr|
964 * |g| = | c3 c4 c5 | x |y |
965 * |b| | c6 c7 c8 | |cb|
967 * Coefficients are s3.12.
969 * Cb and Cr apparently come in as signed already, and
970 * we always get full range data in on account of CLRC0/1.
972 static const s16 csc_matrix[][9] = {
973 /* BT.601 full range YCbCr -> full range RGB */
974 [DRM_COLOR_YCBCR_BT601] = {
975 5743, 4096, 0,
976 -2925, 4096, -1410,
977 0, 4096, 7258,
979 /* BT.709 full range YCbCr -> full range RGB */
980 [DRM_COLOR_YCBCR_BT709] = {
981 6450, 4096, 0,
982 -1917, 4096, -767,
983 0, 4096, 7601,
986 const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
988 /* Seems RGB data bypasses the CSC always */
989 if (!fb->format->is_yuv)
990 return;
992 intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
993 SPCSC_OOFF(0) | SPCSC_IOFF(0));
994 intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
995 SPCSC_OOFF(0) | SPCSC_IOFF(0));
996 intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
997 SPCSC_OOFF(0) | SPCSC_IOFF(0));
999 intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
1000 SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
1001 intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
1002 SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
1003 intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
1004 SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
1005 intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
1006 SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
1007 intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
1009 intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
1010 SPCSC_IMAX(1023) | SPCSC_IMIN(0));
1011 intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
1012 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
1013 intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
1014 SPCSC_IMAX(512) | SPCSC_IMIN(-512));
1016 intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
1017 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
1018 intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
1019 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
1020 intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
1021 SPCSC_OMAX(1023) | SPCSC_OMIN(0));
1024 #define SIN_0 0
1025 #define COS_0 1
1027 static void
1028 vlv_update_clrc(const struct intel_plane_state *plane_state)
1030 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1031 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1032 const struct drm_framebuffer *fb = plane_state->hw.fb;
1033 enum pipe pipe = plane->pipe;
1034 enum plane_id plane_id = plane->id;
1035 int contrast, brightness, sh_scale, sh_sin, sh_cos;
1037 if (fb->format->is_yuv &&
1038 plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
1040 * Expand limited range to full range:
1041 * Contrast is applied first and is used to expand Y range.
1042 * Brightness is applied second and is used to remove the
1043 * offset from Y. Saturation/hue is used to expand CbCr range.
1045 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
1046 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
1047 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
1048 sh_sin = SIN_0 * sh_scale;
1049 sh_cos = COS_0 * sh_scale;
1050 } else {
1051 /* Pass-through everything. */
1052 contrast = 1 << 6;
1053 brightness = 0;
1054 sh_scale = 1 << 7;
1055 sh_sin = SIN_0 * sh_scale;
1056 sh_cos = COS_0 * sh_scale;
1059 /* FIXME these register are single buffered :( */
1060 intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
1061 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
1062 intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
1063 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
1066 static void
1067 vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
1068 const struct intel_plane_state *plane_state,
1069 unsigned int *num, unsigned int *den)
1071 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1072 const struct drm_framebuffer *fb = plane_state->hw.fb;
1073 unsigned int cpp = fb->format->cpp[0];
1076 * VLV bspec only considers cases where all three planes are
1077 * enabled, and cases where the primary and one sprite is enabled.
1078 * Let's assume the case with just two sprites enabled also
1079 * maps to the latter case.
1081 if (hweight8(active_planes) == 3) {
1082 switch (cpp) {
1083 case 8:
1084 *num = 11;
1085 *den = 8;
1086 break;
1087 case 4:
1088 *num = 18;
1089 *den = 16;
1090 break;
1091 default:
1092 *num = 1;
1093 *den = 1;
1094 break;
1096 } else if (hweight8(active_planes) == 2) {
1097 switch (cpp) {
1098 case 8:
1099 *num = 10;
1100 *den = 8;
1101 break;
1102 case 4:
1103 *num = 17;
1104 *den = 16;
1105 break;
1106 default:
1107 *num = 1;
1108 *den = 1;
1109 break;
1111 } else {
1112 switch (cpp) {
1113 case 8:
1114 *num = 10;
1115 *den = 8;
1116 break;
1117 default:
1118 *num = 1;
1119 *den = 1;
1120 break;
1125 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1126 const struct intel_plane_state *plane_state)
1128 unsigned int pixel_rate;
1129 unsigned int num, den;
1132 * Note that crtc_state->pixel_rate accounts for both
1133 * horizontal and vertical panel fitter downscaling factors.
1134 * Pre-HSW bspec tells us to only consider the horizontal
1135 * downscaling factor here. We ignore that and just consider
1136 * both for simplicity.
1138 pixel_rate = crtc_state->pixel_rate;
1140 vlv_plane_ratio(crtc_state, plane_state, &num, &den);
1142 return DIV_ROUND_UP(pixel_rate * num, den);
1145 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1147 u32 sprctl = 0;
1149 if (crtc_state->gamma_enable)
1150 sprctl |= SP_GAMMA_ENABLE;
1152 return sprctl;
1155 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
1156 const struct intel_plane_state *plane_state)
1158 const struct drm_framebuffer *fb = plane_state->hw.fb;
1159 unsigned int rotation = plane_state->hw.rotation;
1160 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1161 u32 sprctl;
1163 sprctl = SP_ENABLE;
1165 switch (fb->format->format) {
1166 case DRM_FORMAT_YUYV:
1167 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
1168 break;
1169 case DRM_FORMAT_YVYU:
1170 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
1171 break;
1172 case DRM_FORMAT_UYVY:
1173 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
1174 break;
1175 case DRM_FORMAT_VYUY:
1176 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
1177 break;
1178 case DRM_FORMAT_C8:
1179 sprctl |= SP_FORMAT_8BPP;
1180 break;
1181 case DRM_FORMAT_RGB565:
1182 sprctl |= SP_FORMAT_BGR565;
1183 break;
1184 case DRM_FORMAT_XRGB8888:
1185 sprctl |= SP_FORMAT_BGRX8888;
1186 break;
1187 case DRM_FORMAT_ARGB8888:
1188 sprctl |= SP_FORMAT_BGRA8888;
1189 break;
1190 case DRM_FORMAT_XBGR2101010:
1191 sprctl |= SP_FORMAT_RGBX1010102;
1192 break;
1193 case DRM_FORMAT_ABGR2101010:
1194 sprctl |= SP_FORMAT_RGBA1010102;
1195 break;
1196 case DRM_FORMAT_XRGB2101010:
1197 sprctl |= SP_FORMAT_BGRX1010102;
1198 break;
1199 case DRM_FORMAT_ARGB2101010:
1200 sprctl |= SP_FORMAT_BGRA1010102;
1201 break;
1202 case DRM_FORMAT_XBGR8888:
1203 sprctl |= SP_FORMAT_RGBX8888;
1204 break;
1205 case DRM_FORMAT_ABGR8888:
1206 sprctl |= SP_FORMAT_RGBA8888;
1207 break;
1208 default:
1209 MISSING_CASE(fb->format->format);
1210 return 0;
1213 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1214 sprctl |= SP_YUV_FORMAT_BT709;
1216 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1217 sprctl |= SP_TILED;
1219 if (rotation & DRM_MODE_ROTATE_180)
1220 sprctl |= SP_ROTATE_180;
1222 if (rotation & DRM_MODE_REFLECT_X)
1223 sprctl |= SP_MIRROR;
1225 if (key->flags & I915_SET_COLORKEY_SOURCE)
1226 sprctl |= SP_SOURCE_KEY;
1228 return sprctl;
1231 static void vlv_update_gamma(const struct intel_plane_state *plane_state)
1233 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1234 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1235 const struct drm_framebuffer *fb = plane_state->hw.fb;
1236 enum pipe pipe = plane->pipe;
1237 enum plane_id plane_id = plane->id;
1238 u16 gamma[8];
1239 int i;
1241 /* Seems RGB data bypasses the gamma always */
1242 if (!fb->format->is_yuv)
1243 return;
1245 i9xx_plane_linear_gamma(gamma);
1247 /* FIXME these register are single buffered :( */
1248 /* The two end points are implicit (0.0 and 1.0) */
1249 for (i = 1; i < 8 - 1; i++)
1250 intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
1251 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1254 static void
1255 vlv_update_plane(struct intel_plane *plane,
1256 const struct intel_crtc_state *crtc_state,
1257 const struct intel_plane_state *plane_state)
1259 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1260 enum pipe pipe = plane->pipe;
1261 enum plane_id plane_id = plane->id;
1262 u32 sprsurf_offset = plane_state->color_plane[0].offset;
1263 u32 linear_offset;
1264 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1265 int crtc_x = plane_state->uapi.dst.x1;
1266 int crtc_y = plane_state->uapi.dst.y1;
1267 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1268 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1269 u32 x = plane_state->color_plane[0].x;
1270 u32 y = plane_state->color_plane[0].y;
1271 unsigned long irqflags;
1272 u32 sprctl;
1274 sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
1276 /* Sizes are 0 based */
1277 crtc_w--;
1278 crtc_h--;
1280 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1282 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1284 intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
1285 plane_state->color_plane[0].stride);
1286 intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
1287 (crtc_y << 16) | crtc_x);
1288 intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
1289 (crtc_h << 16) | crtc_w);
1290 intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
1292 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
1293 chv_update_csc(plane_state);
1295 if (key->flags) {
1296 intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
1297 key->min_value);
1298 intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
1299 key->channel_mask);
1300 intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
1301 key->max_value);
1304 intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
1305 intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id), (y << 16) | x);
1308 * The control register self-arms if the plane was previously
1309 * disabled. Try to make the plane enable atomic by writing
1310 * the control register just before the surface register.
1312 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
1313 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
1314 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1316 vlv_update_clrc(plane_state);
1317 vlv_update_gamma(plane_state);
1319 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1322 static void
1323 vlv_disable_plane(struct intel_plane *plane,
1324 const struct intel_crtc_state *crtc_state)
1326 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1327 enum pipe pipe = plane->pipe;
1328 enum plane_id plane_id = plane->id;
1329 unsigned long irqflags;
1331 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1333 intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
1334 intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
1336 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1339 static bool
1340 vlv_plane_get_hw_state(struct intel_plane *plane,
1341 enum pipe *pipe)
1343 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1344 enum intel_display_power_domain power_domain;
1345 enum plane_id plane_id = plane->id;
1346 intel_wakeref_t wakeref;
1347 bool ret;
1349 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1350 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1351 if (!wakeref)
1352 return false;
1354 ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
1356 *pipe = plane->pipe;
1358 intel_display_power_put(dev_priv, power_domain, wakeref);
1360 return ret;
1363 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
1364 const struct intel_plane_state *plane_state,
1365 unsigned int *num, unsigned int *den)
1367 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1368 const struct drm_framebuffer *fb = plane_state->hw.fb;
1369 unsigned int cpp = fb->format->cpp[0];
1371 if (hweight8(active_planes) == 2) {
1372 switch (cpp) {
1373 case 8:
1374 *num = 10;
1375 *den = 8;
1376 break;
1377 case 4:
1378 *num = 17;
1379 *den = 16;
1380 break;
1381 default:
1382 *num = 1;
1383 *den = 1;
1384 break;
1386 } else {
1387 switch (cpp) {
1388 case 8:
1389 *num = 9;
1390 *den = 8;
1391 break;
1392 default:
1393 *num = 1;
1394 *den = 1;
1395 break;
1400 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
1401 const struct intel_plane_state *plane_state,
1402 unsigned int *num, unsigned int *den)
1404 const struct drm_framebuffer *fb = plane_state->hw.fb;
1405 unsigned int cpp = fb->format->cpp[0];
1407 switch (cpp) {
1408 case 8:
1409 *num = 12;
1410 *den = 8;
1411 break;
1412 case 4:
1413 *num = 19;
1414 *den = 16;
1415 break;
1416 case 2:
1417 *num = 33;
1418 *den = 32;
1419 break;
1420 default:
1421 *num = 1;
1422 *den = 1;
1423 break;
1427 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1428 const struct intel_plane_state *plane_state)
1430 unsigned int pixel_rate;
1431 unsigned int num, den;
1434 * Note that crtc_state->pixel_rate accounts for both
1435 * horizontal and vertical panel fitter downscaling factors.
1436 * Pre-HSW bspec tells us to only consider the horizontal
1437 * downscaling factor here. We ignore that and just consider
1438 * both for simplicity.
1440 pixel_rate = crtc_state->pixel_rate;
1442 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1444 return DIV_ROUND_UP(pixel_rate * num, den);
1447 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1448 const struct intel_plane_state *plane_state)
1450 unsigned int src_w, dst_w, pixel_rate;
1451 unsigned int num, den;
1454 * Note that crtc_state->pixel_rate accounts for both
1455 * horizontal and vertical panel fitter downscaling factors.
1456 * Pre-HSW bspec tells us to only consider the horizontal
1457 * downscaling factor here. We ignore that and just consider
1458 * both for simplicity.
1460 pixel_rate = crtc_state->pixel_rate;
1462 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1463 dst_w = drm_rect_width(&plane_state->uapi.dst);
1465 if (src_w != dst_w)
1466 ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
1467 else
1468 ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1470 /* Horizontal downscaling limits the maximum pixel rate */
1471 dst_w = min(src_w, dst_w);
1473 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
1474 den * dst_w);
1477 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
1478 const struct intel_plane_state *plane_state,
1479 unsigned int *num, unsigned int *den)
1481 u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1482 const struct drm_framebuffer *fb = plane_state->hw.fb;
1483 unsigned int cpp = fb->format->cpp[0];
1485 if (hweight8(active_planes) == 2) {
1486 switch (cpp) {
1487 case 8:
1488 *num = 10;
1489 *den = 8;
1490 break;
1491 default:
1492 *num = 1;
1493 *den = 1;
1494 break;
1496 } else {
1497 switch (cpp) {
1498 case 8:
1499 *num = 9;
1500 *den = 8;
1501 break;
1502 default:
1503 *num = 1;
1504 *den = 1;
1505 break;
1510 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1511 const struct intel_plane_state *plane_state)
1513 unsigned int pixel_rate = crtc_state->pixel_rate;
1514 unsigned int num, den;
1516 hsw_plane_ratio(crtc_state, plane_state, &num, &den);
1518 return DIV_ROUND_UP(pixel_rate * num, den);
1521 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1523 u32 sprctl = 0;
1525 if (crtc_state->gamma_enable)
1526 sprctl |= SPRITE_GAMMA_ENABLE;
1528 if (crtc_state->csc_enable)
1529 sprctl |= SPRITE_PIPE_CSC_ENABLE;
1531 return sprctl;
1534 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
1536 struct drm_i915_private *dev_priv =
1537 to_i915(plane_state->uapi.plane->dev);
1538 const struct drm_framebuffer *fb = plane_state->hw.fb;
1540 return fb->format->cpp[0] == 8 &&
1541 (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
1544 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
1545 const struct intel_plane_state *plane_state)
1547 struct drm_i915_private *dev_priv =
1548 to_i915(plane_state->uapi.plane->dev);
1549 const struct drm_framebuffer *fb = plane_state->hw.fb;
1550 unsigned int rotation = plane_state->hw.rotation;
1551 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1552 u32 sprctl;
1554 sprctl = SPRITE_ENABLE;
1556 if (IS_IVYBRIDGE(dev_priv))
1557 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
1559 switch (fb->format->format) {
1560 case DRM_FORMAT_XBGR8888:
1561 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1562 break;
1563 case DRM_FORMAT_XRGB8888:
1564 sprctl |= SPRITE_FORMAT_RGBX888;
1565 break;
1566 case DRM_FORMAT_XBGR2101010:
1567 sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
1568 break;
1569 case DRM_FORMAT_XRGB2101010:
1570 sprctl |= SPRITE_FORMAT_RGBX101010;
1571 break;
1572 case DRM_FORMAT_XBGR16161616F:
1573 sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
1574 break;
1575 case DRM_FORMAT_XRGB16161616F:
1576 sprctl |= SPRITE_FORMAT_RGBX161616;
1577 break;
1578 case DRM_FORMAT_YUYV:
1579 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
1580 break;
1581 case DRM_FORMAT_YVYU:
1582 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
1583 break;
1584 case DRM_FORMAT_UYVY:
1585 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
1586 break;
1587 case DRM_FORMAT_VYUY:
1588 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
1589 break;
1590 default:
1591 MISSING_CASE(fb->format->format);
1592 return 0;
1595 if (!ivb_need_sprite_gamma(plane_state))
1596 sprctl |= SPRITE_INT_GAMMA_DISABLE;
1598 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1599 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1601 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1602 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1604 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1605 sprctl |= SPRITE_TILED;
1607 if (rotation & DRM_MODE_ROTATE_180)
1608 sprctl |= SPRITE_ROTATE_180;
1610 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1611 sprctl |= SPRITE_DEST_KEY;
1612 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1613 sprctl |= SPRITE_SOURCE_KEY;
1615 return sprctl;
1618 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
1619 u16 gamma[18])
1621 int scale, i;
1624 * WaFP16GammaEnabling:ivb,hsw
1625 * "Workaround : When using the 64-bit format, the sprite output
1626 * on each color channel has one quarter amplitude. It can be
1627 * brought up to full amplitude by using sprite internal gamma
1628 * correction, pipe gamma correction, or pipe color space
1629 * conversion to multiply the sprite output by four."
1631 scale = 4;
1633 for (i = 0; i < 16; i++)
1634 gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
1636 gamma[i] = min((scale * i << 10) / 16, 1 << 10);
1637 i++;
1639 gamma[i] = 3 << 10;
1640 i++;
1643 static void ivb_update_gamma(const struct intel_plane_state *plane_state)
1645 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1646 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1647 enum pipe pipe = plane->pipe;
1648 u16 gamma[18];
1649 int i;
1651 if (!ivb_need_sprite_gamma(plane_state))
1652 return;
1654 ivb_sprite_linear_gamma(plane_state, gamma);
1656 /* FIXME these register are single buffered :( */
1657 for (i = 0; i < 16; i++)
1658 intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
1659 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1661 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
1662 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
1663 intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
1664 i++;
1666 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
1667 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
1668 intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
1669 i++;
1672 static void
1673 ivb_update_plane(struct intel_plane *plane,
1674 const struct intel_crtc_state *crtc_state,
1675 const struct intel_plane_state *plane_state)
1677 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1678 enum pipe pipe = plane->pipe;
1679 u32 sprsurf_offset = plane_state->color_plane[0].offset;
1680 u32 linear_offset;
1681 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1682 int crtc_x = plane_state->uapi.dst.x1;
1683 int crtc_y = plane_state->uapi.dst.y1;
1684 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1685 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1686 u32 x = plane_state->color_plane[0].x;
1687 u32 y = plane_state->color_plane[0].y;
1688 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1689 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1690 u32 sprctl, sprscale = 0;
1691 unsigned long irqflags;
1693 sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1695 /* Sizes are 0 based */
1696 src_w--;
1697 src_h--;
1698 crtc_w--;
1699 crtc_h--;
1701 if (crtc_w != src_w || crtc_h != src_h)
1702 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1704 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1706 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1708 intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
1709 plane_state->color_plane[0].stride);
1710 intel_de_write_fw(dev_priv, SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1711 intel_de_write_fw(dev_priv, SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1712 if (IS_IVYBRIDGE(dev_priv))
1713 intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
1715 if (key->flags) {
1716 intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
1717 intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
1718 key->channel_mask);
1719 intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
1722 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1723 * register */
1724 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1725 intel_de_write_fw(dev_priv, SPROFFSET(pipe), (y << 16) | x);
1726 } else {
1727 intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
1728 intel_de_write_fw(dev_priv, SPRTILEOFF(pipe), (y << 16) | x);
1732 * The control register self-arms if the plane was previously
1733 * disabled. Try to make the plane enable atomic by writing
1734 * the control register just before the surface register.
1736 intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
1737 intel_de_write_fw(dev_priv, SPRSURF(pipe),
1738 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1740 ivb_update_gamma(plane_state);
1742 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1745 static void
1746 ivb_disable_plane(struct intel_plane *plane,
1747 const struct intel_crtc_state *crtc_state)
1749 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1750 enum pipe pipe = plane->pipe;
1751 unsigned long irqflags;
1753 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1755 intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
1756 /* Disable the scaler */
1757 if (IS_IVYBRIDGE(dev_priv))
1758 intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
1759 intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
1761 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1764 static bool
1765 ivb_plane_get_hw_state(struct intel_plane *plane,
1766 enum pipe *pipe)
1768 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1769 enum intel_display_power_domain power_domain;
1770 intel_wakeref_t wakeref;
1771 bool ret;
1773 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1774 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1775 if (!wakeref)
1776 return false;
1778 ret = intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1780 *pipe = plane->pipe;
1782 intel_display_power_put(dev_priv, power_domain, wakeref);
1784 return ret;
1787 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1788 const struct intel_plane_state *plane_state)
1790 const struct drm_framebuffer *fb = plane_state->hw.fb;
1791 unsigned int hscale, pixel_rate;
1792 unsigned int limit, decimate;
1795 * Note that crtc_state->pixel_rate accounts for both
1796 * horizontal and vertical panel fitter downscaling factors.
1797 * Pre-HSW bspec tells us to only consider the horizontal
1798 * downscaling factor here. We ignore that and just consider
1799 * both for simplicity.
1801 pixel_rate = crtc_state->pixel_rate;
1803 /* Horizontal downscaling limits the maximum pixel rate */
1804 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
1805 &plane_state->uapi.dst,
1806 0, INT_MAX);
1807 hscale = max(hscale, 0x10000u);
1809 /* Decimation steps at 2x,4x,8x,16x */
1810 decimate = ilog2(hscale >> 16);
1811 hscale >>= decimate;
1813 /* Starting limit is 90% of cdclk */
1814 limit = 9;
1816 /* -10% per decimation step */
1817 limit -= decimate;
1819 /* -10% for RGB */
1820 if (!fb->format->is_yuv)
1821 limit--;
1824 * We should also do -10% if sprite scaling is enabled
1825 * on the other pipe, but we can't really check for that,
1826 * so we ignore it.
1829 return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
1830 limit << 16);
1833 static unsigned int
1834 g4x_sprite_max_stride(struct intel_plane *plane,
1835 u32 pixel_format, u64 modifier,
1836 unsigned int rotation)
1838 return 16384;
1841 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1843 u32 dvscntr = 0;
1845 if (crtc_state->gamma_enable)
1846 dvscntr |= DVS_GAMMA_ENABLE;
1848 if (crtc_state->csc_enable)
1849 dvscntr |= DVS_PIPE_CSC_ENABLE;
1851 return dvscntr;
1854 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1855 const struct intel_plane_state *plane_state)
1857 struct drm_i915_private *dev_priv =
1858 to_i915(plane_state->uapi.plane->dev);
1859 const struct drm_framebuffer *fb = plane_state->hw.fb;
1860 unsigned int rotation = plane_state->hw.rotation;
1861 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1862 u32 dvscntr;
1864 dvscntr = DVS_ENABLE;
1866 if (IS_GEN(dev_priv, 6))
1867 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1869 switch (fb->format->format) {
1870 case DRM_FORMAT_XBGR8888:
1871 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1872 break;
1873 case DRM_FORMAT_XRGB8888:
1874 dvscntr |= DVS_FORMAT_RGBX888;
1875 break;
1876 case DRM_FORMAT_XBGR2101010:
1877 dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1878 break;
1879 case DRM_FORMAT_XRGB2101010:
1880 dvscntr |= DVS_FORMAT_RGBX101010;
1881 break;
1882 case DRM_FORMAT_XBGR16161616F:
1883 dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1884 break;
1885 case DRM_FORMAT_XRGB16161616F:
1886 dvscntr |= DVS_FORMAT_RGBX161616;
1887 break;
1888 case DRM_FORMAT_YUYV:
1889 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1890 break;
1891 case DRM_FORMAT_YVYU:
1892 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1893 break;
1894 case DRM_FORMAT_UYVY:
1895 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1896 break;
1897 case DRM_FORMAT_VYUY:
1898 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1899 break;
1900 default:
1901 MISSING_CASE(fb->format->format);
1902 return 0;
1905 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1906 dvscntr |= DVS_YUV_FORMAT_BT709;
1908 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1909 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1911 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1912 dvscntr |= DVS_TILED;
1914 if (rotation & DRM_MODE_ROTATE_180)
1915 dvscntr |= DVS_ROTATE_180;
1917 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1918 dvscntr |= DVS_DEST_KEY;
1919 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1920 dvscntr |= DVS_SOURCE_KEY;
1922 return dvscntr;
1925 static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1927 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1928 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1929 const struct drm_framebuffer *fb = plane_state->hw.fb;
1930 enum pipe pipe = plane->pipe;
1931 u16 gamma[8];
1932 int i;
1934 /* Seems RGB data bypasses the gamma always */
1935 if (!fb->format->is_yuv)
1936 return;
1938 i9xx_plane_linear_gamma(gamma);
1940 /* FIXME these register are single buffered :( */
1941 /* The two end points are implicit (0.0 and 1.0) */
1942 for (i = 1; i < 8 - 1; i++)
1943 intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1944 gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1947 static void ilk_sprite_linear_gamma(u16 gamma[17])
1949 int i;
1951 for (i = 0; i < 17; i++)
1952 gamma[i] = (i << 10) / 16;
1955 static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1957 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1958 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1959 const struct drm_framebuffer *fb = plane_state->hw.fb;
1960 enum pipe pipe = plane->pipe;
1961 u16 gamma[17];
1962 int i;
1964 /* Seems RGB data bypasses the gamma always */
1965 if (!fb->format->is_yuv)
1966 return;
1968 ilk_sprite_linear_gamma(gamma);
1970 /* FIXME these register are single buffered :( */
1971 for (i = 0; i < 16; i++)
1972 intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1973 gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1975 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1976 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1977 intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1978 i++;
1981 static void
1982 g4x_update_plane(struct intel_plane *plane,
1983 const struct intel_crtc_state *crtc_state,
1984 const struct intel_plane_state *plane_state)
1986 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1987 enum pipe pipe = plane->pipe;
1988 u32 dvssurf_offset = plane_state->color_plane[0].offset;
1989 u32 linear_offset;
1990 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1991 int crtc_x = plane_state->uapi.dst.x1;
1992 int crtc_y = plane_state->uapi.dst.y1;
1993 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1994 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1995 u32 x = plane_state->color_plane[0].x;
1996 u32 y = plane_state->color_plane[0].y;
1997 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1998 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1999 u32 dvscntr, dvsscale = 0;
2000 unsigned long irqflags;
2002 dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
2004 /* Sizes are 0 based */
2005 src_w--;
2006 src_h--;
2007 crtc_w--;
2008 crtc_h--;
2010 if (crtc_w != src_w || crtc_h != src_h)
2011 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
2013 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
2015 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
2017 intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
2018 plane_state->color_plane[0].stride);
2019 intel_de_write_fw(dev_priv, DVSPOS(pipe), (crtc_y << 16) | crtc_x);
2020 intel_de_write_fw(dev_priv, DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
2021 intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
2023 if (key->flags) {
2024 intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
2025 intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
2026 key->channel_mask);
2027 intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
2030 intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
2031 intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
2034 * The control register self-arms if the plane was previously
2035 * disabled. Try to make the plane enable atomic by writing
2036 * the control register just before the surface register.
2038 intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
2039 intel_de_write_fw(dev_priv, DVSSURF(pipe),
2040 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
2042 if (IS_G4X(dev_priv))
2043 g4x_update_gamma(plane_state);
2044 else
2045 ilk_update_gamma(plane_state);
2047 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
2050 static void
2051 g4x_disable_plane(struct intel_plane *plane,
2052 const struct intel_crtc_state *crtc_state)
2054 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2055 enum pipe pipe = plane->pipe;
2056 unsigned long irqflags;
2058 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
2060 intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
2061 /* Disable the scaler */
2062 intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
2063 intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
2065 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
2068 static bool
2069 g4x_plane_get_hw_state(struct intel_plane *plane,
2070 enum pipe *pipe)
2072 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2073 enum intel_display_power_domain power_domain;
2074 intel_wakeref_t wakeref;
2075 bool ret;
2077 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
2078 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
2079 if (!wakeref)
2080 return false;
2082 ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
2084 *pipe = plane->pipe;
2086 intel_display_power_put(dev_priv, power_domain, wakeref);
2088 return ret;
2091 static bool intel_fb_scalable(const struct drm_framebuffer *fb)
2093 if (!fb)
2094 return false;
2096 switch (fb->format->format) {
2097 case DRM_FORMAT_C8:
2098 return false;
2099 case DRM_FORMAT_XRGB16161616F:
2100 case DRM_FORMAT_ARGB16161616F:
2101 case DRM_FORMAT_XBGR16161616F:
2102 case DRM_FORMAT_ABGR16161616F:
2103 return INTEL_GEN(to_i915(fb->dev)) >= 11;
2104 default:
2105 return true;
2109 static int
2110 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
2111 struct intel_plane_state *plane_state)
2113 const struct drm_framebuffer *fb = plane_state->hw.fb;
2114 const struct drm_rect *src = &plane_state->uapi.src;
2115 const struct drm_rect *dst = &plane_state->uapi.dst;
2116 int src_x, src_w, src_h, crtc_w, crtc_h;
2117 const struct drm_display_mode *adjusted_mode =
2118 &crtc_state->hw.adjusted_mode;
2119 unsigned int stride = plane_state->color_plane[0].stride;
2120 unsigned int cpp = fb->format->cpp[0];
2121 unsigned int width_bytes;
2122 int min_width, min_height;
2124 crtc_w = drm_rect_width(dst);
2125 crtc_h = drm_rect_height(dst);
2127 src_x = src->x1 >> 16;
2128 src_w = drm_rect_width(src) >> 16;
2129 src_h = drm_rect_height(src) >> 16;
2131 if (src_w == crtc_w && src_h == crtc_h)
2132 return 0;
2134 min_width = 3;
2136 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
2137 if (src_h & 1) {
2138 DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
2139 return -EINVAL;
2141 min_height = 6;
2142 } else {
2143 min_height = 3;
2146 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
2148 if (src_w < min_width || src_h < min_height ||
2149 src_w > 2048 || src_h > 2048) {
2150 DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
2151 src_w, src_h, min_width, min_height, 2048, 2048);
2152 return -EINVAL;
2155 if (width_bytes > 4096) {
2156 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
2157 width_bytes, 4096);
2158 return -EINVAL;
2161 if (stride > 4096) {
2162 DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
2163 stride, 4096);
2164 return -EINVAL;
2167 return 0;
2170 static int
2171 g4x_sprite_check(struct intel_crtc_state *crtc_state,
2172 struct intel_plane_state *plane_state)
2174 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2175 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2176 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
2177 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
2178 int ret;
2180 if (intel_fb_scalable(plane_state->hw.fb)) {
2181 if (INTEL_GEN(dev_priv) < 7) {
2182 min_scale = 1;
2183 max_scale = 16 << 16;
2184 } else if (IS_IVYBRIDGE(dev_priv)) {
2185 min_scale = 1;
2186 max_scale = 2 << 16;
2190 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
2191 min_scale, max_scale, true);
2192 if (ret)
2193 return ret;
2195 ret = i9xx_check_plane_surface(plane_state);
2196 if (ret)
2197 return ret;
2199 if (!plane_state->uapi.visible)
2200 return 0;
2202 ret = intel_plane_check_src_coordinates(plane_state);
2203 if (ret)
2204 return ret;
2206 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
2207 if (ret)
2208 return ret;
2210 if (INTEL_GEN(dev_priv) >= 7)
2211 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
2212 else
2213 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
2215 return 0;
2218 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
2220 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2221 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2222 unsigned int rotation = plane_state->hw.rotation;
2224 /* CHV ignores the mirror bit when the rotate bit is set :( */
2225 if (IS_CHERRYVIEW(dev_priv) &&
2226 rotation & DRM_MODE_ROTATE_180 &&
2227 rotation & DRM_MODE_REFLECT_X) {
2228 drm_dbg_kms(&dev_priv->drm,
2229 "Cannot rotate and reflect at the same time\n");
2230 return -EINVAL;
2233 return 0;
2236 static int
2237 vlv_sprite_check(struct intel_crtc_state *crtc_state,
2238 struct intel_plane_state *plane_state)
2240 int ret;
2242 ret = chv_plane_check_rotation(plane_state);
2243 if (ret)
2244 return ret;
2246 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
2247 DRM_PLANE_HELPER_NO_SCALING,
2248 DRM_PLANE_HELPER_NO_SCALING,
2249 true);
2250 if (ret)
2251 return ret;
2253 ret = i9xx_check_plane_surface(plane_state);
2254 if (ret)
2255 return ret;
2257 if (!plane_state->uapi.visible)
2258 return 0;
2260 ret = intel_plane_check_src_coordinates(plane_state);
2261 if (ret)
2262 return ret;
2264 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
2266 return 0;
2269 static bool intel_format_is_p01x(u32 format)
2271 switch (format) {
2272 case DRM_FORMAT_P010:
2273 case DRM_FORMAT_P012:
2274 case DRM_FORMAT_P016:
2275 return true;
2276 default:
2277 return false;
2281 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
2282 const struct intel_plane_state *plane_state)
2284 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2285 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2286 const struct drm_framebuffer *fb = plane_state->hw.fb;
2287 unsigned int rotation = plane_state->hw.rotation;
2288 struct drm_format_name_buf format_name;
2290 if (!fb)
2291 return 0;
2293 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
2294 is_ccs_modifier(fb->modifier)) {
2295 drm_dbg_kms(&dev_priv->drm,
2296 "RC support only with 0/180 degree rotation (%x)\n",
2297 rotation);
2298 return -EINVAL;
2301 if (rotation & DRM_MODE_REFLECT_X &&
2302 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
2303 drm_dbg_kms(&dev_priv->drm,
2304 "horizontal flip is not supported with linear surface formats\n");
2305 return -EINVAL;
2308 if (drm_rotation_90_or_270(rotation)) {
2309 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
2310 fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
2311 drm_dbg_kms(&dev_priv->drm,
2312 "Y/Yf tiling required for 90/270!\n");
2313 return -EINVAL;
2317 * 90/270 is not allowed with RGB64 16:16:16:16 and
2318 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
2320 switch (fb->format->format) {
2321 case DRM_FORMAT_RGB565:
2322 if (INTEL_GEN(dev_priv) >= 11)
2323 break;
2324 fallthrough;
2325 case DRM_FORMAT_C8:
2326 case DRM_FORMAT_XRGB16161616F:
2327 case DRM_FORMAT_XBGR16161616F:
2328 case DRM_FORMAT_ARGB16161616F:
2329 case DRM_FORMAT_ABGR16161616F:
2330 case DRM_FORMAT_Y210:
2331 case DRM_FORMAT_Y212:
2332 case DRM_FORMAT_Y216:
2333 case DRM_FORMAT_XVYU12_16161616:
2334 case DRM_FORMAT_XVYU16161616:
2335 drm_dbg_kms(&dev_priv->drm,
2336 "Unsupported pixel format %s for 90/270!\n",
2337 drm_get_format_name(fb->format->format,
2338 &format_name));
2339 return -EINVAL;
2340 default:
2341 break;
2345 /* Y-tiling is not supported in IF-ID Interlace mode */
2346 if (crtc_state->hw.enable &&
2347 crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
2348 (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
2349 fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
2350 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
2351 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
2352 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
2353 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)) {
2354 drm_dbg_kms(&dev_priv->drm,
2355 "Y/Yf tiling not supported in IF-ID mode\n");
2356 return -EINVAL;
2359 /* Wa_1606054188:tgl */
2360 if (IS_TIGERLAKE(dev_priv) &&
2361 plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
2362 intel_format_is_p01x(fb->format->format)) {
2363 drm_dbg_kms(&dev_priv->drm,
2364 "Source color keying not supported with P01x formats\n");
2365 return -EINVAL;
2368 return 0;
2371 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
2372 const struct intel_plane_state *plane_state)
2374 struct drm_i915_private *dev_priv =
2375 to_i915(plane_state->uapi.plane->dev);
2376 int crtc_x = plane_state->uapi.dst.x1;
2377 int crtc_w = drm_rect_width(&plane_state->uapi.dst);
2378 int pipe_src_w = crtc_state->pipe_src_w;
2381 * Display WA #1175: cnl,glk
2382 * Planes other than the cursor may cause FIFO underflow and display
2383 * corruption if starting less than 4 pixels from the right edge of
2384 * the screen.
2385 * Besides the above WA fix the similar problem, where planes other
2386 * than the cursor ending less than 4 pixels from the left edge of the
2387 * screen may cause FIFO underflow and display corruption.
2389 if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
2390 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
2391 drm_dbg_kms(&dev_priv->drm,
2392 "requested plane X %s position %d invalid (valid range %d-%d)\n",
2393 crtc_x + crtc_w < 4 ? "end" : "start",
2394 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
2395 4, pipe_src_w - 4);
2396 return -ERANGE;
2399 return 0;
2402 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
2404 const struct drm_framebuffer *fb = plane_state->hw.fb;
2405 unsigned int rotation = plane_state->hw.rotation;
2406 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
2408 /* Display WA #1106 */
2409 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2410 src_w & 3 &&
2411 (rotation == DRM_MODE_ROTATE_270 ||
2412 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
2413 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
2414 return -EINVAL;
2417 return 0;
2420 static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
2421 const struct drm_framebuffer *fb)
2424 * We don't yet know the final source width nor
2425 * whether we can use the HQ scaler mode. Assume
2426 * the best case.
2427 * FIXME need to properly check this later.
2429 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
2430 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
2431 return 0x30000 - 1;
2432 else
2433 return 0x20000 - 1;
2436 static int skl_plane_check(struct intel_crtc_state *crtc_state,
2437 struct intel_plane_state *plane_state)
2439 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2440 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2441 const struct drm_framebuffer *fb = plane_state->hw.fb;
2442 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
2443 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
2444 int ret;
2446 ret = skl_plane_check_fb(crtc_state, plane_state);
2447 if (ret)
2448 return ret;
2450 /* use scaler when colorkey is not required */
2451 if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
2452 min_scale = 1;
2453 max_scale = skl_plane_max_scale(dev_priv, fb);
2456 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
2457 min_scale, max_scale, true);
2458 if (ret)
2459 return ret;
2461 ret = skl_check_plane_surface(plane_state);
2462 if (ret)
2463 return ret;
2465 if (!plane_state->uapi.visible)
2466 return 0;
2468 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
2469 if (ret)
2470 return ret;
2472 ret = intel_plane_check_src_coordinates(plane_state);
2473 if (ret)
2474 return ret;
2476 ret = skl_plane_check_nv12_rotation(plane_state);
2477 if (ret)
2478 return ret;
2480 /* HW only has 8 bits pixel precision, disable plane if invisible */
2481 if (!(plane_state->hw.alpha >> 8))
2482 plane_state->uapi.visible = false;
2484 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
2486 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2487 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
2488 plane_state);
2490 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2491 icl_is_hdr_plane(dev_priv, plane->id))
2492 /* Enable and use MPEG-2 chroma siting */
2493 plane_state->cus_ctl = PLANE_CUS_ENABLE |
2494 PLANE_CUS_HPHASE_0 |
2495 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
2496 else
2497 plane_state->cus_ctl = 0;
2499 return 0;
2502 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
2504 return INTEL_GEN(dev_priv) >= 9;
2507 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
2508 const struct drm_intel_sprite_colorkey *set)
2510 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2511 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2512 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
2514 *key = *set;
2517 * We want src key enabled on the
2518 * sprite and not on the primary.
2520 if (plane->id == PLANE_PRIMARY &&
2521 set->flags & I915_SET_COLORKEY_SOURCE)
2522 key->flags = 0;
2525 * On SKL+ we want dst key enabled on
2526 * the primary and not on the sprite.
2528 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
2529 set->flags & I915_SET_COLORKEY_DESTINATION)
2530 key->flags = 0;
2533 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
2534 struct drm_file *file_priv)
2536 struct drm_i915_private *dev_priv = to_i915(dev);
2537 struct drm_intel_sprite_colorkey *set = data;
2538 struct drm_plane *plane;
2539 struct drm_plane_state *plane_state;
2540 struct drm_atomic_state *state;
2541 struct drm_modeset_acquire_ctx ctx;
2542 int ret = 0;
2544 /* ignore the pointless "none" flag */
2545 set->flags &= ~I915_SET_COLORKEY_NONE;
2547 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2548 return -EINVAL;
2550 /* Make sure we don't try to enable both src & dest simultaneously */
2551 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2552 return -EINVAL;
2554 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
2555 set->flags & I915_SET_COLORKEY_DESTINATION)
2556 return -EINVAL;
2558 plane = drm_plane_find(dev, file_priv, set->plane_id);
2559 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
2560 return -ENOENT;
2563 * SKL+ only plane 2 can do destination keying against plane 1.
2564 * Also multiple planes can't do destination keying on the same
2565 * pipe simultaneously.
2567 if (INTEL_GEN(dev_priv) >= 9 &&
2568 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
2569 set->flags & I915_SET_COLORKEY_DESTINATION)
2570 return -EINVAL;
2572 drm_modeset_acquire_init(&ctx, 0);
2574 state = drm_atomic_state_alloc(plane->dev);
2575 if (!state) {
2576 ret = -ENOMEM;
2577 goto out;
2579 state->acquire_ctx = &ctx;
2581 while (1) {
2582 plane_state = drm_atomic_get_plane_state(state, plane);
2583 ret = PTR_ERR_OR_ZERO(plane_state);
2584 if (!ret)
2585 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2588 * On some platforms we have to configure
2589 * the dst colorkey on the primary plane.
2591 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
2592 struct intel_crtc *crtc =
2593 intel_get_crtc_for_pipe(dev_priv,
2594 to_intel_plane(plane)->pipe);
2596 plane_state = drm_atomic_get_plane_state(state,
2597 crtc->base.primary);
2598 ret = PTR_ERR_OR_ZERO(plane_state);
2599 if (!ret)
2600 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2603 if (!ret)
2604 ret = drm_atomic_commit(state);
2606 if (ret != -EDEADLK)
2607 break;
2609 drm_atomic_state_clear(state);
2610 drm_modeset_backoff(&ctx);
2613 drm_atomic_state_put(state);
2614 out:
2615 drm_modeset_drop_locks(&ctx);
2616 drm_modeset_acquire_fini(&ctx);
2617 return ret;
2620 static const u32 g4x_plane_formats[] = {
2621 DRM_FORMAT_XRGB8888,
2622 DRM_FORMAT_YUYV,
2623 DRM_FORMAT_YVYU,
2624 DRM_FORMAT_UYVY,
2625 DRM_FORMAT_VYUY,
2628 static const u64 i9xx_plane_format_modifiers[] = {
2629 I915_FORMAT_MOD_X_TILED,
2630 DRM_FORMAT_MOD_LINEAR,
2631 DRM_FORMAT_MOD_INVALID
2634 static const u32 snb_plane_formats[] = {
2635 DRM_FORMAT_XRGB8888,
2636 DRM_FORMAT_XBGR8888,
2637 DRM_FORMAT_XRGB2101010,
2638 DRM_FORMAT_XBGR2101010,
2639 DRM_FORMAT_XRGB16161616F,
2640 DRM_FORMAT_XBGR16161616F,
2641 DRM_FORMAT_YUYV,
2642 DRM_FORMAT_YVYU,
2643 DRM_FORMAT_UYVY,
2644 DRM_FORMAT_VYUY,
2647 static const u32 vlv_plane_formats[] = {
2648 DRM_FORMAT_C8,
2649 DRM_FORMAT_RGB565,
2650 DRM_FORMAT_XRGB8888,
2651 DRM_FORMAT_XBGR8888,
2652 DRM_FORMAT_ARGB8888,
2653 DRM_FORMAT_ABGR8888,
2654 DRM_FORMAT_XBGR2101010,
2655 DRM_FORMAT_ABGR2101010,
2656 DRM_FORMAT_YUYV,
2657 DRM_FORMAT_YVYU,
2658 DRM_FORMAT_UYVY,
2659 DRM_FORMAT_VYUY,
2662 static const u32 chv_pipe_b_sprite_formats[] = {
2663 DRM_FORMAT_C8,
2664 DRM_FORMAT_RGB565,
2665 DRM_FORMAT_XRGB8888,
2666 DRM_FORMAT_XBGR8888,
2667 DRM_FORMAT_ARGB8888,
2668 DRM_FORMAT_ABGR8888,
2669 DRM_FORMAT_XRGB2101010,
2670 DRM_FORMAT_XBGR2101010,
2671 DRM_FORMAT_ARGB2101010,
2672 DRM_FORMAT_ABGR2101010,
2673 DRM_FORMAT_YUYV,
2674 DRM_FORMAT_YVYU,
2675 DRM_FORMAT_UYVY,
2676 DRM_FORMAT_VYUY,
2679 static const u32 skl_plane_formats[] = {
2680 DRM_FORMAT_C8,
2681 DRM_FORMAT_RGB565,
2682 DRM_FORMAT_XRGB8888,
2683 DRM_FORMAT_XBGR8888,
2684 DRM_FORMAT_ARGB8888,
2685 DRM_FORMAT_ABGR8888,
2686 DRM_FORMAT_XRGB2101010,
2687 DRM_FORMAT_XBGR2101010,
2688 DRM_FORMAT_XRGB16161616F,
2689 DRM_FORMAT_XBGR16161616F,
2690 DRM_FORMAT_YUYV,
2691 DRM_FORMAT_YVYU,
2692 DRM_FORMAT_UYVY,
2693 DRM_FORMAT_VYUY,
2694 DRM_FORMAT_XYUV8888,
2697 static const u32 skl_planar_formats[] = {
2698 DRM_FORMAT_C8,
2699 DRM_FORMAT_RGB565,
2700 DRM_FORMAT_XRGB8888,
2701 DRM_FORMAT_XBGR8888,
2702 DRM_FORMAT_ARGB8888,
2703 DRM_FORMAT_ABGR8888,
2704 DRM_FORMAT_XRGB2101010,
2705 DRM_FORMAT_XBGR2101010,
2706 DRM_FORMAT_XRGB16161616F,
2707 DRM_FORMAT_XBGR16161616F,
2708 DRM_FORMAT_YUYV,
2709 DRM_FORMAT_YVYU,
2710 DRM_FORMAT_UYVY,
2711 DRM_FORMAT_VYUY,
2712 DRM_FORMAT_NV12,
2713 DRM_FORMAT_XYUV8888,
2716 static const u32 glk_planar_formats[] = {
2717 DRM_FORMAT_C8,
2718 DRM_FORMAT_RGB565,
2719 DRM_FORMAT_XRGB8888,
2720 DRM_FORMAT_XBGR8888,
2721 DRM_FORMAT_ARGB8888,
2722 DRM_FORMAT_ABGR8888,
2723 DRM_FORMAT_XRGB2101010,
2724 DRM_FORMAT_XBGR2101010,
2725 DRM_FORMAT_XRGB16161616F,
2726 DRM_FORMAT_XBGR16161616F,
2727 DRM_FORMAT_YUYV,
2728 DRM_FORMAT_YVYU,
2729 DRM_FORMAT_UYVY,
2730 DRM_FORMAT_VYUY,
2731 DRM_FORMAT_NV12,
2732 DRM_FORMAT_XYUV8888,
2733 DRM_FORMAT_P010,
2734 DRM_FORMAT_P012,
2735 DRM_FORMAT_P016,
2738 static const u32 icl_sdr_y_plane_formats[] = {
2739 DRM_FORMAT_C8,
2740 DRM_FORMAT_RGB565,
2741 DRM_FORMAT_XRGB8888,
2742 DRM_FORMAT_XBGR8888,
2743 DRM_FORMAT_ARGB8888,
2744 DRM_FORMAT_ABGR8888,
2745 DRM_FORMAT_XRGB2101010,
2746 DRM_FORMAT_XBGR2101010,
2747 DRM_FORMAT_ARGB2101010,
2748 DRM_FORMAT_ABGR2101010,
2749 DRM_FORMAT_YUYV,
2750 DRM_FORMAT_YVYU,
2751 DRM_FORMAT_UYVY,
2752 DRM_FORMAT_VYUY,
2753 DRM_FORMAT_Y210,
2754 DRM_FORMAT_Y212,
2755 DRM_FORMAT_Y216,
2756 DRM_FORMAT_XYUV8888,
2757 DRM_FORMAT_XVYU2101010,
2758 DRM_FORMAT_XVYU12_16161616,
2759 DRM_FORMAT_XVYU16161616,
2762 static const u32 icl_sdr_uv_plane_formats[] = {
2763 DRM_FORMAT_C8,
2764 DRM_FORMAT_RGB565,
2765 DRM_FORMAT_XRGB8888,
2766 DRM_FORMAT_XBGR8888,
2767 DRM_FORMAT_ARGB8888,
2768 DRM_FORMAT_ABGR8888,
2769 DRM_FORMAT_XRGB2101010,
2770 DRM_FORMAT_XBGR2101010,
2771 DRM_FORMAT_ARGB2101010,
2772 DRM_FORMAT_ABGR2101010,
2773 DRM_FORMAT_YUYV,
2774 DRM_FORMAT_YVYU,
2775 DRM_FORMAT_UYVY,
2776 DRM_FORMAT_VYUY,
2777 DRM_FORMAT_NV12,
2778 DRM_FORMAT_P010,
2779 DRM_FORMAT_P012,
2780 DRM_FORMAT_P016,
2781 DRM_FORMAT_Y210,
2782 DRM_FORMAT_Y212,
2783 DRM_FORMAT_Y216,
2784 DRM_FORMAT_XYUV8888,
2785 DRM_FORMAT_XVYU2101010,
2786 DRM_FORMAT_XVYU12_16161616,
2787 DRM_FORMAT_XVYU16161616,
2790 static const u32 icl_hdr_plane_formats[] = {
2791 DRM_FORMAT_C8,
2792 DRM_FORMAT_RGB565,
2793 DRM_FORMAT_XRGB8888,
2794 DRM_FORMAT_XBGR8888,
2795 DRM_FORMAT_ARGB8888,
2796 DRM_FORMAT_ABGR8888,
2797 DRM_FORMAT_XRGB2101010,
2798 DRM_FORMAT_XBGR2101010,
2799 DRM_FORMAT_ARGB2101010,
2800 DRM_FORMAT_ABGR2101010,
2801 DRM_FORMAT_XRGB16161616F,
2802 DRM_FORMAT_XBGR16161616F,
2803 DRM_FORMAT_ARGB16161616F,
2804 DRM_FORMAT_ABGR16161616F,
2805 DRM_FORMAT_YUYV,
2806 DRM_FORMAT_YVYU,
2807 DRM_FORMAT_UYVY,
2808 DRM_FORMAT_VYUY,
2809 DRM_FORMAT_NV12,
2810 DRM_FORMAT_P010,
2811 DRM_FORMAT_P012,
2812 DRM_FORMAT_P016,
2813 DRM_FORMAT_Y210,
2814 DRM_FORMAT_Y212,
2815 DRM_FORMAT_Y216,
2816 DRM_FORMAT_XYUV8888,
2817 DRM_FORMAT_XVYU2101010,
2818 DRM_FORMAT_XVYU12_16161616,
2819 DRM_FORMAT_XVYU16161616,
2822 static const u64 skl_plane_format_modifiers_noccs[] = {
2823 I915_FORMAT_MOD_Yf_TILED,
2824 I915_FORMAT_MOD_Y_TILED,
2825 I915_FORMAT_MOD_X_TILED,
2826 DRM_FORMAT_MOD_LINEAR,
2827 DRM_FORMAT_MOD_INVALID
2830 static const u64 skl_plane_format_modifiers_ccs[] = {
2831 I915_FORMAT_MOD_Yf_TILED_CCS,
2832 I915_FORMAT_MOD_Y_TILED_CCS,
2833 I915_FORMAT_MOD_Yf_TILED,
2834 I915_FORMAT_MOD_Y_TILED,
2835 I915_FORMAT_MOD_X_TILED,
2836 DRM_FORMAT_MOD_LINEAR,
2837 DRM_FORMAT_MOD_INVALID
2840 static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
2841 I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
2842 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2843 I915_FORMAT_MOD_Y_TILED,
2844 I915_FORMAT_MOD_X_TILED,
2845 DRM_FORMAT_MOD_LINEAR,
2846 DRM_FORMAT_MOD_INVALID
2849 static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
2850 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2851 I915_FORMAT_MOD_Y_TILED,
2852 I915_FORMAT_MOD_X_TILED,
2853 DRM_FORMAT_MOD_LINEAR,
2854 DRM_FORMAT_MOD_INVALID
2857 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
2858 u32 format, u64 modifier)
2860 switch (modifier) {
2861 case DRM_FORMAT_MOD_LINEAR:
2862 case I915_FORMAT_MOD_X_TILED:
2863 break;
2864 default:
2865 return false;
2868 switch (format) {
2869 case DRM_FORMAT_XRGB8888:
2870 case DRM_FORMAT_YUYV:
2871 case DRM_FORMAT_YVYU:
2872 case DRM_FORMAT_UYVY:
2873 case DRM_FORMAT_VYUY:
2874 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2875 modifier == I915_FORMAT_MOD_X_TILED)
2876 return true;
2877 fallthrough;
2878 default:
2879 return false;
2883 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2884 u32 format, u64 modifier)
2886 switch (modifier) {
2887 case DRM_FORMAT_MOD_LINEAR:
2888 case I915_FORMAT_MOD_X_TILED:
2889 break;
2890 default:
2891 return false;
2894 switch (format) {
2895 case DRM_FORMAT_XRGB8888:
2896 case DRM_FORMAT_XBGR8888:
2897 case DRM_FORMAT_XRGB2101010:
2898 case DRM_FORMAT_XBGR2101010:
2899 case DRM_FORMAT_XRGB16161616F:
2900 case DRM_FORMAT_XBGR16161616F:
2901 case DRM_FORMAT_YUYV:
2902 case DRM_FORMAT_YVYU:
2903 case DRM_FORMAT_UYVY:
2904 case DRM_FORMAT_VYUY:
2905 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2906 modifier == I915_FORMAT_MOD_X_TILED)
2907 return true;
2908 fallthrough;
2909 default:
2910 return false;
2914 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2915 u32 format, u64 modifier)
2917 switch (modifier) {
2918 case DRM_FORMAT_MOD_LINEAR:
2919 case I915_FORMAT_MOD_X_TILED:
2920 break;
2921 default:
2922 return false;
2925 switch (format) {
2926 case DRM_FORMAT_C8:
2927 case DRM_FORMAT_RGB565:
2928 case DRM_FORMAT_ABGR8888:
2929 case DRM_FORMAT_ARGB8888:
2930 case DRM_FORMAT_XBGR8888:
2931 case DRM_FORMAT_XRGB8888:
2932 case DRM_FORMAT_XBGR2101010:
2933 case DRM_FORMAT_ABGR2101010:
2934 case DRM_FORMAT_XRGB2101010:
2935 case DRM_FORMAT_ARGB2101010:
2936 case DRM_FORMAT_YUYV:
2937 case DRM_FORMAT_YVYU:
2938 case DRM_FORMAT_UYVY:
2939 case DRM_FORMAT_VYUY:
2940 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2941 modifier == I915_FORMAT_MOD_X_TILED)
2942 return true;
2943 fallthrough;
2944 default:
2945 return false;
2949 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2950 u32 format, u64 modifier)
2952 struct intel_plane *plane = to_intel_plane(_plane);
2954 switch (modifier) {
2955 case DRM_FORMAT_MOD_LINEAR:
2956 case I915_FORMAT_MOD_X_TILED:
2957 case I915_FORMAT_MOD_Y_TILED:
2958 case I915_FORMAT_MOD_Yf_TILED:
2959 break;
2960 case I915_FORMAT_MOD_Y_TILED_CCS:
2961 case I915_FORMAT_MOD_Yf_TILED_CCS:
2962 if (!plane->has_ccs)
2963 return false;
2964 break;
2965 default:
2966 return false;
2969 switch (format) {
2970 case DRM_FORMAT_XRGB8888:
2971 case DRM_FORMAT_XBGR8888:
2972 case DRM_FORMAT_ARGB8888:
2973 case DRM_FORMAT_ABGR8888:
2974 if (is_ccs_modifier(modifier))
2975 return true;
2976 fallthrough;
2977 case DRM_FORMAT_RGB565:
2978 case DRM_FORMAT_XRGB2101010:
2979 case DRM_FORMAT_XBGR2101010:
2980 case DRM_FORMAT_ARGB2101010:
2981 case DRM_FORMAT_ABGR2101010:
2982 case DRM_FORMAT_YUYV:
2983 case DRM_FORMAT_YVYU:
2984 case DRM_FORMAT_UYVY:
2985 case DRM_FORMAT_VYUY:
2986 case DRM_FORMAT_NV12:
2987 case DRM_FORMAT_XYUV8888:
2988 case DRM_FORMAT_P010:
2989 case DRM_FORMAT_P012:
2990 case DRM_FORMAT_P016:
2991 case DRM_FORMAT_XVYU2101010:
2992 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2993 return true;
2994 fallthrough;
2995 case DRM_FORMAT_C8:
2996 case DRM_FORMAT_XBGR16161616F:
2997 case DRM_FORMAT_ABGR16161616F:
2998 case DRM_FORMAT_XRGB16161616F:
2999 case DRM_FORMAT_ARGB16161616F:
3000 case DRM_FORMAT_Y210:
3001 case DRM_FORMAT_Y212:
3002 case DRM_FORMAT_Y216:
3003 case DRM_FORMAT_XVYU12_16161616:
3004 case DRM_FORMAT_XVYU16161616:
3005 if (modifier == DRM_FORMAT_MOD_LINEAR ||
3006 modifier == I915_FORMAT_MOD_X_TILED ||
3007 modifier == I915_FORMAT_MOD_Y_TILED)
3008 return true;
3009 fallthrough;
3010 default:
3011 return false;
3015 static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
3016 enum plane_id plane_id)
3018 /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
3019 if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
3020 IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0))
3021 return false;
3023 return plane_id < PLANE_SPRITE4;
3026 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
3027 u32 format, u64 modifier)
3029 struct drm_i915_private *dev_priv = to_i915(_plane->dev);
3030 struct intel_plane *plane = to_intel_plane(_plane);
3032 switch (modifier) {
3033 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
3034 if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
3035 return false;
3036 fallthrough;
3037 case DRM_FORMAT_MOD_LINEAR:
3038 case I915_FORMAT_MOD_X_TILED:
3039 case I915_FORMAT_MOD_Y_TILED:
3040 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
3041 break;
3042 default:
3043 return false;
3046 switch (format) {
3047 case DRM_FORMAT_XRGB8888:
3048 case DRM_FORMAT_XBGR8888:
3049 case DRM_FORMAT_ARGB8888:
3050 case DRM_FORMAT_ABGR8888:
3051 if (is_ccs_modifier(modifier))
3052 return true;
3053 fallthrough;
3054 case DRM_FORMAT_YUYV:
3055 case DRM_FORMAT_YVYU:
3056 case DRM_FORMAT_UYVY:
3057 case DRM_FORMAT_VYUY:
3058 case DRM_FORMAT_NV12:
3059 case DRM_FORMAT_XYUV8888:
3060 case DRM_FORMAT_P010:
3061 case DRM_FORMAT_P012:
3062 case DRM_FORMAT_P016:
3063 if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
3064 return true;
3065 fallthrough;
3066 case DRM_FORMAT_RGB565:
3067 case DRM_FORMAT_XRGB2101010:
3068 case DRM_FORMAT_XBGR2101010:
3069 case DRM_FORMAT_ARGB2101010:
3070 case DRM_FORMAT_ABGR2101010:
3071 case DRM_FORMAT_XVYU2101010:
3072 case DRM_FORMAT_C8:
3073 case DRM_FORMAT_XBGR16161616F:
3074 case DRM_FORMAT_ABGR16161616F:
3075 case DRM_FORMAT_XRGB16161616F:
3076 case DRM_FORMAT_ARGB16161616F:
3077 case DRM_FORMAT_Y210:
3078 case DRM_FORMAT_Y212:
3079 case DRM_FORMAT_Y216:
3080 case DRM_FORMAT_XVYU12_16161616:
3081 case DRM_FORMAT_XVYU16161616:
3082 if (modifier == DRM_FORMAT_MOD_LINEAR ||
3083 modifier == I915_FORMAT_MOD_X_TILED ||
3084 modifier == I915_FORMAT_MOD_Y_TILED)
3085 return true;
3086 fallthrough;
3087 default:
3088 return false;
3092 static const struct drm_plane_funcs g4x_sprite_funcs = {
3093 .update_plane = drm_atomic_helper_update_plane,
3094 .disable_plane = drm_atomic_helper_disable_plane,
3095 .destroy = intel_plane_destroy,
3096 .atomic_duplicate_state = intel_plane_duplicate_state,
3097 .atomic_destroy_state = intel_plane_destroy_state,
3098 .format_mod_supported = g4x_sprite_format_mod_supported,
3101 static const struct drm_plane_funcs snb_sprite_funcs = {
3102 .update_plane = drm_atomic_helper_update_plane,
3103 .disable_plane = drm_atomic_helper_disable_plane,
3104 .destroy = intel_plane_destroy,
3105 .atomic_duplicate_state = intel_plane_duplicate_state,
3106 .atomic_destroy_state = intel_plane_destroy_state,
3107 .format_mod_supported = snb_sprite_format_mod_supported,
3110 static const struct drm_plane_funcs vlv_sprite_funcs = {
3111 .update_plane = drm_atomic_helper_update_plane,
3112 .disable_plane = drm_atomic_helper_disable_plane,
3113 .destroy = intel_plane_destroy,
3114 .atomic_duplicate_state = intel_plane_duplicate_state,
3115 .atomic_destroy_state = intel_plane_destroy_state,
3116 .format_mod_supported = vlv_sprite_format_mod_supported,
3119 static const struct drm_plane_funcs skl_plane_funcs = {
3120 .update_plane = drm_atomic_helper_update_plane,
3121 .disable_plane = drm_atomic_helper_disable_plane,
3122 .destroy = intel_plane_destroy,
3123 .atomic_duplicate_state = intel_plane_duplicate_state,
3124 .atomic_destroy_state = intel_plane_destroy_state,
3125 .format_mod_supported = skl_plane_format_mod_supported,
3128 static const struct drm_plane_funcs gen12_plane_funcs = {
3129 .update_plane = drm_atomic_helper_update_plane,
3130 .disable_plane = drm_atomic_helper_disable_plane,
3131 .destroy = intel_plane_destroy,
3132 .atomic_duplicate_state = intel_plane_duplicate_state,
3133 .atomic_destroy_state = intel_plane_destroy_state,
3134 .format_mod_supported = gen12_plane_format_mod_supported,
3137 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
3138 enum pipe pipe, enum plane_id plane_id)
3140 if (!HAS_FBC(dev_priv))
3141 return false;
3143 return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
3146 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
3147 enum pipe pipe, enum plane_id plane_id)
3149 /* Display WA #0870: skl, bxt */
3150 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
3151 return false;
3153 if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
3154 return false;
3156 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
3157 return false;
3159 return true;
3162 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
3163 enum pipe pipe, enum plane_id plane_id,
3164 int *num_formats)
3166 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
3167 *num_formats = ARRAY_SIZE(skl_planar_formats);
3168 return skl_planar_formats;
3169 } else {
3170 *num_formats = ARRAY_SIZE(skl_plane_formats);
3171 return skl_plane_formats;
3175 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
3176 enum pipe pipe, enum plane_id plane_id,
3177 int *num_formats)
3179 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
3180 *num_formats = ARRAY_SIZE(glk_planar_formats);
3181 return glk_planar_formats;
3182 } else {
3183 *num_formats = ARRAY_SIZE(skl_plane_formats);
3184 return skl_plane_formats;
3188 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
3189 enum pipe pipe, enum plane_id plane_id,
3190 int *num_formats)
3192 if (icl_is_hdr_plane(dev_priv, plane_id)) {
3193 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
3194 return icl_hdr_plane_formats;
3195 } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
3196 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
3197 return icl_sdr_y_plane_formats;
3198 } else {
3199 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
3200 return icl_sdr_uv_plane_formats;
3204 static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
3205 enum plane_id plane_id)
3207 if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
3208 return gen12_plane_format_modifiers_mc_ccs;
3209 else
3210 return gen12_plane_format_modifiers_rc_ccs;
3213 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
3214 enum pipe pipe, enum plane_id plane_id)
3216 if (plane_id == PLANE_CURSOR)
3217 return false;
3219 if (INTEL_GEN(dev_priv) >= 10)
3220 return true;
3222 if (IS_GEMINILAKE(dev_priv))
3223 return pipe != PIPE_C;
3225 return pipe != PIPE_C &&
3226 (plane_id == PLANE_PRIMARY ||
3227 plane_id == PLANE_SPRITE0);
3230 struct intel_plane *
3231 skl_universal_plane_create(struct drm_i915_private *dev_priv,
3232 enum pipe pipe, enum plane_id plane_id)
3234 const struct drm_plane_funcs *plane_funcs;
3235 struct intel_plane *plane;
3236 enum drm_plane_type plane_type;
3237 unsigned int supported_rotations;
3238 unsigned int supported_csc;
3239 const u64 *modifiers;
3240 const u32 *formats;
3241 int num_formats;
3242 int ret;
3244 plane = intel_plane_alloc();
3245 if (IS_ERR(plane))
3246 return plane;
3248 plane->pipe = pipe;
3249 plane->id = plane_id;
3250 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
3252 plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
3253 if (plane->has_fbc) {
3254 struct intel_fbc *fbc = &dev_priv->fbc;
3256 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
3259 if (INTEL_GEN(dev_priv) >= 11) {
3260 plane->min_width = icl_plane_min_width;
3261 plane->max_width = icl_plane_max_width;
3262 plane->max_height = icl_plane_max_height;
3263 } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
3264 plane->max_width = glk_plane_max_width;
3265 plane->max_height = skl_plane_max_height;
3266 } else {
3267 plane->max_width = skl_plane_max_width;
3268 plane->max_height = skl_plane_max_height;
3271 plane->max_stride = skl_plane_max_stride;
3272 plane->update_plane = skl_update_plane;
3273 plane->disable_plane = skl_disable_plane;
3274 plane->get_hw_state = skl_plane_get_hw_state;
3275 plane->check_plane = skl_plane_check;
3276 plane->min_cdclk = skl_plane_min_cdclk;
3277 plane->async_flip = skl_plane_async_flip;
3279 if (INTEL_GEN(dev_priv) >= 11)
3280 formats = icl_get_plane_formats(dev_priv, pipe,
3281 plane_id, &num_formats);
3282 else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
3283 formats = glk_get_plane_formats(dev_priv, pipe,
3284 plane_id, &num_formats);
3285 else
3286 formats = skl_get_plane_formats(dev_priv, pipe,
3287 plane_id, &num_formats);
3289 plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
3290 if (INTEL_GEN(dev_priv) >= 12) {
3291 modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
3292 plane_funcs = &gen12_plane_funcs;
3293 } else {
3294 if (plane->has_ccs)
3295 modifiers = skl_plane_format_modifiers_ccs;
3296 else
3297 modifiers = skl_plane_format_modifiers_noccs;
3298 plane_funcs = &skl_plane_funcs;
3301 if (plane_id == PLANE_PRIMARY)
3302 plane_type = DRM_PLANE_TYPE_PRIMARY;
3303 else
3304 plane_type = DRM_PLANE_TYPE_OVERLAY;
3306 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3307 0, plane_funcs,
3308 formats, num_formats, modifiers,
3309 plane_type,
3310 "plane %d%c", plane_id + 1,
3311 pipe_name(pipe));
3312 if (ret)
3313 goto fail;
3315 supported_rotations =
3316 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
3317 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
3319 if (INTEL_GEN(dev_priv) >= 10)
3320 supported_rotations |= DRM_MODE_REFLECT_X;
3322 drm_plane_create_rotation_property(&plane->base,
3323 DRM_MODE_ROTATE_0,
3324 supported_rotations);
3326 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
3328 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
3329 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
3331 drm_plane_create_color_properties(&plane->base,
3332 supported_csc,
3333 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3334 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3335 DRM_COLOR_YCBCR_BT709,
3336 DRM_COLOR_YCBCR_LIMITED_RANGE);
3338 drm_plane_create_alpha_property(&plane->base);
3339 drm_plane_create_blend_mode_property(&plane->base,
3340 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
3341 BIT(DRM_MODE_BLEND_PREMULTI) |
3342 BIT(DRM_MODE_BLEND_COVERAGE));
3344 drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
3346 if (INTEL_GEN(dev_priv) >= 12)
3347 drm_plane_enable_fb_damage_clips(&plane->base);
3349 if (INTEL_GEN(dev_priv) >= 10)
3350 drm_plane_create_scaling_filter_property(&plane->base,
3351 BIT(DRM_SCALING_FILTER_DEFAULT) |
3352 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
3354 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3356 return plane;
3358 fail:
3359 intel_plane_free(plane);
3361 return ERR_PTR(ret);
3364 struct intel_plane *
3365 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
3366 enum pipe pipe, int sprite)
3368 struct intel_plane *plane;
3369 const struct drm_plane_funcs *plane_funcs;
3370 unsigned int supported_rotations;
3371 const u64 *modifiers;
3372 const u32 *formats;
3373 int num_formats;
3374 int ret, zpos;
3376 if (INTEL_GEN(dev_priv) >= 9)
3377 return skl_universal_plane_create(dev_priv, pipe,
3378 PLANE_SPRITE0 + sprite);
3380 plane = intel_plane_alloc();
3381 if (IS_ERR(plane))
3382 return plane;
3384 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
3385 plane->max_stride = i9xx_plane_max_stride;
3386 plane->update_plane = vlv_update_plane;
3387 plane->disable_plane = vlv_disable_plane;
3388 plane->get_hw_state = vlv_plane_get_hw_state;
3389 plane->check_plane = vlv_sprite_check;
3390 plane->min_cdclk = vlv_plane_min_cdclk;
3392 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3393 formats = chv_pipe_b_sprite_formats;
3394 num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
3395 } else {
3396 formats = vlv_plane_formats;
3397 num_formats = ARRAY_SIZE(vlv_plane_formats);
3399 modifiers = i9xx_plane_format_modifiers;
3401 plane_funcs = &vlv_sprite_funcs;
3402 } else if (INTEL_GEN(dev_priv) >= 7) {
3403 plane->max_stride = g4x_sprite_max_stride;
3404 plane->update_plane = ivb_update_plane;
3405 plane->disable_plane = ivb_disable_plane;
3406 plane->get_hw_state = ivb_plane_get_hw_state;
3407 plane->check_plane = g4x_sprite_check;
3409 if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
3410 plane->min_cdclk = hsw_plane_min_cdclk;
3411 else
3412 plane->min_cdclk = ivb_sprite_min_cdclk;
3414 formats = snb_plane_formats;
3415 num_formats = ARRAY_SIZE(snb_plane_formats);
3416 modifiers = i9xx_plane_format_modifiers;
3418 plane_funcs = &snb_sprite_funcs;
3419 } else {
3420 plane->max_stride = g4x_sprite_max_stride;
3421 plane->update_plane = g4x_update_plane;
3422 plane->disable_plane = g4x_disable_plane;
3423 plane->get_hw_state = g4x_plane_get_hw_state;
3424 plane->check_plane = g4x_sprite_check;
3425 plane->min_cdclk = g4x_sprite_min_cdclk;
3427 modifiers = i9xx_plane_format_modifiers;
3428 if (IS_GEN(dev_priv, 6)) {
3429 formats = snb_plane_formats;
3430 num_formats = ARRAY_SIZE(snb_plane_formats);
3432 plane_funcs = &snb_sprite_funcs;
3433 } else {
3434 formats = g4x_plane_formats;
3435 num_formats = ARRAY_SIZE(g4x_plane_formats);
3437 plane_funcs = &g4x_sprite_funcs;
3441 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3442 supported_rotations =
3443 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
3444 DRM_MODE_REFLECT_X;
3445 } else {
3446 supported_rotations =
3447 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
3450 plane->pipe = pipe;
3451 plane->id = PLANE_SPRITE0 + sprite;
3452 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
3454 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3455 0, plane_funcs,
3456 formats, num_formats, modifiers,
3457 DRM_PLANE_TYPE_OVERLAY,
3458 "sprite %c", sprite_name(pipe, sprite));
3459 if (ret)
3460 goto fail;
3462 drm_plane_create_rotation_property(&plane->base,
3463 DRM_MODE_ROTATE_0,
3464 supported_rotations);
3466 drm_plane_create_color_properties(&plane->base,
3467 BIT(DRM_COLOR_YCBCR_BT601) |
3468 BIT(DRM_COLOR_YCBCR_BT709),
3469 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3470 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3471 DRM_COLOR_YCBCR_BT709,
3472 DRM_COLOR_YCBCR_LIMITED_RANGE);
3474 zpos = sprite + 1;
3475 drm_plane_create_zpos_immutable_property(&plane->base, zpos);
3477 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3479 return plane;
3481 fail:
3482 intel_plane_free(plane);
3484 return ERR_PTR(ret);