Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2020 Intel Corporation
4 */
5
6#include <drm/drm_atomic_helper.h>
7#include <drm/drm_blend.h>
8#include <drm/drm_damage_helper.h>
9#include <drm/drm_fourcc.h>
10
11#include "i915_drv.h"
12#include "i915_reg.h"
13#include "intel_atomic_plane.h"
14#include "intel_bo.h"
15#include "intel_de.h"
16#include "intel_display_irq.h"
17#include "intel_display_types.h"
18#include "intel_dpt.h"
19#include "intel_fb.h"
20#include "intel_fbc.h"
21#include "intel_frontbuffer.h"
22#include "intel_psr.h"
23#include "intel_psr_regs.h"
24#include "skl_scaler.h"
25#include "skl_universal_plane.h"
26#include "skl_universal_plane_regs.h"
27#include "skl_watermark.h"
28#include "pxp/intel_pxp.h"
29
30static const u32 skl_plane_formats[] = {
31 DRM_FORMAT_C8,
32 DRM_FORMAT_RGB565,
33 DRM_FORMAT_XRGB8888,
34 DRM_FORMAT_XBGR8888,
35 DRM_FORMAT_ARGB8888,
36 DRM_FORMAT_ABGR8888,
37 DRM_FORMAT_XRGB2101010,
38 DRM_FORMAT_XBGR2101010,
39 DRM_FORMAT_XRGB16161616F,
40 DRM_FORMAT_XBGR16161616F,
41 DRM_FORMAT_YUYV,
42 DRM_FORMAT_YVYU,
43 DRM_FORMAT_UYVY,
44 DRM_FORMAT_VYUY,
45 DRM_FORMAT_XYUV8888,
46};
47
48static const u32 skl_planar_formats[] = {
49 DRM_FORMAT_C8,
50 DRM_FORMAT_RGB565,
51 DRM_FORMAT_XRGB8888,
52 DRM_FORMAT_XBGR8888,
53 DRM_FORMAT_ARGB8888,
54 DRM_FORMAT_ABGR8888,
55 DRM_FORMAT_XRGB2101010,
56 DRM_FORMAT_XBGR2101010,
57 DRM_FORMAT_XRGB16161616F,
58 DRM_FORMAT_XBGR16161616F,
59 DRM_FORMAT_YUYV,
60 DRM_FORMAT_YVYU,
61 DRM_FORMAT_UYVY,
62 DRM_FORMAT_VYUY,
63 DRM_FORMAT_NV12,
64 DRM_FORMAT_XYUV8888,
65};
66
67static const u32 glk_planar_formats[] = {
68 DRM_FORMAT_C8,
69 DRM_FORMAT_RGB565,
70 DRM_FORMAT_XRGB8888,
71 DRM_FORMAT_XBGR8888,
72 DRM_FORMAT_ARGB8888,
73 DRM_FORMAT_ABGR8888,
74 DRM_FORMAT_XRGB2101010,
75 DRM_FORMAT_XBGR2101010,
76 DRM_FORMAT_XRGB16161616F,
77 DRM_FORMAT_XBGR16161616F,
78 DRM_FORMAT_YUYV,
79 DRM_FORMAT_YVYU,
80 DRM_FORMAT_UYVY,
81 DRM_FORMAT_VYUY,
82 DRM_FORMAT_NV12,
83 DRM_FORMAT_XYUV8888,
84 DRM_FORMAT_P010,
85 DRM_FORMAT_P012,
86 DRM_FORMAT_P016,
87};
88
89static const u32 icl_sdr_y_plane_formats[] = {
90 DRM_FORMAT_C8,
91 DRM_FORMAT_RGB565,
92 DRM_FORMAT_XRGB8888,
93 DRM_FORMAT_XBGR8888,
94 DRM_FORMAT_ARGB8888,
95 DRM_FORMAT_ABGR8888,
96 DRM_FORMAT_XRGB2101010,
97 DRM_FORMAT_XBGR2101010,
98 DRM_FORMAT_ARGB2101010,
99 DRM_FORMAT_ABGR2101010,
100 DRM_FORMAT_YUYV,
101 DRM_FORMAT_YVYU,
102 DRM_FORMAT_UYVY,
103 DRM_FORMAT_VYUY,
104 DRM_FORMAT_Y210,
105 DRM_FORMAT_Y212,
106 DRM_FORMAT_Y216,
107 DRM_FORMAT_XYUV8888,
108 DRM_FORMAT_XVYU2101010,
109};
110
111static const u32 icl_sdr_uv_plane_formats[] = {
112 DRM_FORMAT_C8,
113 DRM_FORMAT_RGB565,
114 DRM_FORMAT_XRGB8888,
115 DRM_FORMAT_XBGR8888,
116 DRM_FORMAT_ARGB8888,
117 DRM_FORMAT_ABGR8888,
118 DRM_FORMAT_XRGB2101010,
119 DRM_FORMAT_XBGR2101010,
120 DRM_FORMAT_ARGB2101010,
121 DRM_FORMAT_ABGR2101010,
122 DRM_FORMAT_YUYV,
123 DRM_FORMAT_YVYU,
124 DRM_FORMAT_UYVY,
125 DRM_FORMAT_VYUY,
126 DRM_FORMAT_NV12,
127 DRM_FORMAT_P010,
128 DRM_FORMAT_P012,
129 DRM_FORMAT_P016,
130 DRM_FORMAT_Y210,
131 DRM_FORMAT_Y212,
132 DRM_FORMAT_Y216,
133 DRM_FORMAT_XYUV8888,
134 DRM_FORMAT_XVYU2101010,
135};
136
137static const u32 icl_hdr_plane_formats[] = {
138 DRM_FORMAT_C8,
139 DRM_FORMAT_RGB565,
140 DRM_FORMAT_XRGB8888,
141 DRM_FORMAT_XBGR8888,
142 DRM_FORMAT_ARGB8888,
143 DRM_FORMAT_ABGR8888,
144 DRM_FORMAT_XRGB2101010,
145 DRM_FORMAT_XBGR2101010,
146 DRM_FORMAT_ARGB2101010,
147 DRM_FORMAT_ABGR2101010,
148 DRM_FORMAT_XRGB16161616F,
149 DRM_FORMAT_XBGR16161616F,
150 DRM_FORMAT_ARGB16161616F,
151 DRM_FORMAT_ABGR16161616F,
152 DRM_FORMAT_YUYV,
153 DRM_FORMAT_YVYU,
154 DRM_FORMAT_UYVY,
155 DRM_FORMAT_VYUY,
156 DRM_FORMAT_NV12,
157 DRM_FORMAT_P010,
158 DRM_FORMAT_P012,
159 DRM_FORMAT_P016,
160 DRM_FORMAT_Y210,
161 DRM_FORMAT_Y212,
162 DRM_FORMAT_Y216,
163 DRM_FORMAT_XYUV8888,
164 DRM_FORMAT_XVYU2101010,
165 DRM_FORMAT_XVYU12_16161616,
166 DRM_FORMAT_XVYU16161616,
167};
168
169int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
170{
171 switch (format) {
172 case PLANE_CTL_FORMAT_RGB_565:
173 return DRM_FORMAT_RGB565;
174 case PLANE_CTL_FORMAT_NV12:
175 return DRM_FORMAT_NV12;
176 case PLANE_CTL_FORMAT_XYUV:
177 return DRM_FORMAT_XYUV8888;
178 case PLANE_CTL_FORMAT_P010:
179 return DRM_FORMAT_P010;
180 case PLANE_CTL_FORMAT_P012:
181 return DRM_FORMAT_P012;
182 case PLANE_CTL_FORMAT_P016:
183 return DRM_FORMAT_P016;
184 case PLANE_CTL_FORMAT_Y210:
185 return DRM_FORMAT_Y210;
186 case PLANE_CTL_FORMAT_Y212:
187 return DRM_FORMAT_Y212;
188 case PLANE_CTL_FORMAT_Y216:
189 return DRM_FORMAT_Y216;
190 case PLANE_CTL_FORMAT_Y410:
191 return DRM_FORMAT_XVYU2101010;
192 case PLANE_CTL_FORMAT_Y412:
193 return DRM_FORMAT_XVYU12_16161616;
194 case PLANE_CTL_FORMAT_Y416:
195 return DRM_FORMAT_XVYU16161616;
196 default:
197 case PLANE_CTL_FORMAT_XRGB_8888:
198 if (rgb_order) {
199 if (alpha)
200 return DRM_FORMAT_ABGR8888;
201 else
202 return DRM_FORMAT_XBGR8888;
203 } else {
204 if (alpha)
205 return DRM_FORMAT_ARGB8888;
206 else
207 return DRM_FORMAT_XRGB8888;
208 }
209 case PLANE_CTL_FORMAT_XRGB_2101010:
210 if (rgb_order) {
211 if (alpha)
212 return DRM_FORMAT_ABGR2101010;
213 else
214 return DRM_FORMAT_XBGR2101010;
215 } else {
216 if (alpha)
217 return DRM_FORMAT_ARGB2101010;
218 else
219 return DRM_FORMAT_XRGB2101010;
220 }
221 case PLANE_CTL_FORMAT_XRGB_16161616F:
222 if (rgb_order) {
223 if (alpha)
224 return DRM_FORMAT_ABGR16161616F;
225 else
226 return DRM_FORMAT_XBGR16161616F;
227 } else {
228 if (alpha)
229 return DRM_FORMAT_ARGB16161616F;
230 else
231 return DRM_FORMAT_XRGB16161616F;
232 }
233 }
234}
235
236static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
237{
238 if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
239 return BIT(PLANE_4) | BIT(PLANE_5);
240 else
241 return BIT(PLANE_6) | BIT(PLANE_7);
242}
243
244bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
245 enum plane_id plane_id)
246{
247 return DISPLAY_VER(dev_priv) >= 11 &&
248 icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
249}
250
251u8 icl_hdr_plane_mask(void)
252{
253 return BIT(PLANE_1) | BIT(PLANE_2) | BIT(PLANE_3);
254}
255
256bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
257{
258 return DISPLAY_VER(dev_priv) >= 11 &&
259 icl_hdr_plane_mask() & BIT(plane_id);
260}
261
262static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
263 const struct intel_plane_state *plane_state)
264{
265 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
266
267 /* two pixels per clock */
268 return DIV_ROUND_UP(pixel_rate, 2);
269}
270
271static void
272glk_plane_ratio(const struct intel_plane_state *plane_state,
273 unsigned int *num, unsigned int *den)
274{
275 const struct drm_framebuffer *fb = plane_state->hw.fb;
276
277 if (fb->format->cpp[0] == 8) {
278 *num = 10;
279 *den = 8;
280 } else {
281 *num = 1;
282 *den = 1;
283 }
284}
285
286static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
287 const struct intel_plane_state *plane_state)
288{
289 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
290 unsigned int num, den;
291
292 glk_plane_ratio(plane_state, &num, &den);
293
294 /* two pixels per clock */
295 return DIV_ROUND_UP(pixel_rate * num, 2 * den);
296}
297
298static void
299skl_plane_ratio(const struct intel_plane_state *plane_state,
300 unsigned int *num, unsigned int *den)
301{
302 const struct drm_framebuffer *fb = plane_state->hw.fb;
303
304 if (fb->format->cpp[0] == 8) {
305 *num = 9;
306 *den = 8;
307 } else {
308 *num = 1;
309 *den = 1;
310 }
311}
312
313static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
314 const struct intel_plane_state *plane_state)
315{
316 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
317 unsigned int num, den;
318
319 skl_plane_ratio(plane_state, &num, &den);
320
321 return DIV_ROUND_UP(pixel_rate * num, den);
322}
323
324static int skl_plane_max_width(const struct drm_framebuffer *fb,
325 int color_plane,
326 unsigned int rotation)
327{
328 int cpp = fb->format->cpp[color_plane];
329
330 switch (fb->modifier) {
331 case DRM_FORMAT_MOD_LINEAR:
332 case I915_FORMAT_MOD_X_TILED:
333 /*
334 * Validated limit is 4k, but has 5k should
335 * work apart from the following features:
336 * - Ytile (already limited to 4k)
337 * - FP16 (already limited to 4k)
338 * - render compression (already limited to 4k)
339 * - KVMR sprite and cursor (don't care)
340 * - horizontal panning (TODO verify this)
341 * - pipe and plane scaling (TODO verify this)
342 */
343 if (cpp == 8)
344 return 4096;
345 else
346 return 5120;
347 case I915_FORMAT_MOD_Y_TILED_CCS:
348 case I915_FORMAT_MOD_Yf_TILED_CCS:
349 /* FIXME AUX plane? */
350 case I915_FORMAT_MOD_Y_TILED:
351 case I915_FORMAT_MOD_Yf_TILED:
352 if (cpp == 8)
353 return 2048;
354 else
355 return 4096;
356 default:
357 MISSING_CASE(fb->modifier);
358 return 2048;
359 }
360}
361
362static int glk_plane_max_width(const struct drm_framebuffer *fb,
363 int color_plane,
364 unsigned int rotation)
365{
366 int cpp = fb->format->cpp[color_plane];
367
368 switch (fb->modifier) {
369 case DRM_FORMAT_MOD_LINEAR:
370 case I915_FORMAT_MOD_X_TILED:
371 if (cpp == 8)
372 return 4096;
373 else
374 return 5120;
375 case I915_FORMAT_MOD_Y_TILED_CCS:
376 case I915_FORMAT_MOD_Yf_TILED_CCS:
377 /* FIXME AUX plane? */
378 case I915_FORMAT_MOD_Y_TILED:
379 case I915_FORMAT_MOD_Yf_TILED:
380 if (cpp == 8)
381 return 2048;
382 else
383 return 5120;
384 default:
385 MISSING_CASE(fb->modifier);
386 return 2048;
387 }
388}
389
390static int icl_plane_min_width(const struct drm_framebuffer *fb,
391 int color_plane,
392 unsigned int rotation)
393{
394 /* Wa_14011264657, Wa_14011050563: gen11+ */
395 switch (fb->format->format) {
396 case DRM_FORMAT_C8:
397 return 18;
398 case DRM_FORMAT_RGB565:
399 return 10;
400 case DRM_FORMAT_XRGB8888:
401 case DRM_FORMAT_XBGR8888:
402 case DRM_FORMAT_ARGB8888:
403 case DRM_FORMAT_ABGR8888:
404 case DRM_FORMAT_XRGB2101010:
405 case DRM_FORMAT_XBGR2101010:
406 case DRM_FORMAT_ARGB2101010:
407 case DRM_FORMAT_ABGR2101010:
408 case DRM_FORMAT_XVYU2101010:
409 case DRM_FORMAT_Y212:
410 case DRM_FORMAT_Y216:
411 return 6;
412 case DRM_FORMAT_NV12:
413 return 20;
414 case DRM_FORMAT_P010:
415 case DRM_FORMAT_P012:
416 case DRM_FORMAT_P016:
417 return 12;
418 case DRM_FORMAT_XRGB16161616F:
419 case DRM_FORMAT_XBGR16161616F:
420 case DRM_FORMAT_ARGB16161616F:
421 case DRM_FORMAT_ABGR16161616F:
422 case DRM_FORMAT_XVYU12_16161616:
423 case DRM_FORMAT_XVYU16161616:
424 return 4;
425 default:
426 return 1;
427 }
428}
429
430static int xe3_plane_max_width(const struct drm_framebuffer *fb,
431 int color_plane,
432 unsigned int rotation)
433{
434 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
435 return 4096;
436 else
437 return 6144;
438}
439
440static int icl_hdr_plane_max_width(const struct drm_framebuffer *fb,
441 int color_plane,
442 unsigned int rotation)
443{
444 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
445 return 4096;
446 else
447 return 5120;
448}
449
450static int icl_sdr_plane_max_width(const struct drm_framebuffer *fb,
451 int color_plane,
452 unsigned int rotation)
453{
454 return 5120;
455}
456
457static int skl_plane_max_height(const struct drm_framebuffer *fb,
458 int color_plane,
459 unsigned int rotation)
460{
461 return 4096;
462}
463
464static int icl_plane_max_height(const struct drm_framebuffer *fb,
465 int color_plane,
466 unsigned int rotation)
467{
468 return 4320;
469}
470
471static unsigned int
472plane_max_stride(struct intel_plane *plane,
473 u32 pixel_format, u64 modifier,
474 unsigned int rotation,
475 unsigned int max_pixels,
476 unsigned int max_bytes)
477{
478 const struct drm_format_info *info = drm_format_info(pixel_format);
479 int cpp = info->cpp[0];
480
481 if (drm_rotation_90_or_270(rotation))
482 return min(max_pixels, max_bytes / cpp);
483 else
484 return min(max_pixels * cpp, max_bytes);
485}
486
487static unsigned int
488adl_plane_max_stride(struct intel_plane *plane,
489 u32 pixel_format, u64 modifier,
490 unsigned int rotation)
491{
492 unsigned int max_pixels = 65536; /* PLANE_OFFSET limit */
493 unsigned int max_bytes = 128 * 1024;
494
495 return plane_max_stride(plane, pixel_format,
496 modifier, rotation,
497 max_pixels, max_bytes);
498}
499
500static unsigned int
501skl_plane_max_stride(struct intel_plane *plane,
502 u32 pixel_format, u64 modifier,
503 unsigned int rotation)
504{
505 unsigned int max_pixels = 8192; /* PLANE_OFFSET limit */
506 unsigned int max_bytes = 32 * 1024;
507
508 return plane_max_stride(plane, pixel_format,
509 modifier, rotation,
510 max_pixels, max_bytes);
511}
512
513static u32 tgl_plane_min_alignment(struct intel_plane *plane,
514 const struct drm_framebuffer *fb,
515 int color_plane)
516{
517 struct drm_i915_private *i915 = to_i915(plane->base.dev);
518 /* PLANE_SURF GGTT -> DPT alignment */
519 int mult = intel_fb_uses_dpt(fb) ? 512 : 1;
520
521 /* AUX_DIST needs only 4K alignment */
522 if (intel_fb_is_ccs_aux_plane(fb, color_plane))
523 return mult * 4 * 1024;
524
525 switch (fb->modifier) {
526 case DRM_FORMAT_MOD_LINEAR:
527 case I915_FORMAT_MOD_X_TILED:
528 case I915_FORMAT_MOD_Y_TILED:
529 case I915_FORMAT_MOD_4_TILED:
530 /*
531 * FIXME ADL sees GGTT/DMAR faults with async
532 * flips unless we align to 16k at least.
533 * Figure out what's going on here...
534 */
535 if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915))
536 return mult * 16 * 1024;
537 return mult * 4 * 1024;
538 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
539 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
540 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
541 case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
542 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
543 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
544 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
545 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
546 case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
547 case I915_FORMAT_MOD_4_TILED_BMG_CCS:
548 case I915_FORMAT_MOD_4_TILED_LNL_CCS:
549 /*
550 * Align to at least 4x1 main surface
551 * tiles (16K) to match 64B of AUX.
552 */
553 return max(mult * 4 * 1024, 16 * 1024);
554 default:
555 MISSING_CASE(fb->modifier);
556 return 0;
557 }
558}
559
560static u32 skl_plane_min_alignment(struct intel_plane *plane,
561 const struct drm_framebuffer *fb,
562 int color_plane)
563{
564 /*
565 * AUX_DIST needs only 4K alignment,
566 * as does ICL UV PLANE_SURF.
567 */
568 if (color_plane != 0)
569 return 4 * 1024;
570
571 switch (fb->modifier) {
572 case DRM_FORMAT_MOD_LINEAR:
573 case I915_FORMAT_MOD_X_TILED:
574 return 256 * 1024;
575 case I915_FORMAT_MOD_Y_TILED_CCS:
576 case I915_FORMAT_MOD_Yf_TILED_CCS:
577 case I915_FORMAT_MOD_Y_TILED:
578 case I915_FORMAT_MOD_Yf_TILED:
579 return 1 * 1024 * 1024;
580 default:
581 MISSING_CASE(fb->modifier);
582 return 0;
583 }
584}
585
586/* Preoffset values for YUV to RGB Conversion */
587#define PREOFF_YUV_TO_RGB_HI 0x1800
588#define PREOFF_YUV_TO_RGB_ME 0x0000
589#define PREOFF_YUV_TO_RGB_LO 0x1800
590
591#define ROFF(x) (((x) & 0xffff) << 16)
592#define GOFF(x) (((x) & 0xffff) << 0)
593#define BOFF(x) (((x) & 0xffff) << 16)
594
595/*
596 * Programs the input color space conversion stage for ICL HDR planes.
597 * Note that it is assumed that this stage always happens after YUV
598 * range correction. Thus, the input to this stage is assumed to be
599 * in full-range YCbCr.
600 */
601static void
602icl_program_input_csc(struct intel_dsb *dsb,
603 struct intel_plane *plane,
604 const struct intel_plane_state *plane_state)
605{
606 struct intel_display *display = to_intel_display(plane->base.dev);
607 enum pipe pipe = plane->pipe;
608 enum plane_id plane_id = plane->id;
609
610 static const u16 input_csc_matrix[][9] = {
611 /*
612 * BT.601 full range YCbCr -> full range RGB
613 * The matrix required is :
614 * [1.000, 0.000, 1.371,
615 * 1.000, -0.336, -0.698,
616 * 1.000, 1.732, 0.0000]
617 */
618 [DRM_COLOR_YCBCR_BT601] = {
619 0x7AF8, 0x7800, 0x0,
620 0x8B28, 0x7800, 0x9AC0,
621 0x0, 0x7800, 0x7DD8,
622 },
623 /*
624 * BT.709 full range YCbCr -> full range RGB
625 * The matrix required is :
626 * [1.000, 0.000, 1.574,
627 * 1.000, -0.187, -0.468,
628 * 1.000, 1.855, 0.0000]
629 */
630 [DRM_COLOR_YCBCR_BT709] = {
631 0x7C98, 0x7800, 0x0,
632 0x9EF8, 0x7800, 0xAC00,
633 0x0, 0x7800, 0x7ED8,
634 },
635 /*
636 * BT.2020 full range YCbCr -> full range RGB
637 * The matrix required is :
638 * [1.000, 0.000, 1.474,
639 * 1.000, -0.1645, -0.5713,
640 * 1.000, 1.8814, 0.0000]
641 */
642 [DRM_COLOR_YCBCR_BT2020] = {
643 0x7BC8, 0x7800, 0x0,
644 0x8928, 0x7800, 0xAA88,
645 0x0, 0x7800, 0x7F10,
646 },
647 };
648 const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
649
650 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
651 ROFF(csc[0]) | GOFF(csc[1]));
652 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
653 BOFF(csc[2]));
654 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
655 ROFF(csc[3]) | GOFF(csc[4]));
656 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
657 BOFF(csc[5]));
658 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
659 ROFF(csc[6]) | GOFF(csc[7]));
660 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
661 BOFF(csc[8]));
662
663 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
664 PREOFF_YUV_TO_RGB_HI);
665 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
666 PREOFF_YUV_TO_RGB_ME);
667 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
668 PREOFF_YUV_TO_RGB_LO);
669 intel_de_write_dsb(display, dsb,
670 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
671 intel_de_write_dsb(display, dsb,
672 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
673 intel_de_write_dsb(display, dsb,
674 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
675}
676
677static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
678 int color_plane, unsigned int rotation)
679{
680 /*
681 * The stride is either expressed as a multiple of 64 bytes chunks for
682 * linear buffers or in number of tiles for tiled buffers.
683 */
684 if (is_surface_linear(fb, color_plane))
685 return 64;
686 else if (drm_rotation_90_or_270(rotation))
687 return intel_tile_height(fb, color_plane);
688 else
689 return intel_tile_width_bytes(fb, color_plane);
690}
691
692static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
693 int color_plane)
694{
695 const struct drm_framebuffer *fb = plane_state->hw.fb;
696 unsigned int rotation = plane_state->hw.rotation;
697 u32 stride = plane_state->view.color_plane[color_plane].scanout_stride;
698
699 if (color_plane >= fb->format->num_planes)
700 return 0;
701
702 return stride / skl_plane_stride_mult(fb, color_plane, rotation);
703}
704
705static u32 skl_plane_ddb_reg_val(const struct skl_ddb_entry *entry)
706{
707 if (!entry->end)
708 return 0;
709
710 return PLANE_BUF_END(entry->end - 1) |
711 PLANE_BUF_START(entry->start);
712}
713
714static u32 skl_plane_wm_reg_val(const struct skl_wm_level *level)
715{
716 u32 val = 0;
717
718 if (level->enable)
719 val |= PLANE_WM_EN;
720 if (level->ignore_lines)
721 val |= PLANE_WM_IGNORE_LINES;
722 val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks);
723 val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines);
724
725 return val;
726}
727
728static void skl_write_plane_wm(struct intel_dsb *dsb,
729 struct intel_plane *plane,
730 const struct intel_crtc_state *crtc_state)
731{
732 struct intel_display *display = to_intel_display(plane->base.dev);
733 struct drm_i915_private *i915 = to_i915(plane->base.dev);
734 enum plane_id plane_id = plane->id;
735 enum pipe pipe = plane->pipe;
736 const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
737 const struct skl_ddb_entry *ddb =
738 &crtc_state->wm.skl.plane_ddb[plane_id];
739 const struct skl_ddb_entry *ddb_y =
740 &crtc_state->wm.skl.plane_ddb_y[plane_id];
741 int level;
742
743 for (level = 0; level < i915->display.wm.num_levels; level++)
744 intel_de_write_dsb(display, dsb, PLANE_WM(pipe, plane_id, level),
745 skl_plane_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));
746
747 intel_de_write_dsb(display, dsb, PLANE_WM_TRANS(pipe, plane_id),
748 skl_plane_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));
749
750 if (HAS_HW_SAGV_WM(i915)) {
751 const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
752
753 intel_de_write_dsb(display, dsb, PLANE_WM_SAGV(pipe, plane_id),
754 skl_plane_wm_reg_val(&wm->sagv.wm0));
755 intel_de_write_dsb(display, dsb, PLANE_WM_SAGV_TRANS(pipe, plane_id),
756 skl_plane_wm_reg_val(&wm->sagv.trans_wm));
757 }
758
759 intel_de_write_dsb(display, dsb, PLANE_BUF_CFG(pipe, plane_id),
760 skl_plane_ddb_reg_val(ddb));
761
762 if (DISPLAY_VER(i915) < 11)
763 intel_de_write_dsb(display, dsb, PLANE_NV12_BUF_CFG(pipe, plane_id),
764 skl_plane_ddb_reg_val(ddb_y));
765}
766
767static void
768skl_plane_disable_arm(struct intel_dsb *dsb,
769 struct intel_plane *plane,
770 const struct intel_crtc_state *crtc_state)
771{
772 struct intel_display *display = to_intel_display(plane->base.dev);
773 enum plane_id plane_id = plane->id;
774 enum pipe pipe = plane->pipe;
775
776 skl_write_plane_wm(dsb, plane, crtc_state);
777
778 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0);
779 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0);
780}
781
782static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb,
783 struct intel_plane *plane,
784 const struct intel_crtc_state *crtc_state)
785{
786 struct intel_display *display = to_intel_display(plane->base.dev);
787 enum pipe pipe = plane->pipe;
788
789 if (!crtc_state->enable_psr2_sel_fetch)
790 return;
791
792 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0);
793}
794
795static void
796icl_plane_disable_arm(struct intel_dsb *dsb,
797 struct intel_plane *plane,
798 const struct intel_crtc_state *crtc_state)
799{
800 struct intel_display *display = to_intel_display(plane->base.dev);
801 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
802 enum plane_id plane_id = plane->id;
803 enum pipe pipe = plane->pipe;
804
805 if (icl_is_hdr_plane(dev_priv, plane_id))
806 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id), 0);
807
808 skl_write_plane_wm(dsb, plane, crtc_state);
809
810 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state);
811 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0);
812 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0);
813}
814
815static bool
816skl_plane_get_hw_state(struct intel_plane *plane,
817 enum pipe *pipe)
818{
819 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
820 enum intel_display_power_domain power_domain;
821 enum plane_id plane_id = plane->id;
822 intel_wakeref_t wakeref;
823 bool ret;
824
825 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
826 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
827 if (!wakeref)
828 return false;
829
830 ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
831
832 *pipe = plane->pipe;
833
834 intel_display_power_put(dev_priv, power_domain, wakeref);
835
836 return ret;
837}
838
839static u32 skl_plane_ctl_format(u32 pixel_format)
840{
841 switch (pixel_format) {
842 case DRM_FORMAT_C8:
843 return PLANE_CTL_FORMAT_INDEXED;
844 case DRM_FORMAT_RGB565:
845 return PLANE_CTL_FORMAT_RGB_565;
846 case DRM_FORMAT_XBGR8888:
847 case DRM_FORMAT_ABGR8888:
848 return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
849 case DRM_FORMAT_XRGB8888:
850 case DRM_FORMAT_ARGB8888:
851 return PLANE_CTL_FORMAT_XRGB_8888;
852 case DRM_FORMAT_XBGR2101010:
853 case DRM_FORMAT_ABGR2101010:
854 return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
855 case DRM_FORMAT_XRGB2101010:
856 case DRM_FORMAT_ARGB2101010:
857 return PLANE_CTL_FORMAT_XRGB_2101010;
858 case DRM_FORMAT_XBGR16161616F:
859 case DRM_FORMAT_ABGR16161616F:
860 return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
861 case DRM_FORMAT_XRGB16161616F:
862 case DRM_FORMAT_ARGB16161616F:
863 return PLANE_CTL_FORMAT_XRGB_16161616F;
864 case DRM_FORMAT_XYUV8888:
865 return PLANE_CTL_FORMAT_XYUV;
866 case DRM_FORMAT_YUYV:
867 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YUYV;
868 case DRM_FORMAT_YVYU:
869 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YVYU;
870 case DRM_FORMAT_UYVY:
871 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_UYVY;
872 case DRM_FORMAT_VYUY:
873 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_VYUY;
874 case DRM_FORMAT_NV12:
875 return PLANE_CTL_FORMAT_NV12;
876 case DRM_FORMAT_P010:
877 return PLANE_CTL_FORMAT_P010;
878 case DRM_FORMAT_P012:
879 return PLANE_CTL_FORMAT_P012;
880 case DRM_FORMAT_P016:
881 return PLANE_CTL_FORMAT_P016;
882 case DRM_FORMAT_Y210:
883 return PLANE_CTL_FORMAT_Y210;
884 case DRM_FORMAT_Y212:
885 return PLANE_CTL_FORMAT_Y212;
886 case DRM_FORMAT_Y216:
887 return PLANE_CTL_FORMAT_Y216;
888 case DRM_FORMAT_XVYU2101010:
889 return PLANE_CTL_FORMAT_Y410;
890 case DRM_FORMAT_XVYU12_16161616:
891 return PLANE_CTL_FORMAT_Y412;
892 case DRM_FORMAT_XVYU16161616:
893 return PLANE_CTL_FORMAT_Y416;
894 default:
895 MISSING_CASE(pixel_format);
896 }
897
898 return 0;
899}
900
901static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
902{
903 if (!plane_state->hw.fb->format->has_alpha)
904 return PLANE_CTL_ALPHA_DISABLE;
905
906 switch (plane_state->hw.pixel_blend_mode) {
907 case DRM_MODE_BLEND_PIXEL_NONE:
908 return PLANE_CTL_ALPHA_DISABLE;
909 case DRM_MODE_BLEND_PREMULTI:
910 return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
911 case DRM_MODE_BLEND_COVERAGE:
912 return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
913 default:
914 MISSING_CASE(plane_state->hw.pixel_blend_mode);
915 return PLANE_CTL_ALPHA_DISABLE;
916 }
917}
918
919static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
920{
921 if (!plane_state->hw.fb->format->has_alpha)
922 return PLANE_COLOR_ALPHA_DISABLE;
923
924 switch (plane_state->hw.pixel_blend_mode) {
925 case DRM_MODE_BLEND_PIXEL_NONE:
926 return PLANE_COLOR_ALPHA_DISABLE;
927 case DRM_MODE_BLEND_PREMULTI:
928 return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
929 case DRM_MODE_BLEND_COVERAGE:
930 return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
931 default:
932 MISSING_CASE(plane_state->hw.pixel_blend_mode);
933 return PLANE_COLOR_ALPHA_DISABLE;
934 }
935}
936
937static u32 skl_plane_ctl_tiling(u64 fb_modifier)
938{
939 switch (fb_modifier) {
940 case DRM_FORMAT_MOD_LINEAR:
941 break;
942 case I915_FORMAT_MOD_X_TILED:
943 return PLANE_CTL_TILED_X;
944 case I915_FORMAT_MOD_Y_TILED:
945 return PLANE_CTL_TILED_Y;
946 case I915_FORMAT_MOD_4_TILED:
947 return PLANE_CTL_TILED_4;
948 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
949 return PLANE_CTL_TILED_4 |
950 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
951 PLANE_CTL_CLEAR_COLOR_DISABLE;
952 case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
953 return PLANE_CTL_TILED_4 |
954 PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE |
955 PLANE_CTL_CLEAR_COLOR_DISABLE;
956 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
957 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
958 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
959 return PLANE_CTL_TILED_4 |
960 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
961 PLANE_CTL_CLEAR_COLOR_DISABLE;
962 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
963 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
964 case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
965 return PLANE_CTL_TILED_4 | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
966 case I915_FORMAT_MOD_4_TILED_BMG_CCS:
967 case I915_FORMAT_MOD_4_TILED_LNL_CCS:
968 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
969 case I915_FORMAT_MOD_Y_TILED_CCS:
970 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
971 return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
972 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
973 return PLANE_CTL_TILED_Y |
974 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
975 PLANE_CTL_CLEAR_COLOR_DISABLE;
976 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
977 return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
978 case I915_FORMAT_MOD_Yf_TILED:
979 return PLANE_CTL_TILED_YF;
980 case I915_FORMAT_MOD_Yf_TILED_CCS:
981 return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
982 default:
983 MISSING_CASE(fb_modifier);
984 }
985
986 return 0;
987}
988
989static u32 skl_plane_ctl_rotate(unsigned int rotate)
990{
991 switch (rotate) {
992 case DRM_MODE_ROTATE_0:
993 break;
994 /*
995 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
996 * while i915 HW rotation is clockwise, thats why this swapping.
997 */
998 case DRM_MODE_ROTATE_90:
999 return PLANE_CTL_ROTATE_270;
1000 case DRM_MODE_ROTATE_180:
1001 return PLANE_CTL_ROTATE_180;
1002 case DRM_MODE_ROTATE_270:
1003 return PLANE_CTL_ROTATE_90;
1004 default:
1005 MISSING_CASE(rotate);
1006 }
1007
1008 return 0;
1009}
1010
1011static u32 icl_plane_ctl_flip(unsigned int reflect)
1012{
1013 switch (reflect) {
1014 case 0:
1015 break;
1016 case DRM_MODE_REFLECT_X:
1017 return PLANE_CTL_FLIP_HORIZONTAL;
1018 case DRM_MODE_REFLECT_Y:
1019 default:
1020 MISSING_CASE(reflect);
1021 }
1022
1023 return 0;
1024}
1025
1026static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
1027{
1028 const struct drm_framebuffer *fb = plane_state->hw.fb;
1029
1030 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
1031 switch (fb->format->cpp[0]) {
1032 case 2:
1033 return PLANE_CTL_ARB_SLOTS(1);
1034 default:
1035 return PLANE_CTL_ARB_SLOTS(0);
1036 }
1037 } else {
1038 switch (fb->format->cpp[0]) {
1039 case 8:
1040 return PLANE_CTL_ARB_SLOTS(3);
1041 case 4:
1042 return PLANE_CTL_ARB_SLOTS(1);
1043 default:
1044 return PLANE_CTL_ARB_SLOTS(0);
1045 }
1046 }
1047}
1048
1049static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
1050{
1051 struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1052 u32 plane_ctl = 0;
1053
1054 if (DISPLAY_VER(dev_priv) >= 10)
1055 return plane_ctl;
1056
1057 if (crtc_state->gamma_enable)
1058 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
1059
1060 if (crtc_state->csc_enable)
1061 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
1062
1063 return plane_ctl;
1064}
1065
1066static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
1067 const struct intel_plane_state *plane_state)
1068{
1069 struct drm_i915_private *dev_priv =
1070 to_i915(plane_state->uapi.plane->dev);
1071 const struct drm_framebuffer *fb = plane_state->hw.fb;
1072 unsigned int rotation = plane_state->hw.rotation;
1073 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1074 u32 plane_ctl;
1075
1076 plane_ctl = PLANE_CTL_ENABLE;
1077
1078 if (DISPLAY_VER(dev_priv) < 10) {
1079 plane_ctl |= skl_plane_ctl_alpha(plane_state);
1080 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
1081
1082 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1083 plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
1084
1085 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1086 plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
1087 }
1088
1089 plane_ctl |= skl_plane_ctl_format(fb->format->format);
1090 plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
1091 plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
1092
1093 if (DISPLAY_VER(dev_priv) >= 11)
1094 plane_ctl |= icl_plane_ctl_flip(rotation &
1095 DRM_MODE_REFLECT_MASK);
1096
1097 if (key->flags & I915_SET_COLORKEY_DESTINATION)
1098 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
1099 else if (key->flags & I915_SET_COLORKEY_SOURCE)
1100 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
1101
1102 /* Wa_22012358565:adl-p */
1103 if (DISPLAY_VER(dev_priv) == 13)
1104 plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
1105
1106 return plane_ctl;
1107}
1108
1109static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
1110{
1111 struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1112 u32 plane_color_ctl = 0;
1113
1114 if (DISPLAY_VER(dev_priv) >= 11)
1115 return plane_color_ctl;
1116
1117 if (crtc_state->gamma_enable)
1118 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
1119
1120 if (crtc_state->csc_enable)
1121 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
1122
1123 return plane_color_ctl;
1124}
1125
1126static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
1127 const struct intel_plane_state *plane_state)
1128{
1129 struct drm_i915_private *dev_priv =
1130 to_i915(plane_state->uapi.plane->dev);
1131 const struct drm_framebuffer *fb = plane_state->hw.fb;
1132 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1133 u32 plane_color_ctl = 0;
1134
1135 plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
1136 plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
1137
1138 if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
1139 switch (plane_state->hw.color_encoding) {
1140 case DRM_COLOR_YCBCR_BT709:
1141 plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
1142 break;
1143 case DRM_COLOR_YCBCR_BT2020:
1144 plane_color_ctl |=
1145 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
1146 break;
1147 default:
1148 plane_color_ctl |=
1149 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
1150 }
1151 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1152 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
1153 } else if (fb->format->is_yuv) {
1154 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
1155 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1156 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
1157 }
1158
1159 if (plane_state->force_black)
1160 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
1161
1162 return plane_color_ctl;
1163}
1164
1165static u32 skl_surf_address(const struct intel_plane_state *plane_state,
1166 int color_plane)
1167{
1168 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1169 const struct drm_framebuffer *fb = plane_state->hw.fb;
1170 u32 offset = plane_state->view.color_plane[color_plane].offset;
1171
1172 if (intel_fb_uses_dpt(fb)) {
1173 /*
1174 * The DPT object contains only one vma, so the VMA's offset
1175 * within the DPT is always 0.
1176 */
1177 drm_WARN_ON(&i915->drm, plane_state->dpt_vma &&
1178 intel_dpt_offset(plane_state->dpt_vma));
1179 drm_WARN_ON(&i915->drm, offset & 0x1fffff);
1180 return offset >> 9;
1181 } else {
1182 drm_WARN_ON(&i915->drm, offset & 0xfff);
1183 return offset;
1184 }
1185}
1186
1187static u32 skl_plane_surf(const struct intel_plane_state *plane_state,
1188 int color_plane)
1189{
1190 u32 plane_surf;
1191
1192 plane_surf = intel_plane_ggtt_offset(plane_state) +
1193 skl_surf_address(plane_state, color_plane);
1194
1195 if (plane_state->decrypt)
1196 plane_surf |= PLANE_SURF_DECRYPT;
1197
1198 return plane_surf;
1199}
1200
1201static u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state,
1202 int color_plane)
1203{
1204 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1205 const struct drm_framebuffer *fb = plane_state->hw.fb;
1206 int aux_plane = skl_main_to_aux_plane(fb, color_plane);
1207 u32 aux_dist;
1208
1209 if (!aux_plane)
1210 return 0;
1211
1212 aux_dist = skl_surf_address(plane_state, aux_plane) -
1213 skl_surf_address(plane_state, color_plane);
1214
1215 if (DISPLAY_VER(i915) < 12)
1216 aux_dist |= PLANE_AUX_STRIDE(skl_plane_stride(plane_state, aux_plane));
1217
1218 return aux_dist;
1219}
1220
1221static u32 skl_plane_keyval(const struct intel_plane_state *plane_state)
1222{
1223 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1224
1225 return key->min_value;
1226}
1227
1228static u32 skl_plane_keymax(const struct intel_plane_state *plane_state)
1229{
1230 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1231 u8 alpha = plane_state->hw.alpha >> 8;
1232
1233 return (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
1234}
1235
1236static u32 skl_plane_keymsk(const struct intel_plane_state *plane_state)
1237{
1238 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1239 u8 alpha = plane_state->hw.alpha >> 8;
1240 u32 keymsk;
1241
1242 keymsk = key->channel_mask & 0x7ffffff;
1243 if (alpha < 0xff)
1244 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
1245
1246 return keymsk;
1247}
1248
1249static void icl_plane_csc_load_black(struct intel_dsb *dsb,
1250 struct intel_plane *plane,
1251 const struct intel_crtc_state *crtc_state)
1252{
1253 struct intel_display *display = to_intel_display(plane->base.dev);
1254 enum plane_id plane_id = plane->id;
1255 enum pipe pipe = plane->pipe;
1256
1257 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 0), 0);
1258 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 1), 0);
1259
1260 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 2), 0);
1261 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 3), 0);
1262
1263 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 4), 0);
1264 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 5), 0);
1265
1266 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0);
1267 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0);
1268 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0);
1269
1270 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0);
1271 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0);
1272 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0);
1273}
1274
1275static int icl_plane_color_plane(const struct intel_plane_state *plane_state)
1276{
1277 /* Program the UV plane on planar master */
1278 if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1279 return 1;
1280 else
1281 return 0;
1282}
1283
1284static void
1285skl_plane_update_noarm(struct intel_dsb *dsb,
1286 struct intel_plane *plane,
1287 const struct intel_crtc_state *crtc_state,
1288 const struct intel_plane_state *plane_state)
1289{
1290 struct intel_display *display = to_intel_display(plane->base.dev);
1291 enum plane_id plane_id = plane->id;
1292 enum pipe pipe = plane->pipe;
1293 u32 stride = skl_plane_stride(plane_state, 0);
1294 int crtc_x = plane_state->uapi.dst.x1;
1295 int crtc_y = plane_state->uapi.dst.y1;
1296 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1297 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1298
1299 /* The scaler will handle the output position */
1300 if (plane_state->scaler_id >= 0) {
1301 crtc_x = 0;
1302 crtc_y = 0;
1303 }
1304
1305 intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id),
1306 PLANE_STRIDE_(stride));
1307 intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id),
1308 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1309 intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id),
1310 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1311
1312 skl_write_plane_wm(dsb, plane, crtc_state);
1313}
1314
1315static void
1316skl_plane_update_arm(struct intel_dsb *dsb,
1317 struct intel_plane *plane,
1318 const struct intel_crtc_state *crtc_state,
1319 const struct intel_plane_state *plane_state)
1320{
1321 struct intel_display *display = to_intel_display(plane->base.dev);
1322 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1323 enum plane_id plane_id = plane->id;
1324 enum pipe pipe = plane->pipe;
1325 u32 x = plane_state->view.color_plane[0].x;
1326 u32 y = plane_state->view.color_plane[0].y;
1327 u32 plane_ctl, plane_color_ctl = 0;
1328
1329 plane_ctl = plane_state->ctl |
1330 skl_plane_ctl_crtc(crtc_state);
1331
1332 /* see intel_plane_atomic_calc_changes() */
1333 if (plane->need_async_flip_toggle_wa &&
1334 crtc_state->async_flip_planes & BIT(plane->id))
1335 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1336
1337 if (DISPLAY_VER(dev_priv) >= 10)
1338 plane_color_ctl = plane_state->color_ctl |
1339 glk_plane_color_ctl_crtc(crtc_state);
1340
1341 intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id),
1342 skl_plane_keyval(plane_state));
1343 intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id),
1344 skl_plane_keymsk(plane_state));
1345 intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id),
1346 skl_plane_keymax(plane_state));
1347
1348 intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id),
1349 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1350
1351 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id),
1352 skl_plane_aux_dist(plane_state, 0));
1353
1354 intel_de_write_dsb(display, dsb, PLANE_AUX_OFFSET(pipe, plane_id),
1355 PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
1356 PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
1357
1358 if (DISPLAY_VER(dev_priv) >= 10)
1359 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id),
1360 plane_color_ctl);
1361
1362 /*
1363 * Enable the scaler before the plane so that we don't
1364 * get a catastrophic underrun even if the two operations
1365 * end up happening in two different frames.
1366 *
1367 * TODO: split into noarm+arm pair
1368 */
1369 if (plane_state->scaler_id >= 0)
1370 skl_program_plane_scaler(plane, crtc_state, plane_state);
1371
1372 /*
1373 * The control register self-arms if the plane was previously
1374 * disabled. Try to make the plane enable atomic by writing
1375 * the control register just before the surface register.
1376 */
1377 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1378 plane_ctl);
1379 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1380 skl_plane_surf(plane_state, 0));
1381}
1382
1383static void icl_plane_update_sel_fetch_noarm(struct intel_dsb *dsb,
1384 struct intel_plane *plane,
1385 const struct intel_crtc_state *crtc_state,
1386 const struct intel_plane_state *plane_state,
1387 int color_plane)
1388{
1389 struct intel_display *display = to_intel_display(plane->base.dev);
1390 enum pipe pipe = plane->pipe;
1391 const struct drm_rect *clip;
1392 u32 val;
1393 int x, y;
1394
1395 if (!crtc_state->enable_psr2_sel_fetch)
1396 return;
1397
1398 clip = &plane_state->psr2_sel_fetch_area;
1399
1400 if (crtc_state->enable_psr2_su_region_et)
1401 y = max(0, plane_state->uapi.dst.y1 - crtc_state->psr2_su_area.y1);
1402 else
1403 y = (clip->y1 + plane_state->uapi.dst.y1);
1404 val = y << 16;
1405 val |= plane_state->uapi.dst.x1;
1406 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_POS(pipe, plane->id), val);
1407
1408 x = plane_state->view.color_plane[color_plane].x;
1409
1410 /*
1411 * From Bspec: UV surface Start Y Position = half of Y plane Y
1412 * start position.
1413 */
1414 if (!color_plane)
1415 y = plane_state->view.color_plane[color_plane].y + clip->y1;
1416 else
1417 y = plane_state->view.color_plane[color_plane].y + clip->y1 / 2;
1418
1419 val = y << 16 | x;
1420
1421 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_OFFSET(pipe, plane->id), val);
1422
1423 /* Sizes are 0 based */
1424 val = (drm_rect_height(clip) - 1) << 16;
1425 val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1;
1426 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_SIZE(pipe, plane->id), val);
1427}
1428
1429static void
1430icl_plane_update_noarm(struct intel_dsb *dsb,
1431 struct intel_plane *plane,
1432 const struct intel_crtc_state *crtc_state,
1433 const struct intel_plane_state *plane_state)
1434{
1435 struct intel_display *display = to_intel_display(plane->base.dev);
1436 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1437 enum plane_id plane_id = plane->id;
1438 enum pipe pipe = plane->pipe;
1439 int color_plane = icl_plane_color_plane(plane_state);
1440 u32 stride = skl_plane_stride(plane_state, color_plane);
1441 const struct drm_framebuffer *fb = plane_state->hw.fb;
1442 int crtc_x = plane_state->uapi.dst.x1;
1443 int crtc_y = plane_state->uapi.dst.y1;
1444 int x = plane_state->view.color_plane[color_plane].x;
1445 int y = plane_state->view.color_plane[color_plane].y;
1446 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1447 int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1448 u32 plane_color_ctl;
1449
1450 plane_color_ctl = plane_state->color_ctl |
1451 glk_plane_color_ctl_crtc(crtc_state);
1452
1453 /* The scaler will handle the output position */
1454 if (plane_state->scaler_id >= 0) {
1455 crtc_x = 0;
1456 crtc_y = 0;
1457 }
1458
1459 intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id),
1460 PLANE_STRIDE_(stride));
1461 intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id),
1462 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1463 intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id),
1464 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1465
1466 intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id),
1467 skl_plane_keyval(plane_state));
1468 intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id),
1469 skl_plane_keymsk(plane_state));
1470 intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id),
1471 skl_plane_keymax(plane_state));
1472
1473 intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id),
1474 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1475
1476 if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) {
1477 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 0),
1478 lower_32_bits(plane_state->ccval));
1479 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 1),
1480 upper_32_bits(plane_state->ccval));
1481 }
1482
1483 /* FLAT CCS doesn't need to program AUX_DIST */
1484 if (!HAS_FLAT_CCS(dev_priv) && DISPLAY_VER(dev_priv) < 20)
1485 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id),
1486 skl_plane_aux_dist(plane_state, color_plane));
1487
1488 if (icl_is_hdr_plane(dev_priv, plane_id))
1489 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id),
1490 plane_state->cus_ctl);
1491
1492 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id),
1493 plane_color_ctl);
1494
1495 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
1496 icl_program_input_csc(dsb, plane, plane_state);
1497
1498 skl_write_plane_wm(dsb, plane, crtc_state);
1499
1500 /*
1501 * FIXME: pxp session invalidation can hit any time even at time of commit
1502 * or after the commit, display content will be garbage.
1503 */
1504 if (plane_state->force_black)
1505 icl_plane_csc_load_black(dsb, plane, crtc_state);
1506
1507 icl_plane_update_sel_fetch_noarm(dsb, plane, crtc_state, plane_state, color_plane);
1508}
1509
1510static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb,
1511 struct intel_plane *plane,
1512 const struct intel_crtc_state *crtc_state,
1513 const struct intel_plane_state *plane_state)
1514{
1515 struct intel_display *display = to_intel_display(plane->base.dev);
1516 enum pipe pipe = plane->pipe;
1517
1518 if (!crtc_state->enable_psr2_sel_fetch)
1519 return;
1520
1521 if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
1522 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id),
1523 SEL_FETCH_PLANE_CTL_ENABLE);
1524 else
1525 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state);
1526}
1527
1528static void
1529icl_plane_update_arm(struct intel_dsb *dsb,
1530 struct intel_plane *plane,
1531 const struct intel_crtc_state *crtc_state,
1532 const struct intel_plane_state *plane_state)
1533{
1534 struct intel_display *display = to_intel_display(plane->base.dev);
1535 enum plane_id plane_id = plane->id;
1536 enum pipe pipe = plane->pipe;
1537 int color_plane = icl_plane_color_plane(plane_state);
1538 u32 plane_ctl;
1539
1540 plane_ctl = plane_state->ctl |
1541 skl_plane_ctl_crtc(crtc_state);
1542
1543 /*
1544 * Enable the scaler before the plane so that we don't
1545 * get a catastrophic underrun even if the two operations
1546 * end up happening in two different frames.
1547 *
1548 * TODO: split into noarm+arm pair
1549 */
1550 if (plane_state->scaler_id >= 0)
1551 skl_program_plane_scaler(plane, crtc_state, plane_state);
1552
1553 icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
1554
1555 /*
1556 * The control register self-arms if the plane was previously
1557 * disabled. Try to make the plane enable atomic by writing
1558 * the control register just before the surface register.
1559 */
1560 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1561 plane_ctl);
1562 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1563 skl_plane_surf(plane_state, color_plane));
1564}
1565
1566static void
1567skl_plane_async_flip(struct intel_dsb *dsb,
1568 struct intel_plane *plane,
1569 const struct intel_crtc_state *crtc_state,
1570 const struct intel_plane_state *plane_state,
1571 bool async_flip)
1572{
1573 struct intel_display *display = to_intel_display(plane->base.dev);
1574 enum plane_id plane_id = plane->id;
1575 enum pipe pipe = plane->pipe;
1576 u32 plane_ctl = plane_state->ctl, plane_surf;
1577
1578 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1579 plane_surf = skl_plane_surf(plane_state, 0);
1580
1581 if (async_flip) {
1582 if (DISPLAY_VER(display) >= 30)
1583 plane_surf |= PLANE_SURF_ASYNC_UPDATE;
1584 else
1585 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1586 }
1587
1588 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
1589 plane_ctl);
1590 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
1591 plane_surf);
1592}
1593
1594static bool intel_format_is_p01x(u32 format)
1595{
1596 switch (format) {
1597 case DRM_FORMAT_P010:
1598 case DRM_FORMAT_P012:
1599 case DRM_FORMAT_P016:
1600 return true;
1601 default:
1602 return false;
1603 }
1604}
1605
1606static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1607 const struct intel_plane_state *plane_state)
1608{
1609 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1610 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1611 const struct drm_framebuffer *fb = plane_state->hw.fb;
1612 unsigned int rotation = plane_state->hw.rotation;
1613
1614 if (!fb)
1615 return 0;
1616
1617 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1618 intel_fb_is_ccs_modifier(fb->modifier)) {
1619 drm_dbg_kms(&dev_priv->drm,
1620 "RC support only with 0/180 degree rotation (%x)\n",
1621 rotation);
1622 return -EINVAL;
1623 }
1624
1625 if (rotation & DRM_MODE_REFLECT_X &&
1626 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1627 drm_dbg_kms(&dev_priv->drm,
1628 "horizontal flip is not supported with linear surface formats\n");
1629 return -EINVAL;
1630 }
1631
1632 /*
1633 * Display20 onward tile4 hflip is not supported
1634 */
1635 if (rotation & DRM_MODE_REFLECT_X &&
1636 intel_fb_is_tile4_modifier(fb->modifier) &&
1637 DISPLAY_VER(dev_priv) >= 20) {
1638 drm_dbg_kms(&dev_priv->drm,
1639 "horizontal flip is not supported with tile4 surface formats\n");
1640 return -EINVAL;
1641 }
1642
1643 if (drm_rotation_90_or_270(rotation)) {
1644 if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
1645 drm_dbg_kms(&dev_priv->drm,
1646 "Y/Yf tiling required for 90/270!\n");
1647 return -EINVAL;
1648 }
1649
1650 /*
1651 * 90/270 is not allowed with RGB64 16:16:16:16 and
1652 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1653 */
1654 switch (fb->format->format) {
1655 case DRM_FORMAT_RGB565:
1656 if (DISPLAY_VER(dev_priv) >= 11)
1657 break;
1658 fallthrough;
1659 case DRM_FORMAT_C8:
1660 case DRM_FORMAT_XRGB16161616F:
1661 case DRM_FORMAT_XBGR16161616F:
1662 case DRM_FORMAT_ARGB16161616F:
1663 case DRM_FORMAT_ABGR16161616F:
1664 case DRM_FORMAT_Y210:
1665 case DRM_FORMAT_Y212:
1666 case DRM_FORMAT_Y216:
1667 case DRM_FORMAT_XVYU12_16161616:
1668 case DRM_FORMAT_XVYU16161616:
1669 drm_dbg_kms(&dev_priv->drm,
1670 "Unsupported pixel format %p4cc for 90/270!\n",
1671 &fb->format->format);
1672 return -EINVAL;
1673 default:
1674 break;
1675 }
1676 }
1677
1678 /* Y-tiling is not supported in IF-ID Interlace mode */
1679 if (crtc_state->hw.enable &&
1680 crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1681 fb->modifier != DRM_FORMAT_MOD_LINEAR &&
1682 fb->modifier != I915_FORMAT_MOD_X_TILED) {
1683 drm_dbg_kms(&dev_priv->drm,
1684 "Y/Yf tiling not supported in IF-ID mode\n");
1685 return -EINVAL;
1686 }
1687
1688 /* Wa_1606054188:tgl,adl-s */
1689 if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
1690 plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1691 intel_format_is_p01x(fb->format->format)) {
1692 drm_dbg_kms(&dev_priv->drm,
1693 "Source color keying not supported with P01x formats\n");
1694 return -EINVAL;
1695 }
1696
1697 return 0;
1698}
1699
1700static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1701 const struct intel_plane_state *plane_state)
1702{
1703 struct drm_i915_private *dev_priv =
1704 to_i915(plane_state->uapi.plane->dev);
1705 int crtc_x = plane_state->uapi.dst.x1;
1706 int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1707 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
1708
1709 /*
1710 * Display WA #1175: glk
1711 * Planes other than the cursor may cause FIFO underflow and display
1712 * corruption if starting less than 4 pixels from the right edge of
1713 * the screen.
1714 * Besides the above WA fix the similar problem, where planes other
1715 * than the cursor ending less than 4 pixels from the left edge of the
1716 * screen may cause FIFO underflow and display corruption.
1717 */
1718 if (DISPLAY_VER(dev_priv) == 10 &&
1719 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1720 drm_dbg_kms(&dev_priv->drm,
1721 "requested plane X %s position %d invalid (valid range %d-%d)\n",
1722 crtc_x + crtc_w < 4 ? "end" : "start",
1723 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1724 4, pipe_src_w - 4);
1725 return -ERANGE;
1726 }
1727
1728 return 0;
1729}
1730
1731static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1732{
1733 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1734 const struct drm_framebuffer *fb = plane_state->hw.fb;
1735 unsigned int rotation = plane_state->hw.rotation;
1736 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1737
1738 /* Display WA #1106 */
1739 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1740 src_w & 3 &&
1741 (rotation == DRM_MODE_ROTATE_270 ||
1742 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1743 drm_dbg_kms(&i915->drm, "src width must be multiple of 4 for rotated planar YUV\n");
1744 return -EINVAL;
1745 }
1746
1747 return 0;
1748}
1749
1750static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
1751 const struct drm_framebuffer *fb)
1752{
1753 /*
1754 * We don't yet know the final source width nor
1755 * whether we can use the HQ scaler mode. Assume
1756 * the best case.
1757 * FIXME need to properly check this later.
1758 */
1759 if (DISPLAY_VER(dev_priv) >= 10 ||
1760 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1761 return 0x30000 - 1;
1762 else
1763 return 0x20000 - 1;
1764}
1765
1766static int intel_plane_min_width(struct intel_plane *plane,
1767 const struct drm_framebuffer *fb,
1768 int color_plane,
1769 unsigned int rotation)
1770{
1771 if (plane->min_width)
1772 return plane->min_width(fb, color_plane, rotation);
1773 else
1774 return 1;
1775}
1776
1777static int intel_plane_max_width(struct intel_plane *plane,
1778 const struct drm_framebuffer *fb,
1779 int color_plane,
1780 unsigned int rotation)
1781{
1782 if (plane->max_width)
1783 return plane->max_width(fb, color_plane, rotation);
1784 else
1785 return INT_MAX;
1786}
1787
1788static int intel_plane_max_height(struct intel_plane *plane,
1789 const struct drm_framebuffer *fb,
1790 int color_plane,
1791 unsigned int rotation)
1792{
1793 if (plane->max_height)
1794 return plane->max_height(fb, color_plane, rotation);
1795 else
1796 return INT_MAX;
1797}
1798
1799static bool
1800skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1801 int main_x, int main_y, u32 main_offset,
1802 int ccs_plane)
1803{
1804 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1805 const struct drm_framebuffer *fb = plane_state->hw.fb;
1806 int aux_x = plane_state->view.color_plane[ccs_plane].x;
1807 int aux_y = plane_state->view.color_plane[ccs_plane].y;
1808 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1809 unsigned int alignment = plane->min_alignment(plane, fb, ccs_plane);
1810 int hsub;
1811 int vsub;
1812
1813 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1814 while (aux_offset >= main_offset && aux_y <= main_y) {
1815 int x, y;
1816
1817 if (aux_x == main_x && aux_y == main_y)
1818 break;
1819
1820 if (aux_offset == 0)
1821 break;
1822
1823 x = aux_x / hsub;
1824 y = aux_y / vsub;
1825 aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1826 plane_state,
1827 ccs_plane,
1828 aux_offset,
1829 aux_offset - alignment);
1830 aux_x = x * hsub + aux_x % hsub;
1831 aux_y = y * vsub + aux_y % vsub;
1832 }
1833
1834 if (aux_x != main_x || aux_y != main_y)
1835 return false;
1836
1837 plane_state->view.color_plane[ccs_plane].offset = aux_offset;
1838 plane_state->view.color_plane[ccs_plane].x = aux_x;
1839 plane_state->view.color_plane[ccs_plane].y = aux_y;
1840
1841 return true;
1842}
1843
1844
1845int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
1846 int *x, int *y, u32 *offset)
1847{
1848 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1849 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1850 const struct drm_framebuffer *fb = plane_state->hw.fb;
1851 int aux_plane = skl_main_to_aux_plane(fb, 0);
1852 u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
1853 unsigned int alignment = plane->min_alignment(plane, fb, 0);
1854 int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1855
1856 intel_add_fb_offsets(x, y, plane_state, 0);
1857 *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
1858 if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
1859 return -EINVAL;
1860
1861 /*
1862 * AUX surface offset is specified as the distance from the
1863 * main surface offset, and it must be non-negative. Make
1864 * sure that is what we will get.
1865 */
1866 if (aux_plane && *offset > aux_offset)
1867 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1868 *offset,
1869 aux_offset & ~(alignment - 1));
1870
1871 /*
1872 * When using an X-tiled surface, the plane blows up
1873 * if the x offset + width exceed the stride.
1874 *
1875 * TODO: linear and Y-tiled seem fine, Yf untested,
1876 */
1877 if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
1878 int cpp = fb->format->cpp[0];
1879
1880 while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
1881 if (*offset == 0) {
1882 drm_dbg_kms(&dev_priv->drm,
1883 "Unable to find suitable display surface offset due to X-tiling\n");
1884 return -EINVAL;
1885 }
1886
1887 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1888 *offset,
1889 *offset - alignment);
1890 }
1891 }
1892
1893 return 0;
1894}
1895
1896static int skl_check_main_surface(struct intel_plane_state *plane_state)
1897{
1898 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1899 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1900 const struct drm_framebuffer *fb = plane_state->hw.fb;
1901 unsigned int rotation = plane_state->hw.rotation;
1902 int x = plane_state->uapi.src.x1 >> 16;
1903 int y = plane_state->uapi.src.y1 >> 16;
1904 int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1905 int h = drm_rect_height(&plane_state->uapi.src) >> 16;
1906 int min_width = intel_plane_min_width(plane, fb, 0, rotation);
1907 int max_width = intel_plane_max_width(plane, fb, 0, rotation);
1908 int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1909 unsigned int alignment = plane->min_alignment(plane, fb, 0);
1910 int aux_plane = skl_main_to_aux_plane(fb, 0);
1911 u32 offset;
1912 int ret;
1913
1914 if (w > max_width || w < min_width || h > max_height || h < 1) {
1915 drm_dbg_kms(&dev_priv->drm,
1916 "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
1917 w, h, min_width, max_width, max_height);
1918 return -EINVAL;
1919 }
1920
1921 ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
1922 if (ret)
1923 return ret;
1924
1925 /*
1926 * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1927 * they match with the main surface x/y offsets. On DG2
1928 * there's no aux plane on fb so skip this checking.
1929 */
1930 if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) {
1931 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1932 offset, aux_plane)) {
1933 if (offset == 0)
1934 break;
1935
1936 offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
1937 offset, offset - alignment);
1938 }
1939
1940 if (x != plane_state->view.color_plane[aux_plane].x ||
1941 y != plane_state->view.color_plane[aux_plane].y) {
1942 drm_dbg_kms(&dev_priv->drm,
1943 "Unable to find suitable display surface offset due to CCS\n");
1944 return -EINVAL;
1945 }
1946 }
1947
1948 if (DISPLAY_VER(dev_priv) >= 13)
1949 drm_WARN_ON(&dev_priv->drm, x > 65535 || y > 65535);
1950 else
1951 drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
1952
1953 plane_state->view.color_plane[0].offset = offset;
1954 plane_state->view.color_plane[0].x = x;
1955 plane_state->view.color_plane[0].y = y;
1956
1957 /*
1958 * Put the final coordinates back so that the src
1959 * coordinate checks will see the right values.
1960 */
1961 drm_rect_translate_to(&plane_state->uapi.src,
1962 x << 16, y << 16);
1963
1964 return 0;
1965}
1966
1967static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
1968{
1969 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1970 struct drm_i915_private *i915 = to_i915(plane->base.dev);
1971 const struct drm_framebuffer *fb = plane_state->hw.fb;
1972 unsigned int rotation = plane_state->hw.rotation;
1973 int uv_plane = 1;
1974 int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ?
1975 skl_main_to_aux_plane(fb, uv_plane) : 0;
1976 int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
1977 int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
1978 int x = plane_state->uapi.src.x1 >> 17;
1979 int y = plane_state->uapi.src.y1 >> 17;
1980 int w = drm_rect_width(&plane_state->uapi.src) >> 17;
1981 int h = drm_rect_height(&plane_state->uapi.src) >> 17;
1982 u32 offset;
1983
1984 /* FIXME not quite sure how/if these apply to the chroma plane */
1985 if (w > max_width || h > max_height) {
1986 drm_dbg_kms(&i915->drm,
1987 "CbCr source size %dx%d too big (limit %dx%d)\n",
1988 w, h, max_width, max_height);
1989 return -EINVAL;
1990 }
1991
1992 intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
1993 offset = intel_plane_compute_aligned_offset(&x, &y,
1994 plane_state, uv_plane);
1995
1996 if (ccs_plane) {
1997 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1998 unsigned int alignment = plane->min_alignment(plane, fb, uv_plane);
1999
2000 if (offset > aux_offset)
2001 offset = intel_plane_adjust_aligned_offset(&x, &y,
2002 plane_state,
2003 uv_plane,
2004 offset,
2005 aux_offset & ~(alignment - 1));
2006
2007 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
2008 offset, ccs_plane)) {
2009 if (offset == 0)
2010 break;
2011
2012 offset = intel_plane_adjust_aligned_offset(&x, &y,
2013 plane_state,
2014 uv_plane,
2015 offset, offset - alignment);
2016 }
2017
2018 if (x != plane_state->view.color_plane[ccs_plane].x ||
2019 y != plane_state->view.color_plane[ccs_plane].y) {
2020 drm_dbg_kms(&i915->drm,
2021 "Unable to find suitable display surface offset due to CCS\n");
2022 return -EINVAL;
2023 }
2024 }
2025
2026 if (DISPLAY_VER(i915) >= 13)
2027 drm_WARN_ON(&i915->drm, x > 65535 || y > 65535);
2028 else
2029 drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
2030
2031 plane_state->view.color_plane[uv_plane].offset = offset;
2032 plane_state->view.color_plane[uv_plane].x = x;
2033 plane_state->view.color_plane[uv_plane].y = y;
2034
2035 return 0;
2036}
2037
2038static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
2039{
2040 const struct drm_framebuffer *fb = plane_state->hw.fb;
2041 int src_x = plane_state->uapi.src.x1 >> 16;
2042 int src_y = plane_state->uapi.src.y1 >> 16;
2043 u32 offset;
2044 int ccs_plane;
2045
2046 for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
2047 int main_hsub, main_vsub;
2048 int hsub, vsub;
2049 int x, y;
2050
2051 if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane))
2052 continue;
2053
2054 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
2055 skl_ccs_to_main_plane(fb, ccs_plane));
2056 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
2057
2058 hsub *= main_hsub;
2059 vsub *= main_vsub;
2060 x = src_x / hsub;
2061 y = src_y / vsub;
2062
2063 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
2064
2065 offset = intel_plane_compute_aligned_offset(&x, &y,
2066 plane_state,
2067 ccs_plane);
2068
2069 plane_state->view.color_plane[ccs_plane].offset = offset;
2070 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
2071 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
2072 }
2073
2074 return 0;
2075}
2076
2077static int skl_check_plane_surface(struct intel_plane_state *plane_state)
2078{
2079 const struct drm_framebuffer *fb = plane_state->hw.fb;
2080 int ret;
2081
2082 ret = intel_plane_compute_gtt(plane_state);
2083 if (ret)
2084 return ret;
2085
2086 if (!plane_state->uapi.visible)
2087 return 0;
2088
2089 /*
2090 * Handle the AUX surface first since the main surface setup depends on
2091 * it.
2092 */
2093 if (intel_fb_is_ccs_modifier(fb->modifier)) {
2094 ret = skl_check_ccs_aux_surface(plane_state);
2095 if (ret)
2096 return ret;
2097 }
2098
2099 if (intel_format_info_is_yuv_semiplanar(fb->format,
2100 fb->modifier)) {
2101 ret = skl_check_nv12_aux_surface(plane_state);
2102 if (ret)
2103 return ret;
2104 }
2105
2106 ret = skl_check_main_surface(plane_state);
2107 if (ret)
2108 return ret;
2109
2110 return 0;
2111}
2112
2113static bool skl_fb_scalable(const struct drm_framebuffer *fb)
2114{
2115 if (!fb)
2116 return false;
2117
2118 switch (fb->format->format) {
2119 case DRM_FORMAT_C8:
2120 return false;
2121 case DRM_FORMAT_XRGB16161616F:
2122 case DRM_FORMAT_ARGB16161616F:
2123 case DRM_FORMAT_XBGR16161616F:
2124 case DRM_FORMAT_ABGR16161616F:
2125 return DISPLAY_VER(to_i915(fb->dev)) >= 11;
2126 default:
2127 return true;
2128 }
2129}
2130
2131static void check_protection(struct intel_plane_state *plane_state)
2132{
2133 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2134 struct drm_i915_private *i915 = to_i915(plane->base.dev);
2135 const struct drm_framebuffer *fb = plane_state->hw.fb;
2136 struct drm_gem_object *obj = intel_fb_bo(fb);
2137
2138 if (DISPLAY_VER(i915) < 11)
2139 return;
2140
2141 plane_state->decrypt = intel_pxp_key_check(i915->pxp, obj, false) == 0;
2142 plane_state->force_black = intel_bo_is_protected(obj) &&
2143 !plane_state->decrypt;
2144}
2145
2146static int skl_plane_check(struct intel_crtc_state *crtc_state,
2147 struct intel_plane_state *plane_state)
2148{
2149 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2150 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2151 const struct drm_framebuffer *fb = plane_state->hw.fb;
2152 int min_scale = DRM_PLANE_NO_SCALING;
2153 int max_scale = DRM_PLANE_NO_SCALING;
2154 int ret;
2155
2156 ret = skl_plane_check_fb(crtc_state, plane_state);
2157 if (ret)
2158 return ret;
2159
2160 /* use scaler when colorkey is not required */
2161 if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
2162 min_scale = 1;
2163 max_scale = skl_plane_max_scale(dev_priv, fb);
2164 }
2165
2166 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
2167 min_scale, max_scale, true);
2168 if (ret)
2169 return ret;
2170
2171 ret = skl_check_plane_surface(plane_state);
2172 if (ret)
2173 return ret;
2174
2175 if (!plane_state->uapi.visible)
2176 return 0;
2177
2178 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
2179 if (ret)
2180 return ret;
2181
2182 ret = intel_plane_check_src_coordinates(plane_state);
2183 if (ret)
2184 return ret;
2185
2186 ret = skl_plane_check_nv12_rotation(plane_state);
2187 if (ret)
2188 return ret;
2189
2190 check_protection(plane_state);
2191
2192 /* HW only has 8 bits pixel precision, disable plane if invisible */
2193 if (!(plane_state->hw.alpha >> 8))
2194 plane_state->uapi.visible = false;
2195
2196 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
2197
2198 if (DISPLAY_VER(dev_priv) >= 10)
2199 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
2200 plane_state);
2201
2202 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2203 icl_is_hdr_plane(dev_priv, plane->id))
2204 /* Enable and use MPEG-2 chroma siting */
2205 plane_state->cus_ctl = PLANE_CUS_ENABLE |
2206 PLANE_CUS_HPHASE_0 |
2207 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
2208 else
2209 plane_state->cus_ctl = 0;
2210
2211 return 0;
2212}
2213
2214static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
2215{
2216 return pipe - PIPE_A + INTEL_FBC_A;
2217}
2218
2219static bool skl_plane_has_fbc(struct drm_i915_private *i915,
2220 enum intel_fbc_id fbc_id, enum plane_id plane_id)
2221{
2222 if ((DISPLAY_RUNTIME_INFO(i915)->fbc_mask & BIT(fbc_id)) == 0)
2223 return false;
2224
2225 if (DISPLAY_VER(i915) >= 20)
2226 return icl_is_hdr_plane(i915, plane_id);
2227 else
2228 return plane_id == PLANE_1;
2229}
2230
2231static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv,
2232 enum pipe pipe, enum plane_id plane_id)
2233{
2234 enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
2235
2236 if (skl_plane_has_fbc(dev_priv, fbc_id, plane_id))
2237 return dev_priv->display.fbc[fbc_id];
2238 else
2239 return NULL;
2240}
2241
2242static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2243 enum pipe pipe, enum plane_id plane_id)
2244{
2245 /* Display WA #0870: skl, bxt */
2246 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2247 return false;
2248
2249 if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C)
2250 return false;
2251
2252 if (plane_id != PLANE_1 && plane_id != PLANE_2)
2253 return false;
2254
2255 return true;
2256}
2257
2258static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2259 enum pipe pipe, enum plane_id plane_id,
2260 int *num_formats)
2261{
2262 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2263 *num_formats = ARRAY_SIZE(skl_planar_formats);
2264 return skl_planar_formats;
2265 } else {
2266 *num_formats = ARRAY_SIZE(skl_plane_formats);
2267 return skl_plane_formats;
2268 }
2269}
2270
2271static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
2272 enum pipe pipe, enum plane_id plane_id,
2273 int *num_formats)
2274{
2275 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2276 *num_formats = ARRAY_SIZE(glk_planar_formats);
2277 return glk_planar_formats;
2278 } else {
2279 *num_formats = ARRAY_SIZE(skl_plane_formats);
2280 return skl_plane_formats;
2281 }
2282}
2283
2284static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
2285 enum pipe pipe, enum plane_id plane_id,
2286 int *num_formats)
2287{
2288 if (icl_is_hdr_plane(dev_priv, plane_id)) {
2289 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2290 return icl_hdr_plane_formats;
2291 } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
2292 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2293 return icl_sdr_y_plane_formats;
2294 } else {
2295 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2296 return icl_sdr_uv_plane_formats;
2297 }
2298}
2299
2300static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2301 u32 format, u64 modifier)
2302{
2303 struct intel_plane *plane = to_intel_plane(_plane);
2304
2305 if (!intel_fb_plane_supports_modifier(plane, modifier))
2306 return false;
2307
2308 switch (format) {
2309 case DRM_FORMAT_XRGB8888:
2310 case DRM_FORMAT_XBGR8888:
2311 case DRM_FORMAT_ARGB8888:
2312 case DRM_FORMAT_ABGR8888:
2313 if (intel_fb_is_ccs_modifier(modifier))
2314 return true;
2315 fallthrough;
2316 case DRM_FORMAT_RGB565:
2317 case DRM_FORMAT_XRGB2101010:
2318 case DRM_FORMAT_XBGR2101010:
2319 case DRM_FORMAT_ARGB2101010:
2320 case DRM_FORMAT_ABGR2101010:
2321 case DRM_FORMAT_YUYV:
2322 case DRM_FORMAT_YVYU:
2323 case DRM_FORMAT_UYVY:
2324 case DRM_FORMAT_VYUY:
2325 case DRM_FORMAT_NV12:
2326 case DRM_FORMAT_XYUV8888:
2327 case DRM_FORMAT_P010:
2328 case DRM_FORMAT_P012:
2329 case DRM_FORMAT_P016:
2330 case DRM_FORMAT_XVYU2101010:
2331 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2332 return true;
2333 fallthrough;
2334 case DRM_FORMAT_C8:
2335 case DRM_FORMAT_XBGR16161616F:
2336 case DRM_FORMAT_ABGR16161616F:
2337 case DRM_FORMAT_XRGB16161616F:
2338 case DRM_FORMAT_ARGB16161616F:
2339 case DRM_FORMAT_Y210:
2340 case DRM_FORMAT_Y212:
2341 case DRM_FORMAT_Y216:
2342 case DRM_FORMAT_XVYU12_16161616:
2343 case DRM_FORMAT_XVYU16161616:
2344 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2345 modifier == I915_FORMAT_MOD_X_TILED ||
2346 modifier == I915_FORMAT_MOD_Y_TILED)
2347 return true;
2348 fallthrough;
2349 default:
2350 return false;
2351 }
2352}
2353
2354static bool icl_plane_format_mod_supported(struct drm_plane *_plane,
2355 u32 format, u64 modifier)
2356{
2357 struct intel_plane *plane = to_intel_plane(_plane);
2358
2359 if (!intel_fb_plane_supports_modifier(plane, modifier))
2360 return false;
2361
2362 switch (format) {
2363 case DRM_FORMAT_XRGB8888:
2364 case DRM_FORMAT_XBGR8888:
2365 case DRM_FORMAT_ARGB8888:
2366 case DRM_FORMAT_ABGR8888:
2367 case DRM_FORMAT_XRGB2101010:
2368 case DRM_FORMAT_XBGR2101010:
2369 case DRM_FORMAT_ARGB2101010:
2370 case DRM_FORMAT_ABGR2101010:
2371 if (intel_fb_is_ccs_modifier(modifier))
2372 return true;
2373 fallthrough;
2374 case DRM_FORMAT_RGB565:
2375 case DRM_FORMAT_YUYV:
2376 case DRM_FORMAT_YVYU:
2377 case DRM_FORMAT_UYVY:
2378 case DRM_FORMAT_VYUY:
2379 case DRM_FORMAT_NV12:
2380 case DRM_FORMAT_XYUV8888:
2381 case DRM_FORMAT_P010:
2382 case DRM_FORMAT_P012:
2383 case DRM_FORMAT_P016:
2384 case DRM_FORMAT_XVYU2101010:
2385 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2386 return true;
2387 fallthrough;
2388 case DRM_FORMAT_C8:
2389 case DRM_FORMAT_XBGR16161616F:
2390 case DRM_FORMAT_ABGR16161616F:
2391 case DRM_FORMAT_XRGB16161616F:
2392 case DRM_FORMAT_ARGB16161616F:
2393 case DRM_FORMAT_Y210:
2394 case DRM_FORMAT_Y212:
2395 case DRM_FORMAT_Y216:
2396 case DRM_FORMAT_XVYU12_16161616:
2397 case DRM_FORMAT_XVYU16161616:
2398 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2399 modifier == I915_FORMAT_MOD_X_TILED ||
2400 modifier == I915_FORMAT_MOD_Y_TILED)
2401 return true;
2402 fallthrough;
2403 default:
2404 return false;
2405 }
2406}
2407
2408static bool tgl_plane_format_mod_supported(struct drm_plane *_plane,
2409 u32 format, u64 modifier)
2410{
2411 struct intel_plane *plane = to_intel_plane(_plane);
2412
2413 if (!intel_fb_plane_supports_modifier(plane, modifier))
2414 return false;
2415
2416 switch (format) {
2417 case DRM_FORMAT_XRGB8888:
2418 case DRM_FORMAT_XBGR8888:
2419 case DRM_FORMAT_ARGB8888:
2420 case DRM_FORMAT_ABGR8888:
2421 case DRM_FORMAT_XRGB2101010:
2422 case DRM_FORMAT_XBGR2101010:
2423 case DRM_FORMAT_ARGB2101010:
2424 case DRM_FORMAT_ABGR2101010:
2425 case DRM_FORMAT_XBGR16161616F:
2426 case DRM_FORMAT_ABGR16161616F:
2427 case DRM_FORMAT_XRGB16161616F:
2428 case DRM_FORMAT_ARGB16161616F:
2429 if (intel_fb_is_ccs_modifier(modifier))
2430 return true;
2431 fallthrough;
2432 case DRM_FORMAT_YUYV:
2433 case DRM_FORMAT_YVYU:
2434 case DRM_FORMAT_UYVY:
2435 case DRM_FORMAT_VYUY:
2436 case DRM_FORMAT_NV12:
2437 case DRM_FORMAT_XYUV8888:
2438 case DRM_FORMAT_P010:
2439 case DRM_FORMAT_P012:
2440 case DRM_FORMAT_P016:
2441 if (intel_fb_is_mc_ccs_modifier(modifier))
2442 return true;
2443 fallthrough;
2444 case DRM_FORMAT_RGB565:
2445 case DRM_FORMAT_XVYU2101010:
2446 case DRM_FORMAT_C8:
2447 case DRM_FORMAT_Y210:
2448 case DRM_FORMAT_Y212:
2449 case DRM_FORMAT_Y216:
2450 case DRM_FORMAT_XVYU12_16161616:
2451 case DRM_FORMAT_XVYU16161616:
2452 if (!intel_fb_is_ccs_modifier(modifier))
2453 return true;
2454 fallthrough;
2455 default:
2456 return false;
2457 }
2458}
2459
2460static const struct drm_plane_funcs skl_plane_funcs = {
2461 .update_plane = drm_atomic_helper_update_plane,
2462 .disable_plane = drm_atomic_helper_disable_plane,
2463 .destroy = intel_plane_destroy,
2464 .atomic_duplicate_state = intel_plane_duplicate_state,
2465 .atomic_destroy_state = intel_plane_destroy_state,
2466 .format_mod_supported = skl_plane_format_mod_supported,
2467};
2468
2469static const struct drm_plane_funcs icl_plane_funcs = {
2470 .update_plane = drm_atomic_helper_update_plane,
2471 .disable_plane = drm_atomic_helper_disable_plane,
2472 .destroy = intel_plane_destroy,
2473 .atomic_duplicate_state = intel_plane_duplicate_state,
2474 .atomic_destroy_state = intel_plane_destroy_state,
2475 .format_mod_supported = icl_plane_format_mod_supported,
2476};
2477
2478static const struct drm_plane_funcs tgl_plane_funcs = {
2479 .update_plane = drm_atomic_helper_update_plane,
2480 .disable_plane = drm_atomic_helper_disable_plane,
2481 .destroy = intel_plane_destroy,
2482 .atomic_duplicate_state = intel_plane_duplicate_state,
2483 .atomic_destroy_state = intel_plane_destroy_state,
2484 .format_mod_supported = tgl_plane_format_mod_supported,
2485};
2486
2487static void
2488skl_plane_enable_flip_done(struct intel_plane *plane)
2489{
2490 struct drm_i915_private *i915 = to_i915(plane->base.dev);
2491 enum pipe pipe = plane->pipe;
2492
2493 spin_lock_irq(&i915->irq_lock);
2494 bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2495 spin_unlock_irq(&i915->irq_lock);
2496}
2497
2498static void
2499skl_plane_disable_flip_done(struct intel_plane *plane)
2500{
2501 struct drm_i915_private *i915 = to_i915(plane->base.dev);
2502 enum pipe pipe = plane->pipe;
2503
2504 spin_lock_irq(&i915->irq_lock);
2505 bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2506 spin_unlock_irq(&i915->irq_lock);
2507}
2508
2509static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915,
2510 enum pipe pipe, enum plane_id plane_id)
2511{
2512 /* Wa_22011186057 */
2513 if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2514 return false;
2515
2516 if (DISPLAY_VER(i915) >= 11)
2517 return true;
2518
2519 if (IS_GEMINILAKE(i915))
2520 return pipe != PIPE_C;
2521
2522 return pipe != PIPE_C &&
2523 (plane_id == PLANE_1 || plane_id == PLANE_2);
2524}
2525
2526static bool tgl_plane_has_mc_ccs(struct drm_i915_private *i915,
2527 enum plane_id plane_id)
2528{
2529 if (DISPLAY_VER(i915) < 12)
2530 return false;
2531
2532 /* Wa_14010477008 */
2533 if (IS_DG1(i915) || IS_ROCKETLAKE(i915) ||
2534 (IS_TIGERLAKE(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_D0)))
2535 return false;
2536
2537 /* Wa_22011186057 */
2538 if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2539 return false;
2540
2541 return plane_id < PLANE_6;
2542}
2543
2544static u8 skl_get_plane_caps(struct drm_i915_private *i915,
2545 enum pipe pipe, enum plane_id plane_id)
2546{
2547 u8 caps = INTEL_PLANE_CAP_TILING_X;
2548
2549 if (DISPLAY_VER(i915) < 13 || IS_ALDERLAKE_P(i915))
2550 caps |= INTEL_PLANE_CAP_TILING_Y;
2551 if (DISPLAY_VER(i915) < 12)
2552 caps |= INTEL_PLANE_CAP_TILING_Yf;
2553 if (HAS_4TILE(i915))
2554 caps |= INTEL_PLANE_CAP_TILING_4;
2555
2556 if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(i915))
2557 return caps;
2558
2559 if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
2560 caps |= INTEL_PLANE_CAP_CCS_RC;
2561 if (DISPLAY_VER(i915) >= 12)
2562 caps |= INTEL_PLANE_CAP_CCS_RC_CC;
2563 }
2564
2565 if (tgl_plane_has_mc_ccs(i915, plane_id))
2566 caps |= INTEL_PLANE_CAP_CCS_MC;
2567
2568 if (DISPLAY_VER(i915) >= 14 && IS_DGFX(i915))
2569 caps |= INTEL_PLANE_CAP_NEED64K_PHYS;
2570
2571 return caps;
2572}
2573
2574struct intel_plane *
2575skl_universal_plane_create(struct drm_i915_private *dev_priv,
2576 enum pipe pipe, enum plane_id plane_id)
2577{
2578 const struct drm_plane_funcs *plane_funcs;
2579 struct intel_plane *plane;
2580 enum drm_plane_type plane_type;
2581 unsigned int supported_rotations;
2582 unsigned int supported_csc;
2583 const u64 *modifiers;
2584 const u32 *formats;
2585 int num_formats;
2586 int ret;
2587
2588 plane = intel_plane_alloc();
2589 if (IS_ERR(plane))
2590 return plane;
2591
2592 plane->pipe = pipe;
2593 plane->id = plane_id;
2594 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2595
2596 intel_fbc_add_plane(skl_plane_fbc(dev_priv, pipe, plane_id), plane);
2597
2598 if (DISPLAY_VER(dev_priv) >= 30) {
2599 plane->max_width = xe3_plane_max_width;
2600 plane->max_height = icl_plane_max_height;
2601 plane->min_cdclk = icl_plane_min_cdclk;
2602 } else if (DISPLAY_VER(dev_priv) >= 11) {
2603 plane->min_width = icl_plane_min_width;
2604 if (icl_is_hdr_plane(dev_priv, plane_id))
2605 plane->max_width = icl_hdr_plane_max_width;
2606 else
2607 plane->max_width = icl_sdr_plane_max_width;
2608 plane->max_height = icl_plane_max_height;
2609 plane->min_cdclk = icl_plane_min_cdclk;
2610 } else if (DISPLAY_VER(dev_priv) >= 10) {
2611 plane->max_width = glk_plane_max_width;
2612 plane->max_height = skl_plane_max_height;
2613 plane->min_cdclk = glk_plane_min_cdclk;
2614 } else {
2615 plane->max_width = skl_plane_max_width;
2616 plane->max_height = skl_plane_max_height;
2617 plane->min_cdclk = skl_plane_min_cdclk;
2618 }
2619
2620 if (DISPLAY_VER(dev_priv) >= 13)
2621 plane->max_stride = adl_plane_max_stride;
2622 else
2623 plane->max_stride = skl_plane_max_stride;
2624
2625 if (DISPLAY_VER(dev_priv) >= 12)
2626 plane->min_alignment = tgl_plane_min_alignment;
2627 else
2628 plane->min_alignment = skl_plane_min_alignment;
2629
2630 if (DISPLAY_VER(dev_priv) >= 11) {
2631 plane->update_noarm = icl_plane_update_noarm;
2632 plane->update_arm = icl_plane_update_arm;
2633 plane->disable_arm = icl_plane_disable_arm;
2634 } else {
2635 plane->update_noarm = skl_plane_update_noarm;
2636 plane->update_arm = skl_plane_update_arm;
2637 plane->disable_arm = skl_plane_disable_arm;
2638 }
2639 plane->get_hw_state = skl_plane_get_hw_state;
2640 plane->check_plane = skl_plane_check;
2641
2642 if (plane_id == PLANE_1) {
2643 plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(dev_priv, 9, 10);
2644 plane->async_flip = skl_plane_async_flip;
2645 plane->enable_flip_done = skl_plane_enable_flip_done;
2646 plane->disable_flip_done = skl_plane_disable_flip_done;
2647 }
2648
2649 if (DISPLAY_VER(dev_priv) >= 11)
2650 formats = icl_get_plane_formats(dev_priv, pipe,
2651 plane_id, &num_formats);
2652 else if (DISPLAY_VER(dev_priv) >= 10)
2653 formats = glk_get_plane_formats(dev_priv, pipe,
2654 plane_id, &num_formats);
2655 else
2656 formats = skl_get_plane_formats(dev_priv, pipe,
2657 plane_id, &num_formats);
2658
2659 if (DISPLAY_VER(dev_priv) >= 12)
2660 plane_funcs = &tgl_plane_funcs;
2661 else if (DISPLAY_VER(dev_priv) == 11)
2662 plane_funcs = &icl_plane_funcs;
2663 else
2664 plane_funcs = &skl_plane_funcs;
2665
2666 if (plane_id == PLANE_1)
2667 plane_type = DRM_PLANE_TYPE_PRIMARY;
2668 else
2669 plane_type = DRM_PLANE_TYPE_OVERLAY;
2670
2671 modifiers = intel_fb_plane_get_modifiers(dev_priv,
2672 skl_get_plane_caps(dev_priv, pipe, plane_id));
2673
2674 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2675 0, plane_funcs,
2676 formats, num_formats, modifiers,
2677 plane_type,
2678 "plane %d%c", plane_id + 1,
2679 pipe_name(pipe));
2680
2681 kfree(modifiers);
2682
2683 if (ret)
2684 goto fail;
2685
2686 if (DISPLAY_VER(dev_priv) >= 13)
2687 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2688 else
2689 supported_rotations =
2690 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2691 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2692
2693 if (DISPLAY_VER(dev_priv) >= 11)
2694 supported_rotations |= DRM_MODE_REFLECT_X;
2695
2696 drm_plane_create_rotation_property(&plane->base,
2697 DRM_MODE_ROTATE_0,
2698 supported_rotations);
2699
2700 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
2701
2702 if (DISPLAY_VER(dev_priv) >= 10)
2703 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
2704
2705 drm_plane_create_color_properties(&plane->base,
2706 supported_csc,
2707 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2708 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2709 DRM_COLOR_YCBCR_BT709,
2710 DRM_COLOR_YCBCR_LIMITED_RANGE);
2711
2712 drm_plane_create_alpha_property(&plane->base);
2713 drm_plane_create_blend_mode_property(&plane->base,
2714 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2715 BIT(DRM_MODE_BLEND_PREMULTI) |
2716 BIT(DRM_MODE_BLEND_COVERAGE));
2717
2718 drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
2719
2720 if (DISPLAY_VER(dev_priv) >= 12)
2721 drm_plane_enable_fb_damage_clips(&plane->base);
2722
2723 if (DISPLAY_VER(dev_priv) >= 11)
2724 drm_plane_create_scaling_filter_property(&plane->base,
2725 BIT(DRM_SCALING_FILTER_DEFAULT) |
2726 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2727
2728 intel_plane_helper_add(plane);
2729
2730 return plane;
2731
2732fail:
2733 intel_plane_free(plane);
2734
2735 return ERR_PTR(ret);
2736}
2737
2738void
2739skl_get_initial_plane_config(struct intel_crtc *crtc,
2740 struct intel_initial_plane_config *plane_config)
2741{
2742 struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
2743 struct drm_device *dev = crtc->base.dev;
2744 struct drm_i915_private *dev_priv = to_i915(dev);
2745 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2746 enum plane_id plane_id = plane->id;
2747 enum pipe pipe;
2748 u32 val, base, offset, stride_mult, tiling, alpha;
2749 int fourcc, pixel_format;
2750 unsigned int aligned_height;
2751 struct drm_framebuffer *fb;
2752 struct intel_framebuffer *intel_fb;
2753 static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4);
2754
2755 if (!plane->get_hw_state(plane, &pipe))
2756 return;
2757
2758 drm_WARN_ON(dev, pipe != crtc->pipe);
2759
2760 if (crtc_state->joiner_pipes) {
2761 drm_dbg_kms(&dev_priv->drm,
2762 "Unsupported joiner configuration for initial FB\n");
2763 return;
2764 }
2765
2766 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
2767 if (!intel_fb) {
2768 drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
2769 return;
2770 }
2771
2772 fb = &intel_fb->base;
2773
2774 fb->dev = dev;
2775
2776 val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
2777
2778 if (DISPLAY_VER(dev_priv) >= 11)
2779 pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL;
2780 else
2781 pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL;
2782
2783 if (DISPLAY_VER(dev_priv) >= 10) {
2784 u32 color_ctl;
2785
2786 color_ctl = intel_de_read(dev_priv, PLANE_COLOR_CTL(pipe, plane_id));
2787 alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl);
2788 } else {
2789 alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val);
2790 }
2791
2792 fourcc = skl_format_to_fourcc(pixel_format,
2793 val & PLANE_CTL_ORDER_RGBX, alpha);
2794 fb->format = drm_format_info(fourcc);
2795
2796 tiling = val & PLANE_CTL_TILED_MASK;
2797 switch (tiling) {
2798 case PLANE_CTL_TILED_LINEAR:
2799 fb->modifier = DRM_FORMAT_MOD_LINEAR;
2800 break;
2801 case PLANE_CTL_TILED_X:
2802 plane_config->tiling = I915_TILING_X;
2803 fb->modifier = I915_FORMAT_MOD_X_TILED;
2804 break;
2805 case PLANE_CTL_TILED_Y:
2806 plane_config->tiling = I915_TILING_Y;
2807 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2808 if (DISPLAY_VER(dev_priv) >= 14)
2809 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS;
2810 else if (DISPLAY_VER(dev_priv) >= 12)
2811 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
2812 else
2813 fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
2814 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2815 if (DISPLAY_VER(dev_priv) >= 14)
2816 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS;
2817 else
2818 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
2819 else
2820 fb->modifier = I915_FORMAT_MOD_Y_TILED;
2821 break;
2822 case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
2823 if (HAS_4TILE(dev_priv)) {
2824 u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
2825 PLANE_CTL_CLEAR_COLOR_DISABLE;
2826
2827 if ((val & rc_mask) == rc_mask)
2828 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS;
2829 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2830 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS;
2831 else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2832 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
2833 else
2834 fb->modifier = I915_FORMAT_MOD_4_TILED;
2835 } else {
2836 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2837 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
2838 else
2839 fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2840 }
2841 break;
2842 default:
2843 MISSING_CASE(tiling);
2844 goto error;
2845 }
2846
2847 if (!dev_priv->display.params.enable_dpt &&
2848 intel_fb_modifier_uses_dpt(dev_priv, fb->modifier)) {
2849 drm_dbg_kms(&dev_priv->drm, "DPT disabled, skipping initial FB\n");
2850 goto error;
2851 }
2852
2853 /*
2854 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
2855 * while i915 HW rotation is clockwise, thats why this swapping.
2856 */
2857 switch (val & PLANE_CTL_ROTATE_MASK) {
2858 case PLANE_CTL_ROTATE_0:
2859 plane_config->rotation = DRM_MODE_ROTATE_0;
2860 break;
2861 case PLANE_CTL_ROTATE_90:
2862 plane_config->rotation = DRM_MODE_ROTATE_270;
2863 break;
2864 case PLANE_CTL_ROTATE_180:
2865 plane_config->rotation = DRM_MODE_ROTATE_180;
2866 break;
2867 case PLANE_CTL_ROTATE_270:
2868 plane_config->rotation = DRM_MODE_ROTATE_90;
2869 break;
2870 }
2871
2872 if (DISPLAY_VER(dev_priv) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
2873 plane_config->rotation |= DRM_MODE_REFLECT_X;
2874
2875 /* 90/270 degree rotation would require extra work */
2876 if (drm_rotation_90_or_270(plane_config->rotation))
2877 goto error;
2878
2879 base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & PLANE_SURF_ADDR_MASK;
2880 plane_config->base = base;
2881
2882 offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
2883 drm_WARN_ON(&dev_priv->drm, offset != 0);
2884
2885 val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
2886 fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1;
2887 fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1;
2888
2889 val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
2890 stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2891
2892 fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult;
2893
2894 aligned_height = intel_fb_align_height(fb, 0, fb->height);
2895
2896 plane_config->size = fb->pitches[0] * aligned_height;
2897
2898 drm_dbg_kms(&dev_priv->drm,
2899 "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
2900 crtc->base.name, plane->base.name, fb->width, fb->height,
2901 fb->format->cpp[0] * 8, base, fb->pitches[0],
2902 plane_config->size);
2903
2904 plane_config->fb = intel_fb;
2905 return;
2906
2907error:
2908 kfree(intel_fb);
2909}
2910
2911bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
2912 const struct intel_initial_plane_config *plane_config)
2913{
2914 struct drm_i915_private *i915 = to_i915(crtc->base.dev);
2915 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2916 const struct intel_plane_state *plane_state =
2917 to_intel_plane_state(plane->base.state);
2918 enum plane_id plane_id = plane->id;
2919 enum pipe pipe = crtc->pipe;
2920 u32 base;
2921
2922 if (!plane_state->uapi.visible)
2923 return false;
2924
2925 base = intel_plane_ggtt_offset(plane_state);
2926
2927 /*
2928 * We may have moved the surface to a different
2929 * part of ggtt, make the plane aware of that.
2930 */
2931 if (plane_config->base == base)
2932 return false;
2933
2934 intel_de_write(i915, PLANE_SURF(pipe, plane_id), base);
2935
2936 return true;
2937}