brintos

brintos / linux-shallow public Read only

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