xref: /linux/drivers/gpu/drm/i915/display/skl_universal_plane.c (revision 5d97dde4d5f751858390b557729a1a12210024c1)
146d12f91SDave Airlie // SPDX-License-Identifier: MIT
246d12f91SDave Airlie /*
346d12f91SDave Airlie  * Copyright © 2020 Intel Corporation
446d12f91SDave Airlie  */
546d12f91SDave Airlie 
646d12f91SDave Airlie #include <drm/drm_atomic_helper.h>
790bb087fSVille Syrjälä #include <drm/drm_blend.h>
846d12f91SDave Airlie #include <drm/drm_damage_helper.h>
946d12f91SDave Airlie #include <drm/drm_fourcc.h>
1046d12f91SDave Airlie 
1146d12f91SDave Airlie #include "i915_drv.h"
12801543b2SJani Nikula #include "i915_reg.h"
1346d12f91SDave Airlie #include "intel_atomic_plane.h"
147785ae0bSVille Syrjälä #include "intel_de.h"
152b874a02SJani Nikula #include "intel_display_irq.h"
1646d12f91SDave Airlie #include "intel_display_types.h"
176dbd43dcSRodrigo Vivi #include "intel_dpt.h"
18f837a61fSImre Deak #include "intel_fb.h"
19825bd833SVille Syrjälä #include "intel_fbc.h"
20c1464a89SJani Nikula #include "intel_frontbuffer.h"
2146d12f91SDave Airlie #include "intel_psr.h"
22b1f5279bSJouni Högander #include "intel_psr_regs.h"
23714b1cdbSDave Airlie #include "skl_scaler.h"
2446d12f91SDave Airlie #include "skl_universal_plane.h"
258c866768SVille Syrjälä #include "skl_universal_plane_regs.h"
2642a0d256SVille Syrjälä #include "skl_watermark.h"
27ef6ba31dSAnshuman Gupta #include "pxp/intel_pxp.h"
2846d12f91SDave Airlie 
2946d12f91SDave Airlie static const u32 skl_plane_formats[] = {
3046d12f91SDave Airlie 	DRM_FORMAT_C8,
3146d12f91SDave Airlie 	DRM_FORMAT_RGB565,
3246d12f91SDave Airlie 	DRM_FORMAT_XRGB8888,
3346d12f91SDave Airlie 	DRM_FORMAT_XBGR8888,
3446d12f91SDave Airlie 	DRM_FORMAT_ARGB8888,
3546d12f91SDave Airlie 	DRM_FORMAT_ABGR8888,
3646d12f91SDave Airlie 	DRM_FORMAT_XRGB2101010,
3746d12f91SDave Airlie 	DRM_FORMAT_XBGR2101010,
3846d12f91SDave Airlie 	DRM_FORMAT_XRGB16161616F,
3946d12f91SDave Airlie 	DRM_FORMAT_XBGR16161616F,
4046d12f91SDave Airlie 	DRM_FORMAT_YUYV,
4146d12f91SDave Airlie 	DRM_FORMAT_YVYU,
4246d12f91SDave Airlie 	DRM_FORMAT_UYVY,
4346d12f91SDave Airlie 	DRM_FORMAT_VYUY,
4446d12f91SDave Airlie 	DRM_FORMAT_XYUV8888,
4546d12f91SDave Airlie };
4646d12f91SDave Airlie 
4746d12f91SDave Airlie static const u32 skl_planar_formats[] = {
4846d12f91SDave Airlie 	DRM_FORMAT_C8,
4946d12f91SDave Airlie 	DRM_FORMAT_RGB565,
5046d12f91SDave Airlie 	DRM_FORMAT_XRGB8888,
5146d12f91SDave Airlie 	DRM_FORMAT_XBGR8888,
5246d12f91SDave Airlie 	DRM_FORMAT_ARGB8888,
5346d12f91SDave Airlie 	DRM_FORMAT_ABGR8888,
5446d12f91SDave Airlie 	DRM_FORMAT_XRGB2101010,
5546d12f91SDave Airlie 	DRM_FORMAT_XBGR2101010,
5646d12f91SDave Airlie 	DRM_FORMAT_XRGB16161616F,
5746d12f91SDave Airlie 	DRM_FORMAT_XBGR16161616F,
5846d12f91SDave Airlie 	DRM_FORMAT_YUYV,
5946d12f91SDave Airlie 	DRM_FORMAT_YVYU,
6046d12f91SDave Airlie 	DRM_FORMAT_UYVY,
6146d12f91SDave Airlie 	DRM_FORMAT_VYUY,
6246d12f91SDave Airlie 	DRM_FORMAT_NV12,
6346d12f91SDave Airlie 	DRM_FORMAT_XYUV8888,
6446d12f91SDave Airlie };
6546d12f91SDave Airlie 
6646d12f91SDave Airlie static const u32 glk_planar_formats[] = {
6746d12f91SDave Airlie 	DRM_FORMAT_C8,
6846d12f91SDave Airlie 	DRM_FORMAT_RGB565,
6946d12f91SDave Airlie 	DRM_FORMAT_XRGB8888,
7046d12f91SDave Airlie 	DRM_FORMAT_XBGR8888,
7146d12f91SDave Airlie 	DRM_FORMAT_ARGB8888,
7246d12f91SDave Airlie 	DRM_FORMAT_ABGR8888,
7346d12f91SDave Airlie 	DRM_FORMAT_XRGB2101010,
7446d12f91SDave Airlie 	DRM_FORMAT_XBGR2101010,
7546d12f91SDave Airlie 	DRM_FORMAT_XRGB16161616F,
7646d12f91SDave Airlie 	DRM_FORMAT_XBGR16161616F,
7746d12f91SDave Airlie 	DRM_FORMAT_YUYV,
7846d12f91SDave Airlie 	DRM_FORMAT_YVYU,
7946d12f91SDave Airlie 	DRM_FORMAT_UYVY,
8046d12f91SDave Airlie 	DRM_FORMAT_VYUY,
8146d12f91SDave Airlie 	DRM_FORMAT_NV12,
8246d12f91SDave Airlie 	DRM_FORMAT_XYUV8888,
8346d12f91SDave Airlie 	DRM_FORMAT_P010,
8446d12f91SDave Airlie 	DRM_FORMAT_P012,
8546d12f91SDave Airlie 	DRM_FORMAT_P016,
8646d12f91SDave Airlie };
8746d12f91SDave Airlie 
8846d12f91SDave Airlie static const u32 icl_sdr_y_plane_formats[] = {
8946d12f91SDave Airlie 	DRM_FORMAT_C8,
9046d12f91SDave Airlie 	DRM_FORMAT_RGB565,
9146d12f91SDave Airlie 	DRM_FORMAT_XRGB8888,
9246d12f91SDave Airlie 	DRM_FORMAT_XBGR8888,
9346d12f91SDave Airlie 	DRM_FORMAT_ARGB8888,
9446d12f91SDave Airlie 	DRM_FORMAT_ABGR8888,
9546d12f91SDave Airlie 	DRM_FORMAT_XRGB2101010,
9646d12f91SDave Airlie 	DRM_FORMAT_XBGR2101010,
9746d12f91SDave Airlie 	DRM_FORMAT_ARGB2101010,
9846d12f91SDave Airlie 	DRM_FORMAT_ABGR2101010,
9946d12f91SDave Airlie 	DRM_FORMAT_YUYV,
10046d12f91SDave Airlie 	DRM_FORMAT_YVYU,
10146d12f91SDave Airlie 	DRM_FORMAT_UYVY,
10246d12f91SDave Airlie 	DRM_FORMAT_VYUY,
10346d12f91SDave Airlie 	DRM_FORMAT_Y210,
10446d12f91SDave Airlie 	DRM_FORMAT_Y212,
10546d12f91SDave Airlie 	DRM_FORMAT_Y216,
10646d12f91SDave Airlie 	DRM_FORMAT_XYUV8888,
10746d12f91SDave Airlie 	DRM_FORMAT_XVYU2101010,
10846d12f91SDave Airlie 	DRM_FORMAT_XVYU12_16161616,
10946d12f91SDave Airlie 	DRM_FORMAT_XVYU16161616,
11046d12f91SDave Airlie };
11146d12f91SDave Airlie 
11246d12f91SDave Airlie static const u32 icl_sdr_uv_plane_formats[] = {
11346d12f91SDave Airlie 	DRM_FORMAT_C8,
11446d12f91SDave Airlie 	DRM_FORMAT_RGB565,
11546d12f91SDave Airlie 	DRM_FORMAT_XRGB8888,
11646d12f91SDave Airlie 	DRM_FORMAT_XBGR8888,
11746d12f91SDave Airlie 	DRM_FORMAT_ARGB8888,
11846d12f91SDave Airlie 	DRM_FORMAT_ABGR8888,
11946d12f91SDave Airlie 	DRM_FORMAT_XRGB2101010,
12046d12f91SDave Airlie 	DRM_FORMAT_XBGR2101010,
12146d12f91SDave Airlie 	DRM_FORMAT_ARGB2101010,
12246d12f91SDave Airlie 	DRM_FORMAT_ABGR2101010,
12346d12f91SDave Airlie 	DRM_FORMAT_YUYV,
12446d12f91SDave Airlie 	DRM_FORMAT_YVYU,
12546d12f91SDave Airlie 	DRM_FORMAT_UYVY,
12646d12f91SDave Airlie 	DRM_FORMAT_VYUY,
12746d12f91SDave Airlie 	DRM_FORMAT_NV12,
12846d12f91SDave Airlie 	DRM_FORMAT_P010,
12946d12f91SDave Airlie 	DRM_FORMAT_P012,
13046d12f91SDave Airlie 	DRM_FORMAT_P016,
13146d12f91SDave Airlie 	DRM_FORMAT_Y210,
13246d12f91SDave Airlie 	DRM_FORMAT_Y212,
13346d12f91SDave Airlie 	DRM_FORMAT_Y216,
13446d12f91SDave Airlie 	DRM_FORMAT_XYUV8888,
13546d12f91SDave Airlie 	DRM_FORMAT_XVYU2101010,
13646d12f91SDave Airlie 	DRM_FORMAT_XVYU12_16161616,
13746d12f91SDave Airlie 	DRM_FORMAT_XVYU16161616,
13846d12f91SDave Airlie };
13946d12f91SDave Airlie 
14046d12f91SDave Airlie static const u32 icl_hdr_plane_formats[] = {
14146d12f91SDave Airlie 	DRM_FORMAT_C8,
14246d12f91SDave Airlie 	DRM_FORMAT_RGB565,
14346d12f91SDave Airlie 	DRM_FORMAT_XRGB8888,
14446d12f91SDave Airlie 	DRM_FORMAT_XBGR8888,
14546d12f91SDave Airlie 	DRM_FORMAT_ARGB8888,
14646d12f91SDave Airlie 	DRM_FORMAT_ABGR8888,
14746d12f91SDave Airlie 	DRM_FORMAT_XRGB2101010,
14846d12f91SDave Airlie 	DRM_FORMAT_XBGR2101010,
14946d12f91SDave Airlie 	DRM_FORMAT_ARGB2101010,
15046d12f91SDave Airlie 	DRM_FORMAT_ABGR2101010,
15146d12f91SDave Airlie 	DRM_FORMAT_XRGB16161616F,
15246d12f91SDave Airlie 	DRM_FORMAT_XBGR16161616F,
15346d12f91SDave Airlie 	DRM_FORMAT_ARGB16161616F,
15446d12f91SDave Airlie 	DRM_FORMAT_ABGR16161616F,
15546d12f91SDave Airlie 	DRM_FORMAT_YUYV,
15646d12f91SDave Airlie 	DRM_FORMAT_YVYU,
15746d12f91SDave Airlie 	DRM_FORMAT_UYVY,
15846d12f91SDave Airlie 	DRM_FORMAT_VYUY,
15946d12f91SDave Airlie 	DRM_FORMAT_NV12,
16046d12f91SDave Airlie 	DRM_FORMAT_P010,
16146d12f91SDave Airlie 	DRM_FORMAT_P012,
16246d12f91SDave Airlie 	DRM_FORMAT_P016,
16346d12f91SDave Airlie 	DRM_FORMAT_Y210,
16446d12f91SDave Airlie 	DRM_FORMAT_Y212,
16546d12f91SDave Airlie 	DRM_FORMAT_Y216,
16646d12f91SDave Airlie 	DRM_FORMAT_XYUV8888,
16746d12f91SDave Airlie 	DRM_FORMAT_XVYU2101010,
16846d12f91SDave Airlie 	DRM_FORMAT_XVYU12_16161616,
16946d12f91SDave Airlie 	DRM_FORMAT_XVYU16161616,
17046d12f91SDave Airlie };
17146d12f91SDave Airlie 
skl_format_to_fourcc(int format,bool rgb_order,bool alpha)17246d12f91SDave Airlie int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
17346d12f91SDave Airlie {
17446d12f91SDave Airlie 	switch (format) {
17546d12f91SDave Airlie 	case PLANE_CTL_FORMAT_RGB_565:
17646d12f91SDave Airlie 		return DRM_FORMAT_RGB565;
17746d12f91SDave Airlie 	case PLANE_CTL_FORMAT_NV12:
17846d12f91SDave Airlie 		return DRM_FORMAT_NV12;
17946d12f91SDave Airlie 	case PLANE_CTL_FORMAT_XYUV:
18046d12f91SDave Airlie 		return DRM_FORMAT_XYUV8888;
18146d12f91SDave Airlie 	case PLANE_CTL_FORMAT_P010:
18246d12f91SDave Airlie 		return DRM_FORMAT_P010;
18346d12f91SDave Airlie 	case PLANE_CTL_FORMAT_P012:
18446d12f91SDave Airlie 		return DRM_FORMAT_P012;
18546d12f91SDave Airlie 	case PLANE_CTL_FORMAT_P016:
18646d12f91SDave Airlie 		return DRM_FORMAT_P016;
18746d12f91SDave Airlie 	case PLANE_CTL_FORMAT_Y210:
18846d12f91SDave Airlie 		return DRM_FORMAT_Y210;
18946d12f91SDave Airlie 	case PLANE_CTL_FORMAT_Y212:
19046d12f91SDave Airlie 		return DRM_FORMAT_Y212;
19146d12f91SDave Airlie 	case PLANE_CTL_FORMAT_Y216:
19246d12f91SDave Airlie 		return DRM_FORMAT_Y216;
19346d12f91SDave Airlie 	case PLANE_CTL_FORMAT_Y410:
19446d12f91SDave Airlie 		return DRM_FORMAT_XVYU2101010;
19546d12f91SDave Airlie 	case PLANE_CTL_FORMAT_Y412:
19646d12f91SDave Airlie 		return DRM_FORMAT_XVYU12_16161616;
19746d12f91SDave Airlie 	case PLANE_CTL_FORMAT_Y416:
19846d12f91SDave Airlie 		return DRM_FORMAT_XVYU16161616;
19946d12f91SDave Airlie 	default:
20046d12f91SDave Airlie 	case PLANE_CTL_FORMAT_XRGB_8888:
20146d12f91SDave Airlie 		if (rgb_order) {
20246d12f91SDave Airlie 			if (alpha)
20346d12f91SDave Airlie 				return DRM_FORMAT_ABGR8888;
20446d12f91SDave Airlie 			else
20546d12f91SDave Airlie 				return DRM_FORMAT_XBGR8888;
20646d12f91SDave Airlie 		} else {
20746d12f91SDave Airlie 			if (alpha)
20846d12f91SDave Airlie 				return DRM_FORMAT_ARGB8888;
20946d12f91SDave Airlie 			else
21046d12f91SDave Airlie 				return DRM_FORMAT_XRGB8888;
21146d12f91SDave Airlie 		}
21246d12f91SDave Airlie 	case PLANE_CTL_FORMAT_XRGB_2101010:
21346d12f91SDave Airlie 		if (rgb_order) {
21446d12f91SDave Airlie 			if (alpha)
21546d12f91SDave Airlie 				return DRM_FORMAT_ABGR2101010;
21646d12f91SDave Airlie 			else
21746d12f91SDave Airlie 				return DRM_FORMAT_XBGR2101010;
21846d12f91SDave Airlie 		} else {
21946d12f91SDave Airlie 			if (alpha)
22046d12f91SDave Airlie 				return DRM_FORMAT_ARGB2101010;
22146d12f91SDave Airlie 			else
22246d12f91SDave Airlie 				return DRM_FORMAT_XRGB2101010;
22346d12f91SDave Airlie 		}
22446d12f91SDave Airlie 	case PLANE_CTL_FORMAT_XRGB_16161616F:
22546d12f91SDave Airlie 		if (rgb_order) {
22646d12f91SDave Airlie 			if (alpha)
22746d12f91SDave Airlie 				return DRM_FORMAT_ABGR16161616F;
22846d12f91SDave Airlie 			else
22946d12f91SDave Airlie 				return DRM_FORMAT_XBGR16161616F;
23046d12f91SDave Airlie 		} else {
23146d12f91SDave Airlie 			if (alpha)
23246d12f91SDave Airlie 				return DRM_FORMAT_ARGB16161616F;
23346d12f91SDave Airlie 			else
23446d12f91SDave Airlie 				return DRM_FORMAT_XRGB16161616F;
23546d12f91SDave Airlie 		}
23646d12f91SDave Airlie 	}
23746d12f91SDave Airlie }
23846d12f91SDave Airlie 
icl_nv12_y_plane_mask(struct drm_i915_private * i915)23946d12f91SDave Airlie static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
24046d12f91SDave Airlie {
2411649a4ccSMatt Roper 	if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
242df798d43SVille Syrjälä 		return BIT(PLANE_4) | BIT(PLANE_5);
24346d12f91SDave Airlie 	else
244df798d43SVille Syrjälä 		return BIT(PLANE_6) | BIT(PLANE_7);
24546d12f91SDave Airlie }
24646d12f91SDave Airlie 
icl_is_nv12_y_plane(struct drm_i915_private * dev_priv,enum plane_id plane_id)24746d12f91SDave Airlie bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
24846d12f91SDave Airlie 			 enum plane_id plane_id)
24946d12f91SDave Airlie {
250005e9537SMatt Roper 	return DISPLAY_VER(dev_priv) >= 11 &&
25146d12f91SDave Airlie 		icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
25246d12f91SDave Airlie }
25346d12f91SDave Airlie 
icl_hdr_plane_mask(void)254d29c410fSJani Nikula u8 icl_hdr_plane_mask(void)
255d29c410fSJani Nikula {
256df798d43SVille Syrjälä 	return BIT(PLANE_1) | BIT(PLANE_2) | BIT(PLANE_3);
257d29c410fSJani Nikula }
258d29c410fSJani Nikula 
icl_is_hdr_plane(struct drm_i915_private * dev_priv,enum plane_id plane_id)25946d12f91SDave Airlie bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
26046d12f91SDave Airlie {
261005e9537SMatt Roper 	return DISPLAY_VER(dev_priv) >= 11 &&
26246d12f91SDave Airlie 		icl_hdr_plane_mask() & BIT(plane_id);
26346d12f91SDave Airlie }
26446d12f91SDave Airlie 
icl_plane_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)2656195f850SVille Syrjälä static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
2666195f850SVille Syrjälä 			       const struct intel_plane_state *plane_state)
2676195f850SVille Syrjälä {
2686195f850SVille Syrjälä 	unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
2696195f850SVille Syrjälä 
2706195f850SVille Syrjälä 	/* two pixels per clock */
2716195f850SVille Syrjälä 	return DIV_ROUND_UP(pixel_rate, 2);
2726195f850SVille Syrjälä }
2736195f850SVille Syrjälä 
27446d12f91SDave Airlie static void
glk_plane_ratio(const struct intel_plane_state * plane_state,unsigned int * num,unsigned int * den)275efc52308SVille Syrjälä glk_plane_ratio(const struct intel_plane_state *plane_state,
27646d12f91SDave Airlie 		unsigned int *num, unsigned int *den)
27746d12f91SDave Airlie {
27846d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
27946d12f91SDave Airlie 
28046d12f91SDave Airlie 	if (fb->format->cpp[0] == 8) {
28146d12f91SDave Airlie 		*num = 10;
28246d12f91SDave Airlie 		*den = 8;
28346d12f91SDave Airlie 	} else {
284efc52308SVille Syrjälä 		*num = 1;
285efc52308SVille Syrjälä 		*den = 1;
286efc52308SVille Syrjälä 	}
287efc52308SVille Syrjälä }
288efc52308SVille Syrjälä 
glk_plane_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)289efc52308SVille Syrjälä static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
290efc52308SVille Syrjälä 			       const struct intel_plane_state *plane_state)
291efc52308SVille Syrjälä {
292efc52308SVille Syrjälä 	unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
293efc52308SVille Syrjälä 	unsigned int num, den;
294efc52308SVille Syrjälä 
295efc52308SVille Syrjälä 	glk_plane_ratio(plane_state, &num, &den);
296efc52308SVille Syrjälä 
297efc52308SVille Syrjälä 	/* two pixels per clock */
298efc52308SVille Syrjälä 	return DIV_ROUND_UP(pixel_rate * num, 2 * den);
299efc52308SVille Syrjälä }
300efc52308SVille Syrjälä 
301efc52308SVille Syrjälä static void
skl_plane_ratio(const struct intel_plane_state * plane_state,unsigned int * num,unsigned int * den)302efc52308SVille Syrjälä skl_plane_ratio(const struct intel_plane_state *plane_state,
303efc52308SVille Syrjälä 		unsigned int *num, unsigned int *den)
304efc52308SVille Syrjälä {
305efc52308SVille Syrjälä 	const struct drm_framebuffer *fb = plane_state->hw.fb;
306efc52308SVille Syrjälä 
307efc52308SVille Syrjälä 	if (fb->format->cpp[0] == 8) {
30846d12f91SDave Airlie 		*num = 9;
30946d12f91SDave Airlie 		*den = 8;
31046d12f91SDave Airlie 	} else {
31146d12f91SDave Airlie 		*num = 1;
31246d12f91SDave Airlie 		*den = 1;
31346d12f91SDave Airlie 	}
31446d12f91SDave Airlie }
31546d12f91SDave Airlie 
skl_plane_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)31646d12f91SDave Airlie static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
31746d12f91SDave Airlie 			       const struct intel_plane_state *plane_state)
31846d12f91SDave Airlie {
31946d12f91SDave Airlie 	unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
320efc52308SVille Syrjälä 	unsigned int num, den;
32146d12f91SDave Airlie 
322efc52308SVille Syrjälä 	skl_plane_ratio(plane_state, &num, &den);
32346d12f91SDave Airlie 
32446d12f91SDave Airlie 	return DIV_ROUND_UP(pixel_rate * num, den);
32546d12f91SDave Airlie }
32646d12f91SDave Airlie 
skl_plane_max_width(const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)32746d12f91SDave Airlie static int skl_plane_max_width(const struct drm_framebuffer *fb,
32846d12f91SDave Airlie 			       int color_plane,
32946d12f91SDave Airlie 			       unsigned int rotation)
33046d12f91SDave Airlie {
33146d12f91SDave Airlie 	int cpp = fb->format->cpp[color_plane];
33246d12f91SDave Airlie 
33346d12f91SDave Airlie 	switch (fb->modifier) {
33446d12f91SDave Airlie 	case DRM_FORMAT_MOD_LINEAR:
33546d12f91SDave Airlie 	case I915_FORMAT_MOD_X_TILED:
33646d12f91SDave Airlie 		/*
33746d12f91SDave Airlie 		 * Validated limit is 4k, but has 5k should
33846d12f91SDave Airlie 		 * work apart from the following features:
33946d12f91SDave Airlie 		 * - Ytile (already limited to 4k)
34046d12f91SDave Airlie 		 * - FP16 (already limited to 4k)
34146d12f91SDave Airlie 		 * - render compression (already limited to 4k)
34246d12f91SDave Airlie 		 * - KVMR sprite and cursor (don't care)
34346d12f91SDave Airlie 		 * - horizontal panning (TODO verify this)
34446d12f91SDave Airlie 		 * - pipe and plane scaling (TODO verify this)
34546d12f91SDave Airlie 		 */
34646d12f91SDave Airlie 		if (cpp == 8)
34746d12f91SDave Airlie 			return 4096;
34846d12f91SDave Airlie 		else
34946d12f91SDave Airlie 			return 5120;
35046d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED_CCS:
35146d12f91SDave Airlie 	case I915_FORMAT_MOD_Yf_TILED_CCS:
35246d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
35346d12f91SDave Airlie 		/* FIXME AUX plane? */
35446d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED:
35546d12f91SDave Airlie 	case I915_FORMAT_MOD_Yf_TILED:
35646d12f91SDave Airlie 		if (cpp == 8)
35746d12f91SDave Airlie 			return 2048;
35846d12f91SDave Airlie 		else
35946d12f91SDave Airlie 			return 4096;
36046d12f91SDave Airlie 	default:
36146d12f91SDave Airlie 		MISSING_CASE(fb->modifier);
36246d12f91SDave Airlie 		return 2048;
36346d12f91SDave Airlie 	}
36446d12f91SDave Airlie }
36546d12f91SDave Airlie 
glk_plane_max_width(const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)36646d12f91SDave Airlie static int glk_plane_max_width(const struct drm_framebuffer *fb,
36746d12f91SDave Airlie 			       int color_plane,
36846d12f91SDave Airlie 			       unsigned int rotation)
36946d12f91SDave Airlie {
37046d12f91SDave Airlie 	int cpp = fb->format->cpp[color_plane];
37146d12f91SDave Airlie 
37246d12f91SDave Airlie 	switch (fb->modifier) {
37346d12f91SDave Airlie 	case DRM_FORMAT_MOD_LINEAR:
37446d12f91SDave Airlie 	case I915_FORMAT_MOD_X_TILED:
37546d12f91SDave Airlie 		if (cpp == 8)
37646d12f91SDave Airlie 			return 4096;
37746d12f91SDave Airlie 		else
37846d12f91SDave Airlie 			return 5120;
37946d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED_CCS:
38046d12f91SDave Airlie 	case I915_FORMAT_MOD_Yf_TILED_CCS:
38146d12f91SDave Airlie 		/* FIXME AUX plane? */
38246d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED:
38346d12f91SDave Airlie 	case I915_FORMAT_MOD_Yf_TILED:
38446d12f91SDave Airlie 		if (cpp == 8)
38546d12f91SDave Airlie 			return 2048;
38646d12f91SDave Airlie 		else
38746d12f91SDave Airlie 			return 5120;
38846d12f91SDave Airlie 	default:
38946d12f91SDave Airlie 		MISSING_CASE(fb->modifier);
39046d12f91SDave Airlie 		return 2048;
39146d12f91SDave Airlie 	}
39246d12f91SDave Airlie }
39346d12f91SDave Airlie 
icl_plane_min_width(const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)39446d12f91SDave Airlie static int icl_plane_min_width(const struct drm_framebuffer *fb,
39546d12f91SDave Airlie 			       int color_plane,
39646d12f91SDave Airlie 			       unsigned int rotation)
39746d12f91SDave Airlie {
39846d12f91SDave Airlie 	/* Wa_14011264657, Wa_14011050563: gen11+ */
39946d12f91SDave Airlie 	switch (fb->format->format) {
40046d12f91SDave Airlie 	case DRM_FORMAT_C8:
40146d12f91SDave Airlie 		return 18;
40246d12f91SDave Airlie 	case DRM_FORMAT_RGB565:
40346d12f91SDave Airlie 		return 10;
40446d12f91SDave Airlie 	case DRM_FORMAT_XRGB8888:
40546d12f91SDave Airlie 	case DRM_FORMAT_XBGR8888:
40646d12f91SDave Airlie 	case DRM_FORMAT_ARGB8888:
40746d12f91SDave Airlie 	case DRM_FORMAT_ABGR8888:
40846d12f91SDave Airlie 	case DRM_FORMAT_XRGB2101010:
40946d12f91SDave Airlie 	case DRM_FORMAT_XBGR2101010:
41046d12f91SDave Airlie 	case DRM_FORMAT_ARGB2101010:
41146d12f91SDave Airlie 	case DRM_FORMAT_ABGR2101010:
41246d12f91SDave Airlie 	case DRM_FORMAT_XVYU2101010:
41346d12f91SDave Airlie 	case DRM_FORMAT_Y212:
41446d12f91SDave Airlie 	case DRM_FORMAT_Y216:
41546d12f91SDave Airlie 		return 6;
41646d12f91SDave Airlie 	case DRM_FORMAT_NV12:
41746d12f91SDave Airlie 		return 20;
41846d12f91SDave Airlie 	case DRM_FORMAT_P010:
41946d12f91SDave Airlie 	case DRM_FORMAT_P012:
42046d12f91SDave Airlie 	case DRM_FORMAT_P016:
42146d12f91SDave Airlie 		return 12;
42246d12f91SDave Airlie 	case DRM_FORMAT_XRGB16161616F:
42346d12f91SDave Airlie 	case DRM_FORMAT_XBGR16161616F:
42446d12f91SDave Airlie 	case DRM_FORMAT_ARGB16161616F:
42546d12f91SDave Airlie 	case DRM_FORMAT_ABGR16161616F:
42646d12f91SDave Airlie 	case DRM_FORMAT_XVYU12_16161616:
42746d12f91SDave Airlie 	case DRM_FORMAT_XVYU16161616:
42846d12f91SDave Airlie 		return 4;
42946d12f91SDave Airlie 	default:
43046d12f91SDave Airlie 		return 1;
43146d12f91SDave Airlie 	}
43246d12f91SDave Airlie }
43346d12f91SDave Airlie 
icl_hdr_plane_max_width(const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)4340e959b4eSVidya Srinivas static int icl_hdr_plane_max_width(const struct drm_framebuffer *fb,
4350e959b4eSVidya Srinivas 				   int color_plane,
4360e959b4eSVidya Srinivas 				   unsigned int rotation)
4370e959b4eSVidya Srinivas {
4380e959b4eSVidya Srinivas 	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
4390e959b4eSVidya Srinivas 		return 4096;
4400e959b4eSVidya Srinivas 	else
4410e959b4eSVidya Srinivas 		return 5120;
4420e959b4eSVidya Srinivas }
4430e959b4eSVidya Srinivas 
icl_sdr_plane_max_width(const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)4440e959b4eSVidya Srinivas static int icl_sdr_plane_max_width(const struct drm_framebuffer *fb,
44546d12f91SDave Airlie 				   int color_plane,
44646d12f91SDave Airlie 				   unsigned int rotation)
44746d12f91SDave Airlie {
44846d12f91SDave Airlie 	return 5120;
44946d12f91SDave Airlie }
45046d12f91SDave Airlie 
skl_plane_max_height(const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)45146d12f91SDave Airlie static int skl_plane_max_height(const struct drm_framebuffer *fb,
45246d12f91SDave Airlie 				int color_plane,
45346d12f91SDave Airlie 				unsigned int rotation)
45446d12f91SDave Airlie {
45546d12f91SDave Airlie 	return 4096;
45646d12f91SDave Airlie }
45746d12f91SDave Airlie 
icl_plane_max_height(const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)45846d12f91SDave Airlie static int icl_plane_max_height(const struct drm_framebuffer *fb,
45946d12f91SDave Airlie 				int color_plane,
46046d12f91SDave Airlie 				unsigned int rotation)
46146d12f91SDave Airlie {
46246d12f91SDave Airlie 	return 4320;
46346d12f91SDave Airlie }
46446d12f91SDave Airlie 
46546d12f91SDave Airlie static unsigned int
plane_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation,unsigned int max_pixels,unsigned int max_bytes)4661301ce34SVille Syrjälä plane_max_stride(struct intel_plane *plane,
4671301ce34SVille Syrjälä 		 u32 pixel_format, u64 modifier,
4681301ce34SVille Syrjälä 		 unsigned int rotation,
4691301ce34SVille Syrjälä 		 unsigned int max_pixels,
4701301ce34SVille Syrjälä 		 unsigned int max_bytes)
4711301ce34SVille Syrjälä {
4721301ce34SVille Syrjälä 	const struct drm_format_info *info = drm_format_info(pixel_format);
4731301ce34SVille Syrjälä 	int cpp = info->cpp[0];
4741301ce34SVille Syrjälä 
4751301ce34SVille Syrjälä 	if (drm_rotation_90_or_270(rotation))
4761301ce34SVille Syrjälä 		return min(max_pixels, max_bytes / cpp);
4771301ce34SVille Syrjälä 	else
4781301ce34SVille Syrjälä 		return min(max_pixels * cpp, max_bytes);
4791301ce34SVille Syrjälä }
4801301ce34SVille Syrjälä 
4811301ce34SVille Syrjälä static unsigned int
adl_plane_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)4821301ce34SVille Syrjälä adl_plane_max_stride(struct intel_plane *plane,
4831301ce34SVille Syrjälä 		     u32 pixel_format, u64 modifier,
4841301ce34SVille Syrjälä 		     unsigned int rotation)
4851301ce34SVille Syrjälä {
4861301ce34SVille Syrjälä 	unsigned int max_pixels = 65536; /* PLANE_OFFSET limit */
4871301ce34SVille Syrjälä 	unsigned int max_bytes = 128 * 1024;
4881301ce34SVille Syrjälä 
4891301ce34SVille Syrjälä 	return plane_max_stride(plane, pixel_format,
4901301ce34SVille Syrjälä 				modifier, rotation,
4911301ce34SVille Syrjälä 				max_pixels, max_bytes);
4921301ce34SVille Syrjälä }
4931301ce34SVille Syrjälä 
4941301ce34SVille Syrjälä static unsigned int
skl_plane_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)49546d12f91SDave Airlie skl_plane_max_stride(struct intel_plane *plane,
49646d12f91SDave Airlie 		     u32 pixel_format, u64 modifier,
49746d12f91SDave Airlie 		     unsigned int rotation)
49846d12f91SDave Airlie {
4991301ce34SVille Syrjälä 	unsigned int max_pixels = 8192; /* PLANE_OFFSET limit */
5001301ce34SVille Syrjälä 	unsigned int max_bytes = 32 * 1024;
50146d12f91SDave Airlie 
5021301ce34SVille Syrjälä 	return plane_max_stride(plane, pixel_format,
5031301ce34SVille Syrjälä 				modifier, rotation,
5041301ce34SVille Syrjälä 				max_pixels, max_bytes);
505e7367af1SJuha-Pekka Heikkilä }
506e7367af1SJuha-Pekka Heikkilä 
tgl_plane_min_alignment(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane)5077652126cSVille Syrjälä static u32 tgl_plane_min_alignment(struct intel_plane *plane,
508ee3c3e33SVille Syrjälä 				   const struct drm_framebuffer *fb,
509ee3c3e33SVille Syrjälä 				   int color_plane)
510ee3c3e33SVille Syrjälä {
5117652126cSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
5127652126cSVille Syrjälä 	/* PLANE_SURF GGTT -> DPT alignment */
5137652126cSVille Syrjälä 	int mult = intel_fb_uses_dpt(fb) ? 512 : 1;
514ee3c3e33SVille Syrjälä 
515ee3c3e33SVille Syrjälä 	/* AUX_DIST needs only 4K alignment */
516ee3c3e33SVille Syrjälä 	if (intel_fb_is_ccs_aux_plane(fb, color_plane))
5177652126cSVille Syrjälä 		return mult * 4 * 1024;
518ee3c3e33SVille Syrjälä 
519ee3c3e33SVille Syrjälä 	switch (fb->modifier) {
520ee3c3e33SVille Syrjälä 	case DRM_FORMAT_MOD_LINEAR:
521ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_X_TILED:
5227652126cSVille Syrjälä 	case I915_FORMAT_MOD_Y_TILED:
5237652126cSVille Syrjälä 	case I915_FORMAT_MOD_4_TILED:
5247652126cSVille Syrjälä 		/*
5257652126cSVille Syrjälä 		 * FIXME ADL sees GGTT/DMAR faults with async
5267652126cSVille Syrjälä 		 * flips unless we align to 16k at least.
5277652126cSVille Syrjälä 		 * Figure out what's going on here...
5287652126cSVille Syrjälä 		 */
5297652126cSVille Syrjälä 		if (IS_ALDERLAKE_P(i915) && HAS_ASYNC_FLIPS(i915))
5307652126cSVille Syrjälä 			return mult * 16 * 1024;
5317652126cSVille Syrjälä 		return mult * 4 * 1024;
532ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
533ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
534ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
535ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
536ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
537ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
538ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
539ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
540ee3c3e33SVille Syrjälä 	case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
541fca0abb2SJuha-Pekka Heikkila 	case I915_FORMAT_MOD_4_TILED_BMG_CCS:
542fca0abb2SJuha-Pekka Heikkila 	case I915_FORMAT_MOD_4_TILED_LNL_CCS:
5437652126cSVille Syrjälä 		/*
5447652126cSVille Syrjälä 		 * Align to at least 4x1 main surface
5457652126cSVille Syrjälä 		 * tiles (16K) to match 64B of AUX.
5467652126cSVille Syrjälä 		 */
5477652126cSVille Syrjälä 		return max(mult * 4 * 1024, 16 * 1024);
5487652126cSVille Syrjälä 	default:
5497652126cSVille Syrjälä 		MISSING_CASE(fb->modifier);
5507652126cSVille Syrjälä 		return 0;
5517652126cSVille Syrjälä 	}
5527652126cSVille Syrjälä }
5537652126cSVille Syrjälä 
skl_plane_min_alignment(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane)5547652126cSVille Syrjälä static u32 skl_plane_min_alignment(struct intel_plane *plane,
5557652126cSVille Syrjälä 				   const struct drm_framebuffer *fb,
5567652126cSVille Syrjälä 				   int color_plane)
5577652126cSVille Syrjälä {
5587652126cSVille Syrjälä 	/*
5597652126cSVille Syrjälä 	 * AUX_DIST needs only 4K alignment,
5607652126cSVille Syrjälä 	 * as does ICL UV PLANE_SURF.
5617652126cSVille Syrjälä 	 */
5627652126cSVille Syrjälä 	if (color_plane != 0)
5637652126cSVille Syrjälä 		return 4 * 1024;
5647652126cSVille Syrjälä 
5657652126cSVille Syrjälä 	switch (fb->modifier) {
5667652126cSVille Syrjälä 	case DRM_FORMAT_MOD_LINEAR:
5677652126cSVille Syrjälä 	case I915_FORMAT_MOD_X_TILED:
5687652126cSVille Syrjälä 		return 256 * 1024;
5697652126cSVille Syrjälä 	case I915_FORMAT_MOD_Y_TILED_CCS:
5707652126cSVille Syrjälä 	case I915_FORMAT_MOD_Yf_TILED_CCS:
5717652126cSVille Syrjälä 	case I915_FORMAT_MOD_Y_TILED:
5727652126cSVille Syrjälä 	case I915_FORMAT_MOD_Yf_TILED:
5737652126cSVille Syrjälä 		return 1 * 1024 * 1024;
574ee3c3e33SVille Syrjälä 	default:
575ee3c3e33SVille Syrjälä 		MISSING_CASE(fb->modifier);
576ee3c3e33SVille Syrjälä 		return 0;
577ee3c3e33SVille Syrjälä 	}
578ee3c3e33SVille Syrjälä }
579ee3c3e33SVille Syrjälä 
58046d12f91SDave Airlie /* Preoffset values for YUV to RGB Conversion */
58146d12f91SDave Airlie #define PREOFF_YUV_TO_RGB_HI		0x1800
58246d12f91SDave Airlie #define PREOFF_YUV_TO_RGB_ME		0x0000
58346d12f91SDave Airlie #define PREOFF_YUV_TO_RGB_LO		0x1800
58446d12f91SDave Airlie 
58546d12f91SDave Airlie #define  ROFF(x)          (((x) & 0xffff) << 16)
58646d12f91SDave Airlie #define  GOFF(x)          (((x) & 0xffff) << 0)
58746d12f91SDave Airlie #define  BOFF(x)          (((x) & 0xffff) << 16)
58846d12f91SDave Airlie 
58946d12f91SDave Airlie /*
59046d12f91SDave Airlie  * Programs the input color space conversion stage for ICL HDR planes.
59146d12f91SDave Airlie  * Note that it is assumed that this stage always happens after YUV
59246d12f91SDave Airlie  * range correction. Thus, the input to this stage is assumed to be
59346d12f91SDave Airlie  * in full-range YCbCr.
59446d12f91SDave Airlie  */
59546d12f91SDave Airlie static void
icl_program_input_csc(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)59646d12f91SDave Airlie icl_program_input_csc(struct intel_plane *plane,
59746d12f91SDave Airlie 		      const struct intel_crtc_state *crtc_state,
59846d12f91SDave Airlie 		      const struct intel_plane_state *plane_state)
59946d12f91SDave Airlie {
60046d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
60146d12f91SDave Airlie 	enum pipe pipe = plane->pipe;
60246d12f91SDave Airlie 	enum plane_id plane_id = plane->id;
60346d12f91SDave Airlie 
60446d12f91SDave Airlie 	static const u16 input_csc_matrix[][9] = {
60546d12f91SDave Airlie 		/*
60646d12f91SDave Airlie 		 * BT.601 full range YCbCr -> full range RGB
60746d12f91SDave Airlie 		 * The matrix required is :
60846d12f91SDave Airlie 		 * [1.000, 0.000, 1.371,
60946d12f91SDave Airlie 		 *  1.000, -0.336, -0.698,
61046d12f91SDave Airlie 		 *  1.000, 1.732, 0.0000]
61146d12f91SDave Airlie 		 */
61246d12f91SDave Airlie 		[DRM_COLOR_YCBCR_BT601] = {
61346d12f91SDave Airlie 			0x7AF8, 0x7800, 0x0,
61446d12f91SDave Airlie 			0x8B28, 0x7800, 0x9AC0,
61546d12f91SDave Airlie 			0x0, 0x7800, 0x7DD8,
61646d12f91SDave Airlie 		},
61746d12f91SDave Airlie 		/*
61846d12f91SDave Airlie 		 * BT.709 full range YCbCr -> full range RGB
61946d12f91SDave Airlie 		 * The matrix required is :
62046d12f91SDave Airlie 		 * [1.000, 0.000, 1.574,
62146d12f91SDave Airlie 		 *  1.000, -0.187, -0.468,
62246d12f91SDave Airlie 		 *  1.000, 1.855, 0.0000]
62346d12f91SDave Airlie 		 */
62446d12f91SDave Airlie 		[DRM_COLOR_YCBCR_BT709] = {
62546d12f91SDave Airlie 			0x7C98, 0x7800, 0x0,
62646d12f91SDave Airlie 			0x9EF8, 0x7800, 0xAC00,
62746d12f91SDave Airlie 			0x0, 0x7800,  0x7ED8,
62846d12f91SDave Airlie 		},
62946d12f91SDave Airlie 		/*
63046d12f91SDave Airlie 		 * BT.2020 full range YCbCr -> full range RGB
63146d12f91SDave Airlie 		 * The matrix required is :
63246d12f91SDave Airlie 		 * [1.000, 0.000, 1.474,
63346d12f91SDave Airlie 		 *  1.000, -0.1645, -0.5713,
63446d12f91SDave Airlie 		 *  1.000, 1.8814, 0.0000]
63546d12f91SDave Airlie 		 */
63646d12f91SDave Airlie 		[DRM_COLOR_YCBCR_BT2020] = {
63746d12f91SDave Airlie 			0x7BC8, 0x7800, 0x0,
63846d12f91SDave Airlie 			0x8928, 0x7800, 0xAA88,
63946d12f91SDave Airlie 			0x0, 0x7800, 0x7F10,
64046d12f91SDave Airlie 		},
64146d12f91SDave Airlie 	};
64246d12f91SDave Airlie 	const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
64346d12f91SDave Airlie 
64446d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
64546d12f91SDave Airlie 			  ROFF(csc[0]) | GOFF(csc[1]));
64646d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
64746d12f91SDave Airlie 			  BOFF(csc[2]));
64846d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
64946d12f91SDave Airlie 			  ROFF(csc[3]) | GOFF(csc[4]));
65046d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
65146d12f91SDave Airlie 			  BOFF(csc[5]));
65246d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
65346d12f91SDave Airlie 			  ROFF(csc[6]) | GOFF(csc[7]));
65446d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
65546d12f91SDave Airlie 			  BOFF(csc[8]));
65646d12f91SDave Airlie 
65746d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
65846d12f91SDave Airlie 			  PREOFF_YUV_TO_RGB_HI);
65946d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
66046d12f91SDave Airlie 			  PREOFF_YUV_TO_RGB_ME);
66146d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
66246d12f91SDave Airlie 			  PREOFF_YUV_TO_RGB_LO);
66346d12f91SDave Airlie 	intel_de_write_fw(dev_priv,
66446d12f91SDave Airlie 			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
66546d12f91SDave Airlie 	intel_de_write_fw(dev_priv,
66646d12f91SDave Airlie 			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
66746d12f91SDave Airlie 	intel_de_write_fw(dev_priv,
66846d12f91SDave Airlie 			  PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
66946d12f91SDave Airlie }
67046d12f91SDave Airlie 
skl_plane_stride_mult(const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)67146d12f91SDave Airlie static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
67246d12f91SDave Airlie 					  int color_plane, unsigned int rotation)
67346d12f91SDave Airlie {
67446d12f91SDave Airlie 	/*
67546d12f91SDave Airlie 	 * The stride is either expressed as a multiple of 64 bytes chunks for
67646d12f91SDave Airlie 	 * linear buffers or in number of tiles for tiled buffers.
67746d12f91SDave Airlie 	 */
67846d12f91SDave Airlie 	if (is_surface_linear(fb, color_plane))
67946d12f91SDave Airlie 		return 64;
68046d12f91SDave Airlie 	else if (drm_rotation_90_or_270(rotation))
68146d12f91SDave Airlie 		return intel_tile_height(fb, color_plane);
68246d12f91SDave Airlie 	else
68346d12f91SDave Airlie 		return intel_tile_width_bytes(fb, color_plane);
68446d12f91SDave Airlie }
68546d12f91SDave Airlie 
skl_plane_stride(const struct intel_plane_state * plane_state,int color_plane)68646d12f91SDave Airlie static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
68746d12f91SDave Airlie 			    int color_plane)
68846d12f91SDave Airlie {
68946d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
69046d12f91SDave Airlie 	unsigned int rotation = plane_state->hw.rotation;
691e6d6f689SImre Deak 	u32 stride = plane_state->view.color_plane[color_plane].scanout_stride;
69246d12f91SDave Airlie 
69346d12f91SDave Airlie 	if (color_plane >= fb->format->num_planes)
69446d12f91SDave Airlie 		return 0;
69546d12f91SDave Airlie 
69646d12f91SDave Airlie 	return stride / skl_plane_stride_mult(fb, color_plane, rotation);
69746d12f91SDave Airlie }
69846d12f91SDave Airlie 
skl_plane_ddb_reg_val(const struct skl_ddb_entry * entry)69998719270SVille Syrjälä static u32 skl_plane_ddb_reg_val(const struct skl_ddb_entry *entry)
70019be15dcSVille Syrjälä {
70119be15dcSVille Syrjälä 	if (!entry->end)
70219be15dcSVille Syrjälä 		return 0;
70319be15dcSVille Syrjälä 
70419be15dcSVille Syrjälä 	return PLANE_BUF_END(entry->end - 1) |
70519be15dcSVille Syrjälä 		PLANE_BUF_START(entry->start);
70619be15dcSVille Syrjälä }
70719be15dcSVille Syrjälä 
skl_plane_wm_reg_val(const struct skl_wm_level * level)70898719270SVille Syrjälä static u32 skl_plane_wm_reg_val(const struct skl_wm_level *level)
70919be15dcSVille Syrjälä {
71019be15dcSVille Syrjälä 	u32 val = 0;
71119be15dcSVille Syrjälä 
71219be15dcSVille Syrjälä 	if (level->enable)
71319be15dcSVille Syrjälä 		val |= PLANE_WM_EN;
71419be15dcSVille Syrjälä 	if (level->ignore_lines)
71519be15dcSVille Syrjälä 		val |= PLANE_WM_IGNORE_LINES;
71619be15dcSVille Syrjälä 	val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks);
71719be15dcSVille Syrjälä 	val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines);
71819be15dcSVille Syrjälä 
71919be15dcSVille Syrjälä 	return val;
72019be15dcSVille Syrjälä }
72119be15dcSVille Syrjälä 
skl_write_plane_wm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)72219be15dcSVille Syrjälä static void skl_write_plane_wm(struct intel_plane *plane,
72319be15dcSVille Syrjälä 			       const struct intel_crtc_state *crtc_state)
72419be15dcSVille Syrjälä {
72519be15dcSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
72619be15dcSVille Syrjälä 	enum plane_id plane_id = plane->id;
72719be15dcSVille Syrjälä 	enum pipe pipe = plane->pipe;
72819be15dcSVille Syrjälä 	const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal;
72919be15dcSVille Syrjälä 	const struct skl_ddb_entry *ddb =
73019be15dcSVille Syrjälä 		&crtc_state->wm.skl.plane_ddb[plane_id];
73119be15dcSVille Syrjälä 	const struct skl_ddb_entry *ddb_y =
73219be15dcSVille Syrjälä 		&crtc_state->wm.skl.plane_ddb_y[plane_id];
73319be15dcSVille Syrjälä 	int level;
73419be15dcSVille Syrjälä 
73519be15dcSVille Syrjälä 	for (level = 0; level < i915->display.wm.num_levels; level++)
73619be15dcSVille Syrjälä 		intel_de_write_fw(i915, PLANE_WM(pipe, plane_id, level),
73719be15dcSVille Syrjälä 				  skl_plane_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level)));
73819be15dcSVille Syrjälä 
73919be15dcSVille Syrjälä 	intel_de_write_fw(i915, PLANE_WM_TRANS(pipe, plane_id),
74019be15dcSVille Syrjälä 			  skl_plane_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id)));
74119be15dcSVille Syrjälä 
74219be15dcSVille Syrjälä 	if (HAS_HW_SAGV_WM(i915)) {
74319be15dcSVille Syrjälä 		const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id];
74419be15dcSVille Syrjälä 
74519be15dcSVille Syrjälä 		intel_de_write_fw(i915, PLANE_WM_SAGV(pipe, plane_id),
74619be15dcSVille Syrjälä 				  skl_plane_wm_reg_val(&wm->sagv.wm0));
74719be15dcSVille Syrjälä 		intel_de_write_fw(i915, PLANE_WM_SAGV_TRANS(pipe, plane_id),
74819be15dcSVille Syrjälä 				  skl_plane_wm_reg_val(&wm->sagv.trans_wm));
74919be15dcSVille Syrjälä 	}
75019be15dcSVille Syrjälä 
75119be15dcSVille Syrjälä 	intel_de_write_fw(i915, PLANE_BUF_CFG(pipe, plane_id),
75219be15dcSVille Syrjälä 			  skl_plane_ddb_reg_val(ddb));
75319be15dcSVille Syrjälä 
75419be15dcSVille Syrjälä 	if (DISPLAY_VER(i915) < 11)
75519be15dcSVille Syrjälä 		intel_de_write_fw(i915, PLANE_NV12_BUF_CFG(pipe, plane_id),
75619be15dcSVille Syrjälä 				  skl_plane_ddb_reg_val(ddb_y));
75719be15dcSVille Syrjälä }
75819be15dcSVille Syrjälä 
75946d12f91SDave Airlie static void
skl_plane_disable_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)7608ac80733SVille Syrjälä skl_plane_disable_arm(struct intel_plane *plane,
76146d12f91SDave Airlie 		      const struct intel_crtc_state *crtc_state)
76246d12f91SDave Airlie {
76346d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
76446d12f91SDave Airlie 	enum plane_id plane_id = plane->id;
76546d12f91SDave Airlie 	enum pipe pipe = plane->pipe;
76646d12f91SDave Airlie 
767f8a005ebSVille Syrjälä 	skl_write_plane_wm(plane, crtc_state);
768f8a005ebSVille Syrjälä 
769f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
770f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
771f8a005ebSVille Syrjälä }
772f8a005ebSVille Syrjälä 
icl_plane_disable_sel_fetch_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)773b1f5279bSJouni Högander static void icl_plane_disable_sel_fetch_arm(struct intel_plane *plane,
774b1f5279bSJouni Högander 					    const struct intel_crtc_state *crtc_state)
775b1f5279bSJouni Högander {
776b1f5279bSJouni Högander 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
777b1f5279bSJouni Högander 	enum pipe pipe = plane->pipe;
778b1f5279bSJouni Högander 
779b1f5279bSJouni Högander 	if (!crtc_state->enable_psr2_sel_fetch)
780b1f5279bSJouni Högander 		return;
781b1f5279bSJouni Högander 
7820ff7639bSVille Syrjälä 	intel_de_write_fw(i915, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0);
783b1f5279bSJouni Högander }
784b1f5279bSJouni Högander 
785f8a005ebSVille Syrjälä static void
icl_plane_disable_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state)786f8a005ebSVille Syrjälä icl_plane_disable_arm(struct intel_plane *plane,
787f8a005ebSVille Syrjälä 		      const struct intel_crtc_state *crtc_state)
788f8a005ebSVille Syrjälä {
789f8a005ebSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
790f8a005ebSVille Syrjälä 	enum plane_id plane_id = plane->id;
791f8a005ebSVille Syrjälä 	enum pipe pipe = plane->pipe;
792f8a005ebSVille Syrjälä 
79346d12f91SDave Airlie 	if (icl_is_hdr_plane(dev_priv, plane_id))
79446d12f91SDave Airlie 		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
79546d12f91SDave Airlie 
79646d12f91SDave Airlie 	skl_write_plane_wm(plane, crtc_state);
79746d12f91SDave Airlie 
798b1f5279bSJouni Högander 	icl_plane_disable_sel_fetch_arm(plane, crtc_state);
79946d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
80046d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
80146d12f91SDave Airlie }
80246d12f91SDave Airlie 
80346d12f91SDave Airlie static bool
skl_plane_get_hw_state(struct intel_plane * plane,enum pipe * pipe)80446d12f91SDave Airlie skl_plane_get_hw_state(struct intel_plane *plane,
80546d12f91SDave Airlie 		       enum pipe *pipe)
80646d12f91SDave Airlie {
80746d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
80846d12f91SDave Airlie 	enum intel_display_power_domain power_domain;
80946d12f91SDave Airlie 	enum plane_id plane_id = plane->id;
81046d12f91SDave Airlie 	intel_wakeref_t wakeref;
81146d12f91SDave Airlie 	bool ret;
81246d12f91SDave Airlie 
81346d12f91SDave Airlie 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
81446d12f91SDave Airlie 	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
81546d12f91SDave Airlie 	if (!wakeref)
81646d12f91SDave Airlie 		return false;
81746d12f91SDave Airlie 
81846d12f91SDave Airlie 	ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
81946d12f91SDave Airlie 
82046d12f91SDave Airlie 	*pipe = plane->pipe;
82146d12f91SDave Airlie 
82246d12f91SDave Airlie 	intel_display_power_put(dev_priv, power_domain, wakeref);
82346d12f91SDave Airlie 
82446d12f91SDave Airlie 	return ret;
82546d12f91SDave Airlie }
82646d12f91SDave Airlie 
skl_plane_ctl_format(u32 pixel_format)82746d12f91SDave Airlie static u32 skl_plane_ctl_format(u32 pixel_format)
82846d12f91SDave Airlie {
82946d12f91SDave Airlie 	switch (pixel_format) {
83046d12f91SDave Airlie 	case DRM_FORMAT_C8:
83146d12f91SDave Airlie 		return PLANE_CTL_FORMAT_INDEXED;
83246d12f91SDave Airlie 	case DRM_FORMAT_RGB565:
83346d12f91SDave Airlie 		return PLANE_CTL_FORMAT_RGB_565;
83446d12f91SDave Airlie 	case DRM_FORMAT_XBGR8888:
83546d12f91SDave Airlie 	case DRM_FORMAT_ABGR8888:
83646d12f91SDave Airlie 		return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
83746d12f91SDave Airlie 	case DRM_FORMAT_XRGB8888:
83846d12f91SDave Airlie 	case DRM_FORMAT_ARGB8888:
83946d12f91SDave Airlie 		return PLANE_CTL_FORMAT_XRGB_8888;
84046d12f91SDave Airlie 	case DRM_FORMAT_XBGR2101010:
84146d12f91SDave Airlie 	case DRM_FORMAT_ABGR2101010:
84246d12f91SDave Airlie 		return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
84346d12f91SDave Airlie 	case DRM_FORMAT_XRGB2101010:
84446d12f91SDave Airlie 	case DRM_FORMAT_ARGB2101010:
84546d12f91SDave Airlie 		return PLANE_CTL_FORMAT_XRGB_2101010;
84646d12f91SDave Airlie 	case DRM_FORMAT_XBGR16161616F:
84746d12f91SDave Airlie 	case DRM_FORMAT_ABGR16161616F:
84846d12f91SDave Airlie 		return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
84946d12f91SDave Airlie 	case DRM_FORMAT_XRGB16161616F:
85046d12f91SDave Airlie 	case DRM_FORMAT_ARGB16161616F:
85146d12f91SDave Airlie 		return PLANE_CTL_FORMAT_XRGB_16161616F;
85246d12f91SDave Airlie 	case DRM_FORMAT_XYUV8888:
85346d12f91SDave Airlie 		return PLANE_CTL_FORMAT_XYUV;
85446d12f91SDave Airlie 	case DRM_FORMAT_YUYV:
85562f887aeSVille Syrjälä 		return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YUYV;
85646d12f91SDave Airlie 	case DRM_FORMAT_YVYU:
85762f887aeSVille Syrjälä 		return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YVYU;
85846d12f91SDave Airlie 	case DRM_FORMAT_UYVY:
85962f887aeSVille Syrjälä 		return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_UYVY;
86046d12f91SDave Airlie 	case DRM_FORMAT_VYUY:
86162f887aeSVille Syrjälä 		return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_VYUY;
86246d12f91SDave Airlie 	case DRM_FORMAT_NV12:
86346d12f91SDave Airlie 		return PLANE_CTL_FORMAT_NV12;
86446d12f91SDave Airlie 	case DRM_FORMAT_P010:
86546d12f91SDave Airlie 		return PLANE_CTL_FORMAT_P010;
86646d12f91SDave Airlie 	case DRM_FORMAT_P012:
86746d12f91SDave Airlie 		return PLANE_CTL_FORMAT_P012;
86846d12f91SDave Airlie 	case DRM_FORMAT_P016:
86946d12f91SDave Airlie 		return PLANE_CTL_FORMAT_P016;
87046d12f91SDave Airlie 	case DRM_FORMAT_Y210:
87146d12f91SDave Airlie 		return PLANE_CTL_FORMAT_Y210;
87246d12f91SDave Airlie 	case DRM_FORMAT_Y212:
87346d12f91SDave Airlie 		return PLANE_CTL_FORMAT_Y212;
87446d12f91SDave Airlie 	case DRM_FORMAT_Y216:
87546d12f91SDave Airlie 		return PLANE_CTL_FORMAT_Y216;
87646d12f91SDave Airlie 	case DRM_FORMAT_XVYU2101010:
87746d12f91SDave Airlie 		return PLANE_CTL_FORMAT_Y410;
87846d12f91SDave Airlie 	case DRM_FORMAT_XVYU12_16161616:
87946d12f91SDave Airlie 		return PLANE_CTL_FORMAT_Y412;
88046d12f91SDave Airlie 	case DRM_FORMAT_XVYU16161616:
88146d12f91SDave Airlie 		return PLANE_CTL_FORMAT_Y416;
88246d12f91SDave Airlie 	default:
88346d12f91SDave Airlie 		MISSING_CASE(pixel_format);
88446d12f91SDave Airlie 	}
88546d12f91SDave Airlie 
88646d12f91SDave Airlie 	return 0;
88746d12f91SDave Airlie }
88846d12f91SDave Airlie 
skl_plane_ctl_alpha(const struct intel_plane_state * plane_state)88946d12f91SDave Airlie static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
89046d12f91SDave Airlie {
89146d12f91SDave Airlie 	if (!plane_state->hw.fb->format->has_alpha)
89246d12f91SDave Airlie 		return PLANE_CTL_ALPHA_DISABLE;
89346d12f91SDave Airlie 
89446d12f91SDave Airlie 	switch (plane_state->hw.pixel_blend_mode) {
89546d12f91SDave Airlie 	case DRM_MODE_BLEND_PIXEL_NONE:
89646d12f91SDave Airlie 		return PLANE_CTL_ALPHA_DISABLE;
89746d12f91SDave Airlie 	case DRM_MODE_BLEND_PREMULTI:
89846d12f91SDave Airlie 		return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
89946d12f91SDave Airlie 	case DRM_MODE_BLEND_COVERAGE:
90046d12f91SDave Airlie 		return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
90146d12f91SDave Airlie 	default:
90246d12f91SDave Airlie 		MISSING_CASE(plane_state->hw.pixel_blend_mode);
90346d12f91SDave Airlie 		return PLANE_CTL_ALPHA_DISABLE;
90446d12f91SDave Airlie 	}
90546d12f91SDave Airlie }
90646d12f91SDave Airlie 
glk_plane_color_ctl_alpha(const struct intel_plane_state * plane_state)90746d12f91SDave Airlie static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
90846d12f91SDave Airlie {
90946d12f91SDave Airlie 	if (!plane_state->hw.fb->format->has_alpha)
91046d12f91SDave Airlie 		return PLANE_COLOR_ALPHA_DISABLE;
91146d12f91SDave Airlie 
91246d12f91SDave Airlie 	switch (plane_state->hw.pixel_blend_mode) {
91346d12f91SDave Airlie 	case DRM_MODE_BLEND_PIXEL_NONE:
91446d12f91SDave Airlie 		return PLANE_COLOR_ALPHA_DISABLE;
91546d12f91SDave Airlie 	case DRM_MODE_BLEND_PREMULTI:
91646d12f91SDave Airlie 		return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
91746d12f91SDave Airlie 	case DRM_MODE_BLEND_COVERAGE:
91846d12f91SDave Airlie 		return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
91946d12f91SDave Airlie 	default:
92046d12f91SDave Airlie 		MISSING_CASE(plane_state->hw.pixel_blend_mode);
92146d12f91SDave Airlie 		return PLANE_COLOR_ALPHA_DISABLE;
92246d12f91SDave Airlie 	}
92346d12f91SDave Airlie }
92446d12f91SDave Airlie 
skl_plane_ctl_tiling(u64 fb_modifier)92546d12f91SDave Airlie static u32 skl_plane_ctl_tiling(u64 fb_modifier)
92646d12f91SDave Airlie {
92746d12f91SDave Airlie 	switch (fb_modifier) {
92846d12f91SDave Airlie 	case DRM_FORMAT_MOD_LINEAR:
92946d12f91SDave Airlie 		break;
93046d12f91SDave Airlie 	case I915_FORMAT_MOD_X_TILED:
93146d12f91SDave Airlie 		return PLANE_CTL_TILED_X;
93246d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED:
93346d12f91SDave Airlie 		return PLANE_CTL_TILED_Y;
934072ce416SStanislav Lisovskiy 	case I915_FORMAT_MOD_4_TILED:
935072ce416SStanislav Lisovskiy 		return PLANE_CTL_TILED_4;
9364c3afa72SMatt Roper 	case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
9374c3afa72SMatt Roper 		return PLANE_CTL_TILED_4 |
9384c3afa72SMatt Roper 			PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
9394c3afa72SMatt Roper 			PLANE_CTL_CLEAR_COLOR_DISABLE;
9404c3afa72SMatt Roper 	case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
9414c3afa72SMatt Roper 		return PLANE_CTL_TILED_4 |
9424c3afa72SMatt Roper 			PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE |
9434c3afa72SMatt Roper 			PLANE_CTL_CLEAR_COLOR_DISABLE;
944680025dcSJuha-Pekka Heikkilä 	case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
945680025dcSJuha-Pekka Heikkilä 		return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
946f2eb43f0SJuha-Pekka Heikkila 	case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
947f2eb43f0SJuha-Pekka Heikkila 		return PLANE_CTL_TILED_4 |
948f2eb43f0SJuha-Pekka Heikkila 			PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
949f2eb43f0SJuha-Pekka Heikkila 			PLANE_CTL_CLEAR_COLOR_DISABLE;
950f2eb43f0SJuha-Pekka Heikkila 	case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
951f2eb43f0SJuha-Pekka Heikkila 		return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
952f2eb43f0SJuha-Pekka Heikkila 	case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
953f2eb43f0SJuha-Pekka Heikkila 		return PLANE_CTL_TILED_4 | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
954fca0abb2SJuha-Pekka Heikkila 	case I915_FORMAT_MOD_4_TILED_BMG_CCS:
955fca0abb2SJuha-Pekka Heikkila 	case I915_FORMAT_MOD_4_TILED_LNL_CCS:
956fca0abb2SJuha-Pekka Heikkila 		return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
95746d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED_CCS:
95846d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
95946d12f91SDave Airlie 		return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
96046d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
96146d12f91SDave Airlie 		return PLANE_CTL_TILED_Y |
96246d12f91SDave Airlie 		       PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
96346d12f91SDave Airlie 		       PLANE_CTL_CLEAR_COLOR_DISABLE;
96446d12f91SDave Airlie 	case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
96546d12f91SDave Airlie 		return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
96646d12f91SDave Airlie 	case I915_FORMAT_MOD_Yf_TILED:
96746d12f91SDave Airlie 		return PLANE_CTL_TILED_YF;
96846d12f91SDave Airlie 	case I915_FORMAT_MOD_Yf_TILED_CCS:
96946d12f91SDave Airlie 		return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
97046d12f91SDave Airlie 	default:
97146d12f91SDave Airlie 		MISSING_CASE(fb_modifier);
97246d12f91SDave Airlie 	}
97346d12f91SDave Airlie 
97446d12f91SDave Airlie 	return 0;
97546d12f91SDave Airlie }
97646d12f91SDave Airlie 
skl_plane_ctl_rotate(unsigned int rotate)97746d12f91SDave Airlie static u32 skl_plane_ctl_rotate(unsigned int rotate)
97846d12f91SDave Airlie {
97946d12f91SDave Airlie 	switch (rotate) {
98046d12f91SDave Airlie 	case DRM_MODE_ROTATE_0:
98146d12f91SDave Airlie 		break;
98246d12f91SDave Airlie 	/*
98346d12f91SDave Airlie 	 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
98446d12f91SDave Airlie 	 * while i915 HW rotation is clockwise, thats why this swapping.
98546d12f91SDave Airlie 	 */
98646d12f91SDave Airlie 	case DRM_MODE_ROTATE_90:
98746d12f91SDave Airlie 		return PLANE_CTL_ROTATE_270;
98846d12f91SDave Airlie 	case DRM_MODE_ROTATE_180:
98946d12f91SDave Airlie 		return PLANE_CTL_ROTATE_180;
99046d12f91SDave Airlie 	case DRM_MODE_ROTATE_270:
99146d12f91SDave Airlie 		return PLANE_CTL_ROTATE_90;
99246d12f91SDave Airlie 	default:
99346d12f91SDave Airlie 		MISSING_CASE(rotate);
99446d12f91SDave Airlie 	}
99546d12f91SDave Airlie 
99646d12f91SDave Airlie 	return 0;
99746d12f91SDave Airlie }
99846d12f91SDave Airlie 
icl_plane_ctl_flip(unsigned int reflect)999c988d2dcSLucas De Marchi static u32 icl_plane_ctl_flip(unsigned int reflect)
100046d12f91SDave Airlie {
100146d12f91SDave Airlie 	switch (reflect) {
100246d12f91SDave Airlie 	case 0:
100346d12f91SDave Airlie 		break;
100446d12f91SDave Airlie 	case DRM_MODE_REFLECT_X:
100546d12f91SDave Airlie 		return PLANE_CTL_FLIP_HORIZONTAL;
100646d12f91SDave Airlie 	case DRM_MODE_REFLECT_Y:
100746d12f91SDave Airlie 	default:
100846d12f91SDave Airlie 		MISSING_CASE(reflect);
100946d12f91SDave Airlie 	}
101046d12f91SDave Airlie 
101146d12f91SDave Airlie 	return 0;
101246d12f91SDave Airlie }
101346d12f91SDave Airlie 
adlp_plane_ctl_arb_slots(const struct intel_plane_state * plane_state)10140b86952dSVille Syrjälä static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
10150b86952dSVille Syrjälä {
10160b86952dSVille Syrjälä 	const struct drm_framebuffer *fb = plane_state->hw.fb;
10170b86952dSVille Syrjälä 
10180b86952dSVille Syrjälä 	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
10190b86952dSVille Syrjälä 		switch (fb->format->cpp[0]) {
10200b86952dSVille Syrjälä 		case 2:
10210b86952dSVille Syrjälä 			return PLANE_CTL_ARB_SLOTS(1);
10220b86952dSVille Syrjälä 		default:
10230b86952dSVille Syrjälä 			return PLANE_CTL_ARB_SLOTS(0);
10240b86952dSVille Syrjälä 		}
10250b86952dSVille Syrjälä 	} else {
10260b86952dSVille Syrjälä 		switch (fb->format->cpp[0]) {
10270b86952dSVille Syrjälä 		case 8:
10280b86952dSVille Syrjälä 			return PLANE_CTL_ARB_SLOTS(3);
10290b86952dSVille Syrjälä 		case 4:
10300b86952dSVille Syrjälä 			return PLANE_CTL_ARB_SLOTS(1);
10310b86952dSVille Syrjälä 		default:
10320b86952dSVille Syrjälä 			return PLANE_CTL_ARB_SLOTS(0);
10330b86952dSVille Syrjälä 		}
10340b86952dSVille Syrjälä 	}
10350b86952dSVille Syrjälä }
10360b86952dSVille Syrjälä 
skl_plane_ctl_crtc(const struct intel_crtc_state * crtc_state)103746d12f91SDave Airlie static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
103846d12f91SDave Airlie {
103946d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
104046d12f91SDave Airlie 	u32 plane_ctl = 0;
104146d12f91SDave Airlie 
10422b5a4562SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 10)
104346d12f91SDave Airlie 		return plane_ctl;
104446d12f91SDave Airlie 
104546d12f91SDave Airlie 	if (crtc_state->gamma_enable)
104646d12f91SDave Airlie 		plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
104746d12f91SDave Airlie 
104846d12f91SDave Airlie 	if (crtc_state->csc_enable)
104946d12f91SDave Airlie 		plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
105046d12f91SDave Airlie 
105146d12f91SDave Airlie 	return plane_ctl;
105246d12f91SDave Airlie }
105346d12f91SDave Airlie 
skl_plane_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)105446d12f91SDave Airlie static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
105546d12f91SDave Airlie 			 const struct intel_plane_state *plane_state)
105646d12f91SDave Airlie {
105746d12f91SDave Airlie 	struct drm_i915_private *dev_priv =
105846d12f91SDave Airlie 		to_i915(plane_state->uapi.plane->dev);
105946d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
106046d12f91SDave Airlie 	unsigned int rotation = plane_state->hw.rotation;
106146d12f91SDave Airlie 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
106246d12f91SDave Airlie 	u32 plane_ctl;
106346d12f91SDave Airlie 
106446d12f91SDave Airlie 	plane_ctl = PLANE_CTL_ENABLE;
106546d12f91SDave Airlie 
1066ad314fecSVille Syrjälä 	if (DISPLAY_VER(dev_priv) < 10) {
106746d12f91SDave Airlie 		plane_ctl |= skl_plane_ctl_alpha(plane_state);
106846d12f91SDave Airlie 		plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
106946d12f91SDave Airlie 
107046d12f91SDave Airlie 		if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
107146d12f91SDave Airlie 			plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
107246d12f91SDave Airlie 
107346d12f91SDave Airlie 		if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
107446d12f91SDave Airlie 			plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
107546d12f91SDave Airlie 	}
107646d12f91SDave Airlie 
107746d12f91SDave Airlie 	plane_ctl |= skl_plane_ctl_format(fb->format->format);
107846d12f91SDave Airlie 	plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
107946d12f91SDave Airlie 	plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
108046d12f91SDave Airlie 
1081c988d2dcSLucas De Marchi 	if (DISPLAY_VER(dev_priv) >= 11)
1082c988d2dcSLucas De Marchi 		plane_ctl |= icl_plane_ctl_flip(rotation &
108346d12f91SDave Airlie 						DRM_MODE_REFLECT_MASK);
108446d12f91SDave Airlie 
108546d12f91SDave Airlie 	if (key->flags & I915_SET_COLORKEY_DESTINATION)
108646d12f91SDave Airlie 		plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
108746d12f91SDave Airlie 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
108846d12f91SDave Airlie 		plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
108946d12f91SDave Airlie 
10901d2b8fd9SJosé Roberto de Souza 	/* Wa_22012358565:adl-p */
10910b86952dSVille Syrjälä 	if (DISPLAY_VER(dev_priv) == 13)
10920b86952dSVille Syrjälä 		plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
10930b86952dSVille Syrjälä 
109446d12f91SDave Airlie 	return plane_ctl;
109546d12f91SDave Airlie }
109646d12f91SDave Airlie 
glk_plane_color_ctl_crtc(const struct intel_crtc_state * crtc_state)109746d12f91SDave Airlie static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
109846d12f91SDave Airlie {
109946d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
110046d12f91SDave Airlie 	u32 plane_color_ctl = 0;
110146d12f91SDave Airlie 
1102005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
110346d12f91SDave Airlie 		return plane_color_ctl;
110446d12f91SDave Airlie 
110546d12f91SDave Airlie 	if (crtc_state->gamma_enable)
110646d12f91SDave Airlie 		plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
110746d12f91SDave Airlie 
110846d12f91SDave Airlie 	if (crtc_state->csc_enable)
110946d12f91SDave Airlie 		plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
111046d12f91SDave Airlie 
111146d12f91SDave Airlie 	return plane_color_ctl;
111246d12f91SDave Airlie }
111346d12f91SDave Airlie 
glk_plane_color_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)111446d12f91SDave Airlie static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
111546d12f91SDave Airlie 			       const struct intel_plane_state *plane_state)
111646d12f91SDave Airlie {
111746d12f91SDave Airlie 	struct drm_i915_private *dev_priv =
111846d12f91SDave Airlie 		to_i915(plane_state->uapi.plane->dev);
111946d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
112046d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
112146d12f91SDave Airlie 	u32 plane_color_ctl = 0;
112246d12f91SDave Airlie 
112346d12f91SDave Airlie 	plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
112446d12f91SDave Airlie 	plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
112546d12f91SDave Airlie 
112646d12f91SDave Airlie 	if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
112746d12f91SDave Airlie 		switch (plane_state->hw.color_encoding) {
112846d12f91SDave Airlie 		case DRM_COLOR_YCBCR_BT709:
112946d12f91SDave Airlie 			plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
113046d12f91SDave Airlie 			break;
113146d12f91SDave Airlie 		case DRM_COLOR_YCBCR_BT2020:
113246d12f91SDave Airlie 			plane_color_ctl |=
113346d12f91SDave Airlie 				PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
113446d12f91SDave Airlie 			break;
113546d12f91SDave Airlie 		default:
113646d12f91SDave Airlie 			plane_color_ctl |=
113746d12f91SDave Airlie 				PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
113846d12f91SDave Airlie 		}
113946d12f91SDave Airlie 		if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
114046d12f91SDave Airlie 			plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
114146d12f91SDave Airlie 	} else if (fb->format->is_yuv) {
114246d12f91SDave Airlie 		plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
114346d12f91SDave Airlie 		if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
114446d12f91SDave Airlie 			plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
114546d12f91SDave Airlie 	}
114646d12f91SDave Airlie 
1147841f262eSVille Syrjälä 	if (plane_state->force_black)
1148841f262eSVille Syrjälä 		plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
1149841f262eSVille Syrjälä 
115046d12f91SDave Airlie 	return plane_color_ctl;
115146d12f91SDave Airlie }
115246d12f91SDave Airlie 
skl_surf_address(const struct intel_plane_state * plane_state,int color_plane)115333e7a975SVille Syrjälä static u32 skl_surf_address(const struct intel_plane_state *plane_state,
115433e7a975SVille Syrjälä 			    int color_plane)
115533e7a975SVille Syrjälä {
11565acbdcd1SJani Nikula 	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
115733e7a975SVille Syrjälä 	const struct drm_framebuffer *fb = plane_state->hw.fb;
115833e7a975SVille Syrjälä 	u32 offset = plane_state->view.color_plane[color_plane].offset;
115933e7a975SVille Syrjälä 
116033e7a975SVille Syrjälä 	if (intel_fb_uses_dpt(fb)) {
116192dff6c7SImre Deak 		/*
116292dff6c7SImre Deak 		 * The DPT object contains only one vma, so the VMA's offset
116392dff6c7SImre Deak 		 * within the DPT is always 0.
116492dff6c7SImre Deak 		 */
1165185b2488SJuha-Pekka Heikkila 		drm_WARN_ON(&i915->drm, plane_state->dpt_vma &&
11666dbd43dcSRodrigo Vivi 			    intel_dpt_offset(plane_state->dpt_vma));
11675acbdcd1SJani Nikula 		drm_WARN_ON(&i915->drm, offset & 0x1fffff);
116833e7a975SVille Syrjälä 		return offset >> 9;
116933e7a975SVille Syrjälä 	} else {
11705acbdcd1SJani Nikula 		drm_WARN_ON(&i915->drm, offset & 0xfff);
117133e7a975SVille Syrjälä 		return offset;
117233e7a975SVille Syrjälä 	}
117333e7a975SVille Syrjälä }
117433e7a975SVille Syrjälä 
skl_plane_surf(const struct intel_plane_state * plane_state,int color_plane)117550faf7a1SVille Syrjälä static u32 skl_plane_surf(const struct intel_plane_state *plane_state,
117650faf7a1SVille Syrjälä 			  int color_plane)
117750faf7a1SVille Syrjälä {
117850faf7a1SVille Syrjälä 	u32 plane_surf;
117950faf7a1SVille Syrjälä 
118050faf7a1SVille Syrjälä 	plane_surf = intel_plane_ggtt_offset(plane_state) +
118150faf7a1SVille Syrjälä 		skl_surf_address(plane_state, color_plane);
118250faf7a1SVille Syrjälä 
118350faf7a1SVille Syrjälä 	if (plane_state->decrypt)
118450faf7a1SVille Syrjälä 		plane_surf |= PLANE_SURF_DECRYPT;
118550faf7a1SVille Syrjälä 
118650faf7a1SVille Syrjälä 	return plane_surf;
118750faf7a1SVille Syrjälä }
118850faf7a1SVille Syrjälä 
skl_plane_aux_dist(const struct intel_plane_state * plane_state,int color_plane)1189366714b0SVille Syrjälä static u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state,
1190366714b0SVille Syrjälä 			      int color_plane)
1191366714b0SVille Syrjälä {
1192366714b0SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1193366714b0SVille Syrjälä 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1194366714b0SVille Syrjälä 	int aux_plane = skl_main_to_aux_plane(fb, color_plane);
1195366714b0SVille Syrjälä 	u32 aux_dist;
1196366714b0SVille Syrjälä 
1197366714b0SVille Syrjälä 	if (!aux_plane)
1198366714b0SVille Syrjälä 		return 0;
1199366714b0SVille Syrjälä 
1200366714b0SVille Syrjälä 	aux_dist = skl_surf_address(plane_state, aux_plane) -
1201366714b0SVille Syrjälä 		skl_surf_address(plane_state, color_plane);
1202366714b0SVille Syrjälä 
1203366714b0SVille Syrjälä 	if (DISPLAY_VER(i915) < 12)
1204366714b0SVille Syrjälä 		aux_dist |= PLANE_AUX_STRIDE(skl_plane_stride(plane_state, aux_plane));
1205366714b0SVille Syrjälä 
1206366714b0SVille Syrjälä 	return aux_dist;
1207366714b0SVille Syrjälä }
1208366714b0SVille Syrjälä 
skl_plane_keyval(const struct intel_plane_state * plane_state)12094682a6d9SVille Syrjälä static u32 skl_plane_keyval(const struct intel_plane_state *plane_state)
12104682a6d9SVille Syrjälä {
12114682a6d9SVille Syrjälä 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
12124682a6d9SVille Syrjälä 
12134682a6d9SVille Syrjälä 	return key->min_value;
12144682a6d9SVille Syrjälä }
12154682a6d9SVille Syrjälä 
skl_plane_keymax(const struct intel_plane_state * plane_state)12164682a6d9SVille Syrjälä static u32 skl_plane_keymax(const struct intel_plane_state *plane_state)
12174682a6d9SVille Syrjälä {
12184682a6d9SVille Syrjälä 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
12194682a6d9SVille Syrjälä 	u8 alpha = plane_state->hw.alpha >> 8;
12204682a6d9SVille Syrjälä 
12214682a6d9SVille Syrjälä 	return (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
12224682a6d9SVille Syrjälä }
12234682a6d9SVille Syrjälä 
skl_plane_keymsk(const struct intel_plane_state * plane_state)12244682a6d9SVille Syrjälä static u32 skl_plane_keymsk(const struct intel_plane_state *plane_state)
12254682a6d9SVille Syrjälä {
12264682a6d9SVille Syrjälä 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
12274682a6d9SVille Syrjälä 	u8 alpha = plane_state->hw.alpha >> 8;
12284682a6d9SVille Syrjälä 	u32 keymsk;
12294682a6d9SVille Syrjälä 
12304682a6d9SVille Syrjälä 	keymsk = key->channel_mask & 0x7ffffff;
12314682a6d9SVille Syrjälä 	if (alpha < 0xff)
12324682a6d9SVille Syrjälä 		keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
12334682a6d9SVille Syrjälä 
12344682a6d9SVille Syrjälä 	return keymsk;
12354682a6d9SVille Syrjälä }
12364682a6d9SVille Syrjälä 
icl_plane_csc_load_black(struct intel_plane * plane)123717dbbe7bSVille Syrjälä static void icl_plane_csc_load_black(struct intel_plane *plane)
12386eba56f6SAnshuman Gupta {
123917dbbe7bSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
124017dbbe7bSVille Syrjälä 	enum plane_id plane_id = plane->id;
124117dbbe7bSVille Syrjälä 	enum pipe pipe = plane->pipe;
12426eba56f6SAnshuman Gupta 
124317dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 0), 0);
124417dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 1), 0);
12456eba56f6SAnshuman Gupta 
124617dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 2), 0);
124717dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 3), 0);
12486eba56f6SAnshuman Gupta 
124917dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 4), 0);
125017dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 5), 0);
12516eba56f6SAnshuman Gupta 
125217dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0);
125317dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0);
125417dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0);
12556eba56f6SAnshuman Gupta 
125617dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0);
125717dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0);
125817dbbe7bSVille Syrjälä 	intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0);
12596eba56f6SAnshuman Gupta }
12606eba56f6SAnshuman Gupta 
icl_plane_color_plane(const struct intel_plane_state * plane_state)1261f8a005ebSVille Syrjälä static int icl_plane_color_plane(const struct intel_plane_state *plane_state)
1262fee07601SVille Syrjälä {
1263fee07601SVille Syrjälä 	/* Program the UV plane on planar master */
1264fee07601SVille Syrjälä 	if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1265fee07601SVille Syrjälä 		return 1;
1266fee07601SVille Syrjälä 	else
1267fee07601SVille Syrjälä 		return 0;
1268fee07601SVille Syrjälä }
1269fee07601SVille Syrjälä 
127046d12f91SDave Airlie static void
skl_plane_update_noarm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1271fee07601SVille Syrjälä skl_plane_update_noarm(struct intel_plane *plane,
127246d12f91SDave Airlie 		       const struct intel_crtc_state *crtc_state,
1273fee07601SVille Syrjälä 		       const struct intel_plane_state *plane_state)
127446d12f91SDave Airlie {
127546d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
127646d12f91SDave Airlie 	enum plane_id plane_id = plane->id;
127746d12f91SDave Airlie 	enum pipe pipe = plane->pipe;
1278f8a005ebSVille Syrjälä 	u32 stride = skl_plane_stride(plane_state, 0);
127946d12f91SDave Airlie 	int crtc_x = plane_state->uapi.dst.x1;
128046d12f91SDave Airlie 	int crtc_y = plane_state->uapi.dst.y1;
128146d12f91SDave Airlie 	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
128246d12f91SDave Airlie 	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
128346d12f91SDave Airlie 
128446d12f91SDave Airlie 	/* The scaler will handle the output position */
128546d12f91SDave Airlie 	if (plane_state->scaler_id >= 0) {
128646d12f91SDave Airlie 		crtc_x = 0;
128746d12f91SDave Airlie 		crtc_y = 0;
128846d12f91SDave Airlie 	}
128946d12f91SDave Airlie 
129012d7d858SVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id),
129112d7d858SVille Syrjälä 			  PLANE_STRIDE_(stride));
129246d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
129312d7d858SVille Syrjälä 			  PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
129446d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
129512d7d858SVille Syrjälä 			  PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
129646d12f91SDave Airlie 
129746d12f91SDave Airlie 	skl_write_plane_wm(plane, crtc_state);
1298890b6ec4SVille Syrjälä }
1299890b6ec4SVille Syrjälä 
1300890b6ec4SVille Syrjälä static void
skl_plane_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1301fee07601SVille Syrjälä skl_plane_update_arm(struct intel_plane *plane,
1302890b6ec4SVille Syrjälä 		     const struct intel_crtc_state *crtc_state,
1303fee07601SVille Syrjälä 		     const struct intel_plane_state *plane_state)
1304890b6ec4SVille Syrjälä {
1305890b6ec4SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1306890b6ec4SVille Syrjälä 	enum plane_id plane_id = plane->id;
1307890b6ec4SVille Syrjälä 	enum pipe pipe = plane->pipe;
1308f8a005ebSVille Syrjälä 	u32 x = plane_state->view.color_plane[0].x;
1309f8a005ebSVille Syrjälä 	u32 y = plane_state->view.color_plane[0].y;
1310f8a005ebSVille Syrjälä 	u32 plane_ctl, plane_color_ctl = 0;
1311890b6ec4SVille Syrjälä 
1312f8a005ebSVille Syrjälä 	plane_ctl = plane_state->ctl |
1313f8a005ebSVille Syrjälä 		skl_plane_ctl_crtc(crtc_state);
1314890b6ec4SVille Syrjälä 
1315b24d3614SVille Syrjälä 	/* see intel_plane_atomic_calc_changes() */
13162081c6aeSVille Syrjälä 	if (plane->need_async_flip_toggle_wa &&
1317b24d3614SVille Syrjälä 	    crtc_state->async_flip_planes & BIT(plane->id))
1318b24d3614SVille Syrjälä 		plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1319b24d3614SVille Syrjälä 
1320890b6ec4SVille Syrjälä 	if (DISPLAY_VER(dev_priv) >= 10)
1321890b6ec4SVille Syrjälä 		plane_color_ctl = plane_state->color_ctl |
1322890b6ec4SVille Syrjälä 			glk_plane_color_ctl_crtc(crtc_state);
1323890b6ec4SVille Syrjälä 
13244682a6d9SVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
13254682a6d9SVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
13264682a6d9SVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
132746d12f91SDave Airlie 
132846d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
132912d7d858SVille Syrjälä 			  PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
133046d12f91SDave Airlie 
1331366714b0SVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
1332f8a005ebSVille Syrjälä 			  skl_plane_aux_dist(plane_state, 0));
1333890b6ec4SVille Syrjälä 
133446d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
133512d7d858SVille Syrjälä 			  PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
133612d7d858SVille Syrjälä 			  PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
133746d12f91SDave Airlie 
1338890b6ec4SVille Syrjälä 	if (DISPLAY_VER(dev_priv) >= 10)
1339890b6ec4SVille Syrjälä 		intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
134046d12f91SDave Airlie 
134146d12f91SDave Airlie 	/*
13427c653e15SVille Syrjälä 	 * Enable the scaler before the plane so that we don't
13437c653e15SVille Syrjälä 	 * get a catastrophic underrun even if the two operations
13447c653e15SVille Syrjälä 	 * end up happening in two different frames.
1345890b6ec4SVille Syrjälä 	 *
1346890b6ec4SVille Syrjälä 	 * TODO: split into noarm+arm pair
13477c653e15SVille Syrjälä 	 */
13487c653e15SVille Syrjälä 	if (plane_state->scaler_id >= 0)
13497c653e15SVille Syrjälä 		skl_program_plane_scaler(plane, crtc_state, plane_state);
13507c653e15SVille Syrjälä 
13517c653e15SVille Syrjälä 	/*
135246d12f91SDave Airlie 	 * The control register self-arms if the plane was previously
135346d12f91SDave Airlie 	 * disabled. Try to make the plane enable atomic by writing
135446d12f91SDave Airlie 	 * the control register just before the surface register.
135546d12f91SDave Airlie 	 */
135646d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
135750faf7a1SVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1358f8a005ebSVille Syrjälä 			  skl_plane_surf(plane_state, 0));
1359f8a005ebSVille Syrjälä }
1360f8a005ebSVille Syrjälä 
icl_plane_update_sel_fetch_noarm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,int color_plane)1361b1f5279bSJouni Högander static void icl_plane_update_sel_fetch_noarm(struct intel_plane *plane,
1362b1f5279bSJouni Högander 					     const struct intel_crtc_state *crtc_state,
1363b1f5279bSJouni Högander 					     const struct intel_plane_state *plane_state,
1364b1f5279bSJouni Högander 					     int color_plane)
1365b1f5279bSJouni Högander {
1366b1f5279bSJouni Högander 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
1367b1f5279bSJouni Högander 	enum pipe pipe = plane->pipe;
1368b1f5279bSJouni Högander 	const struct drm_rect *clip;
1369b1f5279bSJouni Högander 	u32 val;
1370b1f5279bSJouni Högander 	int x, y;
1371b1f5279bSJouni Högander 
1372b1f5279bSJouni Högander 	if (!crtc_state->enable_psr2_sel_fetch)
1373b1f5279bSJouni Högander 		return;
1374b1f5279bSJouni Högander 
1375b1f5279bSJouni Högander 	clip = &plane_state->psr2_sel_fetch_area;
1376b1f5279bSJouni Högander 
137716b65af8SJouni Högander 	if (crtc_state->enable_psr2_su_region_et)
137816b65af8SJouni Högander 		y = max(0, plane_state->uapi.dst.y1 - crtc_state->psr2_su_area.y1);
137916b65af8SJouni Högander 	else
138016b65af8SJouni Högander 		y = (clip->y1 + plane_state->uapi.dst.y1);
138116b65af8SJouni Högander 	val = y << 16;
1382b1f5279bSJouni Högander 	val |= plane_state->uapi.dst.x1;
13830ff7639bSVille Syrjälä 	intel_de_write_fw(i915, SEL_FETCH_PLANE_POS(pipe, plane->id), val);
1384b1f5279bSJouni Högander 
1385b1f5279bSJouni Högander 	x = plane_state->view.color_plane[color_plane].x;
1386b1f5279bSJouni Högander 
1387b1f5279bSJouni Högander 	/*
1388b1f5279bSJouni Högander 	 * From Bspec: UV surface Start Y Position = half of Y plane Y
1389b1f5279bSJouni Högander 	 * start position.
1390b1f5279bSJouni Högander 	 */
1391b1f5279bSJouni Högander 	if (!color_plane)
1392b1f5279bSJouni Högander 		y = plane_state->view.color_plane[color_plane].y + clip->y1;
1393b1f5279bSJouni Högander 	else
1394b1f5279bSJouni Högander 		y = plane_state->view.color_plane[color_plane].y + clip->y1 / 2;
1395b1f5279bSJouni Högander 
1396b1f5279bSJouni Högander 	val = y << 16 | x;
1397b1f5279bSJouni Högander 
13980ff7639bSVille Syrjälä 	intel_de_write_fw(i915, SEL_FETCH_PLANE_OFFSET(pipe, plane->id),
1399b1f5279bSJouni Högander 			  val);
1400b1f5279bSJouni Högander 
1401b1f5279bSJouni Högander 	/* Sizes are 0 based */
1402b1f5279bSJouni Högander 	val = (drm_rect_height(clip) - 1) << 16;
1403b1f5279bSJouni Högander 	val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1;
14040ff7639bSVille Syrjälä 	intel_de_write_fw(i915, SEL_FETCH_PLANE_SIZE(pipe, plane->id), val);
1405b1f5279bSJouni Högander }
1406b1f5279bSJouni Högander 
1407f8a005ebSVille Syrjälä static void
icl_plane_update_noarm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1408f8a005ebSVille Syrjälä icl_plane_update_noarm(struct intel_plane *plane,
1409f8a005ebSVille Syrjälä 		       const struct intel_crtc_state *crtc_state,
1410f8a005ebSVille Syrjälä 		       const struct intel_plane_state *plane_state)
1411f8a005ebSVille Syrjälä {
1412f8a005ebSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1413f8a005ebSVille Syrjälä 	enum plane_id plane_id = plane->id;
1414f8a005ebSVille Syrjälä 	enum pipe pipe = plane->pipe;
1415f8a005ebSVille Syrjälä 	int color_plane = icl_plane_color_plane(plane_state);
1416f8a005ebSVille Syrjälä 	u32 stride = skl_plane_stride(plane_state, color_plane);
1417f8a005ebSVille Syrjälä 	const struct drm_framebuffer *fb = plane_state->hw.fb;
1418f8a005ebSVille Syrjälä 	int crtc_x = plane_state->uapi.dst.x1;
1419f8a005ebSVille Syrjälä 	int crtc_y = plane_state->uapi.dst.y1;
1420f8a005ebSVille Syrjälä 	int x = plane_state->view.color_plane[color_plane].x;
1421f8a005ebSVille Syrjälä 	int y = plane_state->view.color_plane[color_plane].y;
1422f8a005ebSVille Syrjälä 	int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1423f8a005ebSVille Syrjälä 	int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1424f8a005ebSVille Syrjälä 	u32 plane_color_ctl;
1425f8a005ebSVille Syrjälä 
1426f8a005ebSVille Syrjälä 	plane_color_ctl = plane_state->color_ctl |
1427f8a005ebSVille Syrjälä 		glk_plane_color_ctl_crtc(crtc_state);
1428f8a005ebSVille Syrjälä 
1429f8a005ebSVille Syrjälä 	/* The scaler will handle the output position */
1430f8a005ebSVille Syrjälä 	if (plane_state->scaler_id >= 0) {
1431f8a005ebSVille Syrjälä 		crtc_x = 0;
1432f8a005ebSVille Syrjälä 		crtc_y = 0;
1433f8a005ebSVille Syrjälä 	}
1434f8a005ebSVille Syrjälä 
1435f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id),
1436f8a005ebSVille Syrjälä 			  PLANE_STRIDE_(stride));
1437f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
1438f8a005ebSVille Syrjälä 			  PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1439f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
1440f8a005ebSVille Syrjälä 			  PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1441f8a005ebSVille Syrjälä 
1442f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
1443f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
1444f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
1445f8a005ebSVille Syrjälä 
1446f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
1447f8a005ebSVille Syrjälä 			  PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1448f8a005ebSVille Syrjälä 
1449f8a005ebSVille Syrjälä 	if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) {
1450f8a005ebSVille Syrjälä 		intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 0),
1451f8a005ebSVille Syrjälä 				  lower_32_bits(plane_state->ccval));
1452f8a005ebSVille Syrjälä 		intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 1),
1453f8a005ebSVille Syrjälä 				  upper_32_bits(plane_state->ccval));
1454f8a005ebSVille Syrjälä 	}
1455f8a005ebSVille Syrjälä 
1456680025dcSJuha-Pekka Heikkilä 	/* FLAT CCS doesn't need to program AUX_DIST */
14578ee35345SMatt Roper 	if (!HAS_FLAT_CCS(dev_priv) && DISPLAY_VER(dev_priv) < 20)
1458f8a005ebSVille Syrjälä 		intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
1459f8a005ebSVille Syrjälä 				  skl_plane_aux_dist(plane_state, color_plane));
1460f8a005ebSVille Syrjälä 
1461f8a005ebSVille Syrjälä 	if (icl_is_hdr_plane(dev_priv, plane_id))
1462f8a005ebSVille Syrjälä 		intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
1463f8a005ebSVille Syrjälä 				  plane_state->cus_ctl);
1464f8a005ebSVille Syrjälä 
1465f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
1466f8a005ebSVille Syrjälä 
1467f8a005ebSVille Syrjälä 	if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
1468f8a005ebSVille Syrjälä 		icl_program_input_csc(plane, crtc_state, plane_state);
1469f8a005ebSVille Syrjälä 
1470f8a005ebSVille Syrjälä 	skl_write_plane_wm(plane, crtc_state);
1471f8a005ebSVille Syrjälä 
1472f8a005ebSVille Syrjälä 	/*
1473f8a005ebSVille Syrjälä 	 * FIXME: pxp session invalidation can hit any time even at time of commit
1474f8a005ebSVille Syrjälä 	 * or after the commit, display content will be garbage.
1475f8a005ebSVille Syrjälä 	 */
1476f8a005ebSVille Syrjälä 	if (plane_state->force_black)
1477f8a005ebSVille Syrjälä 		icl_plane_csc_load_black(plane);
1478f8a005ebSVille Syrjälä 
1479b1f5279bSJouni Högander 	icl_plane_update_sel_fetch_noarm(plane, crtc_state, plane_state, color_plane);
1480b1f5279bSJouni Högander }
1481b1f5279bSJouni Högander 
icl_plane_update_sel_fetch_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1482b1f5279bSJouni Högander static void icl_plane_update_sel_fetch_arm(struct intel_plane *plane,
1483b1f5279bSJouni Högander 					   const struct intel_crtc_state *crtc_state,
1484b1f5279bSJouni Högander 					   const struct intel_plane_state *plane_state)
1485b1f5279bSJouni Högander {
1486b1f5279bSJouni Högander 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
1487b1f5279bSJouni Högander 	enum pipe pipe = plane->pipe;
1488b1f5279bSJouni Högander 
1489b1f5279bSJouni Högander 	if (!crtc_state->enable_psr2_sel_fetch)
1490b1f5279bSJouni Högander 		return;
1491b1f5279bSJouni Högander 
1492a4f477e6SJouni Högander 	if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
14930ff7639bSVille Syrjälä 		intel_de_write_fw(i915, SEL_FETCH_PLANE_CTL(pipe, plane->id),
14940ff7639bSVille Syrjälä 				  SEL_FETCH_PLANE_CTL_ENABLE);
1495a4f477e6SJouni Högander 	else
1496a4f477e6SJouni Högander 		icl_plane_disable_sel_fetch_arm(plane, crtc_state);
1497f8a005ebSVille Syrjälä }
1498f8a005ebSVille Syrjälä 
1499f8a005ebSVille Syrjälä static void
icl_plane_update_arm(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)1500f8a005ebSVille Syrjälä icl_plane_update_arm(struct intel_plane *plane,
1501f8a005ebSVille Syrjälä 		     const struct intel_crtc_state *crtc_state,
1502f8a005ebSVille Syrjälä 		     const struct intel_plane_state *plane_state)
1503f8a005ebSVille Syrjälä {
1504f8a005ebSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1505f8a005ebSVille Syrjälä 	enum plane_id plane_id = plane->id;
1506f8a005ebSVille Syrjälä 	enum pipe pipe = plane->pipe;
1507f8a005ebSVille Syrjälä 	int color_plane = icl_plane_color_plane(plane_state);
1508f8a005ebSVille Syrjälä 	u32 plane_ctl;
1509f8a005ebSVille Syrjälä 
1510f8a005ebSVille Syrjälä 	plane_ctl = plane_state->ctl |
1511f8a005ebSVille Syrjälä 		skl_plane_ctl_crtc(crtc_state);
1512f8a005ebSVille Syrjälä 
1513f8a005ebSVille Syrjälä 	/*
1514f8a005ebSVille Syrjälä 	 * Enable the scaler before the plane so that we don't
1515f8a005ebSVille Syrjälä 	 * get a catastrophic underrun even if the two operations
1516f8a005ebSVille Syrjälä 	 * end up happening in two different frames.
1517f8a005ebSVille Syrjälä 	 *
1518f8a005ebSVille Syrjälä 	 * TODO: split into noarm+arm pair
1519f8a005ebSVille Syrjälä 	 */
1520f8a005ebSVille Syrjälä 	if (plane_state->scaler_id >= 0)
1521f8a005ebSVille Syrjälä 		skl_program_plane_scaler(plane, crtc_state, plane_state);
1522f8a005ebSVille Syrjälä 
1523b1f5279bSJouni Högander 	icl_plane_update_sel_fetch_arm(plane, crtc_state, plane_state);
1524c22cf04cSJouni Högander 
1525f8a005ebSVille Syrjälä 	/*
1526f8a005ebSVille Syrjälä 	 * The control register self-arms if the plane was previously
1527f8a005ebSVille Syrjälä 	 * disabled. Try to make the plane enable atomic by writing
1528f8a005ebSVille Syrjälä 	 * the control register just before the surface register.
1529f8a005ebSVille Syrjälä 	 */
1530f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1531f8a005ebSVille Syrjälä 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
153250faf7a1SVille Syrjälä 			  skl_plane_surf(plane_state, color_plane));
153346d12f91SDave Airlie }
153446d12f91SDave Airlie 
153546d12f91SDave Airlie static void
skl_plane_async_flip(struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,bool async_flip)153646d12f91SDave Airlie skl_plane_async_flip(struct intel_plane *plane,
153746d12f91SDave Airlie 		     const struct intel_crtc_state *crtc_state,
153846d12f91SDave Airlie 		     const struct intel_plane_state *plane_state,
153946d12f91SDave Airlie 		     bool async_flip)
154046d12f91SDave Airlie {
154146d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
154246d12f91SDave Airlie 	enum plane_id plane_id = plane->id;
154346d12f91SDave Airlie 	enum pipe pipe = plane->pipe;
154446d12f91SDave Airlie 	u32 plane_ctl = plane_state->ctl;
154546d12f91SDave Airlie 
154646d12f91SDave Airlie 	plane_ctl |= skl_plane_ctl_crtc(crtc_state);
154746d12f91SDave Airlie 
154846d12f91SDave Airlie 	if (async_flip)
154946d12f91SDave Airlie 		plane_ctl |= PLANE_CTL_ASYNC_FLIP;
155046d12f91SDave Airlie 
155146d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
155246d12f91SDave Airlie 	intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
155350faf7a1SVille Syrjälä 			  skl_plane_surf(plane_state, 0));
155446d12f91SDave Airlie }
155546d12f91SDave Airlie 
intel_format_is_p01x(u32 format)155646d12f91SDave Airlie static bool intel_format_is_p01x(u32 format)
155746d12f91SDave Airlie {
155846d12f91SDave Airlie 	switch (format) {
155946d12f91SDave Airlie 	case DRM_FORMAT_P010:
156046d12f91SDave Airlie 	case DRM_FORMAT_P012:
156146d12f91SDave Airlie 	case DRM_FORMAT_P016:
156246d12f91SDave Airlie 		return true;
156346d12f91SDave Airlie 	default:
156446d12f91SDave Airlie 		return false;
156546d12f91SDave Airlie 	}
156646d12f91SDave Airlie }
156746d12f91SDave Airlie 
skl_plane_check_fb(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)156846d12f91SDave Airlie static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
156946d12f91SDave Airlie 			      const struct intel_plane_state *plane_state)
157046d12f91SDave Airlie {
157146d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
157246d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
157346d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
157446d12f91SDave Airlie 	unsigned int rotation = plane_state->hw.rotation;
157546d12f91SDave Airlie 
157646d12f91SDave Airlie 	if (!fb)
157746d12f91SDave Airlie 		return 0;
157846d12f91SDave Airlie 
157946d12f91SDave Airlie 	if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1580e359c47bSImre Deak 	    intel_fb_is_ccs_modifier(fb->modifier)) {
158146d12f91SDave Airlie 		drm_dbg_kms(&dev_priv->drm,
158246d12f91SDave Airlie 			    "RC support only with 0/180 degree rotation (%x)\n",
158346d12f91SDave Airlie 			    rotation);
158446d12f91SDave Airlie 		return -EINVAL;
158546d12f91SDave Airlie 	}
158646d12f91SDave Airlie 
158746d12f91SDave Airlie 	if (rotation & DRM_MODE_REFLECT_X &&
158846d12f91SDave Airlie 	    fb->modifier == DRM_FORMAT_MOD_LINEAR) {
158946d12f91SDave Airlie 		drm_dbg_kms(&dev_priv->drm,
159046d12f91SDave Airlie 			    "horizontal flip is not supported with linear surface formats\n");
159146d12f91SDave Airlie 		return -EINVAL;
159246d12f91SDave Airlie 	}
159346d12f91SDave Airlie 
1594*ffafd126SJuha-Pekka Heikkila 	/*
1595*ffafd126SJuha-Pekka Heikkila 	 * Display20 onward tile4 hflip is not supported
1596*ffafd126SJuha-Pekka Heikkila 	 */
1597*ffafd126SJuha-Pekka Heikkila 	if (rotation & DRM_MODE_REFLECT_X &&
1598*ffafd126SJuha-Pekka Heikkila 	    intel_fb_is_tile4_modifier(fb->modifier) &&
1599*ffafd126SJuha-Pekka Heikkila 	    DISPLAY_VER(dev_priv) >= 20) {
1600*ffafd126SJuha-Pekka Heikkila 		drm_dbg_kms(&dev_priv->drm,
1601*ffafd126SJuha-Pekka Heikkila 			    "horizontal flip is not supported with tile4 surface formats\n");
1602*ffafd126SJuha-Pekka Heikkila 		return -EINVAL;
1603*ffafd126SJuha-Pekka Heikkila 	}
1604*ffafd126SJuha-Pekka Heikkila 
160546d12f91SDave Airlie 	if (drm_rotation_90_or_270(rotation)) {
1606d3b4aa43SImre Deak 		if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
160746d12f91SDave Airlie 			drm_dbg_kms(&dev_priv->drm,
160846d12f91SDave Airlie 				    "Y/Yf tiling required for 90/270!\n");
160946d12f91SDave Airlie 			return -EINVAL;
161046d12f91SDave Airlie 		}
161146d12f91SDave Airlie 
161246d12f91SDave Airlie 		/*
161346d12f91SDave Airlie 		 * 90/270 is not allowed with RGB64 16:16:16:16 and
161446d12f91SDave Airlie 		 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
161546d12f91SDave Airlie 		 */
161646d12f91SDave Airlie 		switch (fb->format->format) {
161746d12f91SDave Airlie 		case DRM_FORMAT_RGB565:
1618005e9537SMatt Roper 			if (DISPLAY_VER(dev_priv) >= 11)
161946d12f91SDave Airlie 				break;
162046d12f91SDave Airlie 			fallthrough;
162146d12f91SDave Airlie 		case DRM_FORMAT_C8:
162246d12f91SDave Airlie 		case DRM_FORMAT_XRGB16161616F:
162346d12f91SDave Airlie 		case DRM_FORMAT_XBGR16161616F:
162446d12f91SDave Airlie 		case DRM_FORMAT_ARGB16161616F:
162546d12f91SDave Airlie 		case DRM_FORMAT_ABGR16161616F:
162646d12f91SDave Airlie 		case DRM_FORMAT_Y210:
162746d12f91SDave Airlie 		case DRM_FORMAT_Y212:
162846d12f91SDave Airlie 		case DRM_FORMAT_Y216:
162946d12f91SDave Airlie 		case DRM_FORMAT_XVYU12_16161616:
163046d12f91SDave Airlie 		case DRM_FORMAT_XVYU16161616:
163146d12f91SDave Airlie 			drm_dbg_kms(&dev_priv->drm,
1632e3c2f187SStephen Rothwell 				    "Unsupported pixel format %p4cc for 90/270!\n",
1633e3c2f187SStephen Rothwell 				    &fb->format->format);
163446d12f91SDave Airlie 			return -EINVAL;
163546d12f91SDave Airlie 		default:
163646d12f91SDave Airlie 			break;
163746d12f91SDave Airlie 		}
163846d12f91SDave Airlie 	}
163946d12f91SDave Airlie 
164046d12f91SDave Airlie 	/* Y-tiling is not supported in IF-ID Interlace mode */
164146d12f91SDave Airlie 	if (crtc_state->hw.enable &&
164246d12f91SDave Airlie 	    crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1643d89357deSImre Deak 	    fb->modifier != DRM_FORMAT_MOD_LINEAR &&
1644d89357deSImre Deak 	    fb->modifier != I915_FORMAT_MOD_X_TILED) {
164546d12f91SDave Airlie 		drm_dbg_kms(&dev_priv->drm,
164646d12f91SDave Airlie 			    "Y/Yf tiling not supported in IF-ID mode\n");
164746d12f91SDave Airlie 		return -EINVAL;
164846d12f91SDave Airlie 	}
164946d12f91SDave Airlie 
165046d12f91SDave Airlie 	/* Wa_1606054188:tgl,adl-s */
165146d12f91SDave Airlie 	if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
165246d12f91SDave Airlie 	    plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
165346d12f91SDave Airlie 	    intel_format_is_p01x(fb->format->format)) {
165446d12f91SDave Airlie 		drm_dbg_kms(&dev_priv->drm,
165546d12f91SDave Airlie 			    "Source color keying not supported with P01x formats\n");
165646d12f91SDave Airlie 		return -EINVAL;
165746d12f91SDave Airlie 	}
165846d12f91SDave Airlie 
165946d12f91SDave Airlie 	return 0;
166046d12f91SDave Airlie }
166146d12f91SDave Airlie 
skl_plane_check_dst_coordinates(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)166246d12f91SDave Airlie static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
166346d12f91SDave Airlie 					   const struct intel_plane_state *plane_state)
166446d12f91SDave Airlie {
166546d12f91SDave Airlie 	struct drm_i915_private *dev_priv =
166646d12f91SDave Airlie 		to_i915(plane_state->uapi.plane->dev);
166746d12f91SDave Airlie 	int crtc_x = plane_state->uapi.dst.x1;
166846d12f91SDave Airlie 	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
166926111a16SVille Syrjälä 	int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
167046d12f91SDave Airlie 
167146d12f91SDave Airlie 	/*
1672244dba4cSLucas De Marchi 	 * Display WA #1175: glk
167346d12f91SDave Airlie 	 * Planes other than the cursor may cause FIFO underflow and display
167446d12f91SDave Airlie 	 * corruption if starting less than 4 pixels from the right edge of
167546d12f91SDave Airlie 	 * the screen.
167646d12f91SDave Airlie 	 * Besides the above WA fix the similar problem, where planes other
167746d12f91SDave Airlie 	 * than the cursor ending less than 4 pixels from the left edge of the
167846d12f91SDave Airlie 	 * screen may cause FIFO underflow and display corruption.
167946d12f91SDave Airlie 	 */
168093e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 10 &&
168146d12f91SDave Airlie 	    (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
168246d12f91SDave Airlie 		drm_dbg_kms(&dev_priv->drm,
168346d12f91SDave Airlie 			    "requested plane X %s position %d invalid (valid range %d-%d)\n",
168446d12f91SDave Airlie 			    crtc_x + crtc_w < 4 ? "end" : "start",
168546d12f91SDave Airlie 			    crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
168646d12f91SDave Airlie 			    4, pipe_src_w - 4);
168746d12f91SDave Airlie 		return -ERANGE;
168846d12f91SDave Airlie 	}
168946d12f91SDave Airlie 
169046d12f91SDave Airlie 	return 0;
169146d12f91SDave Airlie }
169246d12f91SDave Airlie 
skl_plane_check_nv12_rotation(const struct intel_plane_state * plane_state)169346d12f91SDave Airlie static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
169446d12f91SDave Airlie {
16955acbdcd1SJani Nikula 	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
169646d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
169746d12f91SDave Airlie 	unsigned int rotation = plane_state->hw.rotation;
169846d12f91SDave Airlie 	int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
169946d12f91SDave Airlie 
170046d12f91SDave Airlie 	/* Display WA #1106 */
170146d12f91SDave Airlie 	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
170246d12f91SDave Airlie 	    src_w & 3 &&
170346d12f91SDave Airlie 	    (rotation == DRM_MODE_ROTATE_270 ||
170446d12f91SDave Airlie 	     rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
17055acbdcd1SJani Nikula 		drm_dbg_kms(&i915->drm, "src width must be multiple of 4 for rotated planar YUV\n");
170646d12f91SDave Airlie 		return -EINVAL;
170746d12f91SDave Airlie 	}
170846d12f91SDave Airlie 
170946d12f91SDave Airlie 	return 0;
171046d12f91SDave Airlie }
171146d12f91SDave Airlie 
skl_plane_max_scale(struct drm_i915_private * dev_priv,const struct drm_framebuffer * fb)171246d12f91SDave Airlie static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
171346d12f91SDave Airlie 			       const struct drm_framebuffer *fb)
171446d12f91SDave Airlie {
171546d12f91SDave Airlie 	/*
171646d12f91SDave Airlie 	 * We don't yet know the final source width nor
171746d12f91SDave Airlie 	 * whether we can use the HQ scaler mode. Assume
171846d12f91SDave Airlie 	 * the best case.
171946d12f91SDave Airlie 	 * FIXME need to properly check this later.
172046d12f91SDave Airlie 	 */
17212b5a4562SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 10 ||
172246d12f91SDave Airlie 	    !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
172346d12f91SDave Airlie 		return 0x30000 - 1;
172446d12f91SDave Airlie 	else
172546d12f91SDave Airlie 		return 0x20000 - 1;
172646d12f91SDave Airlie }
172746d12f91SDave Airlie 
intel_plane_min_width(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)172846d12f91SDave Airlie static int intel_plane_min_width(struct intel_plane *plane,
172946d12f91SDave Airlie 				 const struct drm_framebuffer *fb,
173046d12f91SDave Airlie 				 int color_plane,
173146d12f91SDave Airlie 				 unsigned int rotation)
173246d12f91SDave Airlie {
173346d12f91SDave Airlie 	if (plane->min_width)
173446d12f91SDave Airlie 		return plane->min_width(fb, color_plane, rotation);
173546d12f91SDave Airlie 	else
173646d12f91SDave Airlie 		return 1;
173746d12f91SDave Airlie }
173846d12f91SDave Airlie 
intel_plane_max_width(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)173946d12f91SDave Airlie static int intel_plane_max_width(struct intel_plane *plane,
174046d12f91SDave Airlie 				 const struct drm_framebuffer *fb,
174146d12f91SDave Airlie 				 int color_plane,
174246d12f91SDave Airlie 				 unsigned int rotation)
174346d12f91SDave Airlie {
174446d12f91SDave Airlie 	if (plane->max_width)
174546d12f91SDave Airlie 		return plane->max_width(fb, color_plane, rotation);
174646d12f91SDave Airlie 	else
174746d12f91SDave Airlie 		return INT_MAX;
174846d12f91SDave Airlie }
174946d12f91SDave Airlie 
intel_plane_max_height(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane,unsigned int rotation)175046d12f91SDave Airlie static int intel_plane_max_height(struct intel_plane *plane,
175146d12f91SDave Airlie 				  const struct drm_framebuffer *fb,
175246d12f91SDave Airlie 				  int color_plane,
175346d12f91SDave Airlie 				  unsigned int rotation)
175446d12f91SDave Airlie {
175546d12f91SDave Airlie 	if (plane->max_height)
175646d12f91SDave Airlie 		return plane->max_height(fb, color_plane, rotation);
175746d12f91SDave Airlie 	else
175846d12f91SDave Airlie 		return INT_MAX;
175946d12f91SDave Airlie }
176046d12f91SDave Airlie 
176146d12f91SDave Airlie static bool
skl_check_main_ccs_coordinates(struct intel_plane_state * plane_state,int main_x,int main_y,u32 main_offset,int ccs_plane)176246d12f91SDave Airlie skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
176346d12f91SDave Airlie 			       int main_x, int main_y, u32 main_offset,
176446d12f91SDave Airlie 			       int ccs_plane)
176546d12f91SDave Airlie {
1766195b7a0dSVille Syrjälä 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
176746d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
176861169987SImre Deak 	int aux_x = plane_state->view.color_plane[ccs_plane].x;
176961169987SImre Deak 	int aux_y = plane_state->view.color_plane[ccs_plane].y;
177061169987SImre Deak 	u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1771195b7a0dSVille Syrjälä 	unsigned int alignment = plane->min_alignment(plane, fb, ccs_plane);
177246d12f91SDave Airlie 	int hsub;
177346d12f91SDave Airlie 	int vsub;
177446d12f91SDave Airlie 
177546d12f91SDave Airlie 	intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
177646d12f91SDave Airlie 	while (aux_offset >= main_offset && aux_y <= main_y) {
177746d12f91SDave Airlie 		int x, y;
177846d12f91SDave Airlie 
177946d12f91SDave Airlie 		if (aux_x == main_x && aux_y == main_y)
178046d12f91SDave Airlie 			break;
178146d12f91SDave Airlie 
178246d12f91SDave Airlie 		if (aux_offset == 0)
178346d12f91SDave Airlie 			break;
178446d12f91SDave Airlie 
178546d12f91SDave Airlie 		x = aux_x / hsub;
178646d12f91SDave Airlie 		y = aux_y / vsub;
178746d12f91SDave Airlie 		aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
178846d12f91SDave Airlie 							       plane_state,
178946d12f91SDave Airlie 							       ccs_plane,
179046d12f91SDave Airlie 							       aux_offset,
179156ac367dSVille Syrjälä 							       aux_offset - alignment);
179246d12f91SDave Airlie 		aux_x = x * hsub + aux_x % hsub;
179346d12f91SDave Airlie 		aux_y = y * vsub + aux_y % vsub;
179446d12f91SDave Airlie 	}
179546d12f91SDave Airlie 
179646d12f91SDave Airlie 	if (aux_x != main_x || aux_y != main_y)
179746d12f91SDave Airlie 		return false;
179846d12f91SDave Airlie 
179961169987SImre Deak 	plane_state->view.color_plane[ccs_plane].offset = aux_offset;
180061169987SImre Deak 	plane_state->view.color_plane[ccs_plane].x = aux_x;
180161169987SImre Deak 	plane_state->view.color_plane[ccs_plane].y = aux_y;
180246d12f91SDave Airlie 
180346d12f91SDave Airlie 	return true;
180446d12f91SDave Airlie }
180546d12f91SDave Airlie 
180646d12f91SDave Airlie 
skl_calc_main_surface_offset(const struct intel_plane_state * plane_state,int * x,int * y,u32 * offset)180746d12f91SDave Airlie int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
180846d12f91SDave Airlie 				 int *x, int *y, u32 *offset)
180946d12f91SDave Airlie {
181046d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
181146d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
181246d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
181356ac367dSVille Syrjälä 	int aux_plane = skl_main_to_aux_plane(fb, 0);
181456ac367dSVille Syrjälä 	u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
1815195b7a0dSVille Syrjälä 	unsigned int alignment = plane->min_alignment(plane, fb, 0);
181656ac367dSVille Syrjälä 	int w = drm_rect_width(&plane_state->uapi.src) >> 16;
181746d12f91SDave Airlie 
181846d12f91SDave Airlie 	intel_add_fb_offsets(x, y, plane_state, 0);
181946d12f91SDave Airlie 	*offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
182046d12f91SDave Airlie 	if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
182146d12f91SDave Airlie 		return -EINVAL;
182246d12f91SDave Airlie 
182346d12f91SDave Airlie 	/*
182446d12f91SDave Airlie 	 * AUX surface offset is specified as the distance from the
182546d12f91SDave Airlie 	 * main surface offset, and it must be non-negative. Make
182646d12f91SDave Airlie 	 * sure that is what we will get.
182746d12f91SDave Airlie 	 */
182846d12f91SDave Airlie 	if (aux_plane && *offset > aux_offset)
182946d12f91SDave Airlie 		*offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
183046d12f91SDave Airlie 							    *offset,
183146d12f91SDave Airlie 							    aux_offset & ~(alignment - 1));
183246d12f91SDave Airlie 
183346d12f91SDave Airlie 	/*
183446d12f91SDave Airlie 	 * When using an X-tiled surface, the plane blows up
183546d12f91SDave Airlie 	 * if the x offset + width exceed the stride.
183646d12f91SDave Airlie 	 *
183746d12f91SDave Airlie 	 * TODO: linear and Y-tiled seem fine, Yf untested,
183846d12f91SDave Airlie 	 */
183946d12f91SDave Airlie 	if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
184046d12f91SDave Airlie 		int cpp = fb->format->cpp[0];
184146d12f91SDave Airlie 
1842be6c1dd5SImre Deak 		while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
184346d12f91SDave Airlie 			if (*offset == 0) {
184446d12f91SDave Airlie 				drm_dbg_kms(&dev_priv->drm,
184546d12f91SDave Airlie 					    "Unable to find suitable display surface offset due to X-tiling\n");
184646d12f91SDave Airlie 				return -EINVAL;
184746d12f91SDave Airlie 			}
184846d12f91SDave Airlie 
184946d12f91SDave Airlie 			*offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
185046d12f91SDave Airlie 								    *offset,
185146d12f91SDave Airlie 								    *offset - alignment);
185246d12f91SDave Airlie 		}
185346d12f91SDave Airlie 	}
185446d12f91SDave Airlie 
185546d12f91SDave Airlie 	return 0;
185646d12f91SDave Airlie }
185746d12f91SDave Airlie 
skl_check_main_surface(struct intel_plane_state * plane_state)185846d12f91SDave Airlie static int skl_check_main_surface(struct intel_plane_state *plane_state)
185946d12f91SDave Airlie {
186046d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
186146d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
186246d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
186356ac367dSVille Syrjälä 	unsigned int rotation = plane_state->hw.rotation;
186446d12f91SDave Airlie 	int x = plane_state->uapi.src.x1 >> 16;
186546d12f91SDave Airlie 	int y = plane_state->uapi.src.y1 >> 16;
186656ac367dSVille Syrjälä 	int w = drm_rect_width(&plane_state->uapi.src) >> 16;
186756ac367dSVille Syrjälä 	int h = drm_rect_height(&plane_state->uapi.src) >> 16;
186856ac367dSVille Syrjälä 	int min_width = intel_plane_min_width(plane, fb, 0, rotation);
186956ac367dSVille Syrjälä 	int max_width = intel_plane_max_width(plane, fb, 0, rotation);
187056ac367dSVille Syrjälä 	int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1871195b7a0dSVille Syrjälä 	unsigned int alignment = plane->min_alignment(plane, fb, 0);
187256ac367dSVille Syrjälä 	int aux_plane = skl_main_to_aux_plane(fb, 0);
187346d12f91SDave Airlie 	u32 offset;
187446d12f91SDave Airlie 	int ret;
187546d12f91SDave Airlie 
18760fe76b19SDrew Davenport 	if (w > max_width || w < min_width || h > max_height || h < 1) {
187746d12f91SDave Airlie 		drm_dbg_kms(&dev_priv->drm,
187846d12f91SDave Airlie 			    "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
187946d12f91SDave Airlie 			    w, h, min_width, max_width, max_height);
188046d12f91SDave Airlie 		return -EINVAL;
188146d12f91SDave Airlie 	}
188246d12f91SDave Airlie 
188346d12f91SDave Airlie 	ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
188446d12f91SDave Airlie 	if (ret)
188546d12f91SDave Airlie 		return ret;
188646d12f91SDave Airlie 
188746d12f91SDave Airlie 	/*
188846d12f91SDave Airlie 	 * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1889680025dcSJuha-Pekka Heikkilä 	 * they match with the main surface x/y offsets. On DG2
1890680025dcSJuha-Pekka Heikkilä 	 * there's no aux plane on fb so skip this checking.
189146d12f91SDave Airlie 	 */
1892680025dcSJuha-Pekka Heikkilä 	if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) {
189346d12f91SDave Airlie 		while (!skl_check_main_ccs_coordinates(plane_state, x, y,
189446d12f91SDave Airlie 						       offset, aux_plane)) {
189546d12f91SDave Airlie 			if (offset == 0)
189646d12f91SDave Airlie 				break;
189746d12f91SDave Airlie 
189846d12f91SDave Airlie 			offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
189946d12f91SDave Airlie 								   offset, offset - alignment);
190046d12f91SDave Airlie 		}
190146d12f91SDave Airlie 
190261169987SImre Deak 		if (x != plane_state->view.color_plane[aux_plane].x ||
190361169987SImre Deak 		    y != plane_state->view.color_plane[aux_plane].y) {
190446d12f91SDave Airlie 			drm_dbg_kms(&dev_priv->drm,
190546d12f91SDave Airlie 				    "Unable to find suitable display surface offset due to CCS\n");
190646d12f91SDave Airlie 			return -EINVAL;
190746d12f91SDave Airlie 		}
190846d12f91SDave Airlie 	}
190946d12f91SDave Airlie 
1910e7367af1SJuha-Pekka Heikkilä 	if (DISPLAY_VER(dev_priv) >= 13)
1911e7367af1SJuha-Pekka Heikkilä 		drm_WARN_ON(&dev_priv->drm, x > 65535 || y > 65535);
1912e7367af1SJuha-Pekka Heikkilä 	else
191346d12f91SDave Airlie 		drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
191446d12f91SDave Airlie 
191561169987SImre Deak 	plane_state->view.color_plane[0].offset = offset;
191661169987SImre Deak 	plane_state->view.color_plane[0].x = x;
191761169987SImre Deak 	plane_state->view.color_plane[0].y = y;
191846d12f91SDave Airlie 
191946d12f91SDave Airlie 	/*
192046d12f91SDave Airlie 	 * Put the final coordinates back so that the src
192146d12f91SDave Airlie 	 * coordinate checks will see the right values.
192246d12f91SDave Airlie 	 */
192346d12f91SDave Airlie 	drm_rect_translate_to(&plane_state->uapi.src,
192446d12f91SDave Airlie 			      x << 16, y << 16);
192546d12f91SDave Airlie 
192646d12f91SDave Airlie 	return 0;
192746d12f91SDave Airlie }
192846d12f91SDave Airlie 
skl_check_nv12_aux_surface(struct intel_plane_state * plane_state)192946d12f91SDave Airlie static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
193046d12f91SDave Airlie {
193146d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
193246d12f91SDave Airlie 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
193346d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
193446d12f91SDave Airlie 	unsigned int rotation = plane_state->hw.rotation;
193546d12f91SDave Airlie 	int uv_plane = 1;
1936680025dcSJuha-Pekka Heikkilä 	int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ?
1937680025dcSJuha-Pekka Heikkilä 			skl_main_to_aux_plane(fb, uv_plane) : 0;
193846d12f91SDave Airlie 	int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
193946d12f91SDave Airlie 	int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
194046d12f91SDave Airlie 	int x = plane_state->uapi.src.x1 >> 17;
194146d12f91SDave Airlie 	int y = plane_state->uapi.src.y1 >> 17;
194246d12f91SDave Airlie 	int w = drm_rect_width(&plane_state->uapi.src) >> 17;
194346d12f91SDave Airlie 	int h = drm_rect_height(&plane_state->uapi.src) >> 17;
194446d12f91SDave Airlie 	u32 offset;
194546d12f91SDave Airlie 
194646d12f91SDave Airlie 	/* FIXME not quite sure how/if these apply to the chroma plane */
194746d12f91SDave Airlie 	if (w > max_width || h > max_height) {
194846d12f91SDave Airlie 		drm_dbg_kms(&i915->drm,
194946d12f91SDave Airlie 			    "CbCr source size %dx%d too big (limit %dx%d)\n",
195046d12f91SDave Airlie 			    w, h, max_width, max_height);
195146d12f91SDave Airlie 		return -EINVAL;
195246d12f91SDave Airlie 	}
195346d12f91SDave Airlie 
195446d12f91SDave Airlie 	intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
195546d12f91SDave Airlie 	offset = intel_plane_compute_aligned_offset(&x, &y,
195646d12f91SDave Airlie 						    plane_state, uv_plane);
195746d12f91SDave Airlie 
1958680025dcSJuha-Pekka Heikkilä 	if (ccs_plane) {
195961169987SImre Deak 		u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1960195b7a0dSVille Syrjälä 		unsigned int alignment = plane->min_alignment(plane, fb, uv_plane);
196146d12f91SDave Airlie 
196246d12f91SDave Airlie 		if (offset > aux_offset)
196346d12f91SDave Airlie 			offset = intel_plane_adjust_aligned_offset(&x, &y,
196446d12f91SDave Airlie 								   plane_state,
196546d12f91SDave Airlie 								   uv_plane,
196646d12f91SDave Airlie 								   offset,
196746d12f91SDave Airlie 								   aux_offset & ~(alignment - 1));
196846d12f91SDave Airlie 
196946d12f91SDave Airlie 		while (!skl_check_main_ccs_coordinates(plane_state, x, y,
197046d12f91SDave Airlie 						       offset, ccs_plane)) {
197146d12f91SDave Airlie 			if (offset == 0)
197246d12f91SDave Airlie 				break;
197346d12f91SDave Airlie 
197446d12f91SDave Airlie 			offset = intel_plane_adjust_aligned_offset(&x, &y,
197546d12f91SDave Airlie 								   plane_state,
197646d12f91SDave Airlie 								   uv_plane,
197746d12f91SDave Airlie 								   offset, offset - alignment);
197846d12f91SDave Airlie 		}
197946d12f91SDave Airlie 
198061169987SImre Deak 		if (x != plane_state->view.color_plane[ccs_plane].x ||
198161169987SImre Deak 		    y != plane_state->view.color_plane[ccs_plane].y) {
198246d12f91SDave Airlie 			drm_dbg_kms(&i915->drm,
198346d12f91SDave Airlie 				    "Unable to find suitable display surface offset due to CCS\n");
198446d12f91SDave Airlie 			return -EINVAL;
198546d12f91SDave Airlie 		}
198646d12f91SDave Airlie 	}
198746d12f91SDave Airlie 
1988e7367af1SJuha-Pekka Heikkilä 	if (DISPLAY_VER(i915) >= 13)
1989e7367af1SJuha-Pekka Heikkilä 		drm_WARN_ON(&i915->drm, x > 65535 || y > 65535);
1990e7367af1SJuha-Pekka Heikkilä 	else
199146d12f91SDave Airlie 		drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
199246d12f91SDave Airlie 
199361169987SImre Deak 	plane_state->view.color_plane[uv_plane].offset = offset;
199461169987SImre Deak 	plane_state->view.color_plane[uv_plane].x = x;
199561169987SImre Deak 	plane_state->view.color_plane[uv_plane].y = y;
199646d12f91SDave Airlie 
199746d12f91SDave Airlie 	return 0;
199846d12f91SDave Airlie }
199946d12f91SDave Airlie 
skl_check_ccs_aux_surface(struct intel_plane_state * plane_state)200046d12f91SDave Airlie static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
200146d12f91SDave Airlie {
200246d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
200346d12f91SDave Airlie 	int src_x = plane_state->uapi.src.x1 >> 16;
200446d12f91SDave Airlie 	int src_y = plane_state->uapi.src.y1 >> 16;
200546d12f91SDave Airlie 	u32 offset;
200646d12f91SDave Airlie 	int ccs_plane;
200746d12f91SDave Airlie 
200846d12f91SDave Airlie 	for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
200946d12f91SDave Airlie 		int main_hsub, main_vsub;
201046d12f91SDave Airlie 		int hsub, vsub;
201146d12f91SDave Airlie 		int x, y;
201246d12f91SDave Airlie 
2013f5042343SImre Deak 		if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane))
201446d12f91SDave Airlie 			continue;
201546d12f91SDave Airlie 
201646d12f91SDave Airlie 		intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
201746d12f91SDave Airlie 					       skl_ccs_to_main_plane(fb, ccs_plane));
201846d12f91SDave Airlie 		intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
201946d12f91SDave Airlie 
202046d12f91SDave Airlie 		hsub *= main_hsub;
202146d12f91SDave Airlie 		vsub *= main_vsub;
202246d12f91SDave Airlie 		x = src_x / hsub;
202346d12f91SDave Airlie 		y = src_y / vsub;
202446d12f91SDave Airlie 
202546d12f91SDave Airlie 		intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
202646d12f91SDave Airlie 
202746d12f91SDave Airlie 		offset = intel_plane_compute_aligned_offset(&x, &y,
202846d12f91SDave Airlie 							    plane_state,
202946d12f91SDave Airlie 							    ccs_plane);
203046d12f91SDave Airlie 
203161169987SImre Deak 		plane_state->view.color_plane[ccs_plane].offset = offset;
203261169987SImre Deak 		plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
203361169987SImre Deak 		plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
203446d12f91SDave Airlie 	}
203546d12f91SDave Airlie 
203646d12f91SDave Airlie 	return 0;
203746d12f91SDave Airlie }
203846d12f91SDave Airlie 
skl_check_plane_surface(struct intel_plane_state * plane_state)203946d12f91SDave Airlie static int skl_check_plane_surface(struct intel_plane_state *plane_state)
204046d12f91SDave Airlie {
204146d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
2042ee456a4cSImre Deak 	int ret;
204346d12f91SDave Airlie 
204446d12f91SDave Airlie 	ret = intel_plane_compute_gtt(plane_state);
204546d12f91SDave Airlie 	if (ret)
204646d12f91SDave Airlie 		return ret;
204746d12f91SDave Airlie 
204846d12f91SDave Airlie 	if (!plane_state->uapi.visible)
204946d12f91SDave Airlie 		return 0;
205046d12f91SDave Airlie 
205146d12f91SDave Airlie 	/*
205246d12f91SDave Airlie 	 * Handle the AUX surface first since the main surface setup depends on
205346d12f91SDave Airlie 	 * it.
205446d12f91SDave Airlie 	 */
2055e359c47bSImre Deak 	if (intel_fb_is_ccs_modifier(fb->modifier)) {
205646d12f91SDave Airlie 		ret = skl_check_ccs_aux_surface(plane_state);
205746d12f91SDave Airlie 		if (ret)
205846d12f91SDave Airlie 			return ret;
205946d12f91SDave Airlie 	}
206046d12f91SDave Airlie 
206146d12f91SDave Airlie 	if (intel_format_info_is_yuv_semiplanar(fb->format,
206246d12f91SDave Airlie 						fb->modifier)) {
206346d12f91SDave Airlie 		ret = skl_check_nv12_aux_surface(plane_state);
206446d12f91SDave Airlie 		if (ret)
206546d12f91SDave Airlie 			return ret;
206646d12f91SDave Airlie 	}
206746d12f91SDave Airlie 
206846d12f91SDave Airlie 	ret = skl_check_main_surface(plane_state);
206946d12f91SDave Airlie 	if (ret)
207046d12f91SDave Airlie 		return ret;
207146d12f91SDave Airlie 
207246d12f91SDave Airlie 	return 0;
207346d12f91SDave Airlie }
207446d12f91SDave Airlie 
skl_fb_scalable(const struct drm_framebuffer * fb)207514cebc1fSDave Airlie static bool skl_fb_scalable(const struct drm_framebuffer *fb)
207646d12f91SDave Airlie {
207746d12f91SDave Airlie 	if (!fb)
207846d12f91SDave Airlie 		return false;
207946d12f91SDave Airlie 
208046d12f91SDave Airlie 	switch (fb->format->format) {
208146d12f91SDave Airlie 	case DRM_FORMAT_C8:
208246d12f91SDave Airlie 		return false;
208346d12f91SDave Airlie 	case DRM_FORMAT_XRGB16161616F:
208446d12f91SDave Airlie 	case DRM_FORMAT_ARGB16161616F:
208546d12f91SDave Airlie 	case DRM_FORMAT_XBGR16161616F:
208646d12f91SDave Airlie 	case DRM_FORMAT_ABGR16161616F:
2087005e9537SMatt Roper 		return DISPLAY_VER(to_i915(fb->dev)) >= 11;
208846d12f91SDave Airlie 	default:
208946d12f91SDave Airlie 		return true;
209046d12f91SDave Airlie 	}
209146d12f91SDave Airlie }
209246d12f91SDave Airlie 
check_protection(struct intel_plane_state * plane_state)209388a6e46cSJani Nikula static void check_protection(struct intel_plane_state *plane_state)
209488a6e46cSJani Nikula {
209588a6e46cSJani Nikula 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
209688a6e46cSJani Nikula 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
209788a6e46cSJani Nikula 	const struct drm_framebuffer *fb = plane_state->hw.fb;
20989b1c97fcSJani Nikula 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
209988a6e46cSJani Nikula 
210088a6e46cSJani Nikula 	if (DISPLAY_VER(i915) < 11)
210188a6e46cSJani Nikula 		return;
210288a6e46cSJani Nikula 
21039b1c97fcSJani Nikula 	plane_state->decrypt = intel_pxp_key_check(i915->pxp, obj, false) == 0;
21049b1c97fcSJani Nikula 	plane_state->force_black = i915_gem_object_is_protected(obj) &&
21059b1c97fcSJani Nikula 		!plane_state->decrypt;
210688a6e46cSJani Nikula }
210788a6e46cSJani Nikula 
skl_plane_check(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)210846d12f91SDave Airlie static int skl_plane_check(struct intel_crtc_state *crtc_state,
210946d12f91SDave Airlie 			   struct intel_plane_state *plane_state)
211046d12f91SDave Airlie {
211146d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
211246d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
211346d12f91SDave Airlie 	const struct drm_framebuffer *fb = plane_state->hw.fb;
2114cce32e4eSThomas Zimmermann 	int min_scale = DRM_PLANE_NO_SCALING;
2115cce32e4eSThomas Zimmermann 	int max_scale = DRM_PLANE_NO_SCALING;
211646d12f91SDave Airlie 	int ret;
211746d12f91SDave Airlie 
211846d12f91SDave Airlie 	ret = skl_plane_check_fb(crtc_state, plane_state);
211946d12f91SDave Airlie 	if (ret)
212046d12f91SDave Airlie 		return ret;
212146d12f91SDave Airlie 
212246d12f91SDave Airlie 	/* use scaler when colorkey is not required */
212314cebc1fSDave Airlie 	if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
212446d12f91SDave Airlie 		min_scale = 1;
212546d12f91SDave Airlie 		max_scale = skl_plane_max_scale(dev_priv, fb);
212646d12f91SDave Airlie 	}
212746d12f91SDave Airlie 
212846d12f91SDave Airlie 	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
212946d12f91SDave Airlie 						min_scale, max_scale, true);
213046d12f91SDave Airlie 	if (ret)
213146d12f91SDave Airlie 		return ret;
213246d12f91SDave Airlie 
213346d12f91SDave Airlie 	ret = skl_check_plane_surface(plane_state);
213446d12f91SDave Airlie 	if (ret)
213546d12f91SDave Airlie 		return ret;
213646d12f91SDave Airlie 
213746d12f91SDave Airlie 	if (!plane_state->uapi.visible)
213846d12f91SDave Airlie 		return 0;
213946d12f91SDave Airlie 
214046d12f91SDave Airlie 	ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
214146d12f91SDave Airlie 	if (ret)
214246d12f91SDave Airlie 		return ret;
214346d12f91SDave Airlie 
214446d12f91SDave Airlie 	ret = intel_plane_check_src_coordinates(plane_state);
214546d12f91SDave Airlie 	if (ret)
214646d12f91SDave Airlie 		return ret;
214746d12f91SDave Airlie 
214846d12f91SDave Airlie 	ret = skl_plane_check_nv12_rotation(plane_state);
214946d12f91SDave Airlie 	if (ret)
215046d12f91SDave Airlie 		return ret;
215146d12f91SDave Airlie 
215288a6e46cSJani Nikula 	check_protection(plane_state);
2153f9a7b19cSVille Syrjälä 
215446d12f91SDave Airlie 	/* HW only has 8 bits pixel precision, disable plane if invisible */
215546d12f91SDave Airlie 	if (!(plane_state->hw.alpha >> 8))
215646d12f91SDave Airlie 		plane_state->uapi.visible = false;
215746d12f91SDave Airlie 
215846d12f91SDave Airlie 	plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
215946d12f91SDave Airlie 
21602b5a4562SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 10)
216146d12f91SDave Airlie 		plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
216246d12f91SDave Airlie 							     plane_state);
216346d12f91SDave Airlie 
216446d12f91SDave Airlie 	if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
216546d12f91SDave Airlie 	    icl_is_hdr_plane(dev_priv, plane->id))
216646d12f91SDave Airlie 		/* Enable and use MPEG-2 chroma siting */
216746d12f91SDave Airlie 		plane_state->cus_ctl = PLANE_CUS_ENABLE |
216846d12f91SDave Airlie 			PLANE_CUS_HPHASE_0 |
216946d12f91SDave Airlie 			PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
217046d12f91SDave Airlie 	else
217146d12f91SDave Airlie 		plane_state->cus_ctl = 0;
217246d12f91SDave Airlie 
217346d12f91SDave Airlie 	return 0;
217446d12f91SDave Airlie }
217546d12f91SDave Airlie 
skl_fbc_id_for_pipe(enum pipe pipe)2176b8ca477eSVille Syrjälä static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
217746d12f91SDave Airlie {
2178b8ca477eSVille Syrjälä 	return pipe - PIPE_A + INTEL_FBC_A;
2179b8ca477eSVille Syrjälä }
2180b8ca477eSVille Syrjälä 
skl_plane_has_fbc(struct drm_i915_private * i915,enum intel_fbc_id fbc_id,enum plane_id plane_id)2181de1ee4e4SVinod Govindapillai static bool skl_plane_has_fbc(struct drm_i915_private *i915,
2182b8ca477eSVille Syrjälä 			      enum intel_fbc_id fbc_id, enum plane_id plane_id)
2183b8ca477eSVille Syrjälä {
2184de1ee4e4SVinod Govindapillai 	if ((DISPLAY_RUNTIME_INFO(i915)->fbc_mask & BIT(fbc_id)) == 0)
218546d12f91SDave Airlie 		return false;
218646d12f91SDave Airlie 
2187de1ee4e4SVinod Govindapillai 	if (DISPLAY_VER(i915) >= 20)
2188de1ee4e4SVinod Govindapillai 		return icl_is_hdr_plane(i915, plane_id);
2189de1ee4e4SVinod Govindapillai 	else
2190df798d43SVille Syrjälä 		return plane_id == PLANE_1;
219146d12f91SDave Airlie }
219246d12f91SDave Airlie 
skl_plane_fbc(struct drm_i915_private * dev_priv,enum pipe pipe,enum plane_id plane_id)2193825bd833SVille Syrjälä static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv,
2194825bd833SVille Syrjälä 				       enum pipe pipe, enum plane_id plane_id)
2195825bd833SVille Syrjälä {
2196b8ca477eSVille Syrjälä 	enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
2197b8ca477eSVille Syrjälä 
2198b8ca477eSVille Syrjälä 	if (skl_plane_has_fbc(dev_priv, fbc_id, plane_id))
219980b3842fSJani Nikula 		return dev_priv->display.fbc[fbc_id];
2200825bd833SVille Syrjälä 	else
2201825bd833SVille Syrjälä 		return NULL;
2202825bd833SVille Syrjälä }
2203825bd833SVille Syrjälä 
skl_plane_has_planar(struct drm_i915_private * dev_priv,enum pipe pipe,enum plane_id plane_id)220446d12f91SDave Airlie static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
220546d12f91SDave Airlie 				 enum pipe pipe, enum plane_id plane_id)
220646d12f91SDave Airlie {
220746d12f91SDave Airlie 	/* Display WA #0870: skl, bxt */
220846d12f91SDave Airlie 	if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
220946d12f91SDave Airlie 		return false;
221046d12f91SDave Airlie 
221193e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C)
221246d12f91SDave Airlie 		return false;
221346d12f91SDave Airlie 
2214df798d43SVille Syrjälä 	if (plane_id != PLANE_1 && plane_id != PLANE_2)
221546d12f91SDave Airlie 		return false;
221646d12f91SDave Airlie 
221746d12f91SDave Airlie 	return true;
221846d12f91SDave Airlie }
221946d12f91SDave Airlie 
skl_get_plane_formats(struct drm_i915_private * dev_priv,enum pipe pipe,enum plane_id plane_id,int * num_formats)222046d12f91SDave Airlie static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
222146d12f91SDave Airlie 					enum pipe pipe, enum plane_id plane_id,
222246d12f91SDave Airlie 					int *num_formats)
222346d12f91SDave Airlie {
222446d12f91SDave Airlie 	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
222546d12f91SDave Airlie 		*num_formats = ARRAY_SIZE(skl_planar_formats);
222646d12f91SDave Airlie 		return skl_planar_formats;
222746d12f91SDave Airlie 	} else {
222846d12f91SDave Airlie 		*num_formats = ARRAY_SIZE(skl_plane_formats);
222946d12f91SDave Airlie 		return skl_plane_formats;
223046d12f91SDave Airlie 	}
223146d12f91SDave Airlie }
223246d12f91SDave Airlie 
glk_get_plane_formats(struct drm_i915_private * dev_priv,enum pipe pipe,enum plane_id plane_id,int * num_formats)223346d12f91SDave Airlie static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
223446d12f91SDave Airlie 					enum pipe pipe, enum plane_id plane_id,
223546d12f91SDave Airlie 					int *num_formats)
223646d12f91SDave Airlie {
223746d12f91SDave Airlie 	if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
223846d12f91SDave Airlie 		*num_formats = ARRAY_SIZE(glk_planar_formats);
223946d12f91SDave Airlie 		return glk_planar_formats;
224046d12f91SDave Airlie 	} else {
224146d12f91SDave Airlie 		*num_formats = ARRAY_SIZE(skl_plane_formats);
224246d12f91SDave Airlie 		return skl_plane_formats;
224346d12f91SDave Airlie 	}
224446d12f91SDave Airlie }
224546d12f91SDave Airlie 
icl_get_plane_formats(struct drm_i915_private * dev_priv,enum pipe pipe,enum plane_id plane_id,int * num_formats)224646d12f91SDave Airlie static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
224746d12f91SDave Airlie 					enum pipe pipe, enum plane_id plane_id,
224846d12f91SDave Airlie 					int *num_formats)
224946d12f91SDave Airlie {
225046d12f91SDave Airlie 	if (icl_is_hdr_plane(dev_priv, plane_id)) {
225146d12f91SDave Airlie 		*num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
225246d12f91SDave Airlie 		return icl_hdr_plane_formats;
225346d12f91SDave Airlie 	} else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
225446d12f91SDave Airlie 		*num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
225546d12f91SDave Airlie 		return icl_sdr_y_plane_formats;
225646d12f91SDave Airlie 	} else {
225746d12f91SDave Airlie 		*num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
225846d12f91SDave Airlie 		return icl_sdr_uv_plane_formats;
225946d12f91SDave Airlie 	}
226046d12f91SDave Airlie }
226146d12f91SDave Airlie 
skl_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)226246d12f91SDave Airlie static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
226346d12f91SDave Airlie 					   u32 format, u64 modifier)
226446d12f91SDave Airlie {
226546d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(_plane);
226646d12f91SDave Airlie 
2267e2b83294SImre Deak 	if (!intel_fb_plane_supports_modifier(plane, modifier))
226846d12f91SDave Airlie 		return false;
226946d12f91SDave Airlie 
227046d12f91SDave Airlie 	switch (format) {
227146d12f91SDave Airlie 	case DRM_FORMAT_XRGB8888:
227246d12f91SDave Airlie 	case DRM_FORMAT_XBGR8888:
227346d12f91SDave Airlie 	case DRM_FORMAT_ARGB8888:
227446d12f91SDave Airlie 	case DRM_FORMAT_ABGR8888:
2275e359c47bSImre Deak 		if (intel_fb_is_ccs_modifier(modifier))
227646d12f91SDave Airlie 			return true;
227746d12f91SDave Airlie 		fallthrough;
227846d12f91SDave Airlie 	case DRM_FORMAT_RGB565:
227946d12f91SDave Airlie 	case DRM_FORMAT_XRGB2101010:
228046d12f91SDave Airlie 	case DRM_FORMAT_XBGR2101010:
228146d12f91SDave Airlie 	case DRM_FORMAT_ARGB2101010:
228246d12f91SDave Airlie 	case DRM_FORMAT_ABGR2101010:
228346d12f91SDave Airlie 	case DRM_FORMAT_YUYV:
228446d12f91SDave Airlie 	case DRM_FORMAT_YVYU:
228546d12f91SDave Airlie 	case DRM_FORMAT_UYVY:
228646d12f91SDave Airlie 	case DRM_FORMAT_VYUY:
228746d12f91SDave Airlie 	case DRM_FORMAT_NV12:
228846d12f91SDave Airlie 	case DRM_FORMAT_XYUV8888:
228946d12f91SDave Airlie 	case DRM_FORMAT_P010:
229046d12f91SDave Airlie 	case DRM_FORMAT_P012:
229146d12f91SDave Airlie 	case DRM_FORMAT_P016:
229246d12f91SDave Airlie 	case DRM_FORMAT_XVYU2101010:
229346d12f91SDave Airlie 		if (modifier == I915_FORMAT_MOD_Yf_TILED)
229446d12f91SDave Airlie 			return true;
229546d12f91SDave Airlie 		fallthrough;
229646d12f91SDave Airlie 	case DRM_FORMAT_C8:
229746d12f91SDave Airlie 	case DRM_FORMAT_XBGR16161616F:
229846d12f91SDave Airlie 	case DRM_FORMAT_ABGR16161616F:
229946d12f91SDave Airlie 	case DRM_FORMAT_XRGB16161616F:
230046d12f91SDave Airlie 	case DRM_FORMAT_ARGB16161616F:
230146d12f91SDave Airlie 	case DRM_FORMAT_Y210:
230246d12f91SDave Airlie 	case DRM_FORMAT_Y212:
230346d12f91SDave Airlie 	case DRM_FORMAT_Y216:
230446d12f91SDave Airlie 	case DRM_FORMAT_XVYU12_16161616:
230546d12f91SDave Airlie 	case DRM_FORMAT_XVYU16161616:
230646d12f91SDave Airlie 		if (modifier == DRM_FORMAT_MOD_LINEAR ||
230746d12f91SDave Airlie 		    modifier == I915_FORMAT_MOD_X_TILED ||
230846d12f91SDave Airlie 		    modifier == I915_FORMAT_MOD_Y_TILED)
230946d12f91SDave Airlie 			return true;
231046d12f91SDave Airlie 		fallthrough;
231146d12f91SDave Airlie 	default:
231246d12f91SDave Airlie 		return false;
231346d12f91SDave Airlie 	}
231446d12f91SDave Airlie }
231546d12f91SDave Airlie 
gen12_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)231646d12f91SDave Airlie static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
231746d12f91SDave Airlie 					     u32 format, u64 modifier)
231846d12f91SDave Airlie {
231946d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(_plane);
232046d12f91SDave Airlie 
2321e2b83294SImre Deak 	if (!intel_fb_plane_supports_modifier(plane, modifier))
232246d12f91SDave Airlie 		return false;
232346d12f91SDave Airlie 
232446d12f91SDave Airlie 	switch (format) {
232546d12f91SDave Airlie 	case DRM_FORMAT_XRGB8888:
232646d12f91SDave Airlie 	case DRM_FORMAT_XBGR8888:
232746d12f91SDave Airlie 	case DRM_FORMAT_ARGB8888:
232846d12f91SDave Airlie 	case DRM_FORMAT_ABGR8888:
2329e359c47bSImre Deak 		if (intel_fb_is_ccs_modifier(modifier))
233046d12f91SDave Airlie 			return true;
233146d12f91SDave Airlie 		fallthrough;
233246d12f91SDave Airlie 	case DRM_FORMAT_YUYV:
233346d12f91SDave Airlie 	case DRM_FORMAT_YVYU:
233446d12f91SDave Airlie 	case DRM_FORMAT_UYVY:
233546d12f91SDave Airlie 	case DRM_FORMAT_VYUY:
233646d12f91SDave Airlie 	case DRM_FORMAT_NV12:
233746d12f91SDave Airlie 	case DRM_FORMAT_XYUV8888:
233846d12f91SDave Airlie 	case DRM_FORMAT_P010:
233946d12f91SDave Airlie 	case DRM_FORMAT_P012:
234046d12f91SDave Airlie 	case DRM_FORMAT_P016:
23410b2c31ddSImre Deak 		if (intel_fb_is_mc_ccs_modifier(modifier))
234246d12f91SDave Airlie 			return true;
234346d12f91SDave Airlie 		fallthrough;
234446d12f91SDave Airlie 	case DRM_FORMAT_RGB565:
234546d12f91SDave Airlie 	case DRM_FORMAT_XRGB2101010:
234646d12f91SDave Airlie 	case DRM_FORMAT_XBGR2101010:
234746d12f91SDave Airlie 	case DRM_FORMAT_ARGB2101010:
234846d12f91SDave Airlie 	case DRM_FORMAT_ABGR2101010:
234946d12f91SDave Airlie 	case DRM_FORMAT_XVYU2101010:
235046d12f91SDave Airlie 	case DRM_FORMAT_C8:
235146d12f91SDave Airlie 	case DRM_FORMAT_XBGR16161616F:
235246d12f91SDave Airlie 	case DRM_FORMAT_ABGR16161616F:
235346d12f91SDave Airlie 	case DRM_FORMAT_XRGB16161616F:
235446d12f91SDave Airlie 	case DRM_FORMAT_ARGB16161616F:
235546d12f91SDave Airlie 	case DRM_FORMAT_Y210:
235646d12f91SDave Airlie 	case DRM_FORMAT_Y212:
235746d12f91SDave Airlie 	case DRM_FORMAT_Y216:
235846d12f91SDave Airlie 	case DRM_FORMAT_XVYU12_16161616:
235946d12f91SDave Airlie 	case DRM_FORMAT_XVYU16161616:
2360072ce416SStanislav Lisovskiy 		if (!intel_fb_is_ccs_modifier(modifier))
236146d12f91SDave Airlie 			return true;
236246d12f91SDave Airlie 		fallthrough;
236346d12f91SDave Airlie 	default:
236446d12f91SDave Airlie 		return false;
236546d12f91SDave Airlie 	}
236646d12f91SDave Airlie }
236746d12f91SDave Airlie 
236846d12f91SDave Airlie static const struct drm_plane_funcs skl_plane_funcs = {
236946d12f91SDave Airlie 	.update_plane = drm_atomic_helper_update_plane,
237046d12f91SDave Airlie 	.disable_plane = drm_atomic_helper_disable_plane,
237146d12f91SDave Airlie 	.destroy = intel_plane_destroy,
237246d12f91SDave Airlie 	.atomic_duplicate_state = intel_plane_duplicate_state,
237346d12f91SDave Airlie 	.atomic_destroy_state = intel_plane_destroy_state,
237446d12f91SDave Airlie 	.format_mod_supported = skl_plane_format_mod_supported,
237546d12f91SDave Airlie };
237646d12f91SDave Airlie 
237746d12f91SDave Airlie static const struct drm_plane_funcs gen12_plane_funcs = {
237846d12f91SDave Airlie 	.update_plane = drm_atomic_helper_update_plane,
237946d12f91SDave Airlie 	.disable_plane = drm_atomic_helper_disable_plane,
238046d12f91SDave Airlie 	.destroy = intel_plane_destroy,
238146d12f91SDave Airlie 	.atomic_duplicate_state = intel_plane_duplicate_state,
238246d12f91SDave Airlie 	.atomic_destroy_state = intel_plane_destroy_state,
238346d12f91SDave Airlie 	.format_mod_supported = gen12_plane_format_mod_supported,
238446d12f91SDave Airlie };
238546d12f91SDave Airlie 
238646d12f91SDave Airlie static void
skl_plane_enable_flip_done(struct intel_plane * plane)238746d12f91SDave Airlie skl_plane_enable_flip_done(struct intel_plane *plane)
238846d12f91SDave Airlie {
238946d12f91SDave Airlie 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
239046d12f91SDave Airlie 	enum pipe pipe = plane->pipe;
239146d12f91SDave Airlie 
239246d12f91SDave Airlie 	spin_lock_irq(&i915->irq_lock);
239346d12f91SDave Airlie 	bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
239446d12f91SDave Airlie 	spin_unlock_irq(&i915->irq_lock);
239546d12f91SDave Airlie }
239646d12f91SDave Airlie 
239746d12f91SDave Airlie static void
skl_plane_disable_flip_done(struct intel_plane * plane)239846d12f91SDave Airlie skl_plane_disable_flip_done(struct intel_plane *plane)
239946d12f91SDave Airlie {
240046d12f91SDave Airlie 	struct drm_i915_private *i915 = to_i915(plane->base.dev);
240146d12f91SDave Airlie 	enum pipe pipe = plane->pipe;
240246d12f91SDave Airlie 
240346d12f91SDave Airlie 	spin_lock_irq(&i915->irq_lock);
240446d12f91SDave Airlie 	bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
240546d12f91SDave Airlie 	spin_unlock_irq(&i915->irq_lock);
240646d12f91SDave Airlie }
240746d12f91SDave Airlie 
skl_plane_has_rc_ccs(struct drm_i915_private * i915,enum pipe pipe,enum plane_id plane_id)2408e2b83294SImre Deak static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915,
2409e2b83294SImre Deak 				 enum pipe pipe, enum plane_id plane_id)
2410e2b83294SImre Deak {
2411e2b83294SImre Deak 	/* Wa_22011186057 */
2412cc0c986aSDnyaneshwar Bhadane 	if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2413e2b83294SImre Deak 		return false;
2414e2b83294SImre Deak 
2415e2b83294SImre Deak 	if (DISPLAY_VER(i915) >= 11)
2416e2b83294SImre Deak 		return true;
2417e2b83294SImre Deak 
2418e2b83294SImre Deak 	if (IS_GEMINILAKE(i915))
2419e2b83294SImre Deak 		return pipe != PIPE_C;
2420e2b83294SImre Deak 
2421e2b83294SImre Deak 	return pipe != PIPE_C &&
2422df798d43SVille Syrjälä 		(plane_id == PLANE_1 || plane_id == PLANE_2);
2423e2b83294SImre Deak }
2424e2b83294SImre Deak 
gen12_plane_has_mc_ccs(struct drm_i915_private * i915,enum plane_id plane_id)2425e2b83294SImre Deak static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915,
2426e2b83294SImre Deak 				   enum plane_id plane_id)
2427e2b83294SImre Deak {
2428da0c3e2cSImre Deak 	if (DISPLAY_VER(i915) < 12)
2429da0c3e2cSImre Deak 		return false;
2430da0c3e2cSImre Deak 
2431d1702963SMatt Roper 	/* Wa_14010477008 */
2432e2b83294SImre Deak 	if (IS_DG1(i915) || IS_ROCKETLAKE(i915) ||
243348077b0bSDnyaneshwar Bhadane 		(IS_TIGERLAKE(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_D0)))
2434e2b83294SImre Deak 		return false;
2435e2b83294SImre Deak 
2436e2b83294SImre Deak 	/* Wa_22011186057 */
2437cc0c986aSDnyaneshwar Bhadane 	if (IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2438e2b83294SImre Deak 		return false;
2439e2b83294SImre Deak 
2440df798d43SVille Syrjälä 	return plane_id < PLANE_6;
2441e2b83294SImre Deak }
2442e2b83294SImre Deak 
skl_get_plane_caps(struct drm_i915_private * i915,enum pipe pipe,enum plane_id plane_id)244310a657ddSImre Deak static u8 skl_get_plane_caps(struct drm_i915_private *i915,
244410a657ddSImre Deak 			     enum pipe pipe, enum plane_id plane_id)
244510a657ddSImre Deak {
244610a657ddSImre Deak 	u8 caps = INTEL_PLANE_CAP_TILING_X;
244710a657ddSImre Deak 
244810a657ddSImre Deak 	if (DISPLAY_VER(i915) < 13 || IS_ALDERLAKE_P(i915))
244910a657ddSImre Deak 		caps |= INTEL_PLANE_CAP_TILING_Y;
245010a657ddSImre Deak 	if (DISPLAY_VER(i915) < 12)
245110a657ddSImre Deak 		caps |= INTEL_PLANE_CAP_TILING_Yf;
2452072ce416SStanislav Lisovskiy 	if (HAS_4TILE(i915))
2453072ce416SStanislav Lisovskiy 		caps |= INTEL_PLANE_CAP_TILING_4;
245410a657ddSImre Deak 
2455b7232a73SJuha-Pekka Heikkila 	if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(i915))
2456b7232a73SJuha-Pekka Heikkila 		return caps;
2457b7232a73SJuha-Pekka Heikkila 
245810a657ddSImre Deak 	if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
245910a657ddSImre Deak 		caps |= INTEL_PLANE_CAP_CCS_RC;
246010a657ddSImre Deak 		if (DISPLAY_VER(i915) >= 12)
246110a657ddSImre Deak 			caps |= INTEL_PLANE_CAP_CCS_RC_CC;
246210a657ddSImre Deak 	}
246310a657ddSImre Deak 
246410a657ddSImre Deak 	if (gen12_plane_has_mc_ccs(i915, plane_id))
246510a657ddSImre Deak 		caps |= INTEL_PLANE_CAP_CCS_MC;
246610a657ddSImre Deak 
2467f7e3885aSJuha-Pekka Heikkila 	if (DISPLAY_VER(i915) >= 14 && IS_DGFX(i915))
2468f7e3885aSJuha-Pekka Heikkila 		caps |= INTEL_PLANE_CAP_NEED64K_PHYS;
2469f7e3885aSJuha-Pekka Heikkila 
247010a657ddSImre Deak 	return caps;
247110a657ddSImre Deak }
247210a657ddSImre Deak 
247346d12f91SDave Airlie struct intel_plane *
skl_universal_plane_create(struct drm_i915_private * dev_priv,enum pipe pipe,enum plane_id plane_id)247446d12f91SDave Airlie skl_universal_plane_create(struct drm_i915_private *dev_priv,
247546d12f91SDave Airlie 			   enum pipe pipe, enum plane_id plane_id)
247646d12f91SDave Airlie {
247746d12f91SDave Airlie 	const struct drm_plane_funcs *plane_funcs;
247846d12f91SDave Airlie 	struct intel_plane *plane;
247946d12f91SDave Airlie 	enum drm_plane_type plane_type;
248046d12f91SDave Airlie 	unsigned int supported_rotations;
248146d12f91SDave Airlie 	unsigned int supported_csc;
248246d12f91SDave Airlie 	const u64 *modifiers;
248346d12f91SDave Airlie 	const u32 *formats;
248446d12f91SDave Airlie 	int num_formats;
248546d12f91SDave Airlie 	int ret;
248646d12f91SDave Airlie 
248746d12f91SDave Airlie 	plane = intel_plane_alloc();
248846d12f91SDave Airlie 	if (IS_ERR(plane))
248946d12f91SDave Airlie 		return plane;
249046d12f91SDave Airlie 
249146d12f91SDave Airlie 	plane->pipe = pipe;
249246d12f91SDave Airlie 	plane->id = plane_id;
249346d12f91SDave Airlie 	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
249446d12f91SDave Airlie 
2495825bd833SVille Syrjälä 	intel_fbc_add_plane(skl_plane_fbc(dev_priv, pipe, plane_id), plane);
249646d12f91SDave Airlie 
2497005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
249846d12f91SDave Airlie 		plane->min_width = icl_plane_min_width;
24990e959b4eSVidya Srinivas 		if (icl_is_hdr_plane(dev_priv, plane_id))
25000e959b4eSVidya Srinivas 			plane->max_width = icl_hdr_plane_max_width;
25010e959b4eSVidya Srinivas 		else
25020e959b4eSVidya Srinivas 			plane->max_width = icl_sdr_plane_max_width;
250346d12f91SDave Airlie 		plane->max_height = icl_plane_max_height;
25046195f850SVille Syrjälä 		plane->min_cdclk = icl_plane_min_cdclk;
25052b5a4562SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 10) {
250646d12f91SDave Airlie 		plane->max_width = glk_plane_max_width;
250746d12f91SDave Airlie 		plane->max_height = skl_plane_max_height;
2508efc52308SVille Syrjälä 		plane->min_cdclk = glk_plane_min_cdclk;
250946d12f91SDave Airlie 	} else {
251046d12f91SDave Airlie 		plane->max_width = skl_plane_max_width;
251146d12f91SDave Airlie 		plane->max_height = skl_plane_max_height;
2512efc52308SVille Syrjälä 		plane->min_cdclk = skl_plane_min_cdclk;
251346d12f91SDave Airlie 	}
251446d12f91SDave Airlie 
25151301ce34SVille Syrjälä 	if (DISPLAY_VER(dev_priv) >= 13)
25161301ce34SVille Syrjälä 		plane->max_stride = adl_plane_max_stride;
25171301ce34SVille Syrjälä 	else
251846d12f91SDave Airlie 		plane->max_stride = skl_plane_max_stride;
25191301ce34SVille Syrjälä 
25207652126cSVille Syrjälä 	if (DISPLAY_VER(dev_priv) >= 12)
25217652126cSVille Syrjälä 		plane->min_alignment = tgl_plane_min_alignment;
25227652126cSVille Syrjälä 	else
2523ee3c3e33SVille Syrjälä 		plane->min_alignment = skl_plane_min_alignment;
2524195b7a0dSVille Syrjälä 
2525f8a005ebSVille Syrjälä 	if (DISPLAY_VER(dev_priv) >= 11) {
2526f8a005ebSVille Syrjälä 		plane->update_noarm = icl_plane_update_noarm;
2527f8a005ebSVille Syrjälä 		plane->update_arm = icl_plane_update_arm;
2528f8a005ebSVille Syrjälä 		plane->disable_arm = icl_plane_disable_arm;
2529f8a005ebSVille Syrjälä 	} else {
2530890b6ec4SVille Syrjälä 		plane->update_noarm = skl_plane_update_noarm;
25318ac80733SVille Syrjälä 		plane->update_arm = skl_plane_update_arm;
25328ac80733SVille Syrjälä 		plane->disable_arm = skl_plane_disable_arm;
2533f8a005ebSVille Syrjälä 	}
253446d12f91SDave Airlie 	plane->get_hw_state = skl_plane_get_hw_state;
253546d12f91SDave Airlie 	plane->check_plane = skl_plane_check;
253646d12f91SDave Airlie 
2537df798d43SVille Syrjälä 	if (plane_id == PLANE_1) {
25382081c6aeSVille Syrjälä 		plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(dev_priv, 9, 10);
253946d12f91SDave Airlie 		plane->async_flip = skl_plane_async_flip;
254046d12f91SDave Airlie 		plane->enable_flip_done = skl_plane_enable_flip_done;
254146d12f91SDave Airlie 		plane->disable_flip_done = skl_plane_disable_flip_done;
254246d12f91SDave Airlie 	}
254346d12f91SDave Airlie 
2544005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
254546d12f91SDave Airlie 		formats = icl_get_plane_formats(dev_priv, pipe,
254646d12f91SDave Airlie 						plane_id, &num_formats);
25472b5a4562SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 10)
254846d12f91SDave Airlie 		formats = glk_get_plane_formats(dev_priv, pipe,
254946d12f91SDave Airlie 						plane_id, &num_formats);
255046d12f91SDave Airlie 	else
255146d12f91SDave Airlie 		formats = skl_get_plane_formats(dev_priv, pipe,
255246d12f91SDave Airlie 						plane_id, &num_formats);
255346d12f91SDave Airlie 
2554e2b83294SImre Deak 	if (DISPLAY_VER(dev_priv) >= 12)
255546d12f91SDave Airlie 		plane_funcs = &gen12_plane_funcs;
255646d12f91SDave Airlie 	else
255746d12f91SDave Airlie 		plane_funcs = &skl_plane_funcs;
255846d12f91SDave Airlie 
2559df798d43SVille Syrjälä 	if (plane_id == PLANE_1)
256046d12f91SDave Airlie 		plane_type = DRM_PLANE_TYPE_PRIMARY;
256146d12f91SDave Airlie 	else
256246d12f91SDave Airlie 		plane_type = DRM_PLANE_TYPE_OVERLAY;
256346d12f91SDave Airlie 
256410a657ddSImre Deak 	modifiers = intel_fb_plane_get_modifiers(dev_priv,
256510a657ddSImre Deak 						 skl_get_plane_caps(dev_priv, pipe, plane_id));
2566e2b83294SImre Deak 
256746d12f91SDave Airlie 	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
256846d12f91SDave Airlie 				       0, plane_funcs,
256946d12f91SDave Airlie 				       formats, num_formats, modifiers,
257046d12f91SDave Airlie 				       plane_type,
257146d12f91SDave Airlie 				       "plane %d%c", plane_id + 1,
257246d12f91SDave Airlie 				       pipe_name(pipe));
2573e2b83294SImre Deak 
2574e2b83294SImre Deak 	kfree(modifiers);
2575e2b83294SImre Deak 
257646d12f91SDave Airlie 	if (ret)
257746d12f91SDave Airlie 		goto fail;
257846d12f91SDave Airlie 
25791649a4ccSMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
25801649a4ccSMatt Roper 		supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
25811649a4ccSMatt Roper 	else
258246d12f91SDave Airlie 		supported_rotations =
258346d12f91SDave Airlie 			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
258446d12f91SDave Airlie 			DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
258546d12f91SDave Airlie 
2586c988d2dcSLucas De Marchi 	if (DISPLAY_VER(dev_priv) >= 11)
258746d12f91SDave Airlie 		supported_rotations |= DRM_MODE_REFLECT_X;
258846d12f91SDave Airlie 
258946d12f91SDave Airlie 	drm_plane_create_rotation_property(&plane->base,
259046d12f91SDave Airlie 					   DRM_MODE_ROTATE_0,
259146d12f91SDave Airlie 					   supported_rotations);
259246d12f91SDave Airlie 
259346d12f91SDave Airlie 	supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
259446d12f91SDave Airlie 
25952b5a4562SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 10)
259646d12f91SDave Airlie 		supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
259746d12f91SDave Airlie 
259846d12f91SDave Airlie 	drm_plane_create_color_properties(&plane->base,
259946d12f91SDave Airlie 					  supported_csc,
260046d12f91SDave Airlie 					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
260146d12f91SDave Airlie 					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
260246d12f91SDave Airlie 					  DRM_COLOR_YCBCR_BT709,
260346d12f91SDave Airlie 					  DRM_COLOR_YCBCR_LIMITED_RANGE);
260446d12f91SDave Airlie 
260546d12f91SDave Airlie 	drm_plane_create_alpha_property(&plane->base);
260646d12f91SDave Airlie 	drm_plane_create_blend_mode_property(&plane->base,
260746d12f91SDave Airlie 					     BIT(DRM_MODE_BLEND_PIXEL_NONE) |
260846d12f91SDave Airlie 					     BIT(DRM_MODE_BLEND_PREMULTI) |
260946d12f91SDave Airlie 					     BIT(DRM_MODE_BLEND_COVERAGE));
261046d12f91SDave Airlie 
261146d12f91SDave Airlie 	drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
261246d12f91SDave Airlie 
2613005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
261446d12f91SDave Airlie 		drm_plane_enable_fb_damage_clips(&plane->base);
261546d12f91SDave Airlie 
2616c988d2dcSLucas De Marchi 	if (DISPLAY_VER(dev_priv) >= 11)
261746d12f91SDave Airlie 		drm_plane_create_scaling_filter_property(&plane->base,
261846d12f91SDave Airlie 						BIT(DRM_SCALING_FILTER_DEFAULT) |
261946d12f91SDave Airlie 						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
262046d12f91SDave Airlie 
2621d372ba42SJani Nikula 	intel_plane_helper_add(plane);
262246d12f91SDave Airlie 
262346d12f91SDave Airlie 	return plane;
262446d12f91SDave Airlie 
262546d12f91SDave Airlie fail:
262646d12f91SDave Airlie 	intel_plane_free(plane);
262746d12f91SDave Airlie 
262846d12f91SDave Airlie 	return ERR_PTR(ret);
262946d12f91SDave Airlie }
263046d12f91SDave Airlie 
263146d12f91SDave Airlie void
skl_get_initial_plane_config(struct intel_crtc * crtc,struct intel_initial_plane_config * plane_config)263246d12f91SDave Airlie skl_get_initial_plane_config(struct intel_crtc *crtc,
263346d12f91SDave Airlie 			     struct intel_initial_plane_config *plane_config)
263446d12f91SDave Airlie {
263546d12f91SDave Airlie 	struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
263646d12f91SDave Airlie 	struct drm_device *dev = crtc->base.dev;
263746d12f91SDave Airlie 	struct drm_i915_private *dev_priv = to_i915(dev);
263846d12f91SDave Airlie 	struct intel_plane *plane = to_intel_plane(crtc->base.primary);
263946d12f91SDave Airlie 	enum plane_id plane_id = plane->id;
264046d12f91SDave Airlie 	enum pipe pipe;
264146d12f91SDave Airlie 	u32 val, base, offset, stride_mult, tiling, alpha;
264246d12f91SDave Airlie 	int fourcc, pixel_format;
264346d12f91SDave Airlie 	unsigned int aligned_height;
264446d12f91SDave Airlie 	struct drm_framebuffer *fb;
264546d12f91SDave Airlie 	struct intel_framebuffer *intel_fb;
2646072ce416SStanislav Lisovskiy 	static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4);
264746d12f91SDave Airlie 
264846d12f91SDave Airlie 	if (!plane->get_hw_state(plane, &pipe))
264946d12f91SDave Airlie 		return;
265046d12f91SDave Airlie 
265146d12f91SDave Airlie 	drm_WARN_ON(dev, pipe != crtc->pipe);
265246d12f91SDave Airlie 
2653fb494357SStanislav Lisovskiy 	if (crtc_state->joiner_pipes) {
265446d12f91SDave Airlie 		drm_dbg_kms(&dev_priv->drm,
2655fb494357SStanislav Lisovskiy 			    "Unsupported joiner configuration for initial FB\n");
265646d12f91SDave Airlie 		return;
265746d12f91SDave Airlie 	}
265846d12f91SDave Airlie 
265946d12f91SDave Airlie 	intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
266046d12f91SDave Airlie 	if (!intel_fb) {
266146d12f91SDave Airlie 		drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
266246d12f91SDave Airlie 		return;
266346d12f91SDave Airlie 	}
266446d12f91SDave Airlie 
266546d12f91SDave Airlie 	fb = &intel_fb->base;
266646d12f91SDave Airlie 
266746d12f91SDave Airlie 	fb->dev = dev;
266846d12f91SDave Airlie 
266946d12f91SDave Airlie 	val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
267046d12f91SDave Airlie 
2671005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
267212d7d858SVille Syrjälä 		pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL;
267346d12f91SDave Airlie 	else
267412d7d858SVille Syrjälä 		pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL;
267546d12f91SDave Airlie 
26762b5a4562SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 10) {
267712d7d858SVille Syrjälä 		u32 color_ctl;
267812d7d858SVille Syrjälä 
267912d7d858SVille Syrjälä 		color_ctl = intel_de_read(dev_priv, PLANE_COLOR_CTL(pipe, plane_id));
268012d7d858SVille Syrjälä 		alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl);
268146d12f91SDave Airlie 	} else {
268212d7d858SVille Syrjälä 		alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val);
268346d12f91SDave Airlie 	}
268446d12f91SDave Airlie 
268546d12f91SDave Airlie 	fourcc = skl_format_to_fourcc(pixel_format,
268646d12f91SDave Airlie 				      val & PLANE_CTL_ORDER_RGBX, alpha);
268746d12f91SDave Airlie 	fb->format = drm_format_info(fourcc);
268846d12f91SDave Airlie 
268946d12f91SDave Airlie 	tiling = val & PLANE_CTL_TILED_MASK;
269046d12f91SDave Airlie 	switch (tiling) {
269146d12f91SDave Airlie 	case PLANE_CTL_TILED_LINEAR:
269246d12f91SDave Airlie 		fb->modifier = DRM_FORMAT_MOD_LINEAR;
269346d12f91SDave Airlie 		break;
269446d12f91SDave Airlie 	case PLANE_CTL_TILED_X:
269546d12f91SDave Airlie 		plane_config->tiling = I915_TILING_X;
269646d12f91SDave Airlie 		fb->modifier = I915_FORMAT_MOD_X_TILED;
269746d12f91SDave Airlie 		break;
269846d12f91SDave Airlie 	case PLANE_CTL_TILED_Y:
269946d12f91SDave Airlie 		plane_config->tiling = I915_TILING_Y;
270046d12f91SDave Airlie 		if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2701f2eb43f0SJuha-Pekka Heikkila 			if (DISPLAY_VER(dev_priv) >= 14)
2702f2eb43f0SJuha-Pekka Heikkila 				fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS;
2703f2eb43f0SJuha-Pekka Heikkila 			else if (DISPLAY_VER(dev_priv) >= 12)
27044c3afa72SMatt Roper 				fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
27054c3afa72SMatt Roper 			else
27064c3afa72SMatt Roper 				fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
270746d12f91SDave Airlie 		else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2708f2eb43f0SJuha-Pekka Heikkila 			if (DISPLAY_VER(dev_priv) >= 14)
2709f2eb43f0SJuha-Pekka Heikkila 				fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS;
2710f2eb43f0SJuha-Pekka Heikkila 			else
271146d12f91SDave Airlie 				fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
271246d12f91SDave Airlie 		else
271346d12f91SDave Airlie 			fb->modifier = I915_FORMAT_MOD_Y_TILED;
271446d12f91SDave Airlie 		break;
2715072ce416SStanislav Lisovskiy 	case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
2716072ce416SStanislav Lisovskiy 		if (HAS_4TILE(dev_priv)) {
2717680025dcSJuha-Pekka Heikkilä 			u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
2718680025dcSJuha-Pekka Heikkilä 				      PLANE_CTL_CLEAR_COLOR_DISABLE;
2719680025dcSJuha-Pekka Heikkilä 
2720680025dcSJuha-Pekka Heikkilä 			if ((val & rc_mask) == rc_mask)
27214c3afa72SMatt Roper 				fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS;
27224c3afa72SMatt Roper 			else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
27234c3afa72SMatt Roper 				fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS;
2724680025dcSJuha-Pekka Heikkilä 			else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2725680025dcSJuha-Pekka Heikkilä 				fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
27264c3afa72SMatt Roper 			else
2727072ce416SStanislav Lisovskiy 				fb->modifier = I915_FORMAT_MOD_4_TILED;
2728072ce416SStanislav Lisovskiy 		} else {
272946d12f91SDave Airlie 			if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
273046d12f91SDave Airlie 				fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
273146d12f91SDave Airlie 			else
273246d12f91SDave Airlie 				fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2733072ce416SStanislav Lisovskiy 		}
273446d12f91SDave Airlie 		break;
273546d12f91SDave Airlie 	default:
273646d12f91SDave Airlie 		MISSING_CASE(tiling);
273746d12f91SDave Airlie 		goto error;
273846d12f91SDave Airlie 	}
273946d12f91SDave Airlie 
274004da42b4SJouni Högander 	if (!dev_priv->display.params.enable_dpt &&
2741c5de2484SVille Syrjälä 	    intel_fb_modifier_uses_dpt(dev_priv, fb->modifier)) {
2742c5de2484SVille Syrjälä 		drm_dbg_kms(&dev_priv->drm, "DPT disabled, skipping initial FB\n");
2743c5de2484SVille Syrjälä 		goto error;
2744c5de2484SVille Syrjälä 	}
2745c5de2484SVille Syrjälä 
274646d12f91SDave Airlie 	/*
274746d12f91SDave Airlie 	 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
274846d12f91SDave Airlie 	 * while i915 HW rotation is clockwise, thats why this swapping.
274946d12f91SDave Airlie 	 */
275046d12f91SDave Airlie 	switch (val & PLANE_CTL_ROTATE_MASK) {
275146d12f91SDave Airlie 	case PLANE_CTL_ROTATE_0:
275246d12f91SDave Airlie 		plane_config->rotation = DRM_MODE_ROTATE_0;
275346d12f91SDave Airlie 		break;
275446d12f91SDave Airlie 	case PLANE_CTL_ROTATE_90:
275546d12f91SDave Airlie 		plane_config->rotation = DRM_MODE_ROTATE_270;
275646d12f91SDave Airlie 		break;
275746d12f91SDave Airlie 	case PLANE_CTL_ROTATE_180:
275846d12f91SDave Airlie 		plane_config->rotation = DRM_MODE_ROTATE_180;
275946d12f91SDave Airlie 		break;
276046d12f91SDave Airlie 	case PLANE_CTL_ROTATE_270:
276146d12f91SDave Airlie 		plane_config->rotation = DRM_MODE_ROTATE_90;
276246d12f91SDave Airlie 		break;
276346d12f91SDave Airlie 	}
276446d12f91SDave Airlie 
2765c988d2dcSLucas De Marchi 	if (DISPLAY_VER(dev_priv) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
276646d12f91SDave Airlie 		plane_config->rotation |= DRM_MODE_REFLECT_X;
276746d12f91SDave Airlie 
276846d12f91SDave Airlie 	/* 90/270 degree rotation would require extra work */
276946d12f91SDave Airlie 	if (drm_rotation_90_or_270(plane_config->rotation))
277046d12f91SDave Airlie 		goto error;
277146d12f91SDave Airlie 
277212d7d858SVille Syrjälä 	base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & PLANE_SURF_ADDR_MASK;
277346d12f91SDave Airlie 	plane_config->base = base;
277446d12f91SDave Airlie 
277546d12f91SDave Airlie 	offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
277647e157a5SJani Nikula 	drm_WARN_ON(&dev_priv->drm, offset != 0);
277746d12f91SDave Airlie 
277846d12f91SDave Airlie 	val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
277912d7d858SVille Syrjälä 	fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1;
278012d7d858SVille Syrjälä 	fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1;
278146d12f91SDave Airlie 
278246d12f91SDave Airlie 	val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
278346d12f91SDave Airlie 	stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2784e7367af1SJuha-Pekka Heikkilä 
278512d7d858SVille Syrjälä 	fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult;
278646d12f91SDave Airlie 
278746d12f91SDave Airlie 	aligned_height = intel_fb_align_height(fb, 0, fb->height);
278846d12f91SDave Airlie 
278946d12f91SDave Airlie 	plane_config->size = fb->pitches[0] * aligned_height;
279046d12f91SDave Airlie 
279146d12f91SDave Airlie 	drm_dbg_kms(&dev_priv->drm,
279246d12f91SDave Airlie 		    "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
279346d12f91SDave Airlie 		    crtc->base.name, plane->base.name, fb->width, fb->height,
279446d12f91SDave Airlie 		    fb->format->cpp[0] * 8, base, fb->pitches[0],
279546d12f91SDave Airlie 		    plane_config->size);
279646d12f91SDave Airlie 
279746d12f91SDave Airlie 	plane_config->fb = intel_fb;
279846d12f91SDave Airlie 	return;
279946d12f91SDave Airlie 
280046d12f91SDave Airlie error:
280146d12f91SDave Airlie 	kfree(intel_fb);
280246d12f91SDave Airlie }
2803a8153627SVille Syrjälä 
skl_fixup_initial_plane_config(struct intel_crtc * crtc,const struct intel_initial_plane_config * plane_config)2804a8153627SVille Syrjälä bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
2805a8153627SVille Syrjälä 				    const struct intel_initial_plane_config *plane_config)
2806a8153627SVille Syrjälä {
2807a8153627SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
2808a8153627SVille Syrjälä 	struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2809a8153627SVille Syrjälä 	const struct intel_plane_state *plane_state =
2810a8153627SVille Syrjälä 		to_intel_plane_state(plane->base.state);
2811a8153627SVille Syrjälä 	enum plane_id plane_id = plane->id;
2812a8153627SVille Syrjälä 	enum pipe pipe = crtc->pipe;
2813a8153627SVille Syrjälä 	u32 base;
2814a8153627SVille Syrjälä 
2815a8153627SVille Syrjälä 	if (!plane_state->uapi.visible)
2816a8153627SVille Syrjälä 		return false;
2817a8153627SVille Syrjälä 
2818a8153627SVille Syrjälä 	base = intel_plane_ggtt_offset(plane_state);
2819a8153627SVille Syrjälä 
2820a8153627SVille Syrjälä 	/*
2821a8153627SVille Syrjälä 	 * We may have moved the surface to a different
2822a8153627SVille Syrjälä 	 * part of ggtt, make the plane aware of that.
2823a8153627SVille Syrjälä 	 */
2824a8153627SVille Syrjälä 	if (plane_config->base == base)
2825a8153627SVille Syrjälä 		return false;
2826a8153627SVille Syrjälä 
2827a8153627SVille Syrjälä 	intel_de_write(i915, PLANE_SURF(pipe, plane_id), base);
2828a8153627SVille Syrjälä 
2829a8153627SVille Syrjälä 	return true;
2830a8153627SVille Syrjälä }
2831