1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2020 Intel Corporation
4  */
5 
6 #include <drm/drm_atomic_helper.h>
7 #include <drm/drm_damage_helper.h>
8 #include <drm/drm_fourcc.h>
9 #include <drm/drm_plane_helper.h>
10 
11 #include "i915_drv.h"
12 #include "intel_atomic_plane.h"
13 #include "intel_display_types.h"
14 #include "intel_pm.h"
15 #include "intel_psr.h"
16 #include "intel_sprite.h"
17 #include "skl_scaler.h"
18 #include "skl_universal_plane.h"
19 
20 static const u32 skl_plane_formats[] = {
21 	DRM_FORMAT_C8,
22 	DRM_FORMAT_RGB565,
23 	DRM_FORMAT_XRGB8888,
24 	DRM_FORMAT_XBGR8888,
25 	DRM_FORMAT_ARGB8888,
26 	DRM_FORMAT_ABGR8888,
27 	DRM_FORMAT_XRGB2101010,
28 	DRM_FORMAT_XBGR2101010,
29 	DRM_FORMAT_XRGB16161616F,
30 	DRM_FORMAT_XBGR16161616F,
31 	DRM_FORMAT_YUYV,
32 	DRM_FORMAT_YVYU,
33 	DRM_FORMAT_UYVY,
34 	DRM_FORMAT_VYUY,
35 	DRM_FORMAT_XYUV8888,
36 };
37 
38 static const u32 skl_planar_formats[] = {
39 	DRM_FORMAT_C8,
40 	DRM_FORMAT_RGB565,
41 	DRM_FORMAT_XRGB8888,
42 	DRM_FORMAT_XBGR8888,
43 	DRM_FORMAT_ARGB8888,
44 	DRM_FORMAT_ABGR8888,
45 	DRM_FORMAT_XRGB2101010,
46 	DRM_FORMAT_XBGR2101010,
47 	DRM_FORMAT_XRGB16161616F,
48 	DRM_FORMAT_XBGR16161616F,
49 	DRM_FORMAT_YUYV,
50 	DRM_FORMAT_YVYU,
51 	DRM_FORMAT_UYVY,
52 	DRM_FORMAT_VYUY,
53 	DRM_FORMAT_NV12,
54 	DRM_FORMAT_XYUV8888,
55 };
56 
57 static const u32 glk_planar_formats[] = {
58 	DRM_FORMAT_C8,
59 	DRM_FORMAT_RGB565,
60 	DRM_FORMAT_XRGB8888,
61 	DRM_FORMAT_XBGR8888,
62 	DRM_FORMAT_ARGB8888,
63 	DRM_FORMAT_ABGR8888,
64 	DRM_FORMAT_XRGB2101010,
65 	DRM_FORMAT_XBGR2101010,
66 	DRM_FORMAT_XRGB16161616F,
67 	DRM_FORMAT_XBGR16161616F,
68 	DRM_FORMAT_YUYV,
69 	DRM_FORMAT_YVYU,
70 	DRM_FORMAT_UYVY,
71 	DRM_FORMAT_VYUY,
72 	DRM_FORMAT_NV12,
73 	DRM_FORMAT_XYUV8888,
74 	DRM_FORMAT_P010,
75 	DRM_FORMAT_P012,
76 	DRM_FORMAT_P016,
77 };
78 
79 static const u32 icl_sdr_y_plane_formats[] = {
80 	DRM_FORMAT_C8,
81 	DRM_FORMAT_RGB565,
82 	DRM_FORMAT_XRGB8888,
83 	DRM_FORMAT_XBGR8888,
84 	DRM_FORMAT_ARGB8888,
85 	DRM_FORMAT_ABGR8888,
86 	DRM_FORMAT_XRGB2101010,
87 	DRM_FORMAT_XBGR2101010,
88 	DRM_FORMAT_ARGB2101010,
89 	DRM_FORMAT_ABGR2101010,
90 	DRM_FORMAT_YUYV,
91 	DRM_FORMAT_YVYU,
92 	DRM_FORMAT_UYVY,
93 	DRM_FORMAT_VYUY,
94 	DRM_FORMAT_Y210,
95 	DRM_FORMAT_Y212,
96 	DRM_FORMAT_Y216,
97 	DRM_FORMAT_XYUV8888,
98 	DRM_FORMAT_XVYU2101010,
99 	DRM_FORMAT_XVYU12_16161616,
100 	DRM_FORMAT_XVYU16161616,
101 };
102 
103 static const u32 icl_sdr_uv_plane_formats[] = {
104 	DRM_FORMAT_C8,
105 	DRM_FORMAT_RGB565,
106 	DRM_FORMAT_XRGB8888,
107 	DRM_FORMAT_XBGR8888,
108 	DRM_FORMAT_ARGB8888,
109 	DRM_FORMAT_ABGR8888,
110 	DRM_FORMAT_XRGB2101010,
111 	DRM_FORMAT_XBGR2101010,
112 	DRM_FORMAT_ARGB2101010,
113 	DRM_FORMAT_ABGR2101010,
114 	DRM_FORMAT_YUYV,
115 	DRM_FORMAT_YVYU,
116 	DRM_FORMAT_UYVY,
117 	DRM_FORMAT_VYUY,
118 	DRM_FORMAT_NV12,
119 	DRM_FORMAT_P010,
120 	DRM_FORMAT_P012,
121 	DRM_FORMAT_P016,
122 	DRM_FORMAT_Y210,
123 	DRM_FORMAT_Y212,
124 	DRM_FORMAT_Y216,
125 	DRM_FORMAT_XYUV8888,
126 	DRM_FORMAT_XVYU2101010,
127 	DRM_FORMAT_XVYU12_16161616,
128 	DRM_FORMAT_XVYU16161616,
129 };
130 
131 static const u32 icl_hdr_plane_formats[] = {
132 	DRM_FORMAT_C8,
133 	DRM_FORMAT_RGB565,
134 	DRM_FORMAT_XRGB8888,
135 	DRM_FORMAT_XBGR8888,
136 	DRM_FORMAT_ARGB8888,
137 	DRM_FORMAT_ABGR8888,
138 	DRM_FORMAT_XRGB2101010,
139 	DRM_FORMAT_XBGR2101010,
140 	DRM_FORMAT_ARGB2101010,
141 	DRM_FORMAT_ABGR2101010,
142 	DRM_FORMAT_XRGB16161616F,
143 	DRM_FORMAT_XBGR16161616F,
144 	DRM_FORMAT_ARGB16161616F,
145 	DRM_FORMAT_ABGR16161616F,
146 	DRM_FORMAT_YUYV,
147 	DRM_FORMAT_YVYU,
148 	DRM_FORMAT_UYVY,
149 	DRM_FORMAT_VYUY,
150 	DRM_FORMAT_NV12,
151 	DRM_FORMAT_P010,
152 	DRM_FORMAT_P012,
153 	DRM_FORMAT_P016,
154 	DRM_FORMAT_Y210,
155 	DRM_FORMAT_Y212,
156 	DRM_FORMAT_Y216,
157 	DRM_FORMAT_XYUV8888,
158 	DRM_FORMAT_XVYU2101010,
159 	DRM_FORMAT_XVYU12_16161616,
160 	DRM_FORMAT_XVYU16161616,
161 };
162 
163 static const u64 skl_plane_format_modifiers_noccs[] = {
164 	I915_FORMAT_MOD_Yf_TILED,
165 	I915_FORMAT_MOD_Y_TILED,
166 	I915_FORMAT_MOD_X_TILED,
167 	DRM_FORMAT_MOD_LINEAR,
168 	DRM_FORMAT_MOD_INVALID
169 };
170 
171 static const u64 skl_plane_format_modifiers_ccs[] = {
172 	I915_FORMAT_MOD_Yf_TILED_CCS,
173 	I915_FORMAT_MOD_Y_TILED_CCS,
174 	I915_FORMAT_MOD_Yf_TILED,
175 	I915_FORMAT_MOD_Y_TILED,
176 	I915_FORMAT_MOD_X_TILED,
177 	DRM_FORMAT_MOD_LINEAR,
178 	DRM_FORMAT_MOD_INVALID
179 };
180 
181 static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
182 	I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
183 	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
184 	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
185 	I915_FORMAT_MOD_Y_TILED,
186 	I915_FORMAT_MOD_X_TILED,
187 	DRM_FORMAT_MOD_LINEAR,
188 	DRM_FORMAT_MOD_INVALID
189 };
190 
191 static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
192 	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
193 	I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
194 	I915_FORMAT_MOD_Y_TILED,
195 	I915_FORMAT_MOD_X_TILED,
196 	DRM_FORMAT_MOD_LINEAR,
197 	DRM_FORMAT_MOD_INVALID
198 };
199 
200 int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
201 {
202 	switch (format) {
203 	case PLANE_CTL_FORMAT_RGB_565:
204 		return DRM_FORMAT_RGB565;
205 	case PLANE_CTL_FORMAT_NV12:
206 		return DRM_FORMAT_NV12;
207 	case PLANE_CTL_FORMAT_XYUV:
208 		return DRM_FORMAT_XYUV8888;
209 	case PLANE_CTL_FORMAT_P010:
210 		return DRM_FORMAT_P010;
211 	case PLANE_CTL_FORMAT_P012:
212 		return DRM_FORMAT_P012;
213 	case PLANE_CTL_FORMAT_P016:
214 		return DRM_FORMAT_P016;
215 	case PLANE_CTL_FORMAT_Y210:
216 		return DRM_FORMAT_Y210;
217 	case PLANE_CTL_FORMAT_Y212:
218 		return DRM_FORMAT_Y212;
219 	case PLANE_CTL_FORMAT_Y216:
220 		return DRM_FORMAT_Y216;
221 	case PLANE_CTL_FORMAT_Y410:
222 		return DRM_FORMAT_XVYU2101010;
223 	case PLANE_CTL_FORMAT_Y412:
224 		return DRM_FORMAT_XVYU12_16161616;
225 	case PLANE_CTL_FORMAT_Y416:
226 		return DRM_FORMAT_XVYU16161616;
227 	default:
228 	case PLANE_CTL_FORMAT_XRGB_8888:
229 		if (rgb_order) {
230 			if (alpha)
231 				return DRM_FORMAT_ABGR8888;
232 			else
233 				return DRM_FORMAT_XBGR8888;
234 		} else {
235 			if (alpha)
236 				return DRM_FORMAT_ARGB8888;
237 			else
238 				return DRM_FORMAT_XRGB8888;
239 		}
240 	case PLANE_CTL_FORMAT_XRGB_2101010:
241 		if (rgb_order) {
242 			if (alpha)
243 				return DRM_FORMAT_ABGR2101010;
244 			else
245 				return DRM_FORMAT_XBGR2101010;
246 		} else {
247 			if (alpha)
248 				return DRM_FORMAT_ARGB2101010;
249 			else
250 				return DRM_FORMAT_XRGB2101010;
251 		}
252 	case PLANE_CTL_FORMAT_XRGB_16161616F:
253 		if (rgb_order) {
254 			if (alpha)
255 				return DRM_FORMAT_ABGR16161616F;
256 			else
257 				return DRM_FORMAT_XBGR16161616F;
258 		} else {
259 			if (alpha)
260 				return DRM_FORMAT_ARGB16161616F;
261 			else
262 				return DRM_FORMAT_XRGB16161616F;
263 		}
264 	}
265 }
266 
267 static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
268 {
269 	if (HAS_D12_PLANE_MINIMIZATION(i915))
270 		return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
271 	else
272 		return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
273 }
274 
275 bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
276 			 enum plane_id plane_id)
277 {
278 	return INTEL_GEN(dev_priv) >= 11 &&
279 		icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
280 }
281 
282 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
283 {
284 	return INTEL_GEN(dev_priv) >= 11 &&
285 		icl_hdr_plane_mask() & BIT(plane_id);
286 }
287 
288 static void
289 skl_plane_ratio(const struct intel_crtc_state *crtc_state,
290 		const struct intel_plane_state *plane_state,
291 		unsigned int *num, unsigned int *den)
292 {
293 	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
294 	const struct drm_framebuffer *fb = plane_state->hw.fb;
295 
296 	if (fb->format->cpp[0] == 8) {
297 		if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
298 			*num = 10;
299 			*den = 8;
300 		} else {
301 			*num = 9;
302 			*den = 8;
303 		}
304 	} else {
305 		*num = 1;
306 		*den = 1;
307 	}
308 }
309 
310 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
311 			       const struct intel_plane_state *plane_state)
312 {
313 	struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
314 	unsigned int num, den;
315 	unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
316 
317 	skl_plane_ratio(crtc_state, plane_state, &num, &den);
318 
319 	/* two pixels per clock on glk+ */
320 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
321 		den *= 2;
322 
323 	return DIV_ROUND_UP(pixel_rate * num, den);
324 }
325 
326 static int skl_plane_max_width(const struct drm_framebuffer *fb,
327 			       int color_plane,
328 			       unsigned int rotation)
329 {
330 	int cpp = fb->format->cpp[color_plane];
331 
332 	switch (fb->modifier) {
333 	case DRM_FORMAT_MOD_LINEAR:
334 	case I915_FORMAT_MOD_X_TILED:
335 		/*
336 		 * Validated limit is 4k, but has 5k should
337 		 * work apart from the following features:
338 		 * - Ytile (already limited to 4k)
339 		 * - FP16 (already limited to 4k)
340 		 * - render compression (already limited to 4k)
341 		 * - KVMR sprite and cursor (don't care)
342 		 * - horizontal panning (TODO verify this)
343 		 * - pipe and plane scaling (TODO verify this)
344 		 */
345 		if (cpp == 8)
346 			return 4096;
347 		else
348 			return 5120;
349 	case I915_FORMAT_MOD_Y_TILED_CCS:
350 	case I915_FORMAT_MOD_Yf_TILED_CCS:
351 	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_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 icl_plane_max_width(const struct drm_framebuffer *fb,
434 			       int color_plane,
435 			       unsigned int rotation)
436 {
437 	return 5120;
438 }
439 
440 static int skl_plane_max_height(const struct drm_framebuffer *fb,
441 				int color_plane,
442 				unsigned int rotation)
443 {
444 	return 4096;
445 }
446 
447 static int icl_plane_max_height(const struct drm_framebuffer *fb,
448 				int color_plane,
449 				unsigned int rotation)
450 {
451 	return 4320;
452 }
453 
454 static unsigned int
455 skl_plane_max_stride(struct intel_plane *plane,
456 		     u32 pixel_format, u64 modifier,
457 		     unsigned int rotation)
458 {
459 	const struct drm_format_info *info = drm_format_info(pixel_format);
460 	int cpp = info->cpp[0];
461 
462 	/*
463 	 * "The stride in bytes must not exceed the
464 	 * of the size of 8K pixels and 32K bytes."
465 	 */
466 	if (drm_rotation_90_or_270(rotation))
467 		return min(8192, 32768 / cpp);
468 	else
469 		return min(8192 * cpp, 32768);
470 }
471 
472 
473 /* Preoffset values for YUV to RGB Conversion */
474 #define PREOFF_YUV_TO_RGB_HI		0x1800
475 #define PREOFF_YUV_TO_RGB_ME		0x0000
476 #define PREOFF_YUV_TO_RGB_LO		0x1800
477 
478 #define  ROFF(x)          (((x) & 0xffff) << 16)
479 #define  GOFF(x)          (((x) & 0xffff) << 0)
480 #define  BOFF(x)          (((x) & 0xffff) << 16)
481 
482 /*
483  * Programs the input color space conversion stage for ICL HDR planes.
484  * Note that it is assumed that this stage always happens after YUV
485  * range correction. Thus, the input to this stage is assumed to be
486  * in full-range YCbCr.
487  */
488 static void
489 icl_program_input_csc(struct intel_plane *plane,
490 		      const struct intel_crtc_state *crtc_state,
491 		      const struct intel_plane_state *plane_state)
492 {
493 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
494 	enum pipe pipe = plane->pipe;
495 	enum plane_id plane_id = plane->id;
496 
497 	static const u16 input_csc_matrix[][9] = {
498 		/*
499 		 * BT.601 full range YCbCr -> full range RGB
500 		 * The matrix required is :
501 		 * [1.000, 0.000, 1.371,
502 		 *  1.000, -0.336, -0.698,
503 		 *  1.000, 1.732, 0.0000]
504 		 */
505 		[DRM_COLOR_YCBCR_BT601] = {
506 			0x7AF8, 0x7800, 0x0,
507 			0x8B28, 0x7800, 0x9AC0,
508 			0x0, 0x7800, 0x7DD8,
509 		},
510 		/*
511 		 * BT.709 full range YCbCr -> full range RGB
512 		 * The matrix required is :
513 		 * [1.000, 0.000, 1.574,
514 		 *  1.000, -0.187, -0.468,
515 		 *  1.000, 1.855, 0.0000]
516 		 */
517 		[DRM_COLOR_YCBCR_BT709] = {
518 			0x7C98, 0x7800, 0x0,
519 			0x9EF8, 0x7800, 0xAC00,
520 			0x0, 0x7800,  0x7ED8,
521 		},
522 		/*
523 		 * BT.2020 full range YCbCr -> full range RGB
524 		 * The matrix required is :
525 		 * [1.000, 0.000, 1.474,
526 		 *  1.000, -0.1645, -0.5713,
527 		 *  1.000, 1.8814, 0.0000]
528 		 */
529 		[DRM_COLOR_YCBCR_BT2020] = {
530 			0x7BC8, 0x7800, 0x0,
531 			0x8928, 0x7800, 0xAA88,
532 			0x0, 0x7800, 0x7F10,
533 		},
534 	};
535 	const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
536 
537 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
538 			  ROFF(csc[0]) | GOFF(csc[1]));
539 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
540 			  BOFF(csc[2]));
541 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
542 			  ROFF(csc[3]) | GOFF(csc[4]));
543 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
544 			  BOFF(csc[5]));
545 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
546 			  ROFF(csc[6]) | GOFF(csc[7]));
547 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
548 			  BOFF(csc[8]));
549 
550 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
551 			  PREOFF_YUV_TO_RGB_HI);
552 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
553 			  PREOFF_YUV_TO_RGB_ME);
554 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
555 			  PREOFF_YUV_TO_RGB_LO);
556 	intel_de_write_fw(dev_priv,
557 			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
558 	intel_de_write_fw(dev_priv,
559 			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
560 	intel_de_write_fw(dev_priv,
561 			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
562 }
563 
564 static bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane)
565 {
566 	return fb->modifier == DRM_FORMAT_MOD_LINEAR ||
567 	       is_gen12_ccs_plane(fb, color_plane);
568 }
569 
570 static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
571 					  int color_plane, unsigned int rotation)
572 {
573 	/*
574 	 * The stride is either expressed as a multiple of 64 bytes chunks for
575 	 * linear buffers or in number of tiles for tiled buffers.
576 	 */
577 	if (is_surface_linear(fb, color_plane))
578 		return 64;
579 	else if (drm_rotation_90_or_270(rotation))
580 		return intel_tile_height(fb, color_plane);
581 	else
582 		return intel_tile_width_bytes(fb, color_plane);
583 }
584 
585 static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
586 			    int color_plane)
587 {
588 	const struct drm_framebuffer *fb = plane_state->hw.fb;
589 	unsigned int rotation = plane_state->hw.rotation;
590 	u32 stride = plane_state->color_plane[color_plane].stride;
591 
592 	if (color_plane >= fb->format->num_planes)
593 		return 0;
594 
595 	return stride / skl_plane_stride_mult(fb, color_plane, rotation);
596 }
597 
598 static void
599 skl_disable_plane(struct intel_plane *plane,
600 		  const struct intel_crtc_state *crtc_state)
601 {
602 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
603 	enum plane_id plane_id = plane->id;
604 	enum pipe pipe = plane->pipe;
605 	unsigned long irqflags;
606 
607 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
608 
609 	if (icl_is_hdr_plane(dev_priv, plane_id))
610 		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
611 
612 	skl_write_plane_wm(plane, crtc_state);
613 
614 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
615 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
616 
617 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
618 }
619 
620 static bool
621 skl_plane_get_hw_state(struct intel_plane *plane,
622 		       enum pipe *pipe)
623 {
624 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
625 	enum intel_display_power_domain power_domain;
626 	enum plane_id plane_id = plane->id;
627 	intel_wakeref_t wakeref;
628 	bool ret;
629 
630 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
631 	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
632 	if (!wakeref)
633 		return false;
634 
635 	ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
636 
637 	*pipe = plane->pipe;
638 
639 	intel_display_power_put(dev_priv, power_domain, wakeref);
640 
641 	return ret;
642 }
643 
644 static u32 skl_plane_ctl_format(u32 pixel_format)
645 {
646 	switch (pixel_format) {
647 	case DRM_FORMAT_C8:
648 		return PLANE_CTL_FORMAT_INDEXED;
649 	case DRM_FORMAT_RGB565:
650 		return PLANE_CTL_FORMAT_RGB_565;
651 	case DRM_FORMAT_XBGR8888:
652 	case DRM_FORMAT_ABGR8888:
653 		return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
654 	case DRM_FORMAT_XRGB8888:
655 	case DRM_FORMAT_ARGB8888:
656 		return PLANE_CTL_FORMAT_XRGB_8888;
657 	case DRM_FORMAT_XBGR2101010:
658 	case DRM_FORMAT_ABGR2101010:
659 		return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
660 	case DRM_FORMAT_XRGB2101010:
661 	case DRM_FORMAT_ARGB2101010:
662 		return PLANE_CTL_FORMAT_XRGB_2101010;
663 	case DRM_FORMAT_XBGR16161616F:
664 	case DRM_FORMAT_ABGR16161616F:
665 		return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
666 	case DRM_FORMAT_XRGB16161616F:
667 	case DRM_FORMAT_ARGB16161616F:
668 		return PLANE_CTL_FORMAT_XRGB_16161616F;
669 	case DRM_FORMAT_XYUV8888:
670 		return PLANE_CTL_FORMAT_XYUV;
671 	case DRM_FORMAT_YUYV:
672 		return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
673 	case DRM_FORMAT_YVYU:
674 		return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
675 	case DRM_FORMAT_UYVY:
676 		return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
677 	case DRM_FORMAT_VYUY:
678 		return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
679 	case DRM_FORMAT_NV12:
680 		return PLANE_CTL_FORMAT_NV12;
681 	case DRM_FORMAT_P010:
682 		return PLANE_CTL_FORMAT_P010;
683 	case DRM_FORMAT_P012:
684 		return PLANE_CTL_FORMAT_P012;
685 	case DRM_FORMAT_P016:
686 		return PLANE_CTL_FORMAT_P016;
687 	case DRM_FORMAT_Y210:
688 		return PLANE_CTL_FORMAT_Y210;
689 	case DRM_FORMAT_Y212:
690 		return PLANE_CTL_FORMAT_Y212;
691 	case DRM_FORMAT_Y216:
692 		return PLANE_CTL_FORMAT_Y216;
693 	case DRM_FORMAT_XVYU2101010:
694 		return PLANE_CTL_FORMAT_Y410;
695 	case DRM_FORMAT_XVYU12_16161616:
696 		return PLANE_CTL_FORMAT_Y412;
697 	case DRM_FORMAT_XVYU16161616:
698 		return PLANE_CTL_FORMAT_Y416;
699 	default:
700 		MISSING_CASE(pixel_format);
701 	}
702 
703 	return 0;
704 }
705 
706 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
707 {
708 	if (!plane_state->hw.fb->format->has_alpha)
709 		return PLANE_CTL_ALPHA_DISABLE;
710 
711 	switch (plane_state->hw.pixel_blend_mode) {
712 	case DRM_MODE_BLEND_PIXEL_NONE:
713 		return PLANE_CTL_ALPHA_DISABLE;
714 	case DRM_MODE_BLEND_PREMULTI:
715 		return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
716 	case DRM_MODE_BLEND_COVERAGE:
717 		return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
718 	default:
719 		MISSING_CASE(plane_state->hw.pixel_blend_mode);
720 		return PLANE_CTL_ALPHA_DISABLE;
721 	}
722 }
723 
724 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
725 {
726 	if (!plane_state->hw.fb->format->has_alpha)
727 		return PLANE_COLOR_ALPHA_DISABLE;
728 
729 	switch (plane_state->hw.pixel_blend_mode) {
730 	case DRM_MODE_BLEND_PIXEL_NONE:
731 		return PLANE_COLOR_ALPHA_DISABLE;
732 	case DRM_MODE_BLEND_PREMULTI:
733 		return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
734 	case DRM_MODE_BLEND_COVERAGE:
735 		return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
736 	default:
737 		MISSING_CASE(plane_state->hw.pixel_blend_mode);
738 		return PLANE_COLOR_ALPHA_DISABLE;
739 	}
740 }
741 
742 static u32 skl_plane_ctl_tiling(u64 fb_modifier)
743 {
744 	switch (fb_modifier) {
745 	case DRM_FORMAT_MOD_LINEAR:
746 		break;
747 	case I915_FORMAT_MOD_X_TILED:
748 		return PLANE_CTL_TILED_X;
749 	case I915_FORMAT_MOD_Y_TILED:
750 		return PLANE_CTL_TILED_Y;
751 	case I915_FORMAT_MOD_Y_TILED_CCS:
752 	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
753 		return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
754 	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
755 		return PLANE_CTL_TILED_Y |
756 		       PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
757 		       PLANE_CTL_CLEAR_COLOR_DISABLE;
758 	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
759 		return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
760 	case I915_FORMAT_MOD_Yf_TILED:
761 		return PLANE_CTL_TILED_YF;
762 	case I915_FORMAT_MOD_Yf_TILED_CCS:
763 		return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
764 	default:
765 		MISSING_CASE(fb_modifier);
766 	}
767 
768 	return 0;
769 }
770 
771 static u32 skl_plane_ctl_rotate(unsigned int rotate)
772 {
773 	switch (rotate) {
774 	case DRM_MODE_ROTATE_0:
775 		break;
776 	/*
777 	 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
778 	 * while i915 HW rotation is clockwise, thats why this swapping.
779 	 */
780 	case DRM_MODE_ROTATE_90:
781 		return PLANE_CTL_ROTATE_270;
782 	case DRM_MODE_ROTATE_180:
783 		return PLANE_CTL_ROTATE_180;
784 	case DRM_MODE_ROTATE_270:
785 		return PLANE_CTL_ROTATE_90;
786 	default:
787 		MISSING_CASE(rotate);
788 	}
789 
790 	return 0;
791 }
792 
793 static u32 cnl_plane_ctl_flip(unsigned int reflect)
794 {
795 	switch (reflect) {
796 	case 0:
797 		break;
798 	case DRM_MODE_REFLECT_X:
799 		return PLANE_CTL_FLIP_HORIZONTAL;
800 	case DRM_MODE_REFLECT_Y:
801 	default:
802 		MISSING_CASE(reflect);
803 	}
804 
805 	return 0;
806 }
807 
808 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
809 {
810 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
811 	u32 plane_ctl = 0;
812 
813 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
814 		return plane_ctl;
815 
816 	if (crtc_state->gamma_enable)
817 		plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
818 
819 	if (crtc_state->csc_enable)
820 		plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
821 
822 	return plane_ctl;
823 }
824 
825 static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
826 			 const struct intel_plane_state *plane_state)
827 {
828 	struct drm_i915_private *dev_priv =
829 		to_i915(plane_state->uapi.plane->dev);
830 	const struct drm_framebuffer *fb = plane_state->hw.fb;
831 	unsigned int rotation = plane_state->hw.rotation;
832 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
833 	u32 plane_ctl;
834 
835 	plane_ctl = PLANE_CTL_ENABLE;
836 
837 	if (INTEL_GEN(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) {
838 		plane_ctl |= skl_plane_ctl_alpha(plane_state);
839 		plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
840 
841 		if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
842 			plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
843 
844 		if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
845 			plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
846 	}
847 
848 	plane_ctl |= skl_plane_ctl_format(fb->format->format);
849 	plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
850 	plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
851 
852 	if (INTEL_GEN(dev_priv) >= 10)
853 		plane_ctl |= cnl_plane_ctl_flip(rotation &
854 						DRM_MODE_REFLECT_MASK);
855 
856 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
857 		plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
858 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
859 		plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
860 
861 	return plane_ctl;
862 }
863 
864 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
865 {
866 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
867 	u32 plane_color_ctl = 0;
868 
869 	if (INTEL_GEN(dev_priv) >= 11)
870 		return plane_color_ctl;
871 
872 	if (crtc_state->gamma_enable)
873 		plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
874 
875 	if (crtc_state->csc_enable)
876 		plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
877 
878 	return plane_color_ctl;
879 }
880 
881 static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
882 			       const struct intel_plane_state *plane_state)
883 {
884 	struct drm_i915_private *dev_priv =
885 		to_i915(plane_state->uapi.plane->dev);
886 	const struct drm_framebuffer *fb = plane_state->hw.fb;
887 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
888 	u32 plane_color_ctl = 0;
889 
890 	plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
891 	plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
892 
893 	if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
894 		switch (plane_state->hw.color_encoding) {
895 		case DRM_COLOR_YCBCR_BT709:
896 			plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
897 			break;
898 		case DRM_COLOR_YCBCR_BT2020:
899 			plane_color_ctl |=
900 				PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
901 			break;
902 		default:
903 			plane_color_ctl |=
904 				PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
905 		}
906 		if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
907 			plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
908 	} else if (fb->format->is_yuv) {
909 		plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
910 		if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
911 			plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
912 	}
913 
914 	return plane_color_ctl;
915 }
916 
917 static int
918 main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane)
919 {
920 	drm_WARN_ON(fb->dev, !is_ccs_modifier(fb->modifier) ||
921 		    (main_plane && main_plane >= fb->format->num_planes / 2));
922 
923 	return fb->format->num_planes / 2 + main_plane;
924 }
925 
926 int skl_ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane)
927 {
928 	drm_WARN_ON(fb->dev, !is_ccs_modifier(fb->modifier) ||
929 		    ccs_plane < fb->format->num_planes / 2);
930 
931 	if (is_gen12_ccs_cc_plane(fb, ccs_plane))
932 		return 0;
933 
934 	return ccs_plane - fb->format->num_planes / 2;
935 }
936 
937 static int
938 skl_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
939 {
940 	struct drm_i915_private *i915 = to_i915(fb->dev);
941 
942 	if (is_ccs_modifier(fb->modifier))
943 		return main_to_ccs_plane(fb, main_plane);
944 	else if (INTEL_GEN(i915) < 11 &&
945 		 intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
946 		return 1;
947 	else
948 		return 0;
949 }
950 
951 static void
952 skl_program_plane(struct intel_plane *plane,
953 		  const struct intel_crtc_state *crtc_state,
954 		  const struct intel_plane_state *plane_state,
955 		  int color_plane)
956 {
957 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
958 	enum plane_id plane_id = plane->id;
959 	enum pipe pipe = plane->pipe;
960 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
961 	u32 surf_addr = plane_state->color_plane[color_plane].offset;
962 	u32 stride = skl_plane_stride(plane_state, color_plane);
963 	const struct drm_framebuffer *fb = plane_state->hw.fb;
964 	int aux_plane = skl_main_to_aux_plane(fb, color_plane);
965 	int crtc_x = plane_state->uapi.dst.x1;
966 	int crtc_y = plane_state->uapi.dst.y1;
967 	u32 x = plane_state->color_plane[color_plane].x;
968 	u32 y = plane_state->color_plane[color_plane].y;
969 	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
970 	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
971 	u8 alpha = plane_state->hw.alpha >> 8;
972 	u32 plane_color_ctl = 0, aux_dist = 0;
973 	unsigned long irqflags;
974 	u32 keymsk, keymax;
975 	u32 plane_ctl = plane_state->ctl;
976 
977 	plane_ctl |= skl_plane_ctl_crtc(crtc_state);
978 
979 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
980 		plane_color_ctl = plane_state->color_ctl |
981 			glk_plane_color_ctl_crtc(crtc_state);
982 
983 	/* Sizes are 0 based */
984 	src_w--;
985 	src_h--;
986 
987 	keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
988 
989 	keymsk = key->channel_mask & 0x7ffffff;
990 	if (alpha < 0xff)
991 		keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
992 
993 	/* The scaler will handle the output position */
994 	if (plane_state->scaler_id >= 0) {
995 		crtc_x = 0;
996 		crtc_y = 0;
997 	}
998 
999 	if (aux_plane) {
1000 		aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
1001 
1002 		if (INTEL_GEN(dev_priv) < 12)
1003 			aux_dist |= skl_plane_stride(plane_state, aux_plane);
1004 	}
1005 
1006 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1007 
1008 	intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride);
1009 	intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
1010 			  (crtc_y << 16) | crtc_x);
1011 	intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
1012 			  (src_h << 16) | src_w);
1013 
1014 	intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist);
1015 
1016 	if (icl_is_hdr_plane(dev_priv, plane_id))
1017 		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
1018 				  plane_state->cus_ctl);
1019 
1020 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1021 		intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id),
1022 				  plane_color_ctl);
1023 
1024 	if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
1025 		icl_program_input_csc(plane, crtc_state, plane_state);
1026 
1027 	if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)
1028 		intel_uncore_write64_fw(&dev_priv->uncore,
1029 					PLANE_CC_VAL(pipe, plane_id), plane_state->ccval);
1030 
1031 	skl_write_plane_wm(plane, crtc_state);
1032 
1033 	intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id),
1034 			  key->min_value);
1035 	intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk);
1036 	intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax);
1037 
1038 	intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
1039 			  (y << 16) | x);
1040 
1041 	if (INTEL_GEN(dev_priv) < 11)
1042 		intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
1043 				  (plane_state->color_plane[1].y << 16) | plane_state->color_plane[1].x);
1044 
1045 	if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
1046 		intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
1047 
1048 	/*
1049 	 * The control register self-arms if the plane was previously
1050 	 * disabled. Try to make the plane enable atomic by writing
1051 	 * the control register just before the surface register.
1052 	 */
1053 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1054 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1055 			  intel_plane_ggtt_offset(plane_state) + surf_addr);
1056 
1057 	if (plane_state->scaler_id >= 0)
1058 		skl_program_plane_scaler(plane, crtc_state, plane_state);
1059 
1060 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1061 }
1062 
1063 static void
1064 skl_plane_async_flip(struct intel_plane *plane,
1065 		     const struct intel_crtc_state *crtc_state,
1066 		     const struct intel_plane_state *plane_state,
1067 		     bool async_flip)
1068 {
1069 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1070 	unsigned long irqflags;
1071 	enum plane_id plane_id = plane->id;
1072 	enum pipe pipe = plane->pipe;
1073 	u32 surf_addr = plane_state->color_plane[0].offset;
1074 	u32 plane_ctl = plane_state->ctl;
1075 
1076 	plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1077 
1078 	if (async_flip)
1079 		plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1080 
1081 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1082 
1083 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1084 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1085 			  intel_plane_ggtt_offset(plane_state) + surf_addr);
1086 
1087 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1088 }
1089 
1090 static void
1091 skl_update_plane(struct intel_plane *plane,
1092 		 const struct intel_crtc_state *crtc_state,
1093 		 const struct intel_plane_state *plane_state)
1094 {
1095 	int color_plane = 0;
1096 
1097 	if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1098 		/* Program the UV plane on planar master */
1099 		color_plane = 1;
1100 
1101 	skl_program_plane(plane, crtc_state, plane_state, color_plane);
1102 }
1103 
1104 static bool intel_format_is_p01x(u32 format)
1105 {
1106 	switch (format) {
1107 	case DRM_FORMAT_P010:
1108 	case DRM_FORMAT_P012:
1109 	case DRM_FORMAT_P016:
1110 		return true;
1111 	default:
1112 		return false;
1113 	}
1114 }
1115 
1116 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1117 			      const struct intel_plane_state *plane_state)
1118 {
1119 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1120 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1121 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1122 	unsigned int rotation = plane_state->hw.rotation;
1123 	struct drm_format_name_buf format_name;
1124 
1125 	if (!fb)
1126 		return 0;
1127 
1128 	if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1129 	    is_ccs_modifier(fb->modifier)) {
1130 		drm_dbg_kms(&dev_priv->drm,
1131 			    "RC support only with 0/180 degree rotation (%x)\n",
1132 			    rotation);
1133 		return -EINVAL;
1134 	}
1135 
1136 	if (rotation & DRM_MODE_REFLECT_X &&
1137 	    fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1138 		drm_dbg_kms(&dev_priv->drm,
1139 			    "horizontal flip is not supported with linear surface formats\n");
1140 		return -EINVAL;
1141 	}
1142 
1143 	if (drm_rotation_90_or_270(rotation)) {
1144 		if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
1145 		    fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
1146 			drm_dbg_kms(&dev_priv->drm,
1147 				    "Y/Yf tiling required for 90/270!\n");
1148 			return -EINVAL;
1149 		}
1150 
1151 		/*
1152 		 * 90/270 is not allowed with RGB64 16:16:16:16 and
1153 		 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
1154 		 */
1155 		switch (fb->format->format) {
1156 		case DRM_FORMAT_RGB565:
1157 			if (INTEL_GEN(dev_priv) >= 11)
1158 				break;
1159 			fallthrough;
1160 		case DRM_FORMAT_C8:
1161 		case DRM_FORMAT_XRGB16161616F:
1162 		case DRM_FORMAT_XBGR16161616F:
1163 		case DRM_FORMAT_ARGB16161616F:
1164 		case DRM_FORMAT_ABGR16161616F:
1165 		case DRM_FORMAT_Y210:
1166 		case DRM_FORMAT_Y212:
1167 		case DRM_FORMAT_Y216:
1168 		case DRM_FORMAT_XVYU12_16161616:
1169 		case DRM_FORMAT_XVYU16161616:
1170 			drm_dbg_kms(&dev_priv->drm,
1171 				    "Unsupported pixel format %s for 90/270!\n",
1172 				    drm_get_format_name(fb->format->format,
1173 							&format_name));
1174 			return -EINVAL;
1175 		default:
1176 			break;
1177 		}
1178 	}
1179 
1180 	/* Y-tiling is not supported in IF-ID Interlace mode */
1181 	if (crtc_state->hw.enable &&
1182 	    crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1183 	    (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1184 	     fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1185 	     fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1186 	     fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
1187 	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
1188 	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
1189 	     fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)) {
1190 		drm_dbg_kms(&dev_priv->drm,
1191 			    "Y/Yf tiling not supported in IF-ID mode\n");
1192 		return -EINVAL;
1193 	}
1194 
1195 	/* Wa_1606054188:tgl,adl-s */
1196 	if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
1197 	    plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1198 	    intel_format_is_p01x(fb->format->format)) {
1199 		drm_dbg_kms(&dev_priv->drm,
1200 			    "Source color keying not supported with P01x formats\n");
1201 		return -EINVAL;
1202 	}
1203 
1204 	return 0;
1205 }
1206 
1207 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1208 					   const struct intel_plane_state *plane_state)
1209 {
1210 	struct drm_i915_private *dev_priv =
1211 		to_i915(plane_state->uapi.plane->dev);
1212 	int crtc_x = plane_state->uapi.dst.x1;
1213 	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1214 	int pipe_src_w = crtc_state->pipe_src_w;
1215 
1216 	/*
1217 	 * Display WA #1175: cnl,glk
1218 	 * Planes other than the cursor may cause FIFO underflow and display
1219 	 * corruption if starting less than 4 pixels from the right edge of
1220 	 * the screen.
1221 	 * Besides the above WA fix the similar problem, where planes other
1222 	 * than the cursor ending less than 4 pixels from the left edge of the
1223 	 * screen may cause FIFO underflow and display corruption.
1224 	 */
1225 	if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
1226 	    (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1227 		drm_dbg_kms(&dev_priv->drm,
1228 			    "requested plane X %s position %d invalid (valid range %d-%d)\n",
1229 			    crtc_x + crtc_w < 4 ? "end" : "start",
1230 			    crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1231 			    4, pipe_src_w - 4);
1232 		return -ERANGE;
1233 	}
1234 
1235 	return 0;
1236 }
1237 
1238 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1239 {
1240 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1241 	unsigned int rotation = plane_state->hw.rotation;
1242 	int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1243 
1244 	/* Display WA #1106 */
1245 	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1246 	    src_w & 3 &&
1247 	    (rotation == DRM_MODE_ROTATE_270 ||
1248 	     rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1249 		DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
1250 		return -EINVAL;
1251 	}
1252 
1253 	return 0;
1254 }
1255 
1256 static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
1257 			       const struct drm_framebuffer *fb)
1258 {
1259 	/*
1260 	 * We don't yet know the final source width nor
1261 	 * whether we can use the HQ scaler mode. Assume
1262 	 * the best case.
1263 	 * FIXME need to properly check this later.
1264 	 */
1265 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
1266 	    !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1267 		return 0x30000 - 1;
1268 	else
1269 		return 0x20000 - 1;
1270 }
1271 
1272 static int intel_plane_min_width(struct intel_plane *plane,
1273 				 const struct drm_framebuffer *fb,
1274 				 int color_plane,
1275 				 unsigned int rotation)
1276 {
1277 	if (plane->min_width)
1278 		return plane->min_width(fb, color_plane, rotation);
1279 	else
1280 		return 1;
1281 }
1282 
1283 static int intel_plane_max_width(struct intel_plane *plane,
1284 				 const struct drm_framebuffer *fb,
1285 				 int color_plane,
1286 				 unsigned int rotation)
1287 {
1288 	if (plane->max_width)
1289 		return plane->max_width(fb, color_plane, rotation);
1290 	else
1291 		return INT_MAX;
1292 }
1293 
1294 static int intel_plane_max_height(struct intel_plane *plane,
1295 				  const struct drm_framebuffer *fb,
1296 				  int color_plane,
1297 				  unsigned int rotation)
1298 {
1299 	if (plane->max_height)
1300 		return plane->max_height(fb, color_plane, rotation);
1301 	else
1302 		return INT_MAX;
1303 }
1304 
1305 static bool
1306 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1307 			       int main_x, int main_y, u32 main_offset,
1308 			       int ccs_plane)
1309 {
1310 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1311 	int aux_x = plane_state->color_plane[ccs_plane].x;
1312 	int aux_y = plane_state->color_plane[ccs_plane].y;
1313 	u32 aux_offset = plane_state->color_plane[ccs_plane].offset;
1314 	u32 alignment = intel_surf_alignment(fb, ccs_plane);
1315 	int hsub;
1316 	int vsub;
1317 
1318 	intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1319 	while (aux_offset >= main_offset && aux_y <= main_y) {
1320 		int x, y;
1321 
1322 		if (aux_x == main_x && aux_y == main_y)
1323 			break;
1324 
1325 		if (aux_offset == 0)
1326 			break;
1327 
1328 		x = aux_x / hsub;
1329 		y = aux_y / vsub;
1330 		aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1331 							       plane_state,
1332 							       ccs_plane,
1333 							       aux_offset,
1334 							       aux_offset -
1335 								alignment);
1336 		aux_x = x * hsub + aux_x % hsub;
1337 		aux_y = y * vsub + aux_y % vsub;
1338 	}
1339 
1340 	if (aux_x != main_x || aux_y != main_y)
1341 		return false;
1342 
1343 	plane_state->color_plane[ccs_plane].offset = aux_offset;
1344 	plane_state->color_plane[ccs_plane].x = aux_x;
1345 	plane_state->color_plane[ccs_plane].y = aux_y;
1346 
1347 	return true;
1348 }
1349 
1350 
1351 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
1352 				 int *x, int *y, u32 *offset)
1353 {
1354 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1355 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1356 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1357 	const int aux_plane = skl_main_to_aux_plane(fb, 0);
1358 	const u32 aux_offset = plane_state->color_plane[aux_plane].offset;
1359 	const u32 alignment = intel_surf_alignment(fb, 0);
1360 	const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1361 
1362 	intel_add_fb_offsets(x, y, plane_state, 0);
1363 	*offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
1364 	if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
1365 		return -EINVAL;
1366 
1367 	/*
1368 	 * AUX surface offset is specified as the distance from the
1369 	 * main surface offset, and it must be non-negative. Make
1370 	 * sure that is what we will get.
1371 	 */
1372 	if (aux_plane && *offset > aux_offset)
1373 		*offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1374 							    *offset,
1375 							    aux_offset & ~(alignment - 1));
1376 
1377 	/*
1378 	 * When using an X-tiled surface, the plane blows up
1379 	 * if the x offset + width exceed the stride.
1380 	 *
1381 	 * TODO: linear and Y-tiled seem fine, Yf untested,
1382 	 */
1383 	if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
1384 		int cpp = fb->format->cpp[0];
1385 
1386 		while ((*x + w) * cpp > plane_state->color_plane[0].stride) {
1387 			if (*offset == 0) {
1388 				drm_dbg_kms(&dev_priv->drm,
1389 					    "Unable to find suitable display surface offset due to X-tiling\n");
1390 				return -EINVAL;
1391 			}
1392 
1393 			*offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1394 								    *offset,
1395 								    *offset - alignment);
1396 		}
1397 	}
1398 
1399 	return 0;
1400 }
1401 
1402 static int skl_check_main_surface(struct intel_plane_state *plane_state)
1403 {
1404 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1405 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1406 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1407 	const unsigned int rotation = plane_state->hw.rotation;
1408 	int x = plane_state->uapi.src.x1 >> 16;
1409 	int y = plane_state->uapi.src.y1 >> 16;
1410 	const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1411 	const int h = drm_rect_height(&plane_state->uapi.src) >> 16;
1412 	const int min_width = intel_plane_min_width(plane, fb, 0, rotation);
1413 	const int max_width = intel_plane_max_width(plane, fb, 0, rotation);
1414 	const int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1415 	const int aux_plane = skl_main_to_aux_plane(fb, 0);
1416 	const u32 alignment = intel_surf_alignment(fb, 0);
1417 	u32 offset;
1418 	int ret;
1419 
1420 	if (w > max_width || w < min_width || h > max_height) {
1421 		drm_dbg_kms(&dev_priv->drm,
1422 			    "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
1423 			    w, h, min_width, max_width, max_height);
1424 		return -EINVAL;
1425 	}
1426 
1427 	ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
1428 	if (ret)
1429 		return ret;
1430 
1431 	/*
1432 	 * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1433 	 * they match with the main surface x/y offsets.
1434 	 */
1435 	if (is_ccs_modifier(fb->modifier)) {
1436 		while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1437 						       offset, aux_plane)) {
1438 			if (offset == 0)
1439 				break;
1440 
1441 			offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
1442 								   offset, offset - alignment);
1443 		}
1444 
1445 		if (x != plane_state->color_plane[aux_plane].x ||
1446 		    y != plane_state->color_plane[aux_plane].y) {
1447 			drm_dbg_kms(&dev_priv->drm,
1448 				    "Unable to find suitable display surface offset due to CCS\n");
1449 			return -EINVAL;
1450 		}
1451 	}
1452 
1453 	drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
1454 
1455 	plane_state->color_plane[0].offset = offset;
1456 	plane_state->color_plane[0].x = x;
1457 	plane_state->color_plane[0].y = y;
1458 
1459 	/*
1460 	 * Put the final coordinates back so that the src
1461 	 * coordinate checks will see the right values.
1462 	 */
1463 	drm_rect_translate_to(&plane_state->uapi.src,
1464 			      x << 16, y << 16);
1465 
1466 	return 0;
1467 }
1468 
1469 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
1470 {
1471 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1472 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
1473 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1474 	unsigned int rotation = plane_state->hw.rotation;
1475 	int uv_plane = 1;
1476 	int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
1477 	int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
1478 	int x = plane_state->uapi.src.x1 >> 17;
1479 	int y = plane_state->uapi.src.y1 >> 17;
1480 	int w = drm_rect_width(&plane_state->uapi.src) >> 17;
1481 	int h = drm_rect_height(&plane_state->uapi.src) >> 17;
1482 	u32 offset;
1483 
1484 	/* FIXME not quite sure how/if these apply to the chroma plane */
1485 	if (w > max_width || h > max_height) {
1486 		drm_dbg_kms(&i915->drm,
1487 			    "CbCr source size %dx%d too big (limit %dx%d)\n",
1488 			    w, h, max_width, max_height);
1489 		return -EINVAL;
1490 	}
1491 
1492 	intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
1493 	offset = intel_plane_compute_aligned_offset(&x, &y,
1494 						    plane_state, uv_plane);
1495 
1496 	if (is_ccs_modifier(fb->modifier)) {
1497 		int ccs_plane = main_to_ccs_plane(fb, uv_plane);
1498 		u32 aux_offset = plane_state->color_plane[ccs_plane].offset;
1499 		u32 alignment = intel_surf_alignment(fb, uv_plane);
1500 
1501 		if (offset > aux_offset)
1502 			offset = intel_plane_adjust_aligned_offset(&x, &y,
1503 								   plane_state,
1504 								   uv_plane,
1505 								   offset,
1506 								   aux_offset & ~(alignment - 1));
1507 
1508 		while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1509 						       offset, ccs_plane)) {
1510 			if (offset == 0)
1511 				break;
1512 
1513 			offset = intel_plane_adjust_aligned_offset(&x, &y,
1514 								   plane_state,
1515 								   uv_plane,
1516 								   offset, offset - alignment);
1517 		}
1518 
1519 		if (x != plane_state->color_plane[ccs_plane].x ||
1520 		    y != plane_state->color_plane[ccs_plane].y) {
1521 			drm_dbg_kms(&i915->drm,
1522 				    "Unable to find suitable display surface offset due to CCS\n");
1523 			return -EINVAL;
1524 		}
1525 	}
1526 
1527 	drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
1528 
1529 	plane_state->color_plane[uv_plane].offset = offset;
1530 	plane_state->color_plane[uv_plane].x = x;
1531 	plane_state->color_plane[uv_plane].y = y;
1532 
1533 	return 0;
1534 }
1535 
1536 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
1537 {
1538 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1539 	int src_x = plane_state->uapi.src.x1 >> 16;
1540 	int src_y = plane_state->uapi.src.y1 >> 16;
1541 	u32 offset;
1542 	int ccs_plane;
1543 
1544 	for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
1545 		int main_hsub, main_vsub;
1546 		int hsub, vsub;
1547 		int x, y;
1548 
1549 		if (!is_ccs_plane(fb, ccs_plane) ||
1550 		    is_gen12_ccs_cc_plane(fb, ccs_plane))
1551 			continue;
1552 
1553 		intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
1554 					       skl_ccs_to_main_plane(fb, ccs_plane));
1555 		intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1556 
1557 		hsub *= main_hsub;
1558 		vsub *= main_vsub;
1559 		x = src_x / hsub;
1560 		y = src_y / vsub;
1561 
1562 		intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
1563 
1564 		offset = intel_plane_compute_aligned_offset(&x, &y,
1565 							    plane_state,
1566 							    ccs_plane);
1567 
1568 		plane_state->color_plane[ccs_plane].offset = offset;
1569 		plane_state->color_plane[ccs_plane].x = (x * hsub +
1570 							 src_x % hsub) /
1571 							main_hsub;
1572 		plane_state->color_plane[ccs_plane].y = (y * vsub +
1573 							 src_y % vsub) /
1574 							main_vsub;
1575 	}
1576 
1577 	return 0;
1578 }
1579 
1580 static int skl_check_plane_surface(struct intel_plane_state *plane_state)
1581 {
1582 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1583 	int ret, i;
1584 
1585 	ret = intel_plane_compute_gtt(plane_state);
1586 	if (ret)
1587 		return ret;
1588 
1589 	if (!plane_state->uapi.visible)
1590 		return 0;
1591 
1592 	/*
1593 	 * Handle the AUX surface first since the main surface setup depends on
1594 	 * it.
1595 	 */
1596 	if (is_ccs_modifier(fb->modifier)) {
1597 		ret = skl_check_ccs_aux_surface(plane_state);
1598 		if (ret)
1599 			return ret;
1600 	}
1601 
1602 	if (intel_format_info_is_yuv_semiplanar(fb->format,
1603 						fb->modifier)) {
1604 		ret = skl_check_nv12_aux_surface(plane_state);
1605 		if (ret)
1606 			return ret;
1607 	}
1608 
1609 	for (i = fb->format->num_planes; i < ARRAY_SIZE(plane_state->color_plane); i++) {
1610 		plane_state->color_plane[i].offset = 0;
1611 		plane_state->color_plane[i].x = 0;
1612 		plane_state->color_plane[i].y = 0;
1613 	}
1614 
1615 	ret = skl_check_main_surface(plane_state);
1616 	if (ret)
1617 		return ret;
1618 
1619 	return 0;
1620 }
1621 
1622 static bool skl_fb_scalable(const struct drm_framebuffer *fb)
1623 {
1624 	if (!fb)
1625 		return false;
1626 
1627 	switch (fb->format->format) {
1628 	case DRM_FORMAT_C8:
1629 		return false;
1630 	case DRM_FORMAT_XRGB16161616F:
1631 	case DRM_FORMAT_ARGB16161616F:
1632 	case DRM_FORMAT_XBGR16161616F:
1633 	case DRM_FORMAT_ABGR16161616F:
1634 		return INTEL_GEN(to_i915(fb->dev)) >= 11;
1635 	default:
1636 		return true;
1637 	}
1638 }
1639 
1640 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1641 			   struct intel_plane_state *plane_state)
1642 {
1643 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1644 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1645 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1646 	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1647 	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1648 	int ret;
1649 
1650 	ret = skl_plane_check_fb(crtc_state, plane_state);
1651 	if (ret)
1652 		return ret;
1653 
1654 	/* use scaler when colorkey is not required */
1655 	if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
1656 		min_scale = 1;
1657 		max_scale = skl_plane_max_scale(dev_priv, fb);
1658 	}
1659 
1660 	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1661 						min_scale, max_scale, true);
1662 	if (ret)
1663 		return ret;
1664 
1665 	ret = skl_check_plane_surface(plane_state);
1666 	if (ret)
1667 		return ret;
1668 
1669 	if (!plane_state->uapi.visible)
1670 		return 0;
1671 
1672 	ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1673 	if (ret)
1674 		return ret;
1675 
1676 	ret = intel_plane_check_src_coordinates(plane_state);
1677 	if (ret)
1678 		return ret;
1679 
1680 	ret = skl_plane_check_nv12_rotation(plane_state);
1681 	if (ret)
1682 		return ret;
1683 
1684 	/* HW only has 8 bits pixel precision, disable plane if invisible */
1685 	if (!(plane_state->hw.alpha >> 8))
1686 		plane_state->uapi.visible = false;
1687 
1688 	plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1689 
1690 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1691 		plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1692 							     plane_state);
1693 
1694 	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1695 	    icl_is_hdr_plane(dev_priv, plane->id))
1696 		/* Enable and use MPEG-2 chroma siting */
1697 		plane_state->cus_ctl = PLANE_CUS_ENABLE |
1698 			PLANE_CUS_HPHASE_0 |
1699 			PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
1700 	else
1701 		plane_state->cus_ctl = 0;
1702 
1703 	return 0;
1704 }
1705 
1706 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
1707 			      enum pipe pipe, enum plane_id plane_id)
1708 {
1709 	if (!HAS_FBC(dev_priv))
1710 		return false;
1711 
1712 	return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
1713 }
1714 
1715 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
1716 				 enum pipe pipe, enum plane_id plane_id)
1717 {
1718 	/* Display WA #0870: skl, bxt */
1719 	if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
1720 		return false;
1721 
1722 	if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
1723 		return false;
1724 
1725 	if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
1726 		return false;
1727 
1728 	return true;
1729 }
1730 
1731 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
1732 					enum pipe pipe, enum plane_id plane_id,
1733 					int *num_formats)
1734 {
1735 	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1736 		*num_formats = ARRAY_SIZE(skl_planar_formats);
1737 		return skl_planar_formats;
1738 	} else {
1739 		*num_formats = ARRAY_SIZE(skl_plane_formats);
1740 		return skl_plane_formats;
1741 	}
1742 }
1743 
1744 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
1745 					enum pipe pipe, enum plane_id plane_id,
1746 					int *num_formats)
1747 {
1748 	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1749 		*num_formats = ARRAY_SIZE(glk_planar_formats);
1750 		return glk_planar_formats;
1751 	} else {
1752 		*num_formats = ARRAY_SIZE(skl_plane_formats);
1753 		return skl_plane_formats;
1754 	}
1755 }
1756 
1757 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
1758 					enum pipe pipe, enum plane_id plane_id,
1759 					int *num_formats)
1760 {
1761 	if (icl_is_hdr_plane(dev_priv, plane_id)) {
1762 		*num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
1763 		return icl_hdr_plane_formats;
1764 	} else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
1765 		*num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
1766 		return icl_sdr_y_plane_formats;
1767 	} else {
1768 		*num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
1769 		return icl_sdr_uv_plane_formats;
1770 	}
1771 }
1772 
1773 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1774 			      enum pipe pipe, enum plane_id plane_id)
1775 {
1776 	if (plane_id == PLANE_CURSOR)
1777 		return false;
1778 
1779 	if (INTEL_GEN(dev_priv) >= 10)
1780 		return true;
1781 
1782 	if (IS_GEMINILAKE(dev_priv))
1783 		return pipe != PIPE_C;
1784 
1785 	return pipe != PIPE_C &&
1786 		(plane_id == PLANE_PRIMARY ||
1787 		 plane_id == PLANE_SPRITE0);
1788 }
1789 
1790 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1791 					   u32 format, u64 modifier)
1792 {
1793 	struct intel_plane *plane = to_intel_plane(_plane);
1794 
1795 	switch (modifier) {
1796 	case DRM_FORMAT_MOD_LINEAR:
1797 	case I915_FORMAT_MOD_X_TILED:
1798 	case I915_FORMAT_MOD_Y_TILED:
1799 	case I915_FORMAT_MOD_Yf_TILED:
1800 		break;
1801 	case I915_FORMAT_MOD_Y_TILED_CCS:
1802 	case I915_FORMAT_MOD_Yf_TILED_CCS:
1803 		if (!plane->has_ccs)
1804 			return false;
1805 		break;
1806 	default:
1807 		return false;
1808 	}
1809 
1810 	switch (format) {
1811 	case DRM_FORMAT_XRGB8888:
1812 	case DRM_FORMAT_XBGR8888:
1813 	case DRM_FORMAT_ARGB8888:
1814 	case DRM_FORMAT_ABGR8888:
1815 		if (is_ccs_modifier(modifier))
1816 			return true;
1817 		fallthrough;
1818 	case DRM_FORMAT_RGB565:
1819 	case DRM_FORMAT_XRGB2101010:
1820 	case DRM_FORMAT_XBGR2101010:
1821 	case DRM_FORMAT_ARGB2101010:
1822 	case DRM_FORMAT_ABGR2101010:
1823 	case DRM_FORMAT_YUYV:
1824 	case DRM_FORMAT_YVYU:
1825 	case DRM_FORMAT_UYVY:
1826 	case DRM_FORMAT_VYUY:
1827 	case DRM_FORMAT_NV12:
1828 	case DRM_FORMAT_XYUV8888:
1829 	case DRM_FORMAT_P010:
1830 	case DRM_FORMAT_P012:
1831 	case DRM_FORMAT_P016:
1832 	case DRM_FORMAT_XVYU2101010:
1833 		if (modifier == I915_FORMAT_MOD_Yf_TILED)
1834 			return true;
1835 		fallthrough;
1836 	case DRM_FORMAT_C8:
1837 	case DRM_FORMAT_XBGR16161616F:
1838 	case DRM_FORMAT_ABGR16161616F:
1839 	case DRM_FORMAT_XRGB16161616F:
1840 	case DRM_FORMAT_ARGB16161616F:
1841 	case DRM_FORMAT_Y210:
1842 	case DRM_FORMAT_Y212:
1843 	case DRM_FORMAT_Y216:
1844 	case DRM_FORMAT_XVYU12_16161616:
1845 	case DRM_FORMAT_XVYU16161616:
1846 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1847 		    modifier == I915_FORMAT_MOD_X_TILED ||
1848 		    modifier == I915_FORMAT_MOD_Y_TILED)
1849 			return true;
1850 		fallthrough;
1851 	default:
1852 		return false;
1853 	}
1854 }
1855 
1856 static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
1857 					enum plane_id plane_id)
1858 {
1859 	/* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
1860 	if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
1861 	    IS_TGL_DISP_STEPPING(dev_priv, STEP_A0, STEP_C0))
1862 		return false;
1863 
1864 	return plane_id < PLANE_SPRITE4;
1865 }
1866 
1867 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
1868 					     u32 format, u64 modifier)
1869 {
1870 	struct drm_i915_private *dev_priv = to_i915(_plane->dev);
1871 	struct intel_plane *plane = to_intel_plane(_plane);
1872 
1873 	switch (modifier) {
1874 	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
1875 		if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
1876 			return false;
1877 		fallthrough;
1878 	case DRM_FORMAT_MOD_LINEAR:
1879 	case I915_FORMAT_MOD_X_TILED:
1880 	case I915_FORMAT_MOD_Y_TILED:
1881 	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
1882 	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
1883 		break;
1884 	default:
1885 		return false;
1886 	}
1887 
1888 	switch (format) {
1889 	case DRM_FORMAT_XRGB8888:
1890 	case DRM_FORMAT_XBGR8888:
1891 	case DRM_FORMAT_ARGB8888:
1892 	case DRM_FORMAT_ABGR8888:
1893 		if (is_ccs_modifier(modifier))
1894 			return true;
1895 		fallthrough;
1896 	case DRM_FORMAT_YUYV:
1897 	case DRM_FORMAT_YVYU:
1898 	case DRM_FORMAT_UYVY:
1899 	case DRM_FORMAT_VYUY:
1900 	case DRM_FORMAT_NV12:
1901 	case DRM_FORMAT_XYUV8888:
1902 	case DRM_FORMAT_P010:
1903 	case DRM_FORMAT_P012:
1904 	case DRM_FORMAT_P016:
1905 		if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
1906 			return true;
1907 		fallthrough;
1908 	case DRM_FORMAT_RGB565:
1909 	case DRM_FORMAT_XRGB2101010:
1910 	case DRM_FORMAT_XBGR2101010:
1911 	case DRM_FORMAT_ARGB2101010:
1912 	case DRM_FORMAT_ABGR2101010:
1913 	case DRM_FORMAT_XVYU2101010:
1914 	case DRM_FORMAT_C8:
1915 	case DRM_FORMAT_XBGR16161616F:
1916 	case DRM_FORMAT_ABGR16161616F:
1917 	case DRM_FORMAT_XRGB16161616F:
1918 	case DRM_FORMAT_ARGB16161616F:
1919 	case DRM_FORMAT_Y210:
1920 	case DRM_FORMAT_Y212:
1921 	case DRM_FORMAT_Y216:
1922 	case DRM_FORMAT_XVYU12_16161616:
1923 	case DRM_FORMAT_XVYU16161616:
1924 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1925 		    modifier == I915_FORMAT_MOD_X_TILED ||
1926 		    modifier == I915_FORMAT_MOD_Y_TILED)
1927 			return true;
1928 		fallthrough;
1929 	default:
1930 		return false;
1931 	}
1932 }
1933 
1934 static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
1935 					    enum plane_id plane_id)
1936 {
1937 	if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
1938 		return gen12_plane_format_modifiers_mc_ccs;
1939 	else
1940 		return gen12_plane_format_modifiers_rc_ccs;
1941 }
1942 
1943 static const struct drm_plane_funcs skl_plane_funcs = {
1944 	.update_plane = drm_atomic_helper_update_plane,
1945 	.disable_plane = drm_atomic_helper_disable_plane,
1946 	.destroy = intel_plane_destroy,
1947 	.atomic_duplicate_state = intel_plane_duplicate_state,
1948 	.atomic_destroy_state = intel_plane_destroy_state,
1949 	.format_mod_supported = skl_plane_format_mod_supported,
1950 };
1951 
1952 static const struct drm_plane_funcs gen12_plane_funcs = {
1953 	.update_plane = drm_atomic_helper_update_plane,
1954 	.disable_plane = drm_atomic_helper_disable_plane,
1955 	.destroy = intel_plane_destroy,
1956 	.atomic_duplicate_state = intel_plane_duplicate_state,
1957 	.atomic_destroy_state = intel_plane_destroy_state,
1958 	.format_mod_supported = gen12_plane_format_mod_supported,
1959 };
1960 
1961 static void
1962 skl_plane_enable_flip_done(struct intel_plane *plane)
1963 {
1964 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
1965 	enum pipe pipe = plane->pipe;
1966 
1967 	spin_lock_irq(&i915->irq_lock);
1968 	bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
1969 	spin_unlock_irq(&i915->irq_lock);
1970 }
1971 
1972 static void
1973 skl_plane_disable_flip_done(struct intel_plane *plane)
1974 {
1975 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
1976 	enum pipe pipe = plane->pipe;
1977 
1978 	spin_lock_irq(&i915->irq_lock);
1979 	bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
1980 	spin_unlock_irq(&i915->irq_lock);
1981 }
1982 
1983 struct intel_plane *
1984 skl_universal_plane_create(struct drm_i915_private *dev_priv,
1985 			   enum pipe pipe, enum plane_id plane_id)
1986 {
1987 	const struct drm_plane_funcs *plane_funcs;
1988 	struct intel_plane *plane;
1989 	enum drm_plane_type plane_type;
1990 	unsigned int supported_rotations;
1991 	unsigned int supported_csc;
1992 	const u64 *modifiers;
1993 	const u32 *formats;
1994 	int num_formats;
1995 	int ret;
1996 
1997 	plane = intel_plane_alloc();
1998 	if (IS_ERR(plane))
1999 		return plane;
2000 
2001 	plane->pipe = pipe;
2002 	plane->id = plane_id;
2003 	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2004 
2005 	plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2006 	if (plane->has_fbc) {
2007 		struct intel_fbc *fbc = &dev_priv->fbc;
2008 
2009 		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2010 	}
2011 
2012 	if (INTEL_GEN(dev_priv) >= 11) {
2013 		plane->min_width = icl_plane_min_width;
2014 		plane->max_width = icl_plane_max_width;
2015 		plane->max_height = icl_plane_max_height;
2016 	} else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
2017 		plane->max_width = glk_plane_max_width;
2018 		plane->max_height = skl_plane_max_height;
2019 	} else {
2020 		plane->max_width = skl_plane_max_width;
2021 		plane->max_height = skl_plane_max_height;
2022 	}
2023 
2024 	plane->max_stride = skl_plane_max_stride;
2025 	plane->update_plane = skl_update_plane;
2026 	plane->disable_plane = skl_disable_plane;
2027 	plane->get_hw_state = skl_plane_get_hw_state;
2028 	plane->check_plane = skl_plane_check;
2029 	plane->min_cdclk = skl_plane_min_cdclk;
2030 
2031 	if (plane_id == PLANE_PRIMARY) {
2032 		plane->need_async_flip_disable_wa = IS_GEN_RANGE(dev_priv, 9, 10);
2033 		plane->async_flip = skl_plane_async_flip;
2034 		plane->enable_flip_done = skl_plane_enable_flip_done;
2035 		plane->disable_flip_done = skl_plane_disable_flip_done;
2036 	}
2037 
2038 	if (INTEL_GEN(dev_priv) >= 11)
2039 		formats = icl_get_plane_formats(dev_priv, pipe,
2040 						plane_id, &num_formats);
2041 	else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2042 		formats = glk_get_plane_formats(dev_priv, pipe,
2043 						plane_id, &num_formats);
2044 	else
2045 		formats = skl_get_plane_formats(dev_priv, pipe,
2046 						plane_id, &num_formats);
2047 
2048 	plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
2049 	if (INTEL_GEN(dev_priv) >= 12) {
2050 		modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
2051 		plane_funcs = &gen12_plane_funcs;
2052 	} else {
2053 		if (plane->has_ccs)
2054 			modifiers = skl_plane_format_modifiers_ccs;
2055 		else
2056 			modifiers = skl_plane_format_modifiers_noccs;
2057 		plane_funcs = &skl_plane_funcs;
2058 	}
2059 
2060 	if (plane_id == PLANE_PRIMARY)
2061 		plane_type = DRM_PLANE_TYPE_PRIMARY;
2062 	else
2063 		plane_type = DRM_PLANE_TYPE_OVERLAY;
2064 
2065 	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2066 				       0, plane_funcs,
2067 				       formats, num_formats, modifiers,
2068 				       plane_type,
2069 				       "plane %d%c", plane_id + 1,
2070 				       pipe_name(pipe));
2071 	if (ret)
2072 		goto fail;
2073 
2074 	supported_rotations =
2075 		DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2076 		DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2077 
2078 	if (INTEL_GEN(dev_priv) >= 10)
2079 		supported_rotations |= DRM_MODE_REFLECT_X;
2080 
2081 	drm_plane_create_rotation_property(&plane->base,
2082 					   DRM_MODE_ROTATE_0,
2083 					   supported_rotations);
2084 
2085 	supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
2086 
2087 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2088 		supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
2089 
2090 	drm_plane_create_color_properties(&plane->base,
2091 					  supported_csc,
2092 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2093 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2094 					  DRM_COLOR_YCBCR_BT709,
2095 					  DRM_COLOR_YCBCR_LIMITED_RANGE);
2096 
2097 	drm_plane_create_alpha_property(&plane->base);
2098 	drm_plane_create_blend_mode_property(&plane->base,
2099 					     BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2100 					     BIT(DRM_MODE_BLEND_PREMULTI) |
2101 					     BIT(DRM_MODE_BLEND_COVERAGE));
2102 
2103 	drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
2104 
2105 	if (INTEL_GEN(dev_priv) >= 12)
2106 		drm_plane_enable_fb_damage_clips(&plane->base);
2107 
2108 	if (INTEL_GEN(dev_priv) >= 10)
2109 		drm_plane_create_scaling_filter_property(&plane->base,
2110 						BIT(DRM_SCALING_FILTER_DEFAULT) |
2111 						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2112 
2113 	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
2114 
2115 	return plane;
2116 
2117 fail:
2118 	intel_plane_free(plane);
2119 
2120 	return ERR_PTR(ret);
2121 }
2122 
2123 void
2124 skl_get_initial_plane_config(struct intel_crtc *crtc,
2125 			     struct intel_initial_plane_config *plane_config)
2126 {
2127 	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
2128 	struct drm_device *dev = crtc->base.dev;
2129 	struct drm_i915_private *dev_priv = to_i915(dev);
2130 	struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2131 	enum plane_id plane_id = plane->id;
2132 	enum pipe pipe;
2133 	u32 val, base, offset, stride_mult, tiling, alpha;
2134 	int fourcc, pixel_format;
2135 	unsigned int aligned_height;
2136 	struct drm_framebuffer *fb;
2137 	struct intel_framebuffer *intel_fb;
2138 
2139 	if (!plane->get_hw_state(plane, &pipe))
2140 		return;
2141 
2142 	drm_WARN_ON(dev, pipe != crtc->pipe);
2143 
2144 	if (crtc_state->bigjoiner) {
2145 		drm_dbg_kms(&dev_priv->drm,
2146 			    "Unsupported bigjoiner configuration for initial FB\n");
2147 		return;
2148 	}
2149 
2150 	intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
2151 	if (!intel_fb) {
2152 		drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
2153 		return;
2154 	}
2155 
2156 	fb = &intel_fb->base;
2157 
2158 	fb->dev = dev;
2159 
2160 	val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
2161 
2162 	if (INTEL_GEN(dev_priv) >= 11)
2163 		pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK;
2164 	else
2165 		pixel_format = val & PLANE_CTL_FORMAT_MASK;
2166 
2167 	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
2168 		alpha = intel_de_read(dev_priv,
2169 				      PLANE_COLOR_CTL(pipe, plane_id));
2170 		alpha &= PLANE_COLOR_ALPHA_MASK;
2171 	} else {
2172 		alpha = val & PLANE_CTL_ALPHA_MASK;
2173 	}
2174 
2175 	fourcc = skl_format_to_fourcc(pixel_format,
2176 				      val & PLANE_CTL_ORDER_RGBX, alpha);
2177 	fb->format = drm_format_info(fourcc);
2178 
2179 	tiling = val & PLANE_CTL_TILED_MASK;
2180 	switch (tiling) {
2181 	case PLANE_CTL_TILED_LINEAR:
2182 		fb->modifier = DRM_FORMAT_MOD_LINEAR;
2183 		break;
2184 	case PLANE_CTL_TILED_X:
2185 		plane_config->tiling = I915_TILING_X;
2186 		fb->modifier = I915_FORMAT_MOD_X_TILED;
2187 		break;
2188 	case PLANE_CTL_TILED_Y:
2189 		plane_config->tiling = I915_TILING_Y;
2190 		if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2191 			fb->modifier = INTEL_GEN(dev_priv) >= 12 ?
2192 				I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
2193 				I915_FORMAT_MOD_Y_TILED_CCS;
2194 		else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2195 			fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
2196 		else
2197 			fb->modifier = I915_FORMAT_MOD_Y_TILED;
2198 		break;
2199 	case PLANE_CTL_TILED_YF:
2200 		if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2201 			fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
2202 		else
2203 			fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2204 		break;
2205 	default:
2206 		MISSING_CASE(tiling);
2207 		goto error;
2208 	}
2209 
2210 	/*
2211 	 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
2212 	 * while i915 HW rotation is clockwise, thats why this swapping.
2213 	 */
2214 	switch (val & PLANE_CTL_ROTATE_MASK) {
2215 	case PLANE_CTL_ROTATE_0:
2216 		plane_config->rotation = DRM_MODE_ROTATE_0;
2217 		break;
2218 	case PLANE_CTL_ROTATE_90:
2219 		plane_config->rotation = DRM_MODE_ROTATE_270;
2220 		break;
2221 	case PLANE_CTL_ROTATE_180:
2222 		plane_config->rotation = DRM_MODE_ROTATE_180;
2223 		break;
2224 	case PLANE_CTL_ROTATE_270:
2225 		plane_config->rotation = DRM_MODE_ROTATE_90;
2226 		break;
2227 	}
2228 
2229 	if (INTEL_GEN(dev_priv) >= 10 &&
2230 	    val & PLANE_CTL_FLIP_HORIZONTAL)
2231 		plane_config->rotation |= DRM_MODE_REFLECT_X;
2232 
2233 	/* 90/270 degree rotation would require extra work */
2234 	if (drm_rotation_90_or_270(plane_config->rotation))
2235 		goto error;
2236 
2237 	base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
2238 	plane_config->base = base;
2239 
2240 	offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
2241 
2242 	val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
2243 	fb->height = ((val >> 16) & 0xffff) + 1;
2244 	fb->width = ((val >> 0) & 0xffff) + 1;
2245 
2246 	val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
2247 	stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2248 	fb->pitches[0] = (val & 0x3ff) * stride_mult;
2249 
2250 	aligned_height = intel_fb_align_height(fb, 0, fb->height);
2251 
2252 	plane_config->size = fb->pitches[0] * aligned_height;
2253 
2254 	drm_dbg_kms(&dev_priv->drm,
2255 		    "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
2256 		    crtc->base.name, plane->base.name, fb->width, fb->height,
2257 		    fb->format->cpp[0] * 8, base, fb->pitches[0],
2258 		    plane_config->size);
2259 
2260 	plane_config->fb = intel_fb;
2261 	return;
2262 
2263 error:
2264 	kfree(intel_fb);
2265 }
2266 
2267