xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c (revision b49024d79fb7304f646003fcd8846ef26dea7e92)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2022-2026 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: AMD
24  *
25  */
26 
27 #include <drm/drm_atomic_helper.h>
28 #include <drm/drm_blend.h>
29 #include "drm/drm_framebuffer.h"
30 #include <drm/drm_gem_atomic_helper.h>
31 #include <drm/drm_plane_helper.h>
32 #include <drm/drm_gem_framebuffer_helper.h>
33 #include <drm/drm_fourcc.h>
34 
35 #include "amdgpu.h"
36 #include "dal_asic_id.h"
37 #include "amdgpu_display.h"
38 #include "amdgpu_dm_trace.h"
39 #include "amdgpu_dm_plane.h"
40 #include "dm_helpers.h"
41 #include "amdgpu_dm_colorop.h"
42 #include "gc/gc_11_0_0_offset.h"
43 #include "gc/gc_11_0_0_sh_mask.h"
44 
45 /*
46  * TODO: these are currently initialized to rgb formats only.
47  * For future use cases we should either initialize them dynamically based on
48  * plane capabilities, or initialize this array to all formats, so internal drm
49  * check will succeed, and let DC implement proper check
50  */
51 static const uint32_t rgb_formats[] = {
52 	DRM_FORMAT_XRGB8888,
53 	DRM_FORMAT_ARGB8888,
54 	DRM_FORMAT_RGBA8888,
55 	DRM_FORMAT_XRGB2101010,
56 	DRM_FORMAT_XBGR2101010,
57 	DRM_FORMAT_ARGB2101010,
58 	DRM_FORMAT_ABGR2101010,
59 	DRM_FORMAT_XRGB16161616,
60 	DRM_FORMAT_XBGR16161616,
61 	DRM_FORMAT_ARGB16161616,
62 	DRM_FORMAT_ABGR16161616,
63 	DRM_FORMAT_XBGR8888,
64 	DRM_FORMAT_ABGR8888,
65 	DRM_FORMAT_RGB565,
66 };
67 
68 static const uint32_t overlay_formats[] = {
69 	DRM_FORMAT_XRGB8888,
70 	DRM_FORMAT_ARGB8888,
71 	DRM_FORMAT_RGBA8888,
72 	DRM_FORMAT_XBGR8888,
73 	DRM_FORMAT_ABGR8888,
74 	DRM_FORMAT_RGB565,
75 	DRM_FORMAT_NV21,
76 	DRM_FORMAT_NV12,
77 	DRM_FORMAT_P010
78 };
79 
80 static const uint32_t video_formats[] = {
81 	DRM_FORMAT_NV21,
82 	DRM_FORMAT_NV12,
83 	DRM_FORMAT_P010
84 };
85 
86 static const u32 cursor_formats[] = {
87 	DRM_FORMAT_ARGB8888
88 };
89 
90 enum dm_micro_swizzle {
91 	MICRO_SWIZZLE_Z = 0,
92 	MICRO_SWIZZLE_S = 1,
93 	MICRO_SWIZZLE_D = 2,
94 	MICRO_SWIZZLE_R = 3
95 };
96 
amdgpu_dm_plane_get_format_info(u32 pixel_format,u64 modifier)97 const struct drm_format_info *amdgpu_dm_plane_get_format_info(u32 pixel_format, u64 modifier)
98 {
99 	return amdgpu_lookup_format_info(pixel_format, modifier);
100 }
101 EXPORT_IF_KUNIT(amdgpu_dm_plane_get_format_info);
102 
amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state * plane_state,bool * per_pixel_alpha,bool * pre_multiplied_alpha,bool * global_alpha,int * global_alpha_value)103 void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
104 			       bool *per_pixel_alpha, bool *pre_multiplied_alpha,
105 			       bool *global_alpha, int *global_alpha_value)
106 {
107 	*per_pixel_alpha = false;
108 	*pre_multiplied_alpha = true;
109 	*global_alpha = false;
110 	*global_alpha_value = 0xff;
111 
112 
113 	if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
114 		plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
115 		static const uint32_t alpha_formats[] = {
116 			DRM_FORMAT_ARGB8888,
117 			DRM_FORMAT_RGBA8888,
118 			DRM_FORMAT_ABGR8888,
119 			DRM_FORMAT_ARGB2101010,
120 			DRM_FORMAT_ABGR2101010,
121 			DRM_FORMAT_ARGB16161616,
122 			DRM_FORMAT_ABGR16161616,
123 			DRM_FORMAT_ARGB16161616F,
124 		};
125 		uint32_t format = plane_state->fb->format->format;
126 		unsigned int i;
127 
128 		for (i = 0; i < ARRAY_SIZE(alpha_formats); ++i) {
129 			if (format == alpha_formats[i]) {
130 				*per_pixel_alpha = true;
131 				break;
132 			}
133 		}
134 
135 		if (*per_pixel_alpha && plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE)
136 			*pre_multiplied_alpha = false;
137 	}
138 
139 	if (plane_state->alpha < 0xffff) {
140 		struct amdgpu_device *adev = drm_to_adev(plane_state->plane->dev);
141 		*global_alpha = true;
142 		/*
143 		 * DCN 4.2 uses a 12-bit MPCC_GLOBAL_ALPHA field, while
144 		 * other ASICs use an 8-bit field. The DRM plane alpha is
145 		 * 16-bit, so scale it down to the width the hardware expects.
146 		 */
147 		if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0)
148 		    || amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(6, 0, 0))
149 			*global_alpha_value = plane_state->alpha >> 4;
150 		else
151 			*global_alpha_value = plane_state->alpha >> 8;
152 
153 	}
154 }
155 EXPORT_IF_KUNIT(amdgpu_dm_plane_fill_blending_from_plane_state);
156 
amdgpu_dm_plane_add_modifier(uint64_t ** mods,uint64_t * size,uint64_t * cap,uint64_t mod)157 STATIC_IFN_KUNIT void amdgpu_dm_plane_add_modifier(uint64_t **mods, uint64_t *size,
158 						   uint64_t *cap, uint64_t mod)
159 {
160 	if (!*mods)
161 		return;
162 
163 	if (*cap - *size < 1) {
164 		uint64_t new_cap = *cap * 2;
165 		uint64_t *new_mods = kmalloc_array(new_cap, sizeof(uint64_t), GFP_KERNEL);
166 
167 		if (!new_mods) {
168 			kfree(*mods);
169 			*mods = NULL;
170 			return;
171 		}
172 
173 		memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
174 		kfree(*mods);
175 		*mods = new_mods;
176 		*cap = new_cap;
177 	}
178 
179 	(*mods)[*size] = mod;
180 	*size += 1;
181 }
182 EXPORT_IF_KUNIT(amdgpu_dm_plane_add_modifier);
183 
amdgpu_dm_plane_add_modifier_dedup(uint64_t ** mods,uint64_t * size,uint64_t * cap,uint64_t mod)184 STATIC_IFN_KUNIT void amdgpu_dm_plane_add_modifier_dedup(uint64_t **mods, uint64_t *size,
185 							 uint64_t *cap, uint64_t mod)
186 {
187 	uint64_t i;
188 
189 	if (!*mods)
190 		return;
191 
192 	for (i = 0; i < *size; ++i)
193 		if ((*mods)[i] == mod)
194 			return;
195 
196 	amdgpu_dm_plane_add_modifier(mods, size, cap, mod);
197 }
198 EXPORT_IF_KUNIT(amdgpu_dm_plane_add_modifier_dedup);
199 
amdgpu_dm_plane_modifier_has_dcc(uint64_t modifier)200 STATIC_IFN_KUNIT bool amdgpu_dm_plane_modifier_has_dcc(uint64_t modifier)
201 {
202 	return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
203 }
204 EXPORT_IF_KUNIT(amdgpu_dm_plane_modifier_has_dcc);
205 
amdgpu_dm_plane_modifier_gfx9_swizzle_mode(uint64_t modifier)206 STATIC_IFN_KUNIT unsigned int amdgpu_dm_plane_modifier_gfx9_swizzle_mode(uint64_t modifier)
207 {
208 	if (modifier == DRM_FORMAT_MOD_LINEAR)
209 		return 0;
210 
211 	return AMD_FMT_MOD_GET(TILE, modifier);
212 }
213 EXPORT_IF_KUNIT(amdgpu_dm_plane_modifier_gfx9_swizzle_mode);
214 
amdgpu_dm_plane_fill_gfx6_tiling_info_from_modifier(struct dc_tiling_info * tiling_info,uint64_t modifier)215 STATIC_IFN_KUNIT int amdgpu_dm_plane_fill_gfx6_tiling_info_from_modifier(
216 						struct dc_tiling_info *tiling_info,
217 						uint64_t modifier)
218 {
219 	if (modifier == DRM_FORMAT_MOD_LINEAR) {
220 		tiling_info->gfx8.array_mode = DC_ARRAY_LINEAR_GENERAL;
221 		tiling_info->gfxversion = DcGfxVersion8;
222 
223 		return 0;
224 	}
225 
226 	if (!IS_AMD_FMT_MOD(modifier))
227 		return -EINVAL;
228 
229 	if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) != AMD_FMT_MOD_TILE_VER_GFX6)
230 		return -EINVAL;
231 
232 	tiling_info->gfx8.array_mode = AMD_FMT_MOD_GET(TILE, modifier);
233 	tiling_info->gfxversion = DcGfxVersion8;
234 	tiling_info->gfx8.tile_mode = AMD_FMT_MOD_GET(MICROTILE, modifier);
235 
236 	if (AMD_FMT_MOD_GET(TILE, modifier) < AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1)
237 		return 0;
238 
239 	tiling_info->gfx8.pipe_config = AMD_FMT_MOD_GET(PIPE_CONFIG, modifier);
240 	tiling_info->gfx8.tile_split = AMD_FMT_MOD_GET(TILE_SPLIT, modifier);
241 	tiling_info->gfx8.bank_width = AMD_FMT_MOD_GET(BANK_WIDTH, modifier);
242 	tiling_info->gfx8.bank_height = AMD_FMT_MOD_GET(BANK_HEIGHT, modifier);
243 	tiling_info->gfx8.tile_aspect = AMD_FMT_MOD_GET(MACRO_TILE_ASPECT, modifier);
244 	tiling_info->gfx8.num_banks = AMD_FMT_MOD_GET(NUM_BANKS, modifier);
245 
246 	return 0;
247 }
248 EXPORT_IF_KUNIT(amdgpu_dm_plane_fill_gfx6_tiling_info_from_modifier);
249 
amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(const struct amdgpu_device * adev,struct dc_tiling_info * tiling_info)250 STATIC_IFN_KUNIT void amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
251 									struct dc_tiling_info *tiling_info)
252 {
253 	/* Fill GFX9 params */
254 	tiling_info->gfx9.num_pipes =
255 		adev->gfx.config.gb_addr_config_fields.num_pipes;
256 	tiling_info->gfx9.num_banks =
257 		adev->gfx.config.gb_addr_config_fields.num_banks;
258 	tiling_info->gfx9.pipe_interleave =
259 		adev->gfx.config.gb_addr_config_fields.pipe_interleave_size;
260 	tiling_info->gfx9.num_shader_engines =
261 		adev->gfx.config.gb_addr_config_fields.num_se;
262 	tiling_info->gfx9.max_compressed_frags =
263 		adev->gfx.config.gb_addr_config_fields.max_compress_frags;
264 	tiling_info->gfx9.num_rb_per_se =
265 		adev->gfx.config.gb_addr_config_fields.num_rb_per_se;
266 	tiling_info->gfx9.shaderEnable = 1;
267 	if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
268 		tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs;
269 }
270 EXPORT_IF_KUNIT(amdgpu_dm_plane_fill_gfx9_tiling_info_from_device);
271 
amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device * adev,struct dc_tiling_info * tiling_info,uint64_t modifier)272 STATIC_IFN_KUNIT void amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
273 									  struct dc_tiling_info *tiling_info,
274 									  uint64_t modifier)
275 {
276 	unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
277 	unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
278 	unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier);
279 	unsigned int pipes_log2;
280 
281 	pipes_log2 = min(5u, mod_pipe_xor_bits);
282 
283 	amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, tiling_info);
284 
285 	if (!IS_AMD_FMT_MOD(modifier))
286 		return;
287 
288 	tiling_info->gfx9.num_pipes = 1u << pipes_log2;
289 	tiling_info->gfx9.num_shader_engines = 1u << (mod_pipe_xor_bits - pipes_log2);
290 
291 	if (adev->family >= AMDGPU_FAMILY_NV) {
292 		tiling_info->gfx9.num_pkrs = 1u << pkrs_log2;
293 	} else {
294 		tiling_info->gfx9.num_banks = 1u << mod_bank_xor_bits;
295 
296 		/* for DCC we know it isn't rb aligned, so rb_per_se doesn't matter. */
297 	}
298 }
299 EXPORT_IF_KUNIT(amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier);
300 
amdgpu_dm_plane_validate_dcc(struct amdgpu_device * adev,const enum surface_pixel_format format,const enum dc_rotation_angle rotation,const struct dc_tiling_info * tiling_info,const struct dc_plane_dcc_param * dcc,const struct dc_plane_address * address,const struct plane_size * plane_size)301 STATIC_IFN_KUNIT int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev,
302 						  const enum surface_pixel_format format,
303 						  const enum dc_rotation_angle rotation,
304 						  const struct dc_tiling_info *tiling_info,
305 						  const struct dc_plane_dcc_param *dcc,
306 						  const struct dc_plane_address *address,
307 						  const struct plane_size *plane_size)
308 {
309 	struct dc *dc = adev->dm.dc;
310 	struct dc_dcc_surface_param input;
311 	struct dc_surface_dcc_cap output;
312 
313 	memset(&input, 0, sizeof(input));
314 	memset(&output, 0, sizeof(output));
315 
316 	if (!dcc->enable)
317 		return 0;
318 
319 	if (adev->family != AMDGPU_FAMILY_GC_12_0_0 &&
320 	    adev->family != AMDGPU_FAMILY_GC_13_0_1 &&
321 	    format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
322 		return -EINVAL;
323 
324 	if (!dc->cap_funcs.get_dcc_compression_cap)
325 		return -EINVAL;
326 
327 	input.format = format;
328 	input.surface_size.width = plane_size->surface_size.width;
329 	input.surface_size.height = plane_size->surface_size.height;
330 	input.swizzle_mode = tiling_info->gfx9.swizzle;
331 
332 	if (rotation == ROTATION_ANGLE_0 || rotation == ROTATION_ANGLE_180)
333 		input.scan = SCAN_DIRECTION_HORIZONTAL;
334 	else if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270)
335 		input.scan = SCAN_DIRECTION_VERTICAL;
336 
337 	if (!dc->cap_funcs.get_dcc_compression_cap(dc, &input, &output))
338 		return -EINVAL;
339 
340 	if (!output.capable)
341 		return -EINVAL;
342 
343 	if (dcc->independent_64b_blks == 0 &&
344 	    output.grph.rgb.independent_64b_blks != 0)
345 		return -EINVAL;
346 
347 	return 0;
348 }
349 EXPORT_IF_KUNIT(amdgpu_dm_plane_validate_dcc);
350 
amdgpu_dm_plane_fill_gfx9_attrs_from_modifiers(struct amdgpu_device * adev,const struct amdgpu_framebuffer * afb,const enum surface_pixel_format format,const enum dc_rotation_angle rotation,const struct plane_size * plane_size,struct dc_tiling_info * tiling_info,struct dc_plane_dcc_param * dcc,struct dc_plane_address * address)351 STATIC_IFN_KUNIT int amdgpu_dm_plane_fill_gfx9_attrs_from_modifiers(struct amdgpu_device *adev,
352 									       const struct amdgpu_framebuffer *afb,
353 									       const enum surface_pixel_format format,
354 									       const enum dc_rotation_angle rotation,
355 									       const struct plane_size *plane_size,
356 									       struct dc_tiling_info *tiling_info,
357 									       struct dc_plane_dcc_param *dcc,
358 									       struct dc_plane_address *address)
359 {
360 	const uint64_t modifier = afb->base.modifier;
361 	int ret = 0;
362 
363 	amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
364 	tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier);
365 	tiling_info->gfxversion = DcGfxVersion9;
366 
367 	if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
368 		uint64_t dcc_address = afb->address + afb->base.offsets[1];
369 		bool independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier);
370 		bool independent_128b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier);
371 
372 		dcc->enable = 1;
373 		dcc->meta_pitch = afb->base.pitches[1];
374 		dcc->independent_64b_blks = independent_64b_blks;
375 		if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) {
376 			if (independent_64b_blks && independent_128b_blks)
377 				dcc->dcc_ind_blk = hubp_ind_block_64b_no_128bcl;
378 			else if (independent_128b_blks)
379 				dcc->dcc_ind_blk = hubp_ind_block_128b;
380 			else if (independent_64b_blks && !independent_128b_blks)
381 				dcc->dcc_ind_blk = hubp_ind_block_64b;
382 			else
383 				dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
384 		} else {
385 			if (independent_64b_blks)
386 				dcc->dcc_ind_blk = hubp_ind_block_64b;
387 			else
388 				dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
389 		}
390 
391 		address->grph.meta_addr.low_part = lower_32_bits(dcc_address);
392 		address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
393 	}
394 
395 	ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
396 	if (ret)
397 		drm_dbg_kms(adev_to_drm(adev), "amdgpu_dm_plane_validate_dcc: returned error: %pe\n", ERR_PTR(ret));
398 
399 	return ret;
400 }
401 EXPORT_IF_KUNIT(amdgpu_dm_plane_fill_gfx9_attrs_from_modifiers);
402 
amdgpu_dm_plane_fill_gfx12_attrs_from_modifiers(struct amdgpu_device * adev,const struct amdgpu_framebuffer * afb,const enum surface_pixel_format format,const enum dc_rotation_angle rotation,const struct plane_size * plane_size,struct dc_tiling_info * tiling_info,struct dc_plane_dcc_param * dcc,struct dc_plane_address * address)403 STATIC_IFN_KUNIT int amdgpu_dm_plane_fill_gfx12_attrs_from_modifiers(struct amdgpu_device *adev,
404 										const struct amdgpu_framebuffer *afb,
405 										const enum surface_pixel_format format,
406 										const enum dc_rotation_angle rotation,
407 										const struct plane_size *plane_size,
408 										struct dc_tiling_info *tiling_info,
409 										struct dc_plane_dcc_param *dcc,
410 										struct dc_plane_address *address)
411 {
412 	const uint64_t modifier = afb->base.modifier;
413 	int ret = 0;
414 
415 	/* TODO: Most of this function shouldn't be needed on GFX12. */
416 	amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, tiling_info);
417 
418 	tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier);
419 	tiling_info->gfxversion = DcGfxAddr3;
420 
421 	if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
422 		int max_compressed_block = AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier);
423 
424 		dcc->enable = 1;
425 		dcc->independent_64b_blks = max_compressed_block == 0;
426 
427 		if (max_compressed_block == 0)
428 			dcc->dcc_ind_blk = hubp_ind_block_64b;
429 		else if (max_compressed_block == 1)
430 			dcc->dcc_ind_blk = hubp_ind_block_128b;
431 		else
432 			dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
433 	}
434 
435 	/* TODO: This seems wrong because there is no DCC plane on GFX12. */
436 	ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
437 	if (ret)
438 		drm_dbg_kms(adev_to_drm(adev), "amdgpu_dm_plane_validate_dcc: returned: %pe\n", ERR_PTR(ret));
439 
440 	return ret;
441 }
442 EXPORT_IF_KUNIT(amdgpu_dm_plane_fill_gfx12_attrs_from_modifiers);
443 
amdgpu_dm_plane_add_gfx10_1_modifiers(const struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)444 static void amdgpu_dm_plane_add_gfx10_1_modifiers(const struct amdgpu_device *adev,
445 						  uint64_t **mods,
446 						  uint64_t *size,
447 						  uint64_t *capacity)
448 {
449 	int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
450 
451 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
452 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
453 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
454 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
455 				     AMD_FMT_MOD_SET(DCC, 1) |
456 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
457 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
458 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
459 
460 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
461 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
462 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
463 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
464 				     AMD_FMT_MOD_SET(DCC, 1) |
465 				     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
466 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
467 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
468 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
469 
470 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
471 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
472 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
473 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
474 
475 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
476 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
477 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
478 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
479 
480 
481 	/* Only supported for 64bpp, will be filtered in amdgpu_dm_plane_format_mod_supported */
482 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
483 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
484 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
485 
486 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
487 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
488 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
489 }
490 
491 /**
492  * amdgpu_dm_plane_get_gfx6_tile_idx() - Get tile mode index on GFX6-8
493  *
494  * @adev: amdgpu_device pointer
495  * @bpp: bits per pixel in the image
496  * @arr: array mode (aka. tile mode) of the image layout
497  *
498  * Select which tiling mode from the table is suitable for the given bits per pixel
499  * using the given array mode, assuming the displayable micro tile mode is used.
500  *
501  * On GFX6-8, the GFX block can only use pre-programmed tiling modes from GB_TILE_MODEn
502  * registers which are programmed by the kernel according to the tiling mode table.
503  * Note that the tiling table is uAPI and userspace relies on specific modes being
504  * present at specific indices.
505  * See SiLib::HwlSetupTileInfo() and CiLib::HwlSetupTileInfo() in addrlib.
506  */
amdgpu_dm_plane_get_gfx6_tile_idx(const struct amdgpu_device * adev,const u32 bpp,const enum array_mode_values arr)507 static u32 amdgpu_dm_plane_get_gfx6_tile_idx(const struct amdgpu_device *adev,
508 					 const u32 bpp,
509 					 const enum array_mode_values arr)
510 {
511 	/* Assume that the microtile mode is DISPLAY. */
512 
513 	if (arr == DC_ARRAY_1D_TILED_THIN1)
514 		return 9;
515 
516 	ASSERT(arr == DC_ARRAY_2D_TILED_THIN1);
517 
518 	if (adev->family > AMDGPU_FAMILY_SI)
519 		return 10;
520 
521 	switch (bpp) {
522 	case 8:
523 		return 10;
524 	case 16:
525 		return 11;
526 	default:
527 		return 12;
528 	}
529 }
530 
531 /**
532  * amdgpu_dm_plane_calc_gfx7_tile_split() - Calculate tile split on GFX7-8
533  *
534  * @adev: amdgpu_device pointer
535  * @bpp: bits per pixel in the image
536  * @gb_tile_mode: GB_TILE_MODEn register value for the current tiling mode
537  *
538  * Calculate the actual tile split value on GFX7-8, assuming 2D_TILED_THIN1 array mode
539  * with a non-depth micro tile mode.
540  *
541  * On GFX7-8, SAMPLE_SPLIT holds a factor from which the actual tile split bytes
542  * can be calculated. The TILE_SPLIT field is only used for the depth micro tile mode.
543  * See CiLib::HwlComputeMacroModeIndex() in addrlib.
544  */
amdgpu_dm_plane_calc_gfx7_tile_split(const struct amdgpu_device * adev,const u32 bpp,const u32 gb_tile_mode)545 static u32 amdgpu_dm_plane_calc_gfx7_tile_split(const struct amdgpu_device *adev,
546 						const u32 bpp,
547 						const u32 gb_tile_mode)
548 {
549 	/* Assume 2D_TILED_THIN1 mode with non-DEPTH microtiles */
550 	const u32 sample_split = (gb_tile_mode >> 25) & 0x3;
551 	const u32 thickness = 1;
552 	const u32 tile_size_pixels = 8 * 8;
553 	const u32 tile_bytes_1x = tile_size_pixels * bpp * thickness / 8;
554 	const u32 sample_split_factor = 1 << sample_split;
555 
556 	return clamp(tile_bytes_1x * sample_split_factor,
557 		     256,
558 		     adev->gfx.config.mem_row_size_in_kb * 1024);
559 }
560 
561 /**
562  * amdgpu_dm_plane_get_gfx7_macro_tile_idx() - Get macro tile mode index on GFX7-8
563  *
564  * @bpp: bits per pixel in the image
565  * @tile_split_bytes: actual tile split bytes, see amdgpu_dm_plane_calc_gfx7_tile_split()
566  *
567  * Select which macro tiling mode from the table is suitable for the given bits per pixel,
568  * assuming 2D_TILED_THIN1 array mode and DISPLAY micro tile mode (and no multisampling).
569  * Note that the tiling table is uAPI and userspace relies on specific modes being
570  * present at specific indices.
571  * See CiLib::HwlComputeMacroModeIndex() in addrlib.
572  */
amdgpu_dm_plane_get_gfx7_macro_tile_idx(const u32 bpp,const u32 tile_split_bytes)573 static u32 amdgpu_dm_plane_get_gfx7_macro_tile_idx(const u32 bpp, const u32 tile_split_bytes)
574 {
575 	const u32 thickness = 1;
576 	const u32 tile_size_pixels = 8 * 8;
577 	const u32 tile_bytes_1x = thickness * tile_size_pixels * bpp / 8;
578 	const u32 tile_bytes = clamp(tile_bytes_1x, 64, tile_split_bytes);
579 	const u32 macro_tile_idx = ilog2(tile_bytes / 64);
580 
581 	WARN_ON(macro_tile_idx >= 16);
582 
583 	return macro_tile_idx;
584 }
585 
586 /**
587  * amdgpu_dm_plane_calc_gfx6_mod() - Calculate a DRM format modifier for GFX6-8
588  *
589  * @adev: amdgpu_device pointer
590  * @bpp: bits per pixel in the image
591  * @arr: array mode (aka. tile mode) of the image layout
592  *
593  * Select suitable micro and macro tile modes for the given bits per pixel,
594  * and calculate the corresponding DRM format modifier.
595  */
amdgpu_dm_plane_calc_gfx6_mod(const struct amdgpu_device * adev,const u32 bpp,const enum array_mode_values arr)596 static u64 amdgpu_dm_plane_calc_gfx6_mod(const struct amdgpu_device *adev,
597 					 const u32 bpp,
598 					 const enum array_mode_values arr)
599 {
600 	u32 array_mode, micro_tile_mode, tile_split_bytes;
601 	u32 gb_macrotile_mode, macrotile_idx;
602 	u32 gb_tile_mode, tile_idx;
603 
604 	u64 modifier_base =
605 		AMD_FMT_MOD |
606 		AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX6) |
607 		AMD_FMT_MOD_SET(TILE, arr) |
608 		AMD_FMT_MOD_SET(MICROTILE, AMD_FMT_MOD_MICROTILE_DISPLAY);
609 
610 	if (arr < DC_ARRAY_2D_TILED_THIN1)
611 		return modifier_base;
612 
613 	tile_idx = amdgpu_dm_plane_get_gfx6_tile_idx(adev, bpp, arr);
614 	gb_tile_mode = adev->gfx.config.tile_mode_array[tile_idx];
615 	array_mode = (gb_tile_mode >> 2) & 0xf;
616 
617 	if (adev->family == AMDGPU_FAMILY_SI) {
618 		micro_tile_mode = (gb_tile_mode >> 0) & 0x3;
619 		tile_split_bytes = 64 << ((gb_tile_mode >> 11) & 0x7);
620 	} else {
621 		micro_tile_mode = (gb_tile_mode >> 22) & 0x7;
622 		tile_split_bytes = amdgpu_dm_plane_calc_gfx7_tile_split(adev, bpp, gb_tile_mode);
623 	}
624 
625 	ASSERT(array_mode == arr);
626 	ASSERT(micro_tile_mode == AMD_FMT_MOD_MICROTILE_DISPLAY);
627 
628 	modifier_base |=
629 		AMD_FMT_MOD_SET(PIPE_CONFIG, (gb_tile_mode >> 6) & 0x1f) |
630 		AMD_FMT_MOD_SET(TILE_SPLIT, ilog2(tile_split_bytes / 64));
631 
632 	if (adev->family == AMDGPU_FAMILY_SI)
633 		return modifier_base |
634 			AMD_FMT_MOD_SET(BANK_WIDTH, (gb_tile_mode >> 14) & 0x3) |
635 			AMD_FMT_MOD_SET(BANK_HEIGHT, (gb_tile_mode >> 16) & 0x3) |
636 			AMD_FMT_MOD_SET(MACRO_TILE_ASPECT, (gb_tile_mode >> 18) & 0x3) |
637 			AMD_FMT_MOD_SET(NUM_BANKS, (gb_tile_mode >> 20) & 0x3);
638 
639 	macrotile_idx = amdgpu_dm_plane_get_gfx7_macro_tile_idx(bpp, tile_split_bytes);
640 	gb_macrotile_mode = adev->gfx.config.macrotile_mode_array[macrotile_idx];
641 
642 	return modifier_base |
643 		AMD_FMT_MOD_SET(BANK_WIDTH, (gb_macrotile_mode >> 0) & 0x3) |
644 		AMD_FMT_MOD_SET(BANK_HEIGHT, (gb_macrotile_mode >> 2) & 0x3) |
645 		AMD_FMT_MOD_SET(MACRO_TILE_ASPECT, (gb_macrotile_mode >> 4) & 0x3) |
646 		AMD_FMT_MOD_SET(NUM_BANKS, (gb_macrotile_mode >> 6) & 0x3);
647 }
648 
649 /**
650  * amdgpu_dm_plane_gfx6_format_mod_supported() - Check if a modifier is supported on GFX6-8
651  *
652  * @adev: amdgpu_device pointer
653  * @bpp: bits per pixel in the image
654  * @modifier: the modifier whose support we check
655  *
656  * On GFX6-8, not all DRM format modifier can be used with all image formats.
657  * Check whether the specified modifier is supported with the given bits per pixel value.
658  */
amdgpu_dm_plane_gfx6_format_mod_supported(const struct amdgpu_device * adev,const u32 bpp,const u64 modifier)659 static bool amdgpu_dm_plane_gfx6_format_mod_supported(const struct amdgpu_device *adev,
660 						      const u32 bpp,
661 						      const u64 modifier)
662 {
663 	const u32 array_mode = AMD_FMT_MOD_GET(TILE, modifier);
664 	const u32 micro_tile_mode = AMD_FMT_MOD_GET(MICROTILE, modifier);
665 
666 	if (!IS_AMD_FMT_MOD(modifier))
667 		return false;
668 
669 	/* GFX9 and newer format modifiers are not supported on GFX6-8. */
670 	if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) != AMD_FMT_MOD_TILE_VER_GFX6)
671 		return false;
672 
673 	/* GFX8 and older format modifiers are not supported on GFX9+. */
674 	if (adev->family >= AMDGPU_FAMILY_AI)
675 		return false;
676 
677 	/* GFX6-7 doesn't have any DCC, GFX8 doesn't support displayable DCC. */
678 	if (AMD_FMT_MOD_GET(DCC, modifier))
679 		return false;
680 
681 	/*
682 	 * For now, only expose 1D and 2D tiles THIN array modes.
683 	 * Linear is already exposed through DRM_FORMAT_MOD_LINEAR.
684 	 */
685 	if (array_mode != AMD_FMT_MOD_TILE_GFX6_1D_TILED_THIN1 &&
686 	    array_mode != AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1)
687 		return false;
688 
689 	/*
690 	 * For now, only allow DISPLAY micro tile mode.
691 	 * THIN, DEPTH and THICK modes are not displayable.
692 	 * ROTATED has never been supported by Linux or Mesa.
693 	 */
694 	if (micro_tile_mode != AMD_FMT_MOD_MICROTILE_DISPLAY)
695 		return false;
696 
697 	/* Verify that the modifier is the same that we'd expose for this bpp */
698 	return amdgpu_dm_plane_calc_gfx6_mod(adev, bpp, array_mode) == modifier;
699 }
700 
701 /**
702  * amdgpu_dm_plane_add_gfx6_modifiers() - Expose modifiers for GFX6-8
703  *
704  * @adev: amdgpu_device pointer
705  * @mods: Pointer to array of format modifiers
706  * @size: Pointer to size of the array
707  * @capacity: Pointer to capacity of the array
708  *
709  * Calculate a DRM format modifier for macro tiled modes for each supported
710  * bits per pixel value. Use de-duplication because on some GPUs it may happen
711  * that different bpp results in the exact same macro tiling mode, depending
712  * on the tiling table.
713  *
714  * Also expose a micro tiled only mode. This is less optimal, but supported.
715  */
amdgpu_dm_plane_add_gfx6_modifiers(const struct amdgpu_device * adev,u64 ** mods,u64 * size,u64 * capacity)716 static void amdgpu_dm_plane_add_gfx6_modifiers(const struct amdgpu_device *adev,
717 					       u64 **mods,
718 					       u64 *size,
719 					       u64 *capacity)
720 {
721 	/* 2D tiled displayable */
722 	amdgpu_dm_plane_add_modifier(mods, size, capacity,
723 		amdgpu_dm_plane_calc_gfx6_mod(adev, 16, DC_ARRAY_2D_TILED_THIN1));
724 	amdgpu_dm_plane_add_modifier_dedup(mods, size, capacity,
725 		amdgpu_dm_plane_calc_gfx6_mod(adev, 32, DC_ARRAY_2D_TILED_THIN1));
726 	amdgpu_dm_plane_add_modifier_dedup(mods, size, capacity,
727 		amdgpu_dm_plane_calc_gfx6_mod(adev, 64, DC_ARRAY_2D_TILED_THIN1));
728 
729 	/* 1D tiled displayable */
730 	amdgpu_dm_plane_add_modifier(mods, size, capacity,
731 		amdgpu_dm_plane_calc_gfx6_mod(adev, 0, DC_ARRAY_1D_TILED_THIN1));
732 }
733 
amdgpu_dm_plane_add_gfx9_modifiers(const struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)734 static void amdgpu_dm_plane_add_gfx9_modifiers(const struct amdgpu_device *adev,
735 					       uint64_t **mods,
736 					       uint64_t *size,
737 					       uint64_t *capacity)
738 {
739 	int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
740 	int pipe_xor_bits = min(8, pipes +
741 				ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
742 	int bank_xor_bits = min(8 - pipe_xor_bits,
743 				ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
744 	int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
745 		 ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
746 
747 
748 	if (adev->family == AMDGPU_FAMILY_RV) {
749 		/* Raven2 and later */
750 		bool has_constant_encode = adev->asic_type > CHIP_RAVEN || adev->external_rev_id >= 0x81;
751 
752 		/*
753 		 * No _D DCC swizzles yet because we only allow 32bpp, which
754 		 * doesn't support _D on DCN
755 		 */
756 
757 		if (has_constant_encode) {
758 			amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
759 						     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
760 						     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
761 						     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
762 						     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
763 						     AMD_FMT_MOD_SET(DCC, 1) |
764 						     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
765 						     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
766 						     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
767 		}
768 
769 		amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
770 					     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
771 					     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
772 					     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
773 					     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
774 					     AMD_FMT_MOD_SET(DCC, 1) |
775 					     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
776 					     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
777 					     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
778 
779 		if (has_constant_encode) {
780 			amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
781 						     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
782 						     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
783 						     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
784 						     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
785 						     AMD_FMT_MOD_SET(DCC, 1) |
786 						     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
787 						     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
788 						     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
789 						     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
790 						     AMD_FMT_MOD_SET(RB, rb) |
791 						     AMD_FMT_MOD_SET(PIPE, pipes));
792 		}
793 
794 		amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
795 					     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
796 					     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
797 					     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
798 					     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
799 					     AMD_FMT_MOD_SET(DCC, 1) |
800 					     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
801 					     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
802 					     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
803 					     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
804 					     AMD_FMT_MOD_SET(RB, rb) |
805 					     AMD_FMT_MOD_SET(PIPE, pipes));
806 	}
807 
808 	/*
809 	 * Only supported for 64bpp on Raven, will be filtered on format in
810 	 * amdgpu_dm_plane_format_mod_supported.
811 	 */
812 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
813 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
814 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
815 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
816 				     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
817 
818 	if (adev->family == AMDGPU_FAMILY_RV) {
819 		amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
820 					     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
821 					     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
822 					     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
823 					     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
824 	}
825 
826 	/*
827 	 * Only supported for 64bpp on Raven, will be filtered on format in
828 	 * amdgpu_dm_plane_format_mod_supported.
829 	 */
830 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
831 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
832 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
833 
834 	if (adev->family == AMDGPU_FAMILY_RV) {
835 		amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
836 					     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
837 					     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
838 	}
839 }
840 
amdgpu_dm_plane_add_gfx10_3_modifiers(const struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)841 static void amdgpu_dm_plane_add_gfx10_3_modifiers(const struct amdgpu_device *adev,
842 						  uint64_t **mods,
843 						  uint64_t *size,
844 						  uint64_t *capacity)
845 {
846 	int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
847 	int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
848 
849 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
850 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
851 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
852 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
853 				     AMD_FMT_MOD_SET(PACKERS, pkrs) |
854 				     AMD_FMT_MOD_SET(DCC, 1) |
855 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
856 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
857 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
858 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
859 
860 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
861 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
862 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
863 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
864 				     AMD_FMT_MOD_SET(PACKERS, pkrs) |
865 				     AMD_FMT_MOD_SET(DCC, 1) |
866 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
867 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
868 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
869 
870 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
871 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
872 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
873 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
874 				     AMD_FMT_MOD_SET(PACKERS, pkrs) |
875 				     AMD_FMT_MOD_SET(DCC, 1) |
876 				     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
877 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
878 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
879 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
880 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
881 
882 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
883 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
884 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
885 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
886 				     AMD_FMT_MOD_SET(PACKERS, pkrs) |
887 				     AMD_FMT_MOD_SET(DCC, 1) |
888 				     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
889 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
890 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
891 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
892 
893 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
894 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
895 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
896 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
897 				     AMD_FMT_MOD_SET(PACKERS, pkrs));
898 
899 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
900 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
901 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
902 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
903 				     AMD_FMT_MOD_SET(PACKERS, pkrs));
904 
905 	/* Only supported for 64bpp, will be filtered in amdgpu_dm_plane_format_mod_supported */
906 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
907 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
908 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
909 
910 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
911 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
912 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
913 }
914 
amdgpu_dm_plane_add_gfx11_modifiers(struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)915 static void amdgpu_dm_plane_add_gfx11_modifiers(struct amdgpu_device *adev,
916 		      uint64_t **mods, uint64_t *size, uint64_t *capacity)
917 {
918 	int num_pipes = 0;
919 	int pipe_xor_bits = 0;
920 	int num_pkrs = 0;
921 	int pkrs = 0;
922 	u32 gb_addr_config;
923 	u8 i = 0;
924 	unsigned int swizzle_r_x;
925 	uint64_t modifier_r_x;
926 	uint64_t modifier_dcc_best;
927 	uint64_t modifier_dcc_4k;
928 
929 	/* TODO: GFX11 IP HW init hasnt finish and we get zero if we read from
930 	 * adev->gfx.config.gb_addr_config_fields.num_{pkrs,pipes}
931 	 */
932 	gb_addr_config = RREG32_SOC15(GC, 0, regGB_ADDR_CONFIG);
933 	ASSERT(gb_addr_config != 0);
934 
935 	num_pkrs = 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS);
936 	pkrs = ilog2(num_pkrs);
937 	num_pipes = 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PIPES);
938 	pipe_xor_bits = ilog2(num_pipes);
939 
940 	for (i = 0; i < 2; i++) {
941 		/* Insert the best one first. */
942 		/* R_X swizzle modes are the best for rendering and DCC requires them. */
943 		if (num_pipes > 16)
944 			swizzle_r_x = !i ? AMD_FMT_MOD_TILE_GFX11_256K_R_X : AMD_FMT_MOD_TILE_GFX9_64K_R_X;
945 		else
946 			swizzle_r_x = !i ? AMD_FMT_MOD_TILE_GFX9_64K_R_X : AMD_FMT_MOD_TILE_GFX11_256K_R_X;
947 
948 		modifier_r_x = AMD_FMT_MOD |
949 			       AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
950 			       AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
951 			       AMD_FMT_MOD_SET(TILE, swizzle_r_x) |
952 			       AMD_FMT_MOD_SET(PACKERS, pkrs);
953 
954 		/* DCC_CONSTANT_ENCODE is not set because it can't vary with gfx11 (it's implied to be 1). */
955 		modifier_dcc_best = modifier_r_x | AMD_FMT_MOD_SET(DCC, 1) |
956 				    AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 0) |
957 				    AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
958 				    AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B);
959 
960 		/* DCC settings for 4K and greater resolutions. (required by display hw) */
961 		modifier_dcc_4k = modifier_r_x | AMD_FMT_MOD_SET(DCC, 1) |
962 				  AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
963 				  AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
964 				  AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B);
965 
966 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_best);
967 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_4k);
968 
969 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_best | AMD_FMT_MOD_SET(DCC_RETILE, 1));
970 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_4k | AMD_FMT_MOD_SET(DCC_RETILE, 1));
971 
972 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_r_x);
973 	}
974 
975 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
976 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
977 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D));
978 }
979 
amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)980 static void amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device *adev,
981 		      uint64_t **mods, uint64_t *size, uint64_t *capacity)
982 {
983 	uint64_t ver = AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12);
984 	uint64_t mod_256k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_256K_2D);
985 	uint64_t mod_64k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D);
986 	uint64_t mod_4k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_4K_2D);
987 	uint64_t mod_256b = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_256B_2D);
988 	uint64_t dcc = ver | AMD_FMT_MOD_SET(DCC, 1);
989 	uint8_t max_comp_block[] = {2, 1, 0};
990 	uint64_t max_comp_block_mod[ARRAY_SIZE(max_comp_block)] = {0};
991 	uint8_t i = 0, j = 0;
992 	/* Note, linear (no DCC) gets added to the modifier list for all chips by the caller. */
993 	uint64_t gfx12_modifiers[] = {mod_256k, mod_64k, mod_4k, mod_256b};
994 
995 	for (i = 0; i < ARRAY_SIZE(max_comp_block); i++)
996 		max_comp_block_mod[i] = AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_comp_block[i]);
997 
998 	/* With DCC: Best choice should be kept first. Hence, add all 256k modifiers of different
999 	 * max compressed blocks first and then move on to the next smaller sized layouts.
1000 	 */
1001 	for (j = 0; j < ARRAY_SIZE(gfx12_modifiers); j++)
1002 		for (i = 0; i < ARRAY_SIZE(max_comp_block); i++)
1003 			amdgpu_dm_plane_add_modifier(mods, size, capacity,
1004 						     ver | dcc | max_comp_block_mod[i] | gfx12_modifiers[j]);
1005 
1006 	/* Without DCC. */
1007 	for (i = 0; i < ARRAY_SIZE(gfx12_modifiers); i++)
1008 		amdgpu_dm_plane_add_modifier(mods, size, capacity, gfx12_modifiers[i]);
1009 
1010 }
1011 
amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device * adev,unsigned int plane_type,uint64_t ** mods)1012 STATIC_IFN_KUNIT int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
1013 {
1014 	uint64_t size = 0, capacity = 128;
1015 	*mods = kmalloc_array(capacity, sizeof(uint64_t), GFP_KERNEL);
1016 
1017 	if (plane_type == DRM_PLANE_TYPE_CURSOR) {
1018 		amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
1019 		amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
1020 		return *mods ? 0 : -ENOMEM;
1021 	}
1022 
1023 	switch (adev->family) {
1024 	case AMDGPU_FAMILY_SI:
1025 	case AMDGPU_FAMILY_CI:
1026 	case AMDGPU_FAMILY_KV:
1027 	case AMDGPU_FAMILY_VI:
1028 	case AMDGPU_FAMILY_CZ:
1029 		amdgpu_dm_plane_add_gfx6_modifiers(adev, mods, &size, &capacity);
1030 		break;
1031 	case AMDGPU_FAMILY_AI:
1032 	case AMDGPU_FAMILY_RV:
1033 		amdgpu_dm_plane_add_gfx9_modifiers(adev, mods, &size, &capacity);
1034 		break;
1035 	case AMDGPU_FAMILY_NV:
1036 	case AMDGPU_FAMILY_VGH:
1037 	case AMDGPU_FAMILY_YC:
1038 	case AMDGPU_FAMILY_GC_10_3_6:
1039 	case AMDGPU_FAMILY_GC_10_3_7:
1040 		if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
1041 			amdgpu_dm_plane_add_gfx10_3_modifiers(adev, mods, &size, &capacity);
1042 		else
1043 			amdgpu_dm_plane_add_gfx10_1_modifiers(adev, mods, &size, &capacity);
1044 		break;
1045 	case AMDGPU_FAMILY_GC_11_0_0:
1046 	case AMDGPU_FAMILY_GC_11_0_1:
1047 	case AMDGPU_FAMILY_GC_11_5_0:
1048 	case AMDGPU_FAMILY_GC_11_5_4:
1049 		amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity);
1050 		break;
1051 	case AMDGPU_FAMILY_GC_12_0_0:
1052 	case AMDGPU_FAMILY_GC_13_0_1:
1053 		/* GFX13 (DCN6) shares the GFX12 tiling/DCC binary modifier format. */
1054 		amdgpu_dm_plane_add_gfx12_modifiers(adev, mods, &size, &capacity);
1055 		break;
1056 	}
1057 
1058 	amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
1059 
1060 	/* INVALID marks the end of the list. */
1061 	amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
1062 
1063 	if (!*mods)
1064 		return -ENOMEM;
1065 
1066 	return 0;
1067 }
1068 EXPORT_IF_KUNIT(amdgpu_dm_plane_get_plane_modifiers);
1069 
amdgpu_dm_plane_get_plane_formats(const struct drm_plane * plane,const struct dc_plane_cap * plane_cap,uint32_t * formats,int max_formats)1070 STATIC_IFN_KUNIT int amdgpu_dm_plane_get_plane_formats(const struct drm_plane *plane,
1071 						       const struct dc_plane_cap *plane_cap,
1072 						       uint32_t *formats, int max_formats)
1073 {
1074 	int i, num_formats = 0;
1075 
1076 	/*
1077 	 * TODO: Query support for each group of formats directly from
1078 	 * DC plane caps. This will require adding more formats to the
1079 	 * caps list.
1080 	 */
1081 
1082 	if (plane->type == DRM_PLANE_TYPE_PRIMARY ||
1083 		(plane_cap && plane_cap->type == DC_PLANE_TYPE_DCN_UNIVERSAL && plane->type != DRM_PLANE_TYPE_CURSOR)) {
1084 		for (i = 0; i < ARRAY_SIZE(rgb_formats); ++i) {
1085 			if (num_formats >= max_formats)
1086 				break;
1087 
1088 			formats[num_formats++] = rgb_formats[i];
1089 		}
1090 
1091 		if (plane_cap && plane_cap->pixel_format_support.nv12)
1092 			formats[num_formats++] = DRM_FORMAT_NV12;
1093 		if (plane_cap && plane_cap->pixel_format_support.p010)
1094 			formats[num_formats++] = DRM_FORMAT_P010;
1095 		if (plane_cap && plane_cap->pixel_format_support.fp16) {
1096 			formats[num_formats++] = DRM_FORMAT_XRGB16161616F;
1097 			formats[num_formats++] = DRM_FORMAT_ARGB16161616F;
1098 			formats[num_formats++] = DRM_FORMAT_XBGR16161616F;
1099 			formats[num_formats++] = DRM_FORMAT_ABGR16161616F;
1100 		}
1101 	} else {
1102 		switch (plane->type) {
1103 		case DRM_PLANE_TYPE_OVERLAY:
1104 			for (i = 0; i < ARRAY_SIZE(overlay_formats); ++i) {
1105 				if (num_formats >= max_formats)
1106 					break;
1107 
1108 				formats[num_formats++] = overlay_formats[i];
1109 			}
1110 			break;
1111 
1112 		case DRM_PLANE_TYPE_CURSOR:
1113 			for (i = 0; i < ARRAY_SIZE(cursor_formats); ++i) {
1114 				if (num_formats >= max_formats)
1115 					break;
1116 
1117 				formats[num_formats++] = cursor_formats[i];
1118 			}
1119 			break;
1120 
1121 		default:
1122 			break;
1123 		}
1124 	}
1125 
1126 	return num_formats;
1127 }
1128 EXPORT_IF_KUNIT(amdgpu_dm_plane_get_plane_formats);
1129 
amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device * adev,const struct amdgpu_framebuffer * afb,const enum surface_pixel_format format,const enum dc_rotation_angle rotation,struct dc_tiling_info * tiling_info,struct plane_size * plane_size,struct dc_plane_dcc_param * dcc,struct dc_plane_address * address,bool tmz_surface)1130 int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
1131 			     const struct amdgpu_framebuffer *afb,
1132 			     const enum surface_pixel_format format,
1133 			     const enum dc_rotation_angle rotation,
1134 			     struct dc_tiling_info *tiling_info,
1135 			     struct plane_size *plane_size,
1136 			     struct dc_plane_dcc_param *dcc,
1137 			     struct dc_plane_address *address,
1138 			     bool tmz_surface)
1139 {
1140 	const struct drm_framebuffer *fb = &afb->base;
1141 	int ret;
1142 
1143 	memset(tiling_info, 0, sizeof(*tiling_info));
1144 	memset(plane_size, 0, sizeof(*plane_size));
1145 	memset(dcc, 0, sizeof(*dcc));
1146 	memset(address, 0, sizeof(*address));
1147 
1148 	address->tmz_surface = tmz_surface;
1149 
1150 	if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
1151 		uint64_t addr = afb->address + fb->offsets[0];
1152 
1153 		plane_size->surface_size.x = 0;
1154 		plane_size->surface_size.y = 0;
1155 		plane_size->surface_size.width = fb->width;
1156 		plane_size->surface_size.height = fb->height;
1157 		plane_size->surface_pitch =
1158 			fb->pitches[0] / fb->format->cpp[0];
1159 
1160 		address->type = PLN_ADDR_TYPE_GRAPHICS;
1161 		address->grph.addr.low_part = lower_32_bits(addr);
1162 		address->grph.addr.high_part = upper_32_bits(addr);
1163 	} else if (format < SURFACE_PIXEL_FORMAT_INVALID) {
1164 		uint64_t luma_addr = afb->address + fb->offsets[0];
1165 		uint64_t chroma_addr = afb->address + fb->offsets[1];
1166 
1167 		plane_size->surface_size.x = 0;
1168 		plane_size->surface_size.y = 0;
1169 		plane_size->surface_size.width = fb->width;
1170 		plane_size->surface_size.height = fb->height;
1171 		plane_size->surface_pitch =
1172 			fb->pitches[0] / fb->format->cpp[0];
1173 
1174 		plane_size->chroma_size.x = 0;
1175 		plane_size->chroma_size.y = 0;
1176 		/* TODO: set these based on surface format */
1177 		plane_size->chroma_size.width = fb->width / 2;
1178 		plane_size->chroma_size.height = fb->height / 2;
1179 
1180 		plane_size->chroma_pitch =
1181 			fb->pitches[1] / fb->format->cpp[1];
1182 
1183 		address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
1184 		address->video_progressive.luma_addr.low_part =
1185 			lower_32_bits(luma_addr);
1186 		address->video_progressive.luma_addr.high_part =
1187 			upper_32_bits(luma_addr);
1188 		address->video_progressive.chroma_addr.low_part =
1189 			lower_32_bits(chroma_addr);
1190 		address->video_progressive.chroma_addr.high_part =
1191 			upper_32_bits(chroma_addr);
1192 	}
1193 
1194 	if (adev->family == AMDGPU_FAMILY_GC_12_0_0
1195 	    || adev->family == AMDGPU_FAMILY_GC_13_0_1) {
1196 		ret = amdgpu_dm_plane_fill_gfx12_attrs_from_modifiers(adev, afb, format,
1197 										 rotation, plane_size,
1198 										 tiling_info, dcc,
1199 										 address);
1200 		if (ret)
1201 			return ret;
1202 	} else if (adev->family >= AMDGPU_FAMILY_AI) {
1203 		ret = amdgpu_dm_plane_fill_gfx9_attrs_from_modifiers(adev, afb, format,
1204 										rotation, plane_size,
1205 										tiling_info, dcc,
1206 										address);
1207 		if (ret)
1208 			return ret;
1209 	} else {
1210 		ret = amdgpu_dm_plane_fill_gfx6_tiling_info_from_modifier(tiling_info,
1211 									  afb->base.modifier);
1212 		if (ret)
1213 			return ret;
1214 	}
1215 
1216 	return 0;
1217 }
1218 EXPORT_IF_KUNIT(amdgpu_dm_plane_fill_plane_buffer_attributes);
1219 
amdgpu_dm_plane_helper_prepare_fb(struct drm_plane * plane,struct drm_plane_state * new_state)1220 static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane,
1221 					     struct drm_plane_state *new_state)
1222 {
1223 	struct amdgpu_framebuffer *afb;
1224 	struct drm_gem_object *obj;
1225 	struct amdgpu_device *adev;
1226 	struct amdgpu_bo *rbo;
1227 	struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old;
1228 	uint32_t domain;
1229 	int r;
1230 
1231 	if (!new_state->fb) {
1232 		DRM_DEBUG_KMS("No FB bound\n");
1233 		return 0;
1234 	}
1235 
1236 	afb = to_amdgpu_framebuffer(new_state->fb);
1237 	obj = drm_gem_fb_get_obj(new_state->fb, 0);
1238 	if (!obj) {
1239 		DRM_ERROR("Failed to get obj from framebuffer\n");
1240 		return -EINVAL;
1241 	}
1242 
1243 	rbo = gem_to_amdgpu_bo(obj);
1244 	adev = amdgpu_ttm_adev(rbo->tbo.bdev);
1245 	r = amdgpu_bo_reserve(rbo, true);
1246 	if (r) {
1247 		drm_err(adev_to_drm(adev), "fail to reserve bo: %pe\n", ERR_PTR(r));
1248 		return r;
1249 	}
1250 
1251 	r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
1252 	if (r) {
1253 		drm_err(adev_to_drm(adev), "reserving fence slot failed: %pe\n", ERR_PTR(r));
1254 		goto error_unlock;
1255 	}
1256 
1257 	if (plane->type != DRM_PLANE_TYPE_CURSOR)
1258 		domain = amdgpu_display_supported_domains(adev, rbo->flags);
1259 	else
1260 		domain = AMDGPU_GEM_DOMAIN_VRAM;
1261 
1262 	rbo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
1263 	r = amdgpu_bo_pin(rbo, domain);
1264 	if (unlikely(r != 0)) {
1265 		if (r != -ERESTARTSYS)
1266 			DRM_ERROR("Failed to pin framebuffer: %pe\n", ERR_PTR(r));
1267 		goto error_unlock;
1268 	}
1269 
1270 	r = amdgpu_ttm_alloc_gart(&rbo->tbo);
1271 	if (unlikely(r != 0)) {
1272 		DRM_ERROR("%p bind failed: %pe\n", rbo, ERR_PTR(r));
1273 		goto error_unpin;
1274 	}
1275 
1276 	r = drm_gem_plane_helper_prepare_fb(plane, new_state);
1277 	if (unlikely(r != 0))
1278 		goto error_unpin;
1279 
1280 	amdgpu_bo_unreserve(rbo);
1281 
1282 	afb->address = amdgpu_bo_gpu_offset(rbo);
1283 
1284 	amdgpu_bo_ref(rbo);
1285 
1286 	/**
1287 	 * We don't do surface updates on planes that have been newly created,
1288 	 * but we also don't have the afb->address during atomic check.
1289 	 *
1290 	 * Fill in buffer attributes depending on the address here, but only on
1291 	 * newly created planes since they're not being used by DC yet and this
1292 	 * won't modify global state.
1293 	 */
1294 	dm_plane_state_old = to_dm_plane_state(plane->state);
1295 	dm_plane_state_new = to_dm_plane_state(new_state);
1296 
1297 	if (dm_plane_state_new->dc_state &&
1298 	    dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
1299 		struct dc_plane_state *plane_state =
1300 			dm_plane_state_new->dc_state;
1301 
1302 		amdgpu_dm_plane_fill_plane_buffer_attributes(
1303 			adev, afb, plane_state->format, plane_state->rotation,
1304 			&plane_state->tiling_info, &plane_state->plane_size,
1305 			&plane_state->dcc, &plane_state->address,
1306 			afb->tmz_surface);
1307 	}
1308 
1309 	return 0;
1310 
1311 error_unpin:
1312 	amdgpu_bo_unpin(rbo);
1313 
1314 error_unlock:
1315 	amdgpu_bo_unreserve(rbo);
1316 	return r;
1317 }
1318 
amdgpu_dm_plane_helper_cleanup_fb(struct drm_plane * plane,struct drm_plane_state * old_state)1319 static void amdgpu_dm_plane_helper_cleanup_fb(struct drm_plane *plane,
1320 					      struct drm_plane_state *old_state)
1321 {
1322 	struct amdgpu_bo *rbo;
1323 	int r;
1324 
1325 	if (!old_state->fb)
1326 		return;
1327 
1328 	rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
1329 	r = amdgpu_bo_reserve(rbo, false);
1330 	if (unlikely(r)) {
1331 		DRM_ERROR("failed to reserve rbo before unpin: %pe\n", ERR_PTR(r));
1332 		return;
1333 	}
1334 
1335 	amdgpu_bo_unpin(rbo);
1336 	amdgpu_bo_unreserve(rbo);
1337 	amdgpu_bo_unref(&rbo);
1338 }
1339 
amdgpu_dm_plane_get_min_max_dc_plane_scaling(struct drm_device * dev,struct drm_framebuffer * fb,int * min_downscale,int * max_upscale)1340 STATIC_IFN_KUNIT void amdgpu_dm_plane_get_min_max_dc_plane_scaling(struct drm_device *dev,
1341 								   struct drm_framebuffer *fb,
1342 								   int *min_downscale, int *max_upscale)
1343 {
1344 	struct amdgpu_device *adev = drm_to_adev(dev);
1345 	struct dc *dc = adev->dm.dc;
1346 	/* Caps for all supported planes are the same on DCE and DCN 1 - 3 */
1347 	struct dc_plane_cap *plane_cap = &dc->caps.planes[0];
1348 
1349 	switch (fb->format->format) {
1350 	case DRM_FORMAT_P010:
1351 	case DRM_FORMAT_NV12:
1352 	case DRM_FORMAT_NV21:
1353 		*max_upscale = plane_cap->max_upscale_factor.nv12;
1354 		*min_downscale = plane_cap->max_downscale_factor.nv12;
1355 		break;
1356 
1357 	/* All 64 bpp formats have the same fp16 scaling limits */
1358 	case DRM_FORMAT_XRGB16161616F:
1359 	case DRM_FORMAT_ARGB16161616F:
1360 	case DRM_FORMAT_XBGR16161616F:
1361 	case DRM_FORMAT_ABGR16161616F:
1362 	case DRM_FORMAT_XRGB16161616:
1363 	case DRM_FORMAT_ARGB16161616:
1364 	case DRM_FORMAT_XBGR16161616:
1365 	case DRM_FORMAT_ABGR16161616:
1366 		*max_upscale = plane_cap->max_upscale_factor.fp16;
1367 		*min_downscale = plane_cap->max_downscale_factor.fp16;
1368 		break;
1369 
1370 	default:
1371 		*max_upscale = plane_cap->max_upscale_factor.argb8888;
1372 		*min_downscale = plane_cap->max_downscale_factor.argb8888;
1373 		break;
1374 	}
1375 
1376 	/*
1377 	 * A factor of 1 in the plane_cap means to not allow scaling, ie. use a
1378 	 * scaling factor of 1.0 == 1000 units.
1379 	 */
1380 	if (*max_upscale == 1)
1381 		*max_upscale = 1000;
1382 
1383 	if (*min_downscale == 1)
1384 		*min_downscale = 1000;
1385 }
1386 EXPORT_IF_KUNIT(amdgpu_dm_plane_get_min_max_dc_plane_scaling);
1387 
amdgpu_dm_plane_helper_check_state(struct drm_plane_state * state,struct drm_crtc_state * new_crtc_state)1388 int amdgpu_dm_plane_helper_check_state(struct drm_plane_state *state,
1389 				       struct drm_crtc_state *new_crtc_state)
1390 {
1391 	struct drm_framebuffer *fb = state->fb;
1392 	int min_downscale, max_upscale;
1393 	int min_scale = 0;
1394 	int max_scale = INT_MAX;
1395 
1396 	/* Plane enabled? Validate viewport and get scaling factors from plane caps. */
1397 	if (fb && state->crtc) {
1398 		/* Validate viewport to cover the case when only the position changes */
1399 		if (state->plane->type != DRM_PLANE_TYPE_CURSOR) {
1400 			int viewport_width = state->crtc_w;
1401 			int viewport_height = state->crtc_h;
1402 
1403 			if (state->crtc_x < 0)
1404 				viewport_width += state->crtc_x;
1405 			else if (state->crtc_x + state->crtc_w > new_crtc_state->mode.crtc_hdisplay)
1406 				viewport_width = new_crtc_state->mode.crtc_hdisplay - state->crtc_x;
1407 
1408 			if (state->crtc_y < 0)
1409 				viewport_height += state->crtc_y;
1410 			else if (state->crtc_y + state->crtc_h > new_crtc_state->mode.crtc_vdisplay)
1411 				viewport_height = new_crtc_state->mode.crtc_vdisplay - state->crtc_y;
1412 
1413 			if (viewport_width < 0 || viewport_height < 0) {
1414 				DRM_DEBUG_ATOMIC("Plane completely outside of screen\n");
1415 				return -EINVAL;
1416 			} else if (viewport_width < MIN_VIEWPORT_SIZE*2) { /* x2 for width is because of pipe-split. */
1417 				DRM_DEBUG_ATOMIC("Viewport width %d smaller than %d\n", viewport_width, MIN_VIEWPORT_SIZE*2);
1418 				return -EINVAL;
1419 			} else if (viewport_height < MIN_VIEWPORT_SIZE) {
1420 				DRM_DEBUG_ATOMIC("Viewport height %d smaller than %d\n", viewport_height, MIN_VIEWPORT_SIZE);
1421 				return -EINVAL;
1422 			}
1423 
1424 		}
1425 
1426 		/* Get min/max allowed scaling factors from plane caps. */
1427 		amdgpu_dm_plane_get_min_max_dc_plane_scaling(state->crtc->dev, fb,
1428 							     &min_downscale, &max_upscale);
1429 		/*
1430 		 * Convert to drm convention: 16.16 fixed point, instead of dc's
1431 		 * 1.0 == 1000. Also drm scaling is src/dst instead of dc's
1432 		 * dst/src, so min_scale = 1.0 / max_upscale, etc.
1433 		 */
1434 		min_scale = (1000 << 16) / max_upscale;
1435 		max_scale = (1000 << 16) / min_downscale;
1436 	}
1437 
1438 	return drm_atomic_helper_check_plane_state(
1439 		state, new_crtc_state, min_scale, max_scale, true, true);
1440 }
1441 EXPORT_IF_KUNIT(amdgpu_dm_plane_helper_check_state);
1442 
amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device * adev,const struct drm_plane_state * state,struct dc_scaling_info * scaling_info)1443 int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev,
1444 				const struct drm_plane_state *state,
1445 				struct dc_scaling_info *scaling_info)
1446 {
1447 	int scale_w, scale_h, min_downscale, max_upscale;
1448 
1449 	memset(scaling_info, 0, sizeof(*scaling_info));
1450 
1451 	/* Source is fixed 16.16 but we ignore mantissa for now... */
1452 	scaling_info->src_rect.x = state->src_x >> 16;
1453 	scaling_info->src_rect.y = state->src_y >> 16;
1454 
1455 	/*
1456 	 * For reasons we don't (yet) fully understand a non-zero
1457 	 * src_y coordinate into an NV12 buffer can cause a
1458 	 * system hang on DCN1x.
1459 	 * To avoid hangs (and maybe be overly cautious)
1460 	 * let's reject both non-zero src_x and src_y.
1461 	 *
1462 	 * We currently know of only one use-case to reproduce a
1463 	 * scenario with non-zero src_x and src_y for NV12, which
1464 	 * is to gesture the YouTube Android app into full screen
1465 	 * on ChromeOS.
1466 	 */
1467 	if (((amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 0)) ||
1468 	    (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 1))) &&
1469 	    (state->fb && state->fb->format->format == DRM_FORMAT_NV12 &&
1470 	    (scaling_info->src_rect.x != 0 || scaling_info->src_rect.y != 0)))
1471 		return -EINVAL;
1472 
1473 	scaling_info->src_rect.width = state->src_w >> 16;
1474 	if (scaling_info->src_rect.width == 0)
1475 		return -EINVAL;
1476 
1477 	scaling_info->src_rect.height = state->src_h >> 16;
1478 	if (scaling_info->src_rect.height == 0)
1479 		return -EINVAL;
1480 
1481 	scaling_info->dst_rect.x = state->crtc_x;
1482 	scaling_info->dst_rect.y = state->crtc_y;
1483 
1484 	if (state->crtc_w == 0)
1485 		return -EINVAL;
1486 
1487 	scaling_info->dst_rect.width = state->crtc_w;
1488 
1489 	if (state->crtc_h == 0)
1490 		return -EINVAL;
1491 
1492 	scaling_info->dst_rect.height = state->crtc_h;
1493 
1494 	/* DRM doesn't specify clipping on destination output. */
1495 	scaling_info->clip_rect = scaling_info->dst_rect;
1496 
1497 	/* Validate scaling per-format with DC plane caps */
1498 	if (state->plane && state->plane->dev && state->fb) {
1499 		amdgpu_dm_plane_get_min_max_dc_plane_scaling(state->plane->dev, state->fb,
1500 							     &min_downscale, &max_upscale);
1501 	} else {
1502 		min_downscale = 250;
1503 		max_upscale = 16000;
1504 	}
1505 
1506 	scale_w = scaling_info->dst_rect.width * 1000 /
1507 		  scaling_info->src_rect.width;
1508 
1509 	if (scale_w < min_downscale || scale_w > max_upscale)
1510 		return -EINVAL;
1511 
1512 	scale_h = scaling_info->dst_rect.height * 1000 /
1513 		  scaling_info->src_rect.height;
1514 
1515 	if (scale_h < min_downscale || scale_h > max_upscale)
1516 		return -EINVAL;
1517 
1518 	/*
1519 	 * The "scaling_quality" can be ignored for now, quality = 0 has DC
1520 	 * assume reasonable defaults based on the format.
1521 	 */
1522 
1523 	return 0;
1524 }
1525 EXPORT_IF_KUNIT(amdgpu_dm_plane_fill_dc_scaling_info);
1526 
amdgpu_dm_plane_atomic_check(struct drm_plane * plane,struct drm_atomic_commit * state)1527 STATIC_IFN_KUNIT int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
1528 						  struct drm_atomic_commit *state)
1529 {
1530 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
1531 										 plane);
1532 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
1533 	struct dc *dc = adev->dm.dc;
1534 	struct dm_plane_state *dm_plane_state;
1535 	struct dc_scaling_info scaling_info;
1536 	struct drm_crtc_state *new_crtc_state;
1537 	int ret;
1538 
1539 	trace_amdgpu_dm_plane_atomic_check(new_plane_state);
1540 
1541 	dm_plane_state = to_dm_plane_state(new_plane_state);
1542 
1543 	if (!dm_plane_state->dc_state)
1544 		return 0;
1545 
1546 	new_crtc_state =
1547 		drm_atomic_get_new_crtc_state(state,
1548 					      new_plane_state->crtc);
1549 	if (!new_crtc_state)
1550 		return -EINVAL;
1551 
1552 	ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state);
1553 	if (ret)
1554 		return ret;
1555 
1556 	/* Reject commits that attempt to use both COLOR_PIPELINE and CRTC DEGAMMA_LUT */
1557 	if (new_plane_state->color_pipeline && new_crtc_state->degamma_lut) {
1558 		drm_dbg_atomic(plane->dev,
1559 			       "[PLANE:%d:%s] COLOR_PIPELINE and CRTC DEGAMMA_LUT cannot be enabled simultaneously\n",
1560 			       plane->base.id, plane->name);
1561 		return -EINVAL;
1562 	}
1563 
1564 	ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info);
1565 	if (ret)
1566 		return ret;
1567 
1568 	if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK)
1569 		return 0;
1570 
1571 	return -EINVAL;
1572 }
1573 EXPORT_IF_KUNIT(amdgpu_dm_plane_atomic_check);
1574 
amdgpu_dm_plane_atomic_async_check(struct drm_plane * plane,struct drm_atomic_commit * state,bool flip)1575 STATIC_IFN_KUNIT int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
1576 							struct drm_atomic_commit *state, bool flip)
1577 {
1578 	struct drm_crtc_state *new_crtc_state;
1579 	struct drm_plane_state *new_plane_state;
1580 	struct dm_crtc_state *dm_new_crtc_state;
1581 
1582 	if (flip) {
1583 		if (plane->type != DRM_PLANE_TYPE_OVERLAY)
1584 			return -EINVAL;
1585 	} else if (plane->type != DRM_PLANE_TYPE_CURSOR) {
1586 		return -EINVAL;
1587 	}
1588 
1589 	new_plane_state = drm_atomic_get_new_plane_state(state, plane);
1590 	new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
1591 	dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
1592 	/* Reject overlay cursors for now*/
1593 	if (!flip && dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
1594 		return -EINVAL;
1595 
1596 	return 0;
1597 }
1598 EXPORT_IF_KUNIT(amdgpu_dm_plane_atomic_async_check);
1599 
amdgpu_dm_plane_get_cursor_position(struct drm_plane * plane,struct drm_crtc * crtc,struct dc_cursor_position * position)1600 int amdgpu_dm_plane_get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
1601 					struct dc_cursor_position *position)
1602 {
1603 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
1604 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
1605 	int x, y;
1606 	int xorigin = 0, yorigin = 0;
1607 
1608 	if (!crtc || !plane->state->fb)
1609 		return 0;
1610 
1611 	if ((plane->state->crtc_w > amdgpu_crtc->max_cursor_width) ||
1612 	    (plane->state->crtc_h > amdgpu_crtc->max_cursor_height)) {
1613 		DRM_ERROR("%s: bad cursor width or height %d x %d\n",
1614 			  __func__,
1615 			  plane->state->crtc_w,
1616 			  plane->state->crtc_h);
1617 		return -EINVAL;
1618 	}
1619 
1620 	x = plane->state->crtc_x;
1621 	y = plane->state->crtc_y;
1622 
1623 	if (x <= -amdgpu_crtc->max_cursor_width ||
1624 	    y <= -amdgpu_crtc->max_cursor_height)
1625 		return 0;
1626 
1627 	if (x < 0) {
1628 		xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1);
1629 		x = 0;
1630 	}
1631 	if (y < 0) {
1632 		yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1);
1633 		y = 0;
1634 	}
1635 	position->enable = true;
1636 	position->x = x;
1637 	position->y = y;
1638 	position->x_hotspot = xorigin;
1639 	position->y_hotspot = yorigin;
1640 
1641 	if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(4, 0, 1))
1642 		position->translate_by_source = true;
1643 
1644 	return 0;
1645 }
1646 EXPORT_IF_KUNIT(amdgpu_dm_plane_get_cursor_position);
1647 
amdgpu_dm_plane_handle_cursor_update(struct drm_plane * plane,struct drm_plane_state * old_plane_state)1648 void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
1649 				 struct drm_plane_state *old_plane_state)
1650 {
1651 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
1652 	struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb);
1653 	struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc;
1654 	struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
1655 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
1656 	uint64_t address = afb ? afb->address : 0;
1657 	struct dc_cursor_position position = {0};
1658 	struct dc_cursor_attributes attributes;
1659 	int ret;
1660 
1661 	if (!plane->state->fb && !old_plane_state->fb)
1662 		return;
1663 
1664 	drm_dbg_atomic(plane->dev, "crtc_id=%d with size %d to %d\n",
1665 		       amdgpu_crtc->crtc_id, plane->state->crtc_w,
1666 		       plane->state->crtc_h);
1667 
1668 	ret = amdgpu_dm_plane_get_cursor_position(plane, crtc, &position);
1669 	if (ret)
1670 		return;
1671 
1672 	if (!position.enable) {
1673 		/* turn off cursor */
1674 		if (crtc_state && crtc_state->stream) {
1675 			mutex_lock(&adev->dm.dc_lock);
1676 			amdgpu_dm_ism_commit_event(
1677 				&amdgpu_crtc->ism,
1678 				DM_ISM_EVENT_BEGIN_CURSOR_UPDATE);
1679 
1680 			dc_stream_program_cursor_position(crtc_state->stream,
1681 						      &position);
1682 
1683 			amdgpu_dm_ism_commit_event(
1684 				&amdgpu_crtc->ism,
1685 				DM_ISM_EVENT_END_CURSOR_UPDATE);
1686 			mutex_unlock(&adev->dm.dc_lock);
1687 		}
1688 		return;
1689 	}
1690 
1691 	amdgpu_crtc->cursor_width = plane->state->crtc_w;
1692 	amdgpu_crtc->cursor_height = plane->state->crtc_h;
1693 
1694 	memset(&attributes, 0, sizeof(attributes));
1695 	attributes.address.high_part = upper_32_bits(address);
1696 	attributes.address.low_part  = lower_32_bits(address);
1697 	attributes.width             = plane->state->crtc_w;
1698 	attributes.height            = plane->state->crtc_h;
1699 	attributes.color_format      = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA;
1700 	attributes.rotation_angle    = 0;
1701 	attributes.attribute_flags.value = 0;
1702 
1703 	/* Enable cursor degamma ROM on DCN3+ for implicit sRGB degamma in DRM
1704 	 * legacy gamma setup.
1705 	 */
1706 	if (crtc_state->cm_is_degamma_srgb &&
1707 	    adev->dm.dc->caps.color.dpp.gamma_corr)
1708 		attributes.attribute_flags.bits.ENABLE_CURSOR_DEGAMMA = 1;
1709 
1710 	if (afb)
1711 		attributes.pitch = afb->base.pitches[0] / afb->base.format->cpp[0];
1712 
1713 	if (crtc_state->stream) {
1714 		mutex_lock(&adev->dm.dc_lock);
1715 		amdgpu_dm_ism_commit_event(
1716 			&amdgpu_crtc->ism,
1717 			DM_ISM_EVENT_BEGIN_CURSOR_UPDATE);
1718 
1719 		if (!dc_stream_program_cursor_attributes(crtc_state->stream,
1720 							 &attributes))
1721 			DRM_ERROR("DC failed to set cursor attributes\n");
1722 
1723 		if (!dc_stream_program_cursor_position(crtc_state->stream,
1724 						   &position))
1725 			DRM_ERROR("DC failed to set cursor position\n");
1726 
1727 		amdgpu_dm_ism_commit_event(
1728 			&amdgpu_crtc->ism,
1729 			DM_ISM_EVENT_END_CURSOR_UPDATE);
1730 		mutex_unlock(&adev->dm.dc_lock);
1731 	}
1732 }
1733 
amdgpu_dm_plane_atomic_async_update(struct drm_plane * plane,struct drm_atomic_commit * state)1734 static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane,
1735 						struct drm_atomic_commit *state)
1736 {
1737 	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
1738 									   plane);
1739 	struct drm_plane_state *old_state =
1740 		drm_atomic_get_old_plane_state(state, plane);
1741 
1742 	trace_amdgpu_dm_atomic_update_cursor(new_state);
1743 
1744 	swap(plane->state->fb, new_state->fb);
1745 
1746 	plane->state->src_x = new_state->src_x;
1747 	plane->state->src_y = new_state->src_y;
1748 	plane->state->src_w = new_state->src_w;
1749 	plane->state->src_h = new_state->src_h;
1750 	plane->state->crtc_x = new_state->crtc_x;
1751 	plane->state->crtc_y = new_state->crtc_y;
1752 	plane->state->crtc_w = new_state->crtc_w;
1753 	plane->state->crtc_h = new_state->crtc_h;
1754 
1755 	amdgpu_dm_plane_handle_cursor_update(plane, old_state);
1756 }
1757 
amdgpu_dm_plane_panic_flush(struct drm_plane * plane)1758 STATIC_IFN_KUNIT void amdgpu_dm_plane_panic_flush(struct drm_plane *plane)
1759 {
1760 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane->state);
1761 	struct drm_framebuffer *fb = plane->state->fb;
1762 	struct dc_plane_state *dc_plane_state;
1763 
1764 	if (!dm_plane_state || !dm_plane_state->dc_state)
1765 		return;
1766 
1767 	dc_plane_state = dm_plane_state->dc_state;
1768 
1769 	dc_plane_force_dcc_and_tiling_disable(dc_plane_state, fb->modifier ? true : false);
1770 }
1771 EXPORT_IF_KUNIT(amdgpu_dm_plane_panic_flush);
1772 
1773 static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
1774 	.prepare_fb = amdgpu_dm_plane_helper_prepare_fb,
1775 	.cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb,
1776 	.atomic_check = amdgpu_dm_plane_atomic_check,
1777 	.atomic_async_check = amdgpu_dm_plane_atomic_async_check,
1778 	.atomic_async_update = amdgpu_dm_plane_atomic_async_update
1779 };
1780 
1781 static const struct drm_plane_helper_funcs dm_primary_plane_helper_funcs = {
1782 	.prepare_fb = amdgpu_dm_plane_helper_prepare_fb,
1783 	.cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb,
1784 	.atomic_check = amdgpu_dm_plane_atomic_check,
1785 	.atomic_async_check = amdgpu_dm_plane_atomic_async_check,
1786 	.atomic_async_update = amdgpu_dm_plane_atomic_async_update,
1787 	.get_scanout_buffer = amdgpu_display_get_scanout_buffer,
1788 	.panic_flush = amdgpu_dm_plane_panic_flush,
1789 };
1790 
amdgpu_dm_plane_drm_plane_reset(struct drm_plane * plane)1791 STATIC_IFN_KUNIT void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane)
1792 {
1793 	struct dm_plane_state *amdgpu_state;
1794 
1795 	amdgpu_state = kzalloc_obj(*amdgpu_state);
1796 	if (!amdgpu_state)
1797 		return;
1798 
1799 	if (plane->state)
1800 		plane->funcs->atomic_destroy_state(plane, plane->state);
1801 
1802 	__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
1803 	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
1804 	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
1805 	amdgpu_state->shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
1806 	amdgpu_state->blend_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
1807 }
1808 EXPORT_IF_KUNIT(amdgpu_dm_plane_drm_plane_reset);
1809 
1810 STATIC_IFN_KUNIT struct drm_plane_state *
amdgpu_dm_plane_drm_plane_duplicate_state(struct drm_plane * plane)1811 amdgpu_dm_plane_drm_plane_duplicate_state(struct drm_plane *plane)
1812 {
1813 	struct dm_plane_state *dm_plane_state, *old_dm_plane_state;
1814 
1815 	old_dm_plane_state = to_dm_plane_state(plane->state);
1816 	dm_plane_state = kzalloc_obj(*dm_plane_state);
1817 	if (!dm_plane_state)
1818 		return NULL;
1819 
1820 	__drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base);
1821 
1822 	if (old_dm_plane_state->dc_state) {
1823 		dm_plane_state->dc_state = old_dm_plane_state->dc_state;
1824 		dc_plane_state_retain(dm_plane_state->dc_state);
1825 	}
1826 
1827 	if (old_dm_plane_state->degamma_lut)
1828 		dm_plane_state->degamma_lut =
1829 			drm_property_blob_get(old_dm_plane_state->degamma_lut);
1830 	if (old_dm_plane_state->ctm)
1831 		dm_plane_state->ctm =
1832 			drm_property_blob_get(old_dm_plane_state->ctm);
1833 	if (old_dm_plane_state->shaper_lut)
1834 		dm_plane_state->shaper_lut =
1835 			drm_property_blob_get(old_dm_plane_state->shaper_lut);
1836 	if (old_dm_plane_state->lut3d)
1837 		dm_plane_state->lut3d =
1838 			drm_property_blob_get(old_dm_plane_state->lut3d);
1839 	if (old_dm_plane_state->blend_lut)
1840 		dm_plane_state->blend_lut =
1841 			drm_property_blob_get(old_dm_plane_state->blend_lut);
1842 
1843 	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
1844 	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
1845 	dm_plane_state->shaper_tf = old_dm_plane_state->shaper_tf;
1846 	dm_plane_state->blend_tf = old_dm_plane_state->blend_tf;
1847 
1848 	return &dm_plane_state->base;
1849 }
1850 EXPORT_IF_KUNIT(amdgpu_dm_plane_drm_plane_duplicate_state);
1851 
amdgpu_dm_plane_format_mod_supported(struct drm_plane * plane,uint32_t format,uint64_t modifier)1852 STATIC_IFN_KUNIT bool amdgpu_dm_plane_format_mod_supported(struct drm_plane *plane,
1853 							   uint32_t format,
1854 							   uint64_t modifier)
1855 {
1856 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
1857 	const struct drm_format_info *info = drm_format_info(format);
1858 	const u32 bpp = drm_format_info_bpp(info, 0);
1859 	int i;
1860 
1861 	if (!info)
1862 		return false;
1863 
1864 	/*
1865 	 * We always have to allow these modifiers:
1866 	 * 1. Core DRM checks for LINEAR support if userspace does not provide modifiers.
1867 	 * 2. Not passing any modifiers is the same as explicitly passing INVALID.
1868 	 */
1869 	if (modifier == DRM_FORMAT_MOD_LINEAR ||
1870 	    modifier == DRM_FORMAT_MOD_INVALID) {
1871 		return true;
1872 	}
1873 
1874 	/* Check that the modifier is on the list of the plane's supported modifiers. */
1875 	for (i = 0; i < plane->modifier_count; i++) {
1876 		if (modifier == plane->modifiers[i])
1877 			break;
1878 	}
1879 	if (i == plane->modifier_count)
1880 		return false;
1881 
1882 	if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX6)
1883 		return amdgpu_dm_plane_gfx6_format_mod_supported(adev, bpp, modifier);
1884 
1885 	/* GFX9+ modifers are not supported on GFX8 and older. */
1886 	if (adev->family < AMDGPU_FAMILY_AI)
1887 		return false;
1888 
1889 	/* GFX12 doesn't have these limitations. */
1890 	if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) <= AMD_FMT_MOD_TILE_VER_GFX11) {
1891 		enum dm_micro_swizzle microtile = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier) & 3;
1892 
1893 		/*
1894 		 * For D swizzle the canonical modifier depends on the bpp, so check
1895 		 * it here.
1896 		 */
1897 		if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
1898 		    adev->family >= AMDGPU_FAMILY_NV) {
1899 			if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
1900 				return false;
1901 		}
1902 
1903 		if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
1904 		    info->cpp[0] < 8)
1905 			return false;
1906 
1907 		if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
1908 			/* Per radeonsi comments 16/64 bpp are more complicated. */
1909 			if (info->cpp[0] != 4)
1910 				return false;
1911 			/* We support multi-planar formats, but not when combined with
1912 			 * additional DCC metadata planes.
1913 			 */
1914 			if (info->num_planes > 1)
1915 				return false;
1916 		}
1917 	}
1918 
1919 	return true;
1920 }
1921 EXPORT_IF_KUNIT(amdgpu_dm_plane_format_mod_supported);
1922 
amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane * plane,struct drm_plane_state * state)1923 STATIC_IFN_KUNIT void amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane *plane,
1924 							      struct drm_plane_state *state)
1925 {
1926 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
1927 
1928 	if (dm_plane_state->degamma_lut)
1929 		drm_property_blob_put(dm_plane_state->degamma_lut);
1930 	if (dm_plane_state->ctm)
1931 		drm_property_blob_put(dm_plane_state->ctm);
1932 	if (dm_plane_state->lut3d)
1933 		drm_property_blob_put(dm_plane_state->lut3d);
1934 	if (dm_plane_state->shaper_lut)
1935 		drm_property_blob_put(dm_plane_state->shaper_lut);
1936 	if (dm_plane_state->blend_lut)
1937 		drm_property_blob_put(dm_plane_state->blend_lut);
1938 
1939 	if (dm_plane_state->dc_state)
1940 		dc_plane_state_release(dm_plane_state->dc_state);
1941 
1942 	drm_atomic_helper_plane_destroy_state(plane, state);
1943 }
1944 EXPORT_IF_KUNIT(amdgpu_dm_plane_drm_plane_destroy_state);
1945 
1946 #ifdef AMD_PRIVATE_COLOR
1947 static void
dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager * dm,struct drm_plane * plane)1948 dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
1949 					     struct drm_plane *plane)
1950 {
1951 	struct amdgpu_mode_info mode_info = dm->adev->mode_info;
1952 	struct dpp_color_caps dpp_color_caps = dm->dc->caps.color.dpp;
1953 
1954 	/* Check HW color pipeline capabilities on DPP block (pre-blending)
1955 	 * before exposing related properties.
1956 	 */
1957 	if (dpp_color_caps.dgam_ram || dpp_color_caps.gamma_corr) {
1958 		drm_object_attach_property(&plane->base,
1959 					   mode_info.plane_degamma_lut_property,
1960 					   0);
1961 		drm_object_attach_property(&plane->base,
1962 					   mode_info.plane_degamma_lut_size_property,
1963 					   MAX_COLOR_LUT_ENTRIES);
1964 		drm_object_attach_property(&plane->base,
1965 					   dm->adev->mode_info.plane_degamma_tf_property,
1966 					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
1967 	}
1968 	/* HDR MULT is always available */
1969 	drm_object_attach_property(&plane->base,
1970 				   dm->adev->mode_info.plane_hdr_mult_property,
1971 				   AMDGPU_HDR_MULT_DEFAULT);
1972 
1973 	/* Only enable plane CTM if both DPP and MPC gamut remap is available. */
1974 	if (dm->dc->caps.color.mpc.gamut_remap)
1975 		drm_object_attach_property(&plane->base,
1976 					   dm->adev->mode_info.plane_ctm_property, 0);
1977 
1978 	if (dpp_color_caps.hw_3d_lut || dm->dc->caps.color.mpc.preblend) {
1979 		drm_object_attach_property(&plane->base,
1980 					   mode_info.plane_shaper_lut_property, 0);
1981 		drm_object_attach_property(&plane->base,
1982 					   mode_info.plane_shaper_lut_size_property,
1983 					   MAX_COLOR_LUT_ENTRIES);
1984 		drm_object_attach_property(&plane->base,
1985 					   mode_info.plane_shaper_tf_property,
1986 					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
1987 		drm_object_attach_property(&plane->base,
1988 					   mode_info.plane_lut3d_property, 0);
1989 		drm_object_attach_property(&plane->base,
1990 					   mode_info.plane_lut3d_size_property,
1991 					   MAX_COLOR_3DLUT_SIZE);
1992 	}
1993 
1994 	if (dpp_color_caps.ogam_ram || dm->dc->caps.color.mpc.preblend) {
1995 		drm_object_attach_property(&plane->base,
1996 					   mode_info.plane_blend_lut_property, 0);
1997 		drm_object_attach_property(&plane->base,
1998 					   mode_info.plane_blend_lut_size_property,
1999 					   MAX_COLOR_LUT_ENTRIES);
2000 		drm_object_attach_property(&plane->base,
2001 					   mode_info.plane_blend_tf_property,
2002 					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
2003 	}
2004 }
2005 
2006 static int
dm_atomic_plane_set_property(struct drm_plane * plane,struct drm_plane_state * state,struct drm_property * property,uint64_t val)2007 dm_atomic_plane_set_property(struct drm_plane *plane,
2008 			     struct drm_plane_state *state,
2009 			     struct drm_property *property,
2010 			     uint64_t val)
2011 {
2012 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
2013 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
2014 	bool replaced = false;
2015 	int ret;
2016 
2017 	if (property == adev->mode_info.plane_degamma_lut_property) {
2018 		ret = drm_property_replace_blob_from_id(plane->dev,
2019 							&dm_plane_state->degamma_lut,
2020 							val,
2021 							-1, -1, sizeof(struct drm_color_lut),
2022 							&replaced);
2023 		dm_plane_state->base.color_mgmt_changed |= replaced;
2024 		return ret;
2025 	} else if (property == adev->mode_info.plane_degamma_tf_property) {
2026 		if (dm_plane_state->degamma_tf != val) {
2027 			dm_plane_state->degamma_tf = val;
2028 			dm_plane_state->base.color_mgmt_changed = 1;
2029 		}
2030 	} else if (property == adev->mode_info.plane_hdr_mult_property) {
2031 		if (dm_plane_state->hdr_mult != val) {
2032 			dm_plane_state->hdr_mult = val;
2033 			dm_plane_state->base.color_mgmt_changed = 1;
2034 		}
2035 	} else if (property == adev->mode_info.plane_ctm_property) {
2036 		ret = drm_property_replace_blob_from_id(plane->dev,
2037 							&dm_plane_state->ctm,
2038 							val,
2039 							-1, sizeof(struct drm_color_ctm_3x4), -1,
2040 							&replaced);
2041 		dm_plane_state->base.color_mgmt_changed |= replaced;
2042 		return ret;
2043 	} else if (property == adev->mode_info.plane_shaper_lut_property) {
2044 		ret = drm_property_replace_blob_from_id(plane->dev,
2045 							&dm_plane_state->shaper_lut,
2046 							val,
2047 							-1, -1, sizeof(struct drm_color_lut),
2048 							&replaced);
2049 		dm_plane_state->base.color_mgmt_changed |= replaced;
2050 		return ret;
2051 	} else if (property == adev->mode_info.plane_shaper_tf_property) {
2052 		if (dm_plane_state->shaper_tf != val) {
2053 			dm_plane_state->shaper_tf = val;
2054 			dm_plane_state->base.color_mgmt_changed = 1;
2055 		}
2056 	} else if (property == adev->mode_info.plane_lut3d_property) {
2057 		ret = drm_property_replace_blob_from_id(plane->dev,
2058 							&dm_plane_state->lut3d,
2059 							val,
2060 							-1, -1, sizeof(struct drm_color_lut),
2061 							&replaced);
2062 		dm_plane_state->base.color_mgmt_changed |= replaced;
2063 		return ret;
2064 	} else if (property == adev->mode_info.plane_blend_lut_property) {
2065 		ret = drm_property_replace_blob_from_id(plane->dev,
2066 							&dm_plane_state->blend_lut,
2067 							val,
2068 							-1, -1, sizeof(struct drm_color_lut),
2069 							&replaced);
2070 		dm_plane_state->base.color_mgmt_changed |= replaced;
2071 		return ret;
2072 	} else if (property == adev->mode_info.plane_blend_tf_property) {
2073 		if (dm_plane_state->blend_tf != val) {
2074 			dm_plane_state->blend_tf = val;
2075 			dm_plane_state->base.color_mgmt_changed = 1;
2076 		}
2077 	} else {
2078 		drm_dbg_atomic(plane->dev,
2079 			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
2080 			       plane->base.id, plane->name,
2081 			       property->base.id, property->name);
2082 		return -EINVAL;
2083 	}
2084 
2085 	return 0;
2086 }
2087 
2088 static int
dm_atomic_plane_get_property(struct drm_plane * plane,const struct drm_plane_state * state,struct drm_property * property,uint64_t * val)2089 dm_atomic_plane_get_property(struct drm_plane *plane,
2090 			     const struct drm_plane_state *state,
2091 			     struct drm_property *property,
2092 			     uint64_t *val)
2093 {
2094 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
2095 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
2096 
2097 	if (property == adev->mode_info.plane_degamma_lut_property) {
2098 		*val = (dm_plane_state->degamma_lut) ?
2099 			dm_plane_state->degamma_lut->base.id : 0;
2100 	} else if (property == adev->mode_info.plane_degamma_tf_property) {
2101 		*val = dm_plane_state->degamma_tf;
2102 	} else if (property == adev->mode_info.plane_hdr_mult_property) {
2103 		*val = dm_plane_state->hdr_mult;
2104 	} else if (property == adev->mode_info.plane_ctm_property) {
2105 		*val = (dm_plane_state->ctm) ?
2106 			dm_plane_state->ctm->base.id : 0;
2107 	} else 	if (property == adev->mode_info.plane_shaper_lut_property) {
2108 		*val = (dm_plane_state->shaper_lut) ?
2109 			dm_plane_state->shaper_lut->base.id : 0;
2110 	} else if (property == adev->mode_info.plane_shaper_tf_property) {
2111 		*val = dm_plane_state->shaper_tf;
2112 	} else 	if (property == adev->mode_info.plane_lut3d_property) {
2113 		*val = (dm_plane_state->lut3d) ?
2114 			dm_plane_state->lut3d->base.id : 0;
2115 	} else 	if (property == adev->mode_info.plane_blend_lut_property) {
2116 		*val = (dm_plane_state->blend_lut) ?
2117 			dm_plane_state->blend_lut->base.id : 0;
2118 	} else if (property == adev->mode_info.plane_blend_tf_property) {
2119 		*val = dm_plane_state->blend_tf;
2120 
2121 	} else {
2122 		return -EINVAL;
2123 	}
2124 
2125 	return 0;
2126 }
2127 #else
2128 
2129 #define MAX_COLOR_PIPELINES 5
2130 
2131 static int
dm_plane_init_colorops(struct drm_plane * plane)2132 dm_plane_init_colorops(struct drm_plane *plane)
2133 {
2134 	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES] = {};
2135 	struct drm_device *dev = plane->dev;
2136 	struct amdgpu_device *adev = drm_to_adev(dev);
2137 	struct dc *dc = adev->dm.dc;
2138 	int len = 0;
2139 	int ret = 0;
2140 	int i;
2141 
2142 	if (plane->type == DRM_PLANE_TYPE_CURSOR)
2143 		return 0;
2144 
2145 	/* initialize pipeline */
2146 	if (dc->ctx->dce_version >= DCN_VERSION_3_0) {
2147 		ret = amdgpu_dm_initialize_default_pipeline(plane, &pipelines[len]);
2148 		if (ret) {
2149 			drm_err(plane->dev, "Failed to create color pipeline for plane %d: %pe\n",
2150 				plane->base.id, ERR_PTR(ret));
2151 			goto out;
2152 		}
2153 		len++;
2154 
2155 		/* Create COLOR_PIPELINE property and attach */
2156 		drm_plane_create_color_pipeline_property(plane, pipelines, len);
2157 	}
2158 
2159 out:
2160 	for (i = 0; i < len; i++)
2161 		kfree(pipelines[i].name);
2162 
2163 	return ret;
2164 }
2165 #endif
2166 
2167 static const struct drm_plane_funcs dm_plane_funcs = {
2168 	.update_plane	= drm_atomic_helper_update_plane,
2169 	.disable_plane	= drm_atomic_helper_disable_plane,
2170 	.destroy	= drm_plane_helper_destroy,
2171 	.reset = amdgpu_dm_plane_drm_plane_reset,
2172 	.atomic_duplicate_state = amdgpu_dm_plane_drm_plane_duplicate_state,
2173 	.atomic_destroy_state = amdgpu_dm_plane_drm_plane_destroy_state,
2174 	.format_mod_supported = amdgpu_dm_plane_format_mod_supported,
2175 	.format_mod_supported_async = amdgpu_dm_plane_format_mod_supported,
2176 #ifdef AMD_PRIVATE_COLOR
2177 	.atomic_set_property = dm_atomic_plane_set_property,
2178 	.atomic_get_property = dm_atomic_plane_get_property,
2179 #endif
2180 };
2181 
amdgpu_dm_plane_init(struct amdgpu_display_manager * dm,struct drm_plane * plane,unsigned long possible_crtcs,const struct dc_plane_cap * plane_cap)2182 int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
2183 				struct drm_plane *plane,
2184 				unsigned long possible_crtcs,
2185 				const struct dc_plane_cap *plane_cap)
2186 {
2187 	uint32_t formats[32];
2188 	int num_formats;
2189 	int res = -EPERM;
2190 	unsigned int supported_rotations;
2191 	uint64_t *modifiers = NULL;
2192 	unsigned int primary_zpos = dm->dc->caps.max_slave_planes;
2193 
2194 	num_formats = amdgpu_dm_plane_get_plane_formats(plane, plane_cap, formats,
2195 							ARRAY_SIZE(formats));
2196 
2197 	res = amdgpu_dm_plane_get_plane_modifiers(dm->adev, plane->type, &modifiers);
2198 	if (res)
2199 		return res;
2200 
2201 	if (modifiers == NULL)
2202 		adev_to_drm(dm->adev)->mode_config.fb_modifiers_not_supported = true;
2203 
2204 	res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs,
2205 				       &dm_plane_funcs, formats, num_formats,
2206 				       modifiers, plane->type, NULL);
2207 	kfree(modifiers);
2208 	if (res)
2209 		return res;
2210 
2211 	if (plane->type == DRM_PLANE_TYPE_OVERLAY &&
2212 	    plane_cap && plane_cap->per_pixel_alpha) {
2213 		unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2214 					  BIT(DRM_MODE_BLEND_PREMULTI) |
2215 					  BIT(DRM_MODE_BLEND_COVERAGE);
2216 
2217 		drm_plane_create_alpha_property(plane);
2218 		drm_plane_create_blend_mode_property(plane, blend_caps);
2219 	}
2220 
2221 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
2222 		/*
2223 		 * Allow OVERLAY planes to be used as underlays by assigning an
2224 		 * immutable zpos = # of OVERLAY planes to the PRIMARY plane.
2225 		 */
2226 		drm_plane_create_zpos_immutable_property(plane, primary_zpos);
2227 	} else if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
2228 		/*
2229 		 * OVERLAY planes can be below or above the PRIMARY, but cannot
2230 		 * be above the CURSOR plane.
2231 		 */
2232 		unsigned int zpos = primary_zpos + 1 + drm_plane_index(plane);
2233 
2234 		drm_plane_create_zpos_property(plane, zpos, 0, 254);
2235 	} else if (plane->type == DRM_PLANE_TYPE_CURSOR) {
2236 		drm_plane_create_zpos_immutable_property(plane, 255);
2237 	}
2238 
2239 	if ((plane->type == DRM_PLANE_TYPE_PRIMARY ||
2240 	     plane->type == DRM_PLANE_TYPE_OVERLAY) &&
2241 	    plane_cap &&
2242 	    (plane_cap->pixel_format_support.nv12 ||
2243 	     plane_cap->pixel_format_support.p010)) {
2244 		/* This only affects YUV formats. */
2245 		drm_plane_create_color_properties(
2246 			plane,
2247 			BIT(DRM_COLOR_YCBCR_BT601) |
2248 			BIT(DRM_COLOR_YCBCR_BT709) |
2249 			BIT(DRM_COLOR_YCBCR_BT2020),
2250 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2251 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2252 			DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE);
2253 	}
2254 
2255 	supported_rotations =
2256 		DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2257 		DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2258 
2259 	if (dm->adev->asic_type >= CHIP_BONAIRE &&
2260 	    plane->type != DRM_PLANE_TYPE_CURSOR)
2261 		drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
2262 						   supported_rotations);
2263 
2264 	if (amdgpu_ip_version(dm->adev, DCE_HWIP, 0) > IP_VERSION(3, 0, 1) &&
2265 	    plane->type != DRM_PLANE_TYPE_CURSOR)
2266 		drm_plane_enable_fb_damage_clips(plane);
2267 
2268 	if (plane->type == DRM_PLANE_TYPE_PRIMARY)
2269 		drm_plane_helper_add(plane, &dm_primary_plane_helper_funcs);
2270 	else
2271 		drm_plane_helper_add(plane, &dm_plane_helper_funcs);
2272 
2273 #ifdef AMD_PRIVATE_COLOR
2274 	dm_atomic_plane_attach_color_mgmt_properties(dm, plane);
2275 #else
2276 	res = dm_plane_init_colorops(plane);
2277 	if (res)
2278 		return res;
2279 #endif
2280 
2281 	/* Create (reset) the plane state */
2282 	if (plane->funcs->reset)
2283 		plane->funcs->reset(plane);
2284 
2285 	return 0;
2286 }
2287 
amdgpu_dm_plane_is_video_format(uint32_t format)2288 bool amdgpu_dm_plane_is_video_format(uint32_t format)
2289 {
2290 	int i;
2291 
2292 	for (i = 0; i < ARRAY_SIZE(video_formats); i++)
2293 		if (format == video_formats[i])
2294 			return true;
2295 
2296 	return false;
2297 }
2298 EXPORT_IF_KUNIT(amdgpu_dm_plane_is_video_format);
2299 
2300