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