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