15d945cbcSRodrigo Siqueira // SPDX-License-Identifier: MIT
25d945cbcSRodrigo Siqueira /*
35d945cbcSRodrigo Siqueira  * Copyright 2022 Advanced Micro Devices, Inc.
45d945cbcSRodrigo Siqueira  *
55d945cbcSRodrigo Siqueira  * Permission is hereby granted, free of charge, to any person obtaining a
65d945cbcSRodrigo Siqueira  * copy of this software and associated documentation files (the "Software"),
75d945cbcSRodrigo Siqueira  * to deal in the Software without restriction, including without limitation
85d945cbcSRodrigo Siqueira  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
95d945cbcSRodrigo Siqueira  * and/or sell copies of the Software, and to permit persons to whom the
105d945cbcSRodrigo Siqueira  * Software is furnished to do so, subject to the following conditions:
115d945cbcSRodrigo Siqueira  *
125d945cbcSRodrigo Siqueira  * The above copyright notice and this permission notice shall be included in
135d945cbcSRodrigo Siqueira  * all copies or substantial portions of the Software.
145d945cbcSRodrigo Siqueira  *
155d945cbcSRodrigo Siqueira  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
165d945cbcSRodrigo Siqueira  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
175d945cbcSRodrigo Siqueira  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
185d945cbcSRodrigo Siqueira  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
195d945cbcSRodrigo Siqueira  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
205d945cbcSRodrigo Siqueira  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
215d945cbcSRodrigo Siqueira  * OTHER DEALINGS IN THE SOFTWARE.
225d945cbcSRodrigo Siqueira  *
235d945cbcSRodrigo Siqueira  * Authors: AMD
245d945cbcSRodrigo Siqueira  *
255d945cbcSRodrigo Siqueira  */
265d945cbcSRodrigo Siqueira 
275d945cbcSRodrigo Siqueira #include <drm/drm_atomic_helper.h>
285d945cbcSRodrigo Siqueira #include <drm/drm_blend.h>
29736692c3SJocelyn Falempe #include "drm/drm_framebuffer.h"
305d945cbcSRodrigo Siqueira #include <drm/drm_gem_atomic_helper.h>
315d945cbcSRodrigo Siqueira #include <drm/drm_plane_helper.h>
3273dd0ad9SMa Ke #include <drm/drm_gem_framebuffer_helper.h>
335d945cbcSRodrigo Siqueira #include <drm/drm_fourcc.h>
345d945cbcSRodrigo Siqueira 
355d945cbcSRodrigo Siqueira #include "amdgpu.h"
365d945cbcSRodrigo Siqueira #include "dal_asic_id.h"
375d945cbcSRodrigo Siqueira #include "amdgpu_display.h"
385d945cbcSRodrigo Siqueira #include "amdgpu_dm_trace.h"
39441b12bcSMaíra Canal #include "amdgpu_dm_plane.h"
405d945cbcSRodrigo Siqueira #include "gc/gc_11_0_0_offset.h"
415d945cbcSRodrigo Siqueira #include "gc/gc_11_0_0_sh_mask.h"
425d945cbcSRodrigo Siqueira 
435d945cbcSRodrigo Siqueira /*
445d945cbcSRodrigo Siqueira  * TODO: these are currently initialized to rgb formats only.
455d945cbcSRodrigo Siqueira  * For future use cases we should either initialize them dynamically based on
465d945cbcSRodrigo Siqueira  * plane capabilities, or initialize this array to all formats, so internal drm
475d945cbcSRodrigo Siqueira  * check will succeed, and let DC implement proper check
485d945cbcSRodrigo Siqueira  */
495d945cbcSRodrigo Siqueira static const uint32_t rgb_formats[] = {
505d945cbcSRodrigo Siqueira 	DRM_FORMAT_XRGB8888,
515d945cbcSRodrigo Siqueira 	DRM_FORMAT_ARGB8888,
525d945cbcSRodrigo Siqueira 	DRM_FORMAT_RGBA8888,
535d945cbcSRodrigo Siqueira 	DRM_FORMAT_XRGB2101010,
545d945cbcSRodrigo Siqueira 	DRM_FORMAT_XBGR2101010,
555d945cbcSRodrigo Siqueira 	DRM_FORMAT_ARGB2101010,
565d945cbcSRodrigo Siqueira 	DRM_FORMAT_ABGR2101010,
575d945cbcSRodrigo Siqueira 	DRM_FORMAT_XRGB16161616,
585d945cbcSRodrigo Siqueira 	DRM_FORMAT_XBGR16161616,
595d945cbcSRodrigo Siqueira 	DRM_FORMAT_ARGB16161616,
605d945cbcSRodrigo Siqueira 	DRM_FORMAT_ABGR16161616,
615d945cbcSRodrigo Siqueira 	DRM_FORMAT_XBGR8888,
625d945cbcSRodrigo Siqueira 	DRM_FORMAT_ABGR8888,
635d945cbcSRodrigo Siqueira 	DRM_FORMAT_RGB565,
645d945cbcSRodrigo Siqueira };
655d945cbcSRodrigo Siqueira 
665d945cbcSRodrigo Siqueira static const uint32_t overlay_formats[] = {
675d945cbcSRodrigo Siqueira 	DRM_FORMAT_XRGB8888,
685d945cbcSRodrigo Siqueira 	DRM_FORMAT_ARGB8888,
695d945cbcSRodrigo Siqueira 	DRM_FORMAT_RGBA8888,
705d945cbcSRodrigo Siqueira 	DRM_FORMAT_XBGR8888,
715d945cbcSRodrigo Siqueira 	DRM_FORMAT_ABGR8888,
7235f33086SBhawanpreet Lakha 	DRM_FORMAT_RGB565,
7335f33086SBhawanpreet Lakha 	DRM_FORMAT_NV21,
7435f33086SBhawanpreet Lakha 	DRM_FORMAT_NV12,
7535f33086SBhawanpreet Lakha 	DRM_FORMAT_P010
7635f33086SBhawanpreet Lakha };
7735f33086SBhawanpreet Lakha 
7835f33086SBhawanpreet Lakha static const uint32_t video_formats[] = {
7935f33086SBhawanpreet Lakha 	DRM_FORMAT_NV21,
8035f33086SBhawanpreet Lakha 	DRM_FORMAT_NV12,
8135f33086SBhawanpreet Lakha 	DRM_FORMAT_P010
825d945cbcSRodrigo Siqueira };
835d945cbcSRodrigo Siqueira 
845d945cbcSRodrigo Siqueira static const u32 cursor_formats[] = {
855d945cbcSRodrigo Siqueira 	DRM_FORMAT_ARGB8888
865d945cbcSRodrigo Siqueira };
875d945cbcSRodrigo Siqueira 
885d945cbcSRodrigo Siqueira enum dm_micro_swizzle {
895d945cbcSRodrigo Siqueira 	MICRO_SWIZZLE_Z = 0,
905d945cbcSRodrigo Siqueira 	MICRO_SWIZZLE_S = 1,
915d945cbcSRodrigo Siqueira 	MICRO_SWIZZLE_D = 2,
925d945cbcSRodrigo Siqueira 	MICRO_SWIZZLE_R = 3
935d945cbcSRodrigo Siqueira };
945d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 * cmd)958bf0d9cdSDavid Tadokoro const struct drm_format_info *amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
965d945cbcSRodrigo Siqueira {
975d945cbcSRodrigo Siqueira 	return amdgpu_lookup_format_info(cmd->pixel_format, cmd->modifier[0]);
985d945cbcSRodrigo Siqueira }
995d945cbcSRodrigo Siqueira 
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)1008bf0d9cdSDavid Tadokoro void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
1015d945cbcSRodrigo Siqueira 			       bool *per_pixel_alpha, bool *pre_multiplied_alpha,
1025d945cbcSRodrigo Siqueira 			       bool *global_alpha, int *global_alpha_value)
1035d945cbcSRodrigo Siqueira {
1045d945cbcSRodrigo Siqueira 	*per_pixel_alpha = false;
1055d945cbcSRodrigo Siqueira 	*pre_multiplied_alpha = true;
1065d945cbcSRodrigo Siqueira 	*global_alpha = false;
1075d945cbcSRodrigo Siqueira 	*global_alpha_value = 0xff;
1085d945cbcSRodrigo Siqueira 
1095d945cbcSRodrigo Siqueira 
1105d945cbcSRodrigo Siqueira 	if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
1115d945cbcSRodrigo Siqueira 		plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
1125d945cbcSRodrigo Siqueira 		static const uint32_t alpha_formats[] = {
1135d945cbcSRodrigo Siqueira 			DRM_FORMAT_ARGB8888,
1145d945cbcSRodrigo Siqueira 			DRM_FORMAT_RGBA8888,
1155d945cbcSRodrigo Siqueira 			DRM_FORMAT_ABGR8888,
116ab4c37feSJoshua Ashton 			DRM_FORMAT_ARGB2101010,
117ab4c37feSJoshua Ashton 			DRM_FORMAT_ABGR2101010,
118ab4c37feSJoshua Ashton 			DRM_FORMAT_ARGB16161616,
119ab4c37feSJoshua Ashton 			DRM_FORMAT_ABGR16161616,
120ab4c37feSJoshua Ashton 			DRM_FORMAT_ARGB16161616F,
1215d945cbcSRodrigo Siqueira 		};
1225d945cbcSRodrigo Siqueira 		uint32_t format = plane_state->fb->format->format;
1235d945cbcSRodrigo Siqueira 		unsigned int i;
1245d945cbcSRodrigo Siqueira 
1255d945cbcSRodrigo Siqueira 		for (i = 0; i < ARRAY_SIZE(alpha_formats); ++i) {
1265d945cbcSRodrigo Siqueira 			if (format == alpha_formats[i]) {
1275d945cbcSRodrigo Siqueira 				*per_pixel_alpha = true;
1285d945cbcSRodrigo Siqueira 				break;
1295d945cbcSRodrigo Siqueira 			}
1305d945cbcSRodrigo Siqueira 		}
1315d945cbcSRodrigo Siqueira 
1325d945cbcSRodrigo Siqueira 		if (*per_pixel_alpha && plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE)
1335d945cbcSRodrigo Siqueira 			*pre_multiplied_alpha = false;
1345d945cbcSRodrigo Siqueira 	}
1355d945cbcSRodrigo Siqueira 
1365d945cbcSRodrigo Siqueira 	if (plane_state->alpha < 0xffff) {
1375d945cbcSRodrigo Siqueira 		*global_alpha = true;
1385d945cbcSRodrigo Siqueira 		*global_alpha_value = plane_state->alpha >> 8;
1395d945cbcSRodrigo Siqueira 	}
1405d945cbcSRodrigo Siqueira }
1415d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_add_modifier(uint64_t ** mods,uint64_t * size,uint64_t * cap,uint64_t mod)142c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
1435d945cbcSRodrigo Siqueira {
1445d945cbcSRodrigo Siqueira 	if (!*mods)
1455d945cbcSRodrigo Siqueira 		return;
1465d945cbcSRodrigo Siqueira 
1475d945cbcSRodrigo Siqueira 	if (*cap - *size < 1) {
1485d945cbcSRodrigo Siqueira 		uint64_t new_cap = *cap * 2;
1495d945cbcSRodrigo Siqueira 		uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t), GFP_KERNEL);
1505d945cbcSRodrigo Siqueira 
1515d945cbcSRodrigo Siqueira 		if (!new_mods) {
1525d945cbcSRodrigo Siqueira 			kfree(*mods);
1535d945cbcSRodrigo Siqueira 			*mods = NULL;
1545d945cbcSRodrigo Siqueira 			return;
1555d945cbcSRodrigo Siqueira 		}
1565d945cbcSRodrigo Siqueira 
1575d945cbcSRodrigo Siqueira 		memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
1585d945cbcSRodrigo Siqueira 		kfree(*mods);
1595d945cbcSRodrigo Siqueira 		*mods = new_mods;
1605d945cbcSRodrigo Siqueira 		*cap = new_cap;
1615d945cbcSRodrigo Siqueira 	}
1625d945cbcSRodrigo Siqueira 
1635d945cbcSRodrigo Siqueira 	(*mods)[*size] = mod;
1645d945cbcSRodrigo Siqueira 	*size += 1;
1655d945cbcSRodrigo Siqueira }
1665d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_modifier_has_dcc(uint64_t modifier)167c4066d8bSRodrigo Siqueira static bool amdgpu_dm_plane_modifier_has_dcc(uint64_t modifier)
1685d945cbcSRodrigo Siqueira {
1695d945cbcSRodrigo Siqueira 	return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
1705d945cbcSRodrigo Siqueira }
1715d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_modifier_gfx9_swizzle_mode(uint64_t modifier)172c4066d8bSRodrigo Siqueira static unsigned int amdgpu_dm_plane_modifier_gfx9_swizzle_mode(uint64_t modifier)
1735d945cbcSRodrigo Siqueira {
1745d945cbcSRodrigo Siqueira 	if (modifier == DRM_FORMAT_MOD_LINEAR)
1755d945cbcSRodrigo Siqueira 		return 0;
1765d945cbcSRodrigo Siqueira 
1775d945cbcSRodrigo Siqueira 	return AMD_FMT_MOD_GET(TILE, modifier);
1785d945cbcSRodrigo Siqueira }
1795d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(struct dc_tiling_info * tiling_info,uint64_t tiling_flags)180080950cbSKarthi Kandasamy static void amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(struct dc_tiling_info *tiling_info,
1815d945cbcSRodrigo Siqueira 							     uint64_t tiling_flags)
1825d945cbcSRodrigo Siqueira {
1835d945cbcSRodrigo Siqueira 	/* Fill GFX8 params */
1845d945cbcSRodrigo Siqueira 	if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) {
1855d945cbcSRodrigo Siqueira 		unsigned int bankw, bankh, mtaspect, tile_split, num_banks;
1865d945cbcSRodrigo Siqueira 
1875d945cbcSRodrigo Siqueira 		bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
1885d945cbcSRodrigo Siqueira 		bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
1895d945cbcSRodrigo Siqueira 		mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
1905d945cbcSRodrigo Siqueira 		tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
1915d945cbcSRodrigo Siqueira 		num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
1925d945cbcSRodrigo Siqueira 
193c7c703e4SKarthi Kandasamy 		tiling_info->gfxversion = DcGfxVersion8;
1945d945cbcSRodrigo Siqueira 		/* XXX fix me for VI */
1955d945cbcSRodrigo Siqueira 		tiling_info->gfx8.num_banks = num_banks;
1965d945cbcSRodrigo Siqueira 		tiling_info->gfx8.array_mode =
1975d945cbcSRodrigo Siqueira 				DC_ARRAY_2D_TILED_THIN1;
1985d945cbcSRodrigo Siqueira 		tiling_info->gfx8.tile_split = tile_split;
1995d945cbcSRodrigo Siqueira 		tiling_info->gfx8.bank_width = bankw;
2005d945cbcSRodrigo Siqueira 		tiling_info->gfx8.bank_height = bankh;
2015d945cbcSRodrigo Siqueira 		tiling_info->gfx8.tile_aspect = mtaspect;
2025d945cbcSRodrigo Siqueira 		tiling_info->gfx8.tile_mode =
2035d945cbcSRodrigo Siqueira 				DC_ADDR_SURF_MICRO_TILING_DISPLAY;
2045d945cbcSRodrigo Siqueira 	} else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
2055d945cbcSRodrigo Siqueira 			== DC_ARRAY_1D_TILED_THIN1) {
2065d945cbcSRodrigo Siqueira 		tiling_info->gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1;
2075d945cbcSRodrigo Siqueira 	}
2085d945cbcSRodrigo Siqueira 
2095d945cbcSRodrigo Siqueira 	tiling_info->gfx8.pipe_config =
2105d945cbcSRodrigo Siqueira 			AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
2115d945cbcSRodrigo Siqueira }
2125d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(const struct amdgpu_device * adev,struct dc_tiling_info * tiling_info)213c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
214080950cbSKarthi Kandasamy 							      struct dc_tiling_info *tiling_info)
2155d945cbcSRodrigo Siqueira {
2165d945cbcSRodrigo Siqueira 	/* Fill GFX9 params */
2175d945cbcSRodrigo Siqueira 	tiling_info->gfx9.num_pipes =
2185d945cbcSRodrigo Siqueira 		adev->gfx.config.gb_addr_config_fields.num_pipes;
2195d945cbcSRodrigo Siqueira 	tiling_info->gfx9.num_banks =
2205d945cbcSRodrigo Siqueira 		adev->gfx.config.gb_addr_config_fields.num_banks;
2215d945cbcSRodrigo Siqueira 	tiling_info->gfx9.pipe_interleave =
2225d945cbcSRodrigo Siqueira 		adev->gfx.config.gb_addr_config_fields.pipe_interleave_size;
2235d945cbcSRodrigo Siqueira 	tiling_info->gfx9.num_shader_engines =
2245d945cbcSRodrigo Siqueira 		adev->gfx.config.gb_addr_config_fields.num_se;
2255d945cbcSRodrigo Siqueira 	tiling_info->gfx9.max_compressed_frags =
2265d945cbcSRodrigo Siqueira 		adev->gfx.config.gb_addr_config_fields.max_compress_frags;
2275d945cbcSRodrigo Siqueira 	tiling_info->gfx9.num_rb_per_se =
2285d945cbcSRodrigo Siqueira 		adev->gfx.config.gb_addr_config_fields.num_rb_per_se;
2295d945cbcSRodrigo Siqueira 	tiling_info->gfx9.shaderEnable = 1;
2304e8303cfSLijo Lazar 	if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
2315d945cbcSRodrigo Siqueira 		tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs;
2325d945cbcSRodrigo Siqueira }
2335d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device * adev,struct dc_tiling_info * tiling_info,uint64_t modifier)234c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
235080950cbSKarthi Kandasamy 								struct dc_tiling_info *tiling_info,
2365d945cbcSRodrigo Siqueira 								uint64_t modifier)
2375d945cbcSRodrigo Siqueira {
2385d945cbcSRodrigo Siqueira 	unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
2395d945cbcSRodrigo Siqueira 	unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
2405d945cbcSRodrigo Siqueira 	unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier);
2415d945cbcSRodrigo Siqueira 	unsigned int pipes_log2;
2425d945cbcSRodrigo Siqueira 
2435d945cbcSRodrigo Siqueira 	pipes_log2 = min(5u, mod_pipe_xor_bits);
2445d945cbcSRodrigo Siqueira 
245c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, tiling_info);
2465d945cbcSRodrigo Siqueira 
2475d945cbcSRodrigo Siqueira 	if (!IS_AMD_FMT_MOD(modifier))
2485d945cbcSRodrigo Siqueira 		return;
2495d945cbcSRodrigo Siqueira 
2505d945cbcSRodrigo Siqueira 	tiling_info->gfx9.num_pipes = 1u << pipes_log2;
2515d945cbcSRodrigo Siqueira 	tiling_info->gfx9.num_shader_engines = 1u << (mod_pipe_xor_bits - pipes_log2);
2525d945cbcSRodrigo Siqueira 
2535d945cbcSRodrigo Siqueira 	if (adev->family >= AMDGPU_FAMILY_NV) {
2545d945cbcSRodrigo Siqueira 		tiling_info->gfx9.num_pkrs = 1u << pkrs_log2;
2555d945cbcSRodrigo Siqueira 	} else {
2565d945cbcSRodrigo Siqueira 		tiling_info->gfx9.num_banks = 1u << mod_bank_xor_bits;
2575d945cbcSRodrigo Siqueira 
2585d945cbcSRodrigo Siqueira 		/* for DCC we know it isn't rb aligned, so rb_per_se doesn't matter. */
2595d945cbcSRodrigo Siqueira 	}
2605d945cbcSRodrigo Siqueira }
2615d945cbcSRodrigo Siqueira 
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)262c4066d8bSRodrigo Siqueira static int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev,
2635d945cbcSRodrigo Siqueira 					const enum surface_pixel_format format,
2645d945cbcSRodrigo Siqueira 					const enum dc_rotation_angle rotation,
265080950cbSKarthi Kandasamy 					const struct dc_tiling_info *tiling_info,
2665d945cbcSRodrigo Siqueira 					const struct dc_plane_dcc_param *dcc,
2675d945cbcSRodrigo Siqueira 					const struct dc_plane_address *address,
2685d945cbcSRodrigo Siqueira 					const struct plane_size *plane_size)
2695d945cbcSRodrigo Siqueira {
2705d945cbcSRodrigo Siqueira 	struct dc *dc = adev->dm.dc;
2715d945cbcSRodrigo Siqueira 	struct dc_dcc_surface_param input;
2725d945cbcSRodrigo Siqueira 	struct dc_surface_dcc_cap output;
2735d945cbcSRodrigo Siqueira 
2745d945cbcSRodrigo Siqueira 	memset(&input, 0, sizeof(input));
2755d945cbcSRodrigo Siqueira 	memset(&output, 0, sizeof(output));
2765d945cbcSRodrigo Siqueira 
2775d945cbcSRodrigo Siqueira 	if (!dcc->enable)
2785d945cbcSRodrigo Siqueira 		return 0;
2795d945cbcSRodrigo Siqueira 
280*df1e82e7SDavid Rosca 	if (adev->family < AMDGPU_FAMILY_GC_12_0_0 &&
281*df1e82e7SDavid Rosca 	    format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
282*df1e82e7SDavid Rosca 		return -EINVAL;
283*df1e82e7SDavid Rosca 
284*df1e82e7SDavid Rosca 	if (!dc->cap_funcs.get_dcc_compression_cap)
2855d945cbcSRodrigo Siqueira 		return -EINVAL;
2865d945cbcSRodrigo Siqueira 
2875d945cbcSRodrigo Siqueira 	input.format = format;
2885d945cbcSRodrigo Siqueira 	input.surface_size.width = plane_size->surface_size.width;
2895d945cbcSRodrigo Siqueira 	input.surface_size.height = plane_size->surface_size.height;
2905d945cbcSRodrigo Siqueira 	input.swizzle_mode = tiling_info->gfx9.swizzle;
2915d945cbcSRodrigo Siqueira 
2925d945cbcSRodrigo Siqueira 	if (rotation == ROTATION_ANGLE_0 || rotation == ROTATION_ANGLE_180)
2935d945cbcSRodrigo Siqueira 		input.scan = SCAN_DIRECTION_HORIZONTAL;
2945d945cbcSRodrigo Siqueira 	else if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270)
2955d945cbcSRodrigo Siqueira 		input.scan = SCAN_DIRECTION_VERTICAL;
2965d945cbcSRodrigo Siqueira 
2975d945cbcSRodrigo Siqueira 	if (!dc->cap_funcs.get_dcc_compression_cap(dc, &input, &output))
2985d945cbcSRodrigo Siqueira 		return -EINVAL;
2995d945cbcSRodrigo Siqueira 
3005d945cbcSRodrigo Siqueira 	if (!output.capable)
3015d945cbcSRodrigo Siqueira 		return -EINVAL;
3025d945cbcSRodrigo Siqueira 
3035d945cbcSRodrigo Siqueira 	if (dcc->independent_64b_blks == 0 &&
3045d945cbcSRodrigo Siqueira 	    output.grph.rgb.independent_64b_blks != 0)
3055d945cbcSRodrigo Siqueira 		return -EINVAL;
3065d945cbcSRodrigo Siqueira 
3075d945cbcSRodrigo Siqueira 	return 0;
3085d945cbcSRodrigo Siqueira }
3095d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_fill_gfx9_plane_attributes_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)310c4066d8bSRodrigo Siqueira static int amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
3115d945cbcSRodrigo Siqueira 								     const struct amdgpu_framebuffer *afb,
3125d945cbcSRodrigo Siqueira 								     const enum surface_pixel_format format,
3135d945cbcSRodrigo Siqueira 								     const enum dc_rotation_angle rotation,
3145d945cbcSRodrigo Siqueira 								     const struct plane_size *plane_size,
315080950cbSKarthi Kandasamy 								     struct dc_tiling_info *tiling_info,
3165d945cbcSRodrigo Siqueira 								     struct dc_plane_dcc_param *dcc,
31704d6273fSRodrigo Siqueira 								     struct dc_plane_address *address)
3185d945cbcSRodrigo Siqueira {
3195d945cbcSRodrigo Siqueira 	const uint64_t modifier = afb->base.modifier;
3205d945cbcSRodrigo Siqueira 	int ret = 0;
3215d945cbcSRodrigo Siqueira 
322c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
323c4066d8bSRodrigo Siqueira 	tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier);
324c7c703e4SKarthi Kandasamy 	tiling_info->gfxversion = DcGfxVersion9;
3255d945cbcSRodrigo Siqueira 
32604d6273fSRodrigo Siqueira 	if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
3275d945cbcSRodrigo Siqueira 		uint64_t dcc_address = afb->address + afb->base.offsets[1];
3285d945cbcSRodrigo Siqueira 		bool independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier);
3295d945cbcSRodrigo Siqueira 		bool independent_128b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier);
3305d945cbcSRodrigo Siqueira 
3315d945cbcSRodrigo Siqueira 		dcc->enable = 1;
3325d945cbcSRodrigo Siqueira 		dcc->meta_pitch = afb->base.pitches[1];
3335d945cbcSRodrigo Siqueira 		dcc->independent_64b_blks = independent_64b_blks;
3345d945cbcSRodrigo Siqueira 		if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) {
3355d945cbcSRodrigo Siqueira 			if (independent_64b_blks && independent_128b_blks)
3365d945cbcSRodrigo Siqueira 				dcc->dcc_ind_blk = hubp_ind_block_64b_no_128bcl;
3375d945cbcSRodrigo Siqueira 			else if (independent_128b_blks)
3385d945cbcSRodrigo Siqueira 				dcc->dcc_ind_blk = hubp_ind_block_128b;
3395d945cbcSRodrigo Siqueira 			else if (independent_64b_blks && !independent_128b_blks)
3405d945cbcSRodrigo Siqueira 				dcc->dcc_ind_blk = hubp_ind_block_64b;
3415d945cbcSRodrigo Siqueira 			else
3425d945cbcSRodrigo Siqueira 				dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
3435d945cbcSRodrigo Siqueira 		} else {
3445d945cbcSRodrigo Siqueira 			if (independent_64b_blks)
3455d945cbcSRodrigo Siqueira 				dcc->dcc_ind_blk = hubp_ind_block_64b;
3465d945cbcSRodrigo Siqueira 			else
3475d945cbcSRodrigo Siqueira 				dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
3485d945cbcSRodrigo Siqueira 		}
3495d945cbcSRodrigo Siqueira 
3505d945cbcSRodrigo Siqueira 		address->grph.meta_addr.low_part = lower_32_bits(dcc_address);
3515d945cbcSRodrigo Siqueira 		address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
3525d945cbcSRodrigo Siqueira 	}
3535d945cbcSRodrigo Siqueira 
354c4066d8bSRodrigo Siqueira 	ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
3555d945cbcSRodrigo Siqueira 	if (ret)
356c4066d8bSRodrigo Siqueira 		drm_dbg_kms(adev_to_drm(adev), "amdgpu_dm_plane_validate_dcc: returned error: %d\n", ret);
3575d945cbcSRodrigo Siqueira 
3585d945cbcSRodrigo Siqueira 	return ret;
3595d945cbcSRodrigo Siqueira }
3605d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_fill_gfx12_plane_attributes_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)361ce7985fdSMarek Olšák static int amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(struct amdgpu_device *adev,
362ce7985fdSMarek Olšák 								      const struct amdgpu_framebuffer *afb,
363ce7985fdSMarek Olšák 								      const enum surface_pixel_format format,
364ce7985fdSMarek Olšák 								      const enum dc_rotation_angle rotation,
365ce7985fdSMarek Olšák 								      const struct plane_size *plane_size,
366080950cbSKarthi Kandasamy 								      struct dc_tiling_info *tiling_info,
367ce7985fdSMarek Olšák 								      struct dc_plane_dcc_param *dcc,
36804d6273fSRodrigo Siqueira 								      struct dc_plane_address *address)
369ce7985fdSMarek Olšák {
370ce7985fdSMarek Olšák 	const uint64_t modifier = afb->base.modifier;
371ce7985fdSMarek Olšák 	int ret = 0;
372ce7985fdSMarek Olšák 
373ce7985fdSMarek Olšák 	/* TODO: Most of this function shouldn't be needed on GFX12. */
374ce7985fdSMarek Olšák 	amdgpu_dm_plane_fill_gfx9_tiling_info_from_device(adev, tiling_info);
375ce7985fdSMarek Olšák 
376ce7985fdSMarek Olšák 	tiling_info->gfx9.swizzle = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier);
377c7c703e4SKarthi Kandasamy 	tiling_info->gfxversion = DcGfxAddr3;
378ce7985fdSMarek Olšák 
37904d6273fSRodrigo Siqueira 	if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
380ce7985fdSMarek Olšák 		int max_compressed_block = AMD_FMT_MOD_GET(DCC_MAX_COMPRESSED_BLOCK, modifier);
381ce7985fdSMarek Olšák 
382ce7985fdSMarek Olšák 		dcc->enable = 1;
383ce7985fdSMarek Olšák 		dcc->independent_64b_blks = max_compressed_block == 0;
384ce7985fdSMarek Olšák 
385ce7985fdSMarek Olšák 		if (max_compressed_block == 0)
386ce7985fdSMarek Olšák 			dcc->dcc_ind_blk = hubp_ind_block_64b;
387ce7985fdSMarek Olšák 		else if (max_compressed_block == 1)
388ce7985fdSMarek Olšák 			dcc->dcc_ind_blk = hubp_ind_block_128b;
389ce7985fdSMarek Olšák 		else
390ce7985fdSMarek Olšák 			dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
391ce7985fdSMarek Olšák 	}
392ce7985fdSMarek Olšák 
393ce7985fdSMarek Olšák 	/* TODO: This seems wrong because there is no DCC plane on GFX12. */
394ce7985fdSMarek Olšák 	ret = amdgpu_dm_plane_validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
395ce7985fdSMarek Olšák 	if (ret)
396ce7985fdSMarek Olšák 		drm_dbg_kms(adev_to_drm(adev), "amdgpu_dm_plane_validate_dcc: returned error: %d\n", ret);
397ce7985fdSMarek Olšák 
398ce7985fdSMarek Olšák 	return ret;
399ce7985fdSMarek Olšák }
400ce7985fdSMarek Olšák 
amdgpu_dm_plane_add_gfx10_1_modifiers(const struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)401c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_add_gfx10_1_modifiers(const struct amdgpu_device *adev,
402c4066d8bSRodrigo Siqueira 						  uint64_t **mods,
403c4066d8bSRodrigo Siqueira 						  uint64_t *size,
404c4066d8bSRodrigo Siqueira 						  uint64_t *capacity)
4055d945cbcSRodrigo Siqueira {
4065d945cbcSRodrigo Siqueira 	int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
4075d945cbcSRodrigo Siqueira 
408c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4095d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
4105d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
4115d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
4125d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC, 1) |
4135d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
4145d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
4155d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
4165d945cbcSRodrigo Siqueira 
417c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4185d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
4195d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
4205d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
4215d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC, 1) |
4225d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
4235d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
4245d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
4255d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
4265d945cbcSRodrigo Siqueira 
427c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4285d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
4295d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
4305d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
4315d945cbcSRodrigo Siqueira 
432c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4335d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
4345d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
4355d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
4365d945cbcSRodrigo Siqueira 
4375d945cbcSRodrigo Siqueira 
438c4066d8bSRodrigo Siqueira 	/* Only supported for 64bpp, will be filtered in amdgpu_dm_plane_format_mod_supported */
439c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4405d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
4415d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
4425d945cbcSRodrigo Siqueira 
443c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4445d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
4455d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
4465d945cbcSRodrigo Siqueira }
4475d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_add_gfx9_modifiers(const struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)448c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_add_gfx9_modifiers(const struct amdgpu_device *adev,
449c4066d8bSRodrigo Siqueira 					       uint64_t **mods,
450c4066d8bSRodrigo Siqueira 					       uint64_t *size,
451c4066d8bSRodrigo Siqueira 					       uint64_t *capacity)
4525d945cbcSRodrigo Siqueira {
4535d945cbcSRodrigo Siqueira 	int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
4545d945cbcSRodrigo Siqueira 	int pipe_xor_bits = min(8, pipes +
4555d945cbcSRodrigo Siqueira 				ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
4565d945cbcSRodrigo Siqueira 	int bank_xor_bits = min(8 - pipe_xor_bits,
4575d945cbcSRodrigo Siqueira 				ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
4585d945cbcSRodrigo Siqueira 	int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
4595d945cbcSRodrigo Siqueira 		 ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
4605d945cbcSRodrigo Siqueira 
4615d945cbcSRodrigo Siqueira 
4625d945cbcSRodrigo Siqueira 	if (adev->family == AMDGPU_FAMILY_RV) {
4635d945cbcSRodrigo Siqueira 		/* Raven2 and later */
4645d945cbcSRodrigo Siqueira 		bool has_constant_encode = adev->asic_type > CHIP_RAVEN || adev->external_rev_id >= 0x81;
4655d945cbcSRodrigo Siqueira 
4665d945cbcSRodrigo Siqueira 		/*
4675d945cbcSRodrigo Siqueira 		 * No _D DCC swizzles yet because we only allow 32bpp, which
4685d945cbcSRodrigo Siqueira 		 * doesn't support _D on DCN
4695d945cbcSRodrigo Siqueira 		 */
4705d945cbcSRodrigo Siqueira 
4715d945cbcSRodrigo Siqueira 		if (has_constant_encode) {
472c4066d8bSRodrigo Siqueira 			amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4735d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
4745d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
4755d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
4765d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
4775d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC, 1) |
4785d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
4795d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
4805d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
4815d945cbcSRodrigo Siqueira 		}
4825d945cbcSRodrigo Siqueira 
483c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4845d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
4855d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
4865d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
4875d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
4885d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC, 1) |
4895d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
4905d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
4915d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
4925d945cbcSRodrigo Siqueira 
4935d945cbcSRodrigo Siqueira 		if (has_constant_encode) {
494c4066d8bSRodrigo Siqueira 			amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
4955d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
4965d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
4975d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
4985d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
4995d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC, 1) |
5005d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
5015d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
5025d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
5035d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
5045d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(RB, rb) |
5055d945cbcSRodrigo Siqueira 						     AMD_FMT_MOD_SET(PIPE, pipes));
5065d945cbcSRodrigo Siqueira 		}
5075d945cbcSRodrigo Siqueira 
508c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5095d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
5105d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
5115d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
5125d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
5135d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC, 1) |
5145d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
5155d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
5165d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
5175d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
5185d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(RB, rb) |
5195d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(PIPE, pipes));
5205d945cbcSRodrigo Siqueira 	}
5215d945cbcSRodrigo Siqueira 
5225d945cbcSRodrigo Siqueira 	/*
5235d945cbcSRodrigo Siqueira 	 * Only supported for 64bpp on Raven, will be filtered on format in
524c4066d8bSRodrigo Siqueira 	 * amdgpu_dm_plane_format_mod_supported.
5255d945cbcSRodrigo Siqueira 	 */
526c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5275d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
5285d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
5295d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
5305d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
5315d945cbcSRodrigo Siqueira 
5325d945cbcSRodrigo Siqueira 	if (adev->family == AMDGPU_FAMILY_RV) {
533c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5345d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
5355d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
5365d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
5375d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
5385d945cbcSRodrigo Siqueira 	}
5395d945cbcSRodrigo Siqueira 
5405d945cbcSRodrigo Siqueira 	/*
5415d945cbcSRodrigo Siqueira 	 * Only supported for 64bpp on Raven, will be filtered on format in
542c4066d8bSRodrigo Siqueira 	 * amdgpu_dm_plane_format_mod_supported.
5435d945cbcSRodrigo Siqueira 	 */
544c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5455d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
5465d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
5475d945cbcSRodrigo Siqueira 
5485d945cbcSRodrigo Siqueira 	if (adev->family == AMDGPU_FAMILY_RV) {
549c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5505d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
5515d945cbcSRodrigo Siqueira 					     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
5525d945cbcSRodrigo Siqueira 	}
5535d945cbcSRodrigo Siqueira }
5545d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_add_gfx10_3_modifiers(const struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)555c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_add_gfx10_3_modifiers(const struct amdgpu_device *adev,
556c4066d8bSRodrigo Siqueira 						  uint64_t **mods,
557c4066d8bSRodrigo Siqueira 						  uint64_t *size,
558c4066d8bSRodrigo Siqueira 						  uint64_t *capacity)
5595d945cbcSRodrigo Siqueira {
5605d945cbcSRodrigo Siqueira 	int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
5615d945cbcSRodrigo Siqueira 	int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
5625d945cbcSRodrigo Siqueira 
563c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5645d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
5655d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
5665d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
5675d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PACKERS, pkrs) |
5685d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC, 1) |
5695d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
5705d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
5715d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
5725d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
5735d945cbcSRodrigo Siqueira 
574c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5755d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
5765d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
5775d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
5785d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PACKERS, pkrs) |
5795d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC, 1) |
5805d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
5815d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
5825d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
5835d945cbcSRodrigo Siqueira 
584c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5855d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
5865d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
5875d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
5885d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PACKERS, pkrs) |
5895d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC, 1) |
5905d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
5915d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
5925d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
5935d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
5945d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
5955d945cbcSRodrigo Siqueira 
596c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
5975d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
5985d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
5995d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
6005d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PACKERS, pkrs) |
6015d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC, 1) |
6025d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
6035d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
6045d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
6055d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
6065d945cbcSRodrigo Siqueira 
607c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
6085d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
6095d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
6105d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
6115d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PACKERS, pkrs));
6125d945cbcSRodrigo Siqueira 
613c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
6145d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
6155d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
6165d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
6175d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(PACKERS, pkrs));
6185d945cbcSRodrigo Siqueira 
619c4066d8bSRodrigo Siqueira 	/* Only supported for 64bpp, will be filtered in amdgpu_dm_plane_format_mod_supported */
620c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
6215d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
6225d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
6235d945cbcSRodrigo Siqueira 
624c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
6255d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
6265d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
6275d945cbcSRodrigo Siqueira }
6285d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_add_gfx11_modifiers(struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)629c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_add_gfx11_modifiers(struct amdgpu_device *adev,
6305d945cbcSRodrigo Siqueira 		      uint64_t **mods, uint64_t *size, uint64_t *capacity)
6315d945cbcSRodrigo Siqueira {
6325d945cbcSRodrigo Siqueira 	int num_pipes = 0;
6335d945cbcSRodrigo Siqueira 	int pipe_xor_bits = 0;
6345d945cbcSRodrigo Siqueira 	int num_pkrs = 0;
6355d945cbcSRodrigo Siqueira 	int pkrs = 0;
6365d945cbcSRodrigo Siqueira 	u32 gb_addr_config;
6375d945cbcSRodrigo Siqueira 	u8 i = 0;
638788dbb6bSSrinivasan Shanmugam 	unsigned int swizzle_r_x;
6395d945cbcSRodrigo Siqueira 	uint64_t modifier_r_x;
6405d945cbcSRodrigo Siqueira 	uint64_t modifier_dcc_best;
6415d945cbcSRodrigo Siqueira 	uint64_t modifier_dcc_4k;
6425d945cbcSRodrigo Siqueira 
6435d945cbcSRodrigo Siqueira 	/* TODO: GFX11 IP HW init hasnt finish and we get zero if we read from
6445d945cbcSRodrigo Siqueira 	 * adev->gfx.config.gb_addr_config_fields.num_{pkrs,pipes}
6455d945cbcSRodrigo Siqueira 	 */
6465d945cbcSRodrigo Siqueira 	gb_addr_config = RREG32_SOC15(GC, 0, regGB_ADDR_CONFIG);
6475d945cbcSRodrigo Siqueira 	ASSERT(gb_addr_config != 0);
6485d945cbcSRodrigo Siqueira 
6495d945cbcSRodrigo Siqueira 	num_pkrs = 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS);
6505d945cbcSRodrigo Siqueira 	pkrs = ilog2(num_pkrs);
6515d945cbcSRodrigo Siqueira 	num_pipes = 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PIPES);
6525d945cbcSRodrigo Siqueira 	pipe_xor_bits = ilog2(num_pipes);
6535d945cbcSRodrigo Siqueira 
6545d945cbcSRodrigo Siqueira 	for (i = 0; i < 2; i++) {
6555d945cbcSRodrigo Siqueira 		/* Insert the best one first. */
6565d945cbcSRodrigo Siqueira 		/* R_X swizzle modes are the best for rendering and DCC requires them. */
6575d945cbcSRodrigo Siqueira 		if (num_pipes > 16)
6585d945cbcSRodrigo Siqueira 			swizzle_r_x = !i ? AMD_FMT_MOD_TILE_GFX11_256K_R_X : AMD_FMT_MOD_TILE_GFX9_64K_R_X;
6595d945cbcSRodrigo Siqueira 		else
6605d945cbcSRodrigo Siqueira 			swizzle_r_x = !i ? AMD_FMT_MOD_TILE_GFX9_64K_R_X : AMD_FMT_MOD_TILE_GFX11_256K_R_X;
6615d945cbcSRodrigo Siqueira 
6625d945cbcSRodrigo Siqueira 		modifier_r_x = AMD_FMT_MOD |
6635d945cbcSRodrigo Siqueira 			       AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
6645d945cbcSRodrigo Siqueira 			       AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
6655d945cbcSRodrigo Siqueira 			       AMD_FMT_MOD_SET(TILE, swizzle_r_x) |
6665d945cbcSRodrigo Siqueira 			       AMD_FMT_MOD_SET(PACKERS, pkrs);
6675d945cbcSRodrigo Siqueira 
6685d945cbcSRodrigo Siqueira 		/* DCC_CONSTANT_ENCODE is not set because it can't vary with gfx11 (it's implied to be 1). */
6695d945cbcSRodrigo Siqueira 		modifier_dcc_best = modifier_r_x | AMD_FMT_MOD_SET(DCC, 1) |
6705d945cbcSRodrigo Siqueira 				    AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 0) |
6715d945cbcSRodrigo Siqueira 				    AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
6725d945cbcSRodrigo Siqueira 				    AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B);
6735d945cbcSRodrigo Siqueira 
6745d945cbcSRodrigo Siqueira 		/* DCC settings for 4K and greater resolutions. (required by display hw) */
6755d945cbcSRodrigo Siqueira 		modifier_dcc_4k = modifier_r_x | AMD_FMT_MOD_SET(DCC, 1) |
6765d945cbcSRodrigo Siqueira 				  AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
6775d945cbcSRodrigo Siqueira 				  AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
6785d945cbcSRodrigo Siqueira 				  AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B);
6795d945cbcSRodrigo Siqueira 
680c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_best);
681c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_4k);
6825d945cbcSRodrigo Siqueira 
683c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_best | AMD_FMT_MOD_SET(DCC_RETILE, 1));
684c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_dcc_4k | AMD_FMT_MOD_SET(DCC_RETILE, 1));
6855d945cbcSRodrigo Siqueira 
686c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, size, capacity, modifier_r_x);
6875d945cbcSRodrigo Siqueira 	}
6885d945cbcSRodrigo Siqueira 
689c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, size, capacity, AMD_FMT_MOD |
6905d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
6915d945cbcSRodrigo Siqueira 				     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D));
6925d945cbcSRodrigo Siqueira }
6935d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device * adev,uint64_t ** mods,uint64_t * size,uint64_t * capacity)694a64a5212SAurabindo Pillai static void amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device *adev,
695a64a5212SAurabindo Pillai 		      uint64_t **mods, uint64_t *size, uint64_t *capacity)
696a64a5212SAurabindo Pillai {
697cc6e00a6SMarek Olšák 	uint64_t ver = AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX12);
69821e6f608SAurabindo Pillai 	uint64_t mod_256k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_256K_2D);
69921e6f608SAurabindo Pillai 	uint64_t mod_64k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_64K_2D);
70021e6f608SAurabindo Pillai 	uint64_t mod_4k = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_4K_2D);
70121e6f608SAurabindo Pillai 	uint64_t mod_256b = ver | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX12_256B_2D);
70221e6f608SAurabindo Pillai 	uint64_t dcc = ver | AMD_FMT_MOD_SET(DCC, 1);
70321e6f608SAurabindo Pillai 	uint8_t max_comp_block[] = {2, 1, 0};
70421e6f608SAurabindo Pillai 	uint64_t max_comp_block_mod[ARRAY_SIZE(max_comp_block)] = {0};
70521e6f608SAurabindo Pillai 	uint8_t i = 0, j = 0;
70621e6f608SAurabindo Pillai 	uint64_t gfx12_modifiers[] = {mod_256k, mod_64k, mod_4k, mod_256b, DRM_FORMAT_MOD_LINEAR};
707a64a5212SAurabindo Pillai 
70821e6f608SAurabindo Pillai 	for (i = 0; i < ARRAY_SIZE(max_comp_block); i++)
70921e6f608SAurabindo Pillai 		max_comp_block_mod[i] = AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_comp_block[i]);
71021e6f608SAurabindo Pillai 
71121e6f608SAurabindo Pillai 	/* With DCC: Best choice should be kept first. Hence, add all 256k modifiers of different
71221e6f608SAurabindo Pillai 	 * max compressed blocks first and then move on to the next smaller sized layouts.
71321e6f608SAurabindo Pillai 	 * Do not add the linear modifier here, and hence the condition of size-1 for the loop
71421e6f608SAurabindo Pillai 	 */
71521e6f608SAurabindo Pillai 	for (j = 0; j < ARRAY_SIZE(gfx12_modifiers) - 1; j++)
71621e6f608SAurabindo Pillai 		for (i = 0; i < ARRAY_SIZE(max_comp_block); i++)
71721e6f608SAurabindo Pillai 			amdgpu_dm_plane_add_modifier(mods, size, capacity,
71821e6f608SAurabindo Pillai 						     ver | dcc | max_comp_block_mod[i] | gfx12_modifiers[j]);
71921e6f608SAurabindo Pillai 
72021e6f608SAurabindo Pillai 	/* Without DCC. Add all modifiers including linear at the end */
72121e6f608SAurabindo Pillai 	for (i = 0; i < ARRAY_SIZE(gfx12_modifiers); i++)
72221e6f608SAurabindo Pillai 		amdgpu_dm_plane_add_modifier(mods, size, capacity, gfx12_modifiers[i]);
72321e6f608SAurabindo Pillai 
724a64a5212SAurabindo Pillai }
725a64a5212SAurabindo Pillai 
amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device * adev,unsigned int plane_type,uint64_t ** mods)726c4066d8bSRodrigo Siqueira static int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
7275d945cbcSRodrigo Siqueira {
7285d945cbcSRodrigo Siqueira 	uint64_t size = 0, capacity = 128;
7295d945cbcSRodrigo Siqueira 	*mods = NULL;
7305d945cbcSRodrigo Siqueira 
7315d945cbcSRodrigo Siqueira 	/* We have not hooked up any pre-GFX9 modifiers. */
7325d945cbcSRodrigo Siqueira 	if (adev->family < AMDGPU_FAMILY_AI)
7335d945cbcSRodrigo Siqueira 		return 0;
7345d945cbcSRodrigo Siqueira 
7355d945cbcSRodrigo Siqueira 	*mods = kmalloc(capacity * sizeof(uint64_t), GFP_KERNEL);
7365d945cbcSRodrigo Siqueira 
7375d945cbcSRodrigo Siqueira 	if (plane_type == DRM_PLANE_TYPE_CURSOR) {
738c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
739c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
7405d945cbcSRodrigo Siqueira 		return *mods ? 0 : -ENOMEM;
7415d945cbcSRodrigo Siqueira 	}
7425d945cbcSRodrigo Siqueira 
7435d945cbcSRodrigo Siqueira 	switch (adev->family) {
7445d945cbcSRodrigo Siqueira 	case AMDGPU_FAMILY_AI:
7455d945cbcSRodrigo Siqueira 	case AMDGPU_FAMILY_RV:
746c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_gfx9_modifiers(adev, mods, &size, &capacity);
7475d945cbcSRodrigo Siqueira 		break;
7485d945cbcSRodrigo Siqueira 	case AMDGPU_FAMILY_NV:
7495d945cbcSRodrigo Siqueira 	case AMDGPU_FAMILY_VGH:
7505d945cbcSRodrigo Siqueira 	case AMDGPU_FAMILY_YC:
7515d945cbcSRodrigo Siqueira 	case AMDGPU_FAMILY_GC_10_3_6:
7525d945cbcSRodrigo Siqueira 	case AMDGPU_FAMILY_GC_10_3_7:
7534e8303cfSLijo Lazar 		if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0))
754c4066d8bSRodrigo Siqueira 			amdgpu_dm_plane_add_gfx10_3_modifiers(adev, mods, &size, &capacity);
7555d945cbcSRodrigo Siqueira 		else
756c4066d8bSRodrigo Siqueira 			amdgpu_dm_plane_add_gfx10_1_modifiers(adev, mods, &size, &capacity);
7575d945cbcSRodrigo Siqueira 		break;
7585d945cbcSRodrigo Siqueira 	case AMDGPU_FAMILY_GC_11_0_0:
75908ebadfcSYifan Zhang 	case AMDGPU_FAMILY_GC_11_0_1:
76006b1661eSQingqing Zhuo 	case AMDGPU_FAMILY_GC_11_5_0:
761c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity);
7625d945cbcSRodrigo Siqueira 		break;
763a64a5212SAurabindo Pillai 	case AMDGPU_FAMILY_GC_12_0_0:
764a64a5212SAurabindo Pillai 		amdgpu_dm_plane_add_gfx12_modifiers(adev, mods, &size, &capacity);
765a64a5212SAurabindo Pillai 		break;
7665d945cbcSRodrigo Siqueira 	}
7675d945cbcSRodrigo Siqueira 
768c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
7695d945cbcSRodrigo Siqueira 
7705d945cbcSRodrigo Siqueira 	/* INVALID marks the end of the list. */
771c4066d8bSRodrigo Siqueira 	amdgpu_dm_plane_add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
7725d945cbcSRodrigo Siqueira 
7735d945cbcSRodrigo Siqueira 	if (!*mods)
7745d945cbcSRodrigo Siqueira 		return -ENOMEM;
7755d945cbcSRodrigo Siqueira 
7765d945cbcSRodrigo Siqueira 	return 0;
7775d945cbcSRodrigo Siqueira }
7785d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_get_plane_formats(const struct drm_plane * plane,const struct dc_plane_cap * plane_cap,uint32_t * formats,int max_formats)779c4066d8bSRodrigo Siqueira static int amdgpu_dm_plane_get_plane_formats(const struct drm_plane *plane,
7805d945cbcSRodrigo Siqueira 					     const struct dc_plane_cap *plane_cap,
7815d945cbcSRodrigo Siqueira 					     uint32_t *formats, int max_formats)
7825d945cbcSRodrigo Siqueira {
7835d945cbcSRodrigo Siqueira 	int i, num_formats = 0;
7845d945cbcSRodrigo Siqueira 
7855d945cbcSRodrigo Siqueira 	/*
7865d945cbcSRodrigo Siqueira 	 * TODO: Query support for each group of formats directly from
7875d945cbcSRodrigo Siqueira 	 * DC plane caps. This will require adding more formats to the
7885d945cbcSRodrigo Siqueira 	 * caps list.
7895d945cbcSRodrigo Siqueira 	 */
7905d945cbcSRodrigo Siqueira 
791ab4c37feSJoshua Ashton 	if (plane->type == DRM_PLANE_TYPE_PRIMARY ||
792ab4c37feSJoshua Ashton 		(plane_cap && plane_cap->type == DC_PLANE_TYPE_DCN_UNIVERSAL && plane->type != DRM_PLANE_TYPE_CURSOR)) {
7935d945cbcSRodrigo Siqueira 		for (i = 0; i < ARRAY_SIZE(rgb_formats); ++i) {
7945d945cbcSRodrigo Siqueira 			if (num_formats >= max_formats)
7955d945cbcSRodrigo Siqueira 				break;
7965d945cbcSRodrigo Siqueira 
7975d945cbcSRodrigo Siqueira 			formats[num_formats++] = rgb_formats[i];
7985d945cbcSRodrigo Siqueira 		}
7995d945cbcSRodrigo Siqueira 
8005d945cbcSRodrigo Siqueira 		if (plane_cap && plane_cap->pixel_format_support.nv12)
8015d945cbcSRodrigo Siqueira 			formats[num_formats++] = DRM_FORMAT_NV12;
8025d945cbcSRodrigo Siqueira 		if (plane_cap && plane_cap->pixel_format_support.p010)
8035d945cbcSRodrigo Siqueira 			formats[num_formats++] = DRM_FORMAT_P010;
8045d945cbcSRodrigo Siqueira 		if (plane_cap && plane_cap->pixel_format_support.fp16) {
8055d945cbcSRodrigo Siqueira 			formats[num_formats++] = DRM_FORMAT_XRGB16161616F;
8065d945cbcSRodrigo Siqueira 			formats[num_formats++] = DRM_FORMAT_ARGB16161616F;
8075d945cbcSRodrigo Siqueira 			formats[num_formats++] = DRM_FORMAT_XBGR16161616F;
8085d945cbcSRodrigo Siqueira 			formats[num_formats++] = DRM_FORMAT_ABGR16161616F;
8095d945cbcSRodrigo Siqueira 		}
810ab4c37feSJoshua Ashton 	} else {
811ab4c37feSJoshua Ashton 		switch (plane->type) {
8125d945cbcSRodrigo Siqueira 		case DRM_PLANE_TYPE_OVERLAY:
8135d945cbcSRodrigo Siqueira 			for (i = 0; i < ARRAY_SIZE(overlay_formats); ++i) {
8145d945cbcSRodrigo Siqueira 				if (num_formats >= max_formats)
8155d945cbcSRodrigo Siqueira 					break;
8165d945cbcSRodrigo Siqueira 
8175d945cbcSRodrigo Siqueira 				formats[num_formats++] = overlay_formats[i];
8185d945cbcSRodrigo Siqueira 			}
8195d945cbcSRodrigo Siqueira 			break;
8205d945cbcSRodrigo Siqueira 
8215d945cbcSRodrigo Siqueira 		case DRM_PLANE_TYPE_CURSOR:
8225d945cbcSRodrigo Siqueira 			for (i = 0; i < ARRAY_SIZE(cursor_formats); ++i) {
8235d945cbcSRodrigo Siqueira 				if (num_formats >= max_formats)
8245d945cbcSRodrigo Siqueira 					break;
8255d945cbcSRodrigo Siqueira 
8265d945cbcSRodrigo Siqueira 				formats[num_formats++] = cursor_formats[i];
8275d945cbcSRodrigo Siqueira 			}
8285d945cbcSRodrigo Siqueira 			break;
829ab4c37feSJoshua Ashton 
830ab4c37feSJoshua Ashton 		default:
831ab4c37feSJoshua Ashton 			break;
832ab4c37feSJoshua Ashton 		}
8335d945cbcSRodrigo Siqueira 	}
8345d945cbcSRodrigo Siqueira 
8355d945cbcSRodrigo Siqueira 	return num_formats;
8365d945cbcSRodrigo Siqueira }
8375d945cbcSRodrigo Siqueira 
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,const uint64_t tiling_flags,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)8388bf0d9cdSDavid Tadokoro int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
8395d945cbcSRodrigo Siqueira 			     const struct amdgpu_framebuffer *afb,
8405d945cbcSRodrigo Siqueira 			     const enum surface_pixel_format format,
8415d945cbcSRodrigo Siqueira 			     const enum dc_rotation_angle rotation,
8425d945cbcSRodrigo Siqueira 			     const uint64_t tiling_flags,
843080950cbSKarthi Kandasamy 			     struct dc_tiling_info *tiling_info,
8445d945cbcSRodrigo Siqueira 			     struct plane_size *plane_size,
8455d945cbcSRodrigo Siqueira 			     struct dc_plane_dcc_param *dcc,
8465d945cbcSRodrigo Siqueira 			     struct dc_plane_address *address,
84704d6273fSRodrigo Siqueira 			     bool tmz_surface)
8485d945cbcSRodrigo Siqueira {
8495d945cbcSRodrigo Siqueira 	const struct drm_framebuffer *fb = &afb->base;
8505d945cbcSRodrigo Siqueira 	int ret;
8515d945cbcSRodrigo Siqueira 
8525d945cbcSRodrigo Siqueira 	memset(tiling_info, 0, sizeof(*tiling_info));
8535d945cbcSRodrigo Siqueira 	memset(plane_size, 0, sizeof(*plane_size));
8545d945cbcSRodrigo Siqueira 	memset(dcc, 0, sizeof(*dcc));
8555d945cbcSRodrigo Siqueira 	memset(address, 0, sizeof(*address));
8565d945cbcSRodrigo Siqueira 
8575d945cbcSRodrigo Siqueira 	address->tmz_surface = tmz_surface;
8585d945cbcSRodrigo Siqueira 
8595d945cbcSRodrigo Siqueira 	if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
8605d945cbcSRodrigo Siqueira 		uint64_t addr = afb->address + fb->offsets[0];
8615d945cbcSRodrigo Siqueira 
8625d945cbcSRodrigo Siqueira 		plane_size->surface_size.x = 0;
8635d945cbcSRodrigo Siqueira 		plane_size->surface_size.y = 0;
8645d945cbcSRodrigo Siqueira 		plane_size->surface_size.width = fb->width;
8655d945cbcSRodrigo Siqueira 		plane_size->surface_size.height = fb->height;
8665d945cbcSRodrigo Siqueira 		plane_size->surface_pitch =
8675d945cbcSRodrigo Siqueira 			fb->pitches[0] / fb->format->cpp[0];
8685d945cbcSRodrigo Siqueira 
8695d945cbcSRodrigo Siqueira 		address->type = PLN_ADDR_TYPE_GRAPHICS;
8705d945cbcSRodrigo Siqueira 		address->grph.addr.low_part = lower_32_bits(addr);
8715d945cbcSRodrigo Siqueira 		address->grph.addr.high_part = upper_32_bits(addr);
8725d945cbcSRodrigo Siqueira 	} else if (format < SURFACE_PIXEL_FORMAT_INVALID) {
8735d945cbcSRodrigo Siqueira 		uint64_t luma_addr = afb->address + fb->offsets[0];
8745d945cbcSRodrigo Siqueira 		uint64_t chroma_addr = afb->address + fb->offsets[1];
8755d945cbcSRodrigo Siqueira 
8765d945cbcSRodrigo Siqueira 		plane_size->surface_size.x = 0;
8775d945cbcSRodrigo Siqueira 		plane_size->surface_size.y = 0;
8785d945cbcSRodrigo Siqueira 		plane_size->surface_size.width = fb->width;
8795d945cbcSRodrigo Siqueira 		plane_size->surface_size.height = fb->height;
8805d945cbcSRodrigo Siqueira 		plane_size->surface_pitch =
8815d945cbcSRodrigo Siqueira 			fb->pitches[0] / fb->format->cpp[0];
8825d945cbcSRodrigo Siqueira 
8835d945cbcSRodrigo Siqueira 		plane_size->chroma_size.x = 0;
8845d945cbcSRodrigo Siqueira 		plane_size->chroma_size.y = 0;
8855d945cbcSRodrigo Siqueira 		/* TODO: set these based on surface format */
8865d945cbcSRodrigo Siqueira 		plane_size->chroma_size.width = fb->width / 2;
8875d945cbcSRodrigo Siqueira 		plane_size->chroma_size.height = fb->height / 2;
8885d945cbcSRodrigo Siqueira 
8895d945cbcSRodrigo Siqueira 		plane_size->chroma_pitch =
8905d945cbcSRodrigo Siqueira 			fb->pitches[1] / fb->format->cpp[1];
8915d945cbcSRodrigo Siqueira 
8925d945cbcSRodrigo Siqueira 		address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
8935d945cbcSRodrigo Siqueira 		address->video_progressive.luma_addr.low_part =
8945d945cbcSRodrigo Siqueira 			lower_32_bits(luma_addr);
8955d945cbcSRodrigo Siqueira 		address->video_progressive.luma_addr.high_part =
8965d945cbcSRodrigo Siqueira 			upper_32_bits(luma_addr);
8975d945cbcSRodrigo Siqueira 		address->video_progressive.chroma_addr.low_part =
8985d945cbcSRodrigo Siqueira 			lower_32_bits(chroma_addr);
8995d945cbcSRodrigo Siqueira 		address->video_progressive.chroma_addr.high_part =
9005d945cbcSRodrigo Siqueira 			upper_32_bits(chroma_addr);
9015d945cbcSRodrigo Siqueira 	}
9025d945cbcSRodrigo Siqueira 
903ce7985fdSMarek Olšák 	if (adev->family >= AMDGPU_FAMILY_GC_12_0_0) {
904ce7985fdSMarek Olšák 		ret = amdgpu_dm_plane_fill_gfx12_plane_attributes_from_modifiers(adev, afb, format,
905ce7985fdSMarek Olšák 										 rotation, plane_size,
906ce7985fdSMarek Olšák 										 tiling_info, dcc,
90704d6273fSRodrigo Siqueira 										 address);
908ce7985fdSMarek Olšák 		if (ret)
909ce7985fdSMarek Olšák 			return ret;
910ce7985fdSMarek Olšák 	} else if (adev->family >= AMDGPU_FAMILY_AI) {
911c4066d8bSRodrigo Siqueira 		ret = amdgpu_dm_plane_fill_gfx9_plane_attributes_from_modifiers(adev, afb, format,
9125d945cbcSRodrigo Siqueira 										rotation, plane_size,
9135d945cbcSRodrigo Siqueira 										tiling_info, dcc,
91404d6273fSRodrigo Siqueira 										address);
9155d945cbcSRodrigo Siqueira 		if (ret)
9165d945cbcSRodrigo Siqueira 			return ret;
9175d945cbcSRodrigo Siqueira 	} else {
918c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags);
9195d945cbcSRodrigo Siqueira 	}
9205d945cbcSRodrigo Siqueira 
9215d945cbcSRodrigo Siqueira 	return 0;
9225d945cbcSRodrigo Siqueira }
9235d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_helper_prepare_fb(struct drm_plane * plane,struct drm_plane_state * new_state)924c4066d8bSRodrigo Siqueira static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane,
9255d945cbcSRodrigo Siqueira 					     struct drm_plane_state *new_state)
9265d945cbcSRodrigo Siqueira {
9275d945cbcSRodrigo Siqueira 	struct amdgpu_framebuffer *afb;
9285d945cbcSRodrigo Siqueira 	struct drm_gem_object *obj;
9295d945cbcSRodrigo Siqueira 	struct amdgpu_device *adev;
9305d945cbcSRodrigo Siqueira 	struct amdgpu_bo *rbo;
9315d945cbcSRodrigo Siqueira 	struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old;
9325d945cbcSRodrigo Siqueira 	uint32_t domain;
9335d945cbcSRodrigo Siqueira 	int r;
9345d945cbcSRodrigo Siqueira 
9355d945cbcSRodrigo Siqueira 	if (!new_state->fb) {
9365d945cbcSRodrigo Siqueira 		DRM_DEBUG_KMS("No FB bound\n");
9375d945cbcSRodrigo Siqueira 		return 0;
9385d945cbcSRodrigo Siqueira 	}
9395d945cbcSRodrigo Siqueira 
9405d945cbcSRodrigo Siqueira 	afb = to_amdgpu_framebuffer(new_state->fb);
94173dd0ad9SMa Ke 	obj = drm_gem_fb_get_obj(new_state->fb, 0);
94273dd0ad9SMa Ke 	if (!obj) {
94373dd0ad9SMa Ke 		DRM_ERROR("Failed to get obj from framebuffer\n");
94473dd0ad9SMa Ke 		return -EINVAL;
94573dd0ad9SMa Ke 	}
94673dd0ad9SMa Ke 
9475d945cbcSRodrigo Siqueira 	rbo = gem_to_amdgpu_bo(obj);
9485d945cbcSRodrigo Siqueira 	adev = amdgpu_ttm_adev(rbo->tbo.bdev);
9495d945cbcSRodrigo Siqueira 	r = amdgpu_bo_reserve(rbo, true);
9505d945cbcSRodrigo Siqueira 	if (r) {
9515d945cbcSRodrigo Siqueira 		dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
9525d945cbcSRodrigo Siqueira 		return r;
9535d945cbcSRodrigo Siqueira 	}
9545d945cbcSRodrigo Siqueira 
9555d945cbcSRodrigo Siqueira 	r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
9565d945cbcSRodrigo Siqueira 	if (r) {
9575d945cbcSRodrigo Siqueira 		dev_err(adev->dev, "reserving fence slot failed (%d)\n", r);
9585d945cbcSRodrigo Siqueira 		goto error_unlock;
9595d945cbcSRodrigo Siqueira 	}
9605d945cbcSRodrigo Siqueira 
9615d945cbcSRodrigo Siqueira 	if (plane->type != DRM_PLANE_TYPE_CURSOR)
9625d945cbcSRodrigo Siqueira 		domain = amdgpu_display_supported_domains(adev, rbo->flags);
9635d945cbcSRodrigo Siqueira 	else
9645d945cbcSRodrigo Siqueira 		domain = AMDGPU_GEM_DOMAIN_VRAM;
9655d945cbcSRodrigo Siqueira 
96654b86443SChristian König 	rbo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
9675d945cbcSRodrigo Siqueira 	r = amdgpu_bo_pin(rbo, domain);
9685d945cbcSRodrigo Siqueira 	if (unlikely(r != 0)) {
9695d945cbcSRodrigo Siqueira 		if (r != -ERESTARTSYS)
9705d945cbcSRodrigo Siqueira 			DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
9715d945cbcSRodrigo Siqueira 		goto error_unlock;
9725d945cbcSRodrigo Siqueira 	}
9735d945cbcSRodrigo Siqueira 
9745d945cbcSRodrigo Siqueira 	r = amdgpu_ttm_alloc_gart(&rbo->tbo);
9755d945cbcSRodrigo Siqueira 	if (unlikely(r != 0)) {
9765d945cbcSRodrigo Siqueira 		DRM_ERROR("%p bind failed\n", rbo);
9775d945cbcSRodrigo Siqueira 		goto error_unpin;
9785d945cbcSRodrigo Siqueira 	}
9795d945cbcSRodrigo Siqueira 
9805d945cbcSRodrigo Siqueira 	r = drm_gem_plane_helper_prepare_fb(plane, new_state);
9815d945cbcSRodrigo Siqueira 	if (unlikely(r != 0))
9825d945cbcSRodrigo Siqueira 		goto error_unpin;
9835d945cbcSRodrigo Siqueira 
9845d945cbcSRodrigo Siqueira 	amdgpu_bo_unreserve(rbo);
9855d945cbcSRodrigo Siqueira 
9865d945cbcSRodrigo Siqueira 	afb->address = amdgpu_bo_gpu_offset(rbo);
9875d945cbcSRodrigo Siqueira 
9885d945cbcSRodrigo Siqueira 	amdgpu_bo_ref(rbo);
9895d945cbcSRodrigo Siqueira 
9905d945cbcSRodrigo Siqueira 	/**
9915d945cbcSRodrigo Siqueira 	 * We don't do surface updates on planes that have been newly created,
9925d945cbcSRodrigo Siqueira 	 * but we also don't have the afb->address during atomic check.
9935d945cbcSRodrigo Siqueira 	 *
9945d945cbcSRodrigo Siqueira 	 * Fill in buffer attributes depending on the address here, but only on
9955d945cbcSRodrigo Siqueira 	 * newly created planes since they're not being used by DC yet and this
9965d945cbcSRodrigo Siqueira 	 * won't modify global state.
9975d945cbcSRodrigo Siqueira 	 */
9985d945cbcSRodrigo Siqueira 	dm_plane_state_old = to_dm_plane_state(plane->state);
9995d945cbcSRodrigo Siqueira 	dm_plane_state_new = to_dm_plane_state(new_state);
10005d945cbcSRodrigo Siqueira 
10015d945cbcSRodrigo Siqueira 	if (dm_plane_state_new->dc_state &&
10025d945cbcSRodrigo Siqueira 	    dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
10035d945cbcSRodrigo Siqueira 		struct dc_plane_state *plane_state =
10045d945cbcSRodrigo Siqueira 			dm_plane_state_new->dc_state;
10055d945cbcSRodrigo Siqueira 
10068bf0d9cdSDavid Tadokoro 		amdgpu_dm_plane_fill_plane_buffer_attributes(
10075d945cbcSRodrigo Siqueira 			adev, afb, plane_state->format, plane_state->rotation,
10085d945cbcSRodrigo Siqueira 			afb->tiling_flags,
10095d945cbcSRodrigo Siqueira 			&plane_state->tiling_info, &plane_state->plane_size,
10105d945cbcSRodrigo Siqueira 			&plane_state->dcc, &plane_state->address,
101104d6273fSRodrigo Siqueira 			afb->tmz_surface);
10125d945cbcSRodrigo Siqueira 	}
10135d945cbcSRodrigo Siqueira 
10145d945cbcSRodrigo Siqueira 	return 0;
10155d945cbcSRodrigo Siqueira 
10165d945cbcSRodrigo Siqueira error_unpin:
10175d945cbcSRodrigo Siqueira 	amdgpu_bo_unpin(rbo);
10185d945cbcSRodrigo Siqueira 
10195d945cbcSRodrigo Siqueira error_unlock:
10205d945cbcSRodrigo Siqueira 	amdgpu_bo_unreserve(rbo);
10215d945cbcSRodrigo Siqueira 	return r;
10225d945cbcSRodrigo Siqueira }
10235d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_helper_cleanup_fb(struct drm_plane * plane,struct drm_plane_state * old_state)1024c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_helper_cleanup_fb(struct drm_plane *plane,
10255d945cbcSRodrigo Siqueira 					      struct drm_plane_state *old_state)
10265d945cbcSRodrigo Siqueira {
10275d945cbcSRodrigo Siqueira 	struct amdgpu_bo *rbo;
10285d945cbcSRodrigo Siqueira 	int r;
10295d945cbcSRodrigo Siqueira 
10305d945cbcSRodrigo Siqueira 	if (!old_state->fb)
10315d945cbcSRodrigo Siqueira 		return;
10325d945cbcSRodrigo Siqueira 
10335d945cbcSRodrigo Siqueira 	rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
10345d945cbcSRodrigo Siqueira 	r = amdgpu_bo_reserve(rbo, false);
10355d945cbcSRodrigo Siqueira 	if (unlikely(r)) {
10365d945cbcSRodrigo Siqueira 		DRM_ERROR("failed to reserve rbo before unpin\n");
10375d945cbcSRodrigo Siqueira 		return;
10385d945cbcSRodrigo Siqueira 	}
10395d945cbcSRodrigo Siqueira 
10405d945cbcSRodrigo Siqueira 	amdgpu_bo_unpin(rbo);
10415d945cbcSRodrigo Siqueira 	amdgpu_bo_unreserve(rbo);
10425d945cbcSRodrigo Siqueira 	amdgpu_bo_unref(&rbo);
10435d945cbcSRodrigo Siqueira }
10445d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_get_min_max_dc_plane_scaling(struct drm_device * dev,struct drm_framebuffer * fb,int * min_downscale,int * max_upscale)1045c4066d8bSRodrigo Siqueira static void amdgpu_dm_plane_get_min_max_dc_plane_scaling(struct drm_device *dev,
10465d945cbcSRodrigo Siqueira 					 struct drm_framebuffer *fb,
10475d945cbcSRodrigo Siqueira 					 int *min_downscale, int *max_upscale)
10485d945cbcSRodrigo Siqueira {
10495d945cbcSRodrigo Siqueira 	struct amdgpu_device *adev = drm_to_adev(dev);
10505d945cbcSRodrigo Siqueira 	struct dc *dc = adev->dm.dc;
10515d945cbcSRodrigo Siqueira 	/* Caps for all supported planes are the same on DCE and DCN 1 - 3 */
10525d945cbcSRodrigo Siqueira 	struct dc_plane_cap *plane_cap = &dc->caps.planes[0];
10535d945cbcSRodrigo Siqueira 
10545d945cbcSRodrigo Siqueira 	switch (fb->format->format) {
10555d945cbcSRodrigo Siqueira 	case DRM_FORMAT_P010:
10565d945cbcSRodrigo Siqueira 	case DRM_FORMAT_NV12:
10575d945cbcSRodrigo Siqueira 	case DRM_FORMAT_NV21:
10585d945cbcSRodrigo Siqueira 		*max_upscale = plane_cap->max_upscale_factor.nv12;
10595d945cbcSRodrigo Siqueira 		*min_downscale = plane_cap->max_downscale_factor.nv12;
10605d945cbcSRodrigo Siqueira 		break;
10615d945cbcSRodrigo Siqueira 
10625d945cbcSRodrigo Siqueira 	case DRM_FORMAT_XRGB16161616F:
10635d945cbcSRodrigo Siqueira 	case DRM_FORMAT_ARGB16161616F:
10645d945cbcSRodrigo Siqueira 	case DRM_FORMAT_XBGR16161616F:
10655d945cbcSRodrigo Siqueira 	case DRM_FORMAT_ABGR16161616F:
10665d945cbcSRodrigo Siqueira 		*max_upscale = plane_cap->max_upscale_factor.fp16;
10675d945cbcSRodrigo Siqueira 		*min_downscale = plane_cap->max_downscale_factor.fp16;
10685d945cbcSRodrigo Siqueira 		break;
10695d945cbcSRodrigo Siqueira 
10705d945cbcSRodrigo Siqueira 	default:
10715d945cbcSRodrigo Siqueira 		*max_upscale = plane_cap->max_upscale_factor.argb8888;
10725d945cbcSRodrigo Siqueira 		*min_downscale = plane_cap->max_downscale_factor.argb8888;
10735d945cbcSRodrigo Siqueira 		break;
10745d945cbcSRodrigo Siqueira 	}
10755d945cbcSRodrigo Siqueira 
10765d945cbcSRodrigo Siqueira 	/*
10775d945cbcSRodrigo Siqueira 	 * A factor of 1 in the plane_cap means to not allow scaling, ie. use a
10785d945cbcSRodrigo Siqueira 	 * scaling factor of 1.0 == 1000 units.
10795d945cbcSRodrigo Siqueira 	 */
10805d945cbcSRodrigo Siqueira 	if (*max_upscale == 1)
10815d945cbcSRodrigo Siqueira 		*max_upscale = 1000;
10825d945cbcSRodrigo Siqueira 
10835d945cbcSRodrigo Siqueira 	if (*min_downscale == 1)
10845d945cbcSRodrigo Siqueira 		*min_downscale = 1000;
10855d945cbcSRodrigo Siqueira }
10865d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_helper_check_state(struct drm_plane_state * state,struct drm_crtc_state * new_crtc_state)10878bf0d9cdSDavid Tadokoro int amdgpu_dm_plane_helper_check_state(struct drm_plane_state *state,
10885d945cbcSRodrigo Siqueira 				       struct drm_crtc_state *new_crtc_state)
10895d945cbcSRodrigo Siqueira {
10905d945cbcSRodrigo Siqueira 	struct drm_framebuffer *fb = state->fb;
10915d945cbcSRodrigo Siqueira 	int min_downscale, max_upscale;
10925d945cbcSRodrigo Siqueira 	int min_scale = 0;
10935d945cbcSRodrigo Siqueira 	int max_scale = INT_MAX;
10945d945cbcSRodrigo Siqueira 
10955d945cbcSRodrigo Siqueira 	/* Plane enabled? Validate viewport and get scaling factors from plane caps. */
10965d945cbcSRodrigo Siqueira 	if (fb && state->crtc) {
10975d945cbcSRodrigo Siqueira 		/* Validate viewport to cover the case when only the position changes */
10985d945cbcSRodrigo Siqueira 		if (state->plane->type != DRM_PLANE_TYPE_CURSOR) {
10995d945cbcSRodrigo Siqueira 			int viewport_width = state->crtc_w;
11005d945cbcSRodrigo Siqueira 			int viewport_height = state->crtc_h;
11015d945cbcSRodrigo Siqueira 
11025d945cbcSRodrigo Siqueira 			if (state->crtc_x < 0)
11035d945cbcSRodrigo Siqueira 				viewport_width += state->crtc_x;
11045d945cbcSRodrigo Siqueira 			else if (state->crtc_x + state->crtc_w > new_crtc_state->mode.crtc_hdisplay)
11055d945cbcSRodrigo Siqueira 				viewport_width = new_crtc_state->mode.crtc_hdisplay - state->crtc_x;
11065d945cbcSRodrigo Siqueira 
11075d945cbcSRodrigo Siqueira 			if (state->crtc_y < 0)
11085d945cbcSRodrigo Siqueira 				viewport_height += state->crtc_y;
11095d945cbcSRodrigo Siqueira 			else if (state->crtc_y + state->crtc_h > new_crtc_state->mode.crtc_vdisplay)
11105d945cbcSRodrigo Siqueira 				viewport_height = new_crtc_state->mode.crtc_vdisplay - state->crtc_y;
11115d945cbcSRodrigo Siqueira 
11125d945cbcSRodrigo Siqueira 			if (viewport_width < 0 || viewport_height < 0) {
11135d945cbcSRodrigo Siqueira 				DRM_DEBUG_ATOMIC("Plane completely outside of screen\n");
11145d945cbcSRodrigo Siqueira 				return -EINVAL;
11155d945cbcSRodrigo Siqueira 			} else if (viewport_width < MIN_VIEWPORT_SIZE*2) { /* x2 for width is because of pipe-split. */
11165d945cbcSRodrigo Siqueira 				DRM_DEBUG_ATOMIC("Viewport width %d smaller than %d\n", viewport_width, MIN_VIEWPORT_SIZE*2);
11175d945cbcSRodrigo Siqueira 				return -EINVAL;
11185d945cbcSRodrigo Siqueira 			} else if (viewport_height < MIN_VIEWPORT_SIZE) {
11195d945cbcSRodrigo Siqueira 				DRM_DEBUG_ATOMIC("Viewport height %d smaller than %d\n", viewport_height, MIN_VIEWPORT_SIZE);
11205d945cbcSRodrigo Siqueira 				return -EINVAL;
11215d945cbcSRodrigo Siqueira 			}
11225d945cbcSRodrigo Siqueira 
11235d945cbcSRodrigo Siqueira 		}
11245d945cbcSRodrigo Siqueira 
11255d945cbcSRodrigo Siqueira 		/* Get min/max allowed scaling factors from plane caps. */
1126c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_get_min_max_dc_plane_scaling(state->crtc->dev, fb,
11275d945cbcSRodrigo Siqueira 							     &min_downscale, &max_upscale);
11285d945cbcSRodrigo Siqueira 		/*
11295d945cbcSRodrigo Siqueira 		 * Convert to drm convention: 16.16 fixed point, instead of dc's
11305d945cbcSRodrigo Siqueira 		 * 1.0 == 1000. Also drm scaling is src/dst instead of dc's
11315d945cbcSRodrigo Siqueira 		 * dst/src, so min_scale = 1.0 / max_upscale, etc.
11325d945cbcSRodrigo Siqueira 		 */
11335d945cbcSRodrigo Siqueira 		min_scale = (1000 << 16) / max_upscale;
11345d945cbcSRodrigo Siqueira 		max_scale = (1000 << 16) / min_downscale;
11355d945cbcSRodrigo Siqueira 	}
11365d945cbcSRodrigo Siqueira 
11375d945cbcSRodrigo Siqueira 	return drm_atomic_helper_check_plane_state(
11385d945cbcSRodrigo Siqueira 		state, new_crtc_state, min_scale, max_scale, true, true);
11395d945cbcSRodrigo Siqueira }
11405d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device * adev,const struct drm_plane_state * state,struct dc_scaling_info * scaling_info)11418bf0d9cdSDavid Tadokoro int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev,
11425d945cbcSRodrigo Siqueira 				const struct drm_plane_state *state,
11435d945cbcSRodrigo Siqueira 				struct dc_scaling_info *scaling_info)
11445d945cbcSRodrigo Siqueira {
11455d945cbcSRodrigo Siqueira 	int scale_w, scale_h, min_downscale, max_upscale;
11465d945cbcSRodrigo Siqueira 
11475d945cbcSRodrigo Siqueira 	memset(scaling_info, 0, sizeof(*scaling_info));
11485d945cbcSRodrigo Siqueira 
11495d945cbcSRodrigo Siqueira 	/* Source is fixed 16.16 but we ignore mantissa for now... */
11505d945cbcSRodrigo Siqueira 	scaling_info->src_rect.x = state->src_x >> 16;
11515d945cbcSRodrigo Siqueira 	scaling_info->src_rect.y = state->src_y >> 16;
11525d945cbcSRodrigo Siqueira 
11535d945cbcSRodrigo Siqueira 	/*
11545d945cbcSRodrigo Siqueira 	 * For reasons we don't (yet) fully understand a non-zero
11555d945cbcSRodrigo Siqueira 	 * src_y coordinate into an NV12 buffer can cause a
11565d945cbcSRodrigo Siqueira 	 * system hang on DCN1x.
11575d945cbcSRodrigo Siqueira 	 * To avoid hangs (and maybe be overly cautious)
11585d945cbcSRodrigo Siqueira 	 * let's reject both non-zero src_x and src_y.
11595d945cbcSRodrigo Siqueira 	 *
11605d945cbcSRodrigo Siqueira 	 * We currently know of only one use-case to reproduce a
11615d945cbcSRodrigo Siqueira 	 * scenario with non-zero src_x and src_y for NV12, which
11625d945cbcSRodrigo Siqueira 	 * is to gesture the YouTube Android app into full screen
11635d945cbcSRodrigo Siqueira 	 * on ChromeOS.
11645d945cbcSRodrigo Siqueira 	 */
11654e8303cfSLijo Lazar 	if (((amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 0)) ||
11664e8303cfSLijo Lazar 	    (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(1, 0, 1))) &&
11675d945cbcSRodrigo Siqueira 	    (state->fb && state->fb->format->format == DRM_FORMAT_NV12 &&
11685d945cbcSRodrigo Siqueira 	    (scaling_info->src_rect.x != 0 || scaling_info->src_rect.y != 0)))
11695d945cbcSRodrigo Siqueira 		return -EINVAL;
11705d945cbcSRodrigo Siqueira 
11715d945cbcSRodrigo Siqueira 	scaling_info->src_rect.width = state->src_w >> 16;
11725d945cbcSRodrigo Siqueira 	if (scaling_info->src_rect.width == 0)
11735d945cbcSRodrigo Siqueira 		return -EINVAL;
11745d945cbcSRodrigo Siqueira 
11755d945cbcSRodrigo Siqueira 	scaling_info->src_rect.height = state->src_h >> 16;
11765d945cbcSRodrigo Siqueira 	if (scaling_info->src_rect.height == 0)
11775d945cbcSRodrigo Siqueira 		return -EINVAL;
11785d945cbcSRodrigo Siqueira 
11795d945cbcSRodrigo Siqueira 	scaling_info->dst_rect.x = state->crtc_x;
11805d945cbcSRodrigo Siqueira 	scaling_info->dst_rect.y = state->crtc_y;
11815d945cbcSRodrigo Siqueira 
11825d945cbcSRodrigo Siqueira 	if (state->crtc_w == 0)
11835d945cbcSRodrigo Siqueira 		return -EINVAL;
11845d945cbcSRodrigo Siqueira 
11855d945cbcSRodrigo Siqueira 	scaling_info->dst_rect.width = state->crtc_w;
11865d945cbcSRodrigo Siqueira 
11875d945cbcSRodrigo Siqueira 	if (state->crtc_h == 0)
11885d945cbcSRodrigo Siqueira 		return -EINVAL;
11895d945cbcSRodrigo Siqueira 
11905d945cbcSRodrigo Siqueira 	scaling_info->dst_rect.height = state->crtc_h;
11915d945cbcSRodrigo Siqueira 
11925d945cbcSRodrigo Siqueira 	/* DRM doesn't specify clipping on destination output. */
11935d945cbcSRodrigo Siqueira 	scaling_info->clip_rect = scaling_info->dst_rect;
11945d945cbcSRodrigo Siqueira 
11955d945cbcSRodrigo Siqueira 	/* Validate scaling per-format with DC plane caps */
11965d945cbcSRodrigo Siqueira 	if (state->plane && state->plane->dev && state->fb) {
1197c4066d8bSRodrigo Siqueira 		amdgpu_dm_plane_get_min_max_dc_plane_scaling(state->plane->dev, state->fb,
11985d945cbcSRodrigo Siqueira 							     &min_downscale, &max_upscale);
11995d945cbcSRodrigo Siqueira 	} else {
12005d945cbcSRodrigo Siqueira 		min_downscale = 250;
12015d945cbcSRodrigo Siqueira 		max_upscale = 16000;
12025d945cbcSRodrigo Siqueira 	}
12035d945cbcSRodrigo Siqueira 
12045d945cbcSRodrigo Siqueira 	scale_w = scaling_info->dst_rect.width * 1000 /
12055d945cbcSRodrigo Siqueira 		  scaling_info->src_rect.width;
12065d945cbcSRodrigo Siqueira 
12075d945cbcSRodrigo Siqueira 	if (scale_w < min_downscale || scale_w > max_upscale)
12085d945cbcSRodrigo Siqueira 		return -EINVAL;
12095d945cbcSRodrigo Siqueira 
12105d945cbcSRodrigo Siqueira 	scale_h = scaling_info->dst_rect.height * 1000 /
12115d945cbcSRodrigo Siqueira 		  scaling_info->src_rect.height;
12125d945cbcSRodrigo Siqueira 
12135d945cbcSRodrigo Siqueira 	if (scale_h < min_downscale || scale_h > max_upscale)
12145d945cbcSRodrigo Siqueira 		return -EINVAL;
12155d945cbcSRodrigo Siqueira 
12165d945cbcSRodrigo Siqueira 	/*
12175d945cbcSRodrigo Siqueira 	 * The "scaling_quality" can be ignored for now, quality = 0 has DC
12185d945cbcSRodrigo Siqueira 	 * assume reasonable defaults based on the format.
12195d945cbcSRodrigo Siqueira 	 */
12205d945cbcSRodrigo Siqueira 
12215d945cbcSRodrigo Siqueira 	return 0;
12225d945cbcSRodrigo Siqueira }
12235d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_atomic_check(struct drm_plane * plane,struct drm_atomic_state * state)1224c4066d8bSRodrigo Siqueira static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
12255d945cbcSRodrigo Siqueira 					struct drm_atomic_state *state)
12265d945cbcSRodrigo Siqueira {
12275d945cbcSRodrigo Siqueira 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
12285d945cbcSRodrigo Siqueira 										 plane);
12295d945cbcSRodrigo Siqueira 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
12305d945cbcSRodrigo Siqueira 	struct dc *dc = adev->dm.dc;
12315d945cbcSRodrigo Siqueira 	struct dm_plane_state *dm_plane_state;
12325d945cbcSRodrigo Siqueira 	struct dc_scaling_info scaling_info;
12335d945cbcSRodrigo Siqueira 	struct drm_crtc_state *new_crtc_state;
12345d945cbcSRodrigo Siqueira 	int ret;
12355d945cbcSRodrigo Siqueira 
12365d945cbcSRodrigo Siqueira 	trace_amdgpu_dm_plane_atomic_check(new_plane_state);
12375d945cbcSRodrigo Siqueira 
12385d945cbcSRodrigo Siqueira 	dm_plane_state = to_dm_plane_state(new_plane_state);
12395d945cbcSRodrigo Siqueira 
12405d945cbcSRodrigo Siqueira 	if (!dm_plane_state->dc_state)
12415d945cbcSRodrigo Siqueira 		return 0;
12425d945cbcSRodrigo Siqueira 
12435d945cbcSRodrigo Siqueira 	new_crtc_state =
12445d945cbcSRodrigo Siqueira 		drm_atomic_get_new_crtc_state(state,
12455d945cbcSRodrigo Siqueira 					      new_plane_state->crtc);
12465d945cbcSRodrigo Siqueira 	if (!new_crtc_state)
12475d945cbcSRodrigo Siqueira 		return -EINVAL;
12485d945cbcSRodrigo Siqueira 
12498bf0d9cdSDavid Tadokoro 	ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state);
12505d945cbcSRodrigo Siqueira 	if (ret)
12515d945cbcSRodrigo Siqueira 		return ret;
12525d945cbcSRodrigo Siqueira 
12538bf0d9cdSDavid Tadokoro 	ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info);
12545d945cbcSRodrigo Siqueira 	if (ret)
12555d945cbcSRodrigo Siqueira 		return ret;
12565d945cbcSRodrigo Siqueira 
12575d945cbcSRodrigo Siqueira 	if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK)
12585d945cbcSRodrigo Siqueira 		return 0;
12595d945cbcSRodrigo Siqueira 
12605d945cbcSRodrigo Siqueira 	return -EINVAL;
12615d945cbcSRodrigo Siqueira }
12625d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_atomic_async_check(struct drm_plane * plane,struct drm_atomic_state * state,bool flip)1263c4066d8bSRodrigo Siqueira static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
12645d945cbcSRodrigo Siqueira 					      struct drm_atomic_state *state, bool flip)
12655d945cbcSRodrigo Siqueira {
12661b04dccaSLeo Li 	struct drm_crtc_state *new_crtc_state;
12671b04dccaSLeo Li 	struct drm_plane_state *new_plane_state;
12681b04dccaSLeo Li 	struct dm_crtc_state *dm_new_crtc_state;
12691b04dccaSLeo Li 
12705d945cbcSRodrigo Siqueira 	if (flip) {
12715d945cbcSRodrigo Siqueira 		if (plane->type != DRM_PLANE_TYPE_OVERLAY)
12725d945cbcSRodrigo Siqueira 			return -EINVAL;
12735d945cbcSRodrigo Siqueira 	} else if (plane->type != DRM_PLANE_TYPE_CURSOR) {
12741b04dccaSLeo Li 		return -EINVAL;
12751b04dccaSLeo Li 	}
12761b04dccaSLeo Li 
12771b04dccaSLeo Li 	new_plane_state = drm_atomic_get_new_plane_state(state, plane);
12781b04dccaSLeo Li 	new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
12791b04dccaSLeo Li 	dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
12801b04dccaSLeo Li 	/* Reject overlay cursors for now*/
12815d945cbcSRodrigo Siqueira 	if (!flip && dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
12825d945cbcSRodrigo Siqueira 		return -EINVAL;
12835d945cbcSRodrigo Siqueira 
128466eba12aSHarry Wentland 	return 0;
12855d945cbcSRodrigo Siqueira }
12865d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_get_cursor_position(struct drm_plane * plane,struct drm_crtc * crtc,struct dc_cursor_position * position)12875d945cbcSRodrigo Siqueira int amdgpu_dm_plane_get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
128887d23164SAurabindo Pillai 					struct dc_cursor_position *position)
12895d945cbcSRodrigo Siqueira {
12905d945cbcSRodrigo Siqueira 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
12915d945cbcSRodrigo Siqueira 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
12925d945cbcSRodrigo Siqueira 	int x, y;
12935d945cbcSRodrigo Siqueira 	int xorigin = 0, yorigin = 0;
12945d945cbcSRodrigo Siqueira 
12955d945cbcSRodrigo Siqueira 	if (!crtc || !plane->state->fb)
12965d945cbcSRodrigo Siqueira 		return 0;
12975d945cbcSRodrigo Siqueira 
12985d945cbcSRodrigo Siqueira 	if ((plane->state->crtc_w > amdgpu_crtc->max_cursor_width) ||
12995d945cbcSRodrigo Siqueira 	    (plane->state->crtc_h > amdgpu_crtc->max_cursor_height)) {
13005d945cbcSRodrigo Siqueira 		DRM_ERROR("%s: bad cursor width or height %d x %d\n",
13015d945cbcSRodrigo Siqueira 			  __func__,
13025d945cbcSRodrigo Siqueira 			  plane->state->crtc_w,
13035d945cbcSRodrigo Siqueira 			  plane->state->crtc_h);
13045d945cbcSRodrigo Siqueira 		return -EINVAL;
13055d945cbcSRodrigo Siqueira 	}
13065d945cbcSRodrigo Siqueira 
13075d945cbcSRodrigo Siqueira 	x = plane->state->crtc_x;
13085d945cbcSRodrigo Siqueira 	y = plane->state->crtc_y;
13095d945cbcSRodrigo Siqueira 
13105d945cbcSRodrigo Siqueira 	if (x <= -amdgpu_crtc->max_cursor_width ||
13115d945cbcSRodrigo Siqueira 	    y <= -amdgpu_crtc->max_cursor_height)
13125d945cbcSRodrigo Siqueira 		return 0;
13135d945cbcSRodrigo Siqueira 
13145d945cbcSRodrigo Siqueira 	if (x < 0) {
13155d945cbcSRodrigo Siqueira 		xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1);
13165d945cbcSRodrigo Siqueira 		x = 0;
13175d945cbcSRodrigo Siqueira 	}
13185d945cbcSRodrigo Siqueira 	if (y < 0) {
13195d945cbcSRodrigo Siqueira 		yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1);
13205d945cbcSRodrigo Siqueira 		y = 0;
13215d945cbcSRodrigo Siqueira 	}
13225d945cbcSRodrigo Siqueira 	position->enable = true;
13235d945cbcSRodrigo Siqueira 	position->x = x;
13245d945cbcSRodrigo Siqueira 	position->y = y;
132587d23164SAurabindo Pillai 	position->x_hotspot = xorigin;
132687d23164SAurabindo Pillai 	position->y_hotspot = yorigin;
132787d23164SAurabindo Pillai 
13285d945cbcSRodrigo Siqueira 	if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(4, 0, 1))
13295d945cbcSRodrigo Siqueira 		position->translate_by_source = true;
13305d945cbcSRodrigo Siqueira 
13318bf0d9cdSDavid Tadokoro 	return 0;
13325d945cbcSRodrigo Siqueira }
13335d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_handle_cursor_update(struct drm_plane * plane,struct drm_plane_state * old_plane_state)13345d945cbcSRodrigo Siqueira void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
13355d945cbcSRodrigo Siqueira 				 struct drm_plane_state *old_plane_state)
1336778e3979SIvan Lipski {
1337778e3979SIvan Lipski 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
1338778e3979SIvan Lipski 	struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb);
1339778e3979SIvan Lipski 	struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc;
13405d945cbcSRodrigo Siqueira 	struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
13415d945cbcSRodrigo Siqueira 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
13425d945cbcSRodrigo Siqueira 	uint64_t address = afb ? afb->address : 0;
13435d945cbcSRodrigo Siqueira 	struct dc_cursor_position position = {0};
13445d945cbcSRodrigo Siqueira 	struct dc_cursor_attributes attributes;
13455d945cbcSRodrigo Siqueira 	int ret;
13465d945cbcSRodrigo Siqueira 
13475d72e247SHamza Mahfooz 	if (!plane->state->fb && !old_plane_state->fb)
13485d72e247SHamza Mahfooz 		return;
13495d945cbcSRodrigo Siqueira 
13505d945cbcSRodrigo Siqueira 	drm_dbg_atomic(plane->dev, "crtc_id=%d with size %d to %d\n",
1351c4066d8bSRodrigo Siqueira 		       amdgpu_crtc->crtc_id, plane->state->crtc_w,
13525d945cbcSRodrigo Siqueira 		       plane->state->crtc_h);
13535d945cbcSRodrigo Siqueira 
13545d945cbcSRodrigo Siqueira 	ret = amdgpu_dm_plane_get_cursor_position(plane, crtc, &position);
13555d945cbcSRodrigo Siqueira 	if (ret)
13565d945cbcSRodrigo Siqueira 		return;
13575d945cbcSRodrigo Siqueira 
13585d945cbcSRodrigo Siqueira 	if (!position.enable) {
1359f63f86b5SHarry Wentland 		/* turn off cursor */
13605d945cbcSRodrigo Siqueira 		if (crtc_state && crtc_state->stream) {
13615d945cbcSRodrigo Siqueira 			mutex_lock(&adev->dm.dc_lock);
13625d945cbcSRodrigo Siqueira 			dc_stream_program_cursor_position(crtc_state->stream,
13635d945cbcSRodrigo Siqueira 						      &position);
13645d945cbcSRodrigo Siqueira 			mutex_unlock(&adev->dm.dc_lock);
13655d945cbcSRodrigo Siqueira 		}
13665d945cbcSRodrigo Siqueira 		return;
13675d945cbcSRodrigo Siqueira 	}
13685d945cbcSRodrigo Siqueira 
13695d945cbcSRodrigo Siqueira 	amdgpu_crtc->cursor_width = plane->state->crtc_w;
13705d945cbcSRodrigo Siqueira 	amdgpu_crtc->cursor_height = plane->state->crtc_h;
13715d945cbcSRodrigo Siqueira 
13725d945cbcSRodrigo Siqueira 	memset(&attributes, 0, sizeof(attributes));
13735d945cbcSRodrigo Siqueira 	attributes.address.high_part = upper_32_bits(address);
13745d945cbcSRodrigo Siqueira 	attributes.address.low_part  = lower_32_bits(address);
13755d945cbcSRodrigo Siqueira 	attributes.width             = plane->state->crtc_w;
13765d945cbcSRodrigo Siqueira 	attributes.height            = plane->state->crtc_h;
13775d945cbcSRodrigo Siqueira 	attributes.color_format      = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA;
1378fabd2165SMelissa Wen 	attributes.rotation_angle    = 0;
1379fabd2165SMelissa Wen 	attributes.attribute_flags.value = 0;
1380fabd2165SMelissa Wen 
1381fabd2165SMelissa Wen 	/* Enable cursor degamma ROM on DCN3+ for implicit sRGB degamma in DRM
1382fabd2165SMelissa Wen 	 * legacy gamma setup.
1383fabd2165SMelissa Wen 	 */
1384fabd2165SMelissa Wen 	if (crtc_state->cm_is_degamma_srgb &&
1385cd9e9e08SSrinivasan Shanmugam 	    adev->dm.dc->caps.color.dpp.gamma_corr)
13865d945cbcSRodrigo Siqueira 		attributes.attribute_flags.bits.ENABLE_CURSOR_DEGAMMA = 1;
13875d945cbcSRodrigo Siqueira 
13885d945cbcSRodrigo Siqueira 	if (afb)
13895d945cbcSRodrigo Siqueira 		attributes.pitch = afb->base.pitches[0] / afb->base.format->cpp[0];
1390f63f86b5SHarry Wentland 
13915d945cbcSRodrigo Siqueira 	if (crtc_state->stream) {
13925d945cbcSRodrigo Siqueira 		mutex_lock(&adev->dm.dc_lock);
13935d945cbcSRodrigo Siqueira 		if (!dc_stream_program_cursor_attributes(crtc_state->stream,
1394f63f86b5SHarry Wentland 							 &attributes))
13955d945cbcSRodrigo Siqueira 			DRM_ERROR("DC failed to set cursor attributes\n");
13965d945cbcSRodrigo Siqueira 
13975d945cbcSRodrigo Siqueira 		if (!dc_stream_program_cursor_position(crtc_state->stream,
13985d945cbcSRodrigo Siqueira 						   &position))
13995d945cbcSRodrigo Siqueira 			DRM_ERROR("DC failed to set cursor position\n");
14005d945cbcSRodrigo Siqueira 		mutex_unlock(&adev->dm.dc_lock);
1401c4066d8bSRodrigo Siqueira 	}
14025d945cbcSRodrigo Siqueira }
14035d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_atomic_async_update(struct drm_plane * plane,struct drm_atomic_state * state)14045d945cbcSRodrigo Siqueira static void amdgpu_dm_plane_atomic_async_update(struct drm_plane *plane,
14055d945cbcSRodrigo Siqueira 						struct drm_atomic_state *state)
14065d945cbcSRodrigo Siqueira {
14075d945cbcSRodrigo Siqueira 	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
14085d945cbcSRodrigo Siqueira 									   plane);
14095d945cbcSRodrigo Siqueira 	struct drm_plane_state *old_state =
14105d945cbcSRodrigo Siqueira 		drm_atomic_get_old_plane_state(state, plane);
14115d945cbcSRodrigo Siqueira 
14125d945cbcSRodrigo Siqueira 	trace_amdgpu_dm_atomic_update_cursor(new_state);
14135d945cbcSRodrigo Siqueira 
14145d945cbcSRodrigo Siqueira 	swap(plane->state->fb, new_state->fb);
14155d945cbcSRodrigo Siqueira 
14165d945cbcSRodrigo Siqueira 	plane->state->src_x = new_state->src_x;
14175d945cbcSRodrigo Siqueira 	plane->state->src_y = new_state->src_y;
14185d945cbcSRodrigo Siqueira 	plane->state->src_w = new_state->src_w;
14195d945cbcSRodrigo Siqueira 	plane->state->src_h = new_state->src_h;
14205d945cbcSRodrigo Siqueira 	plane->state->crtc_x = new_state->crtc_x;
14215d945cbcSRodrigo Siqueira 	plane->state->crtc_y = new_state->crtc_y;
14228bf0d9cdSDavid Tadokoro 	plane->state->crtc_w = new_state->crtc_w;
14235d945cbcSRodrigo Siqueira 	plane->state->crtc_h = new_state->crtc_h;
14245d945cbcSRodrigo Siqueira 
1425736692c3SJocelyn Falempe 	amdgpu_dm_plane_handle_cursor_update(plane, old_state);
1426736692c3SJocelyn Falempe }
1427736692c3SJocelyn Falempe 
amdgpu_dm_plane_panic_flush(struct drm_plane * plane)1428736692c3SJocelyn Falempe static void amdgpu_dm_plane_panic_flush(struct drm_plane *plane)
1429736692c3SJocelyn Falempe {
1430736692c3SJocelyn Falempe 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane->state);
1431736692c3SJocelyn Falempe 	struct drm_framebuffer *fb = plane->state->fb;
1432736692c3SJocelyn Falempe 	struct dc_plane_state *dc_plane_state;
1433736692c3SJocelyn Falempe 
1434736692c3SJocelyn Falempe 	if (!dm_plane_state || !dm_plane_state->dc_state)
1435736692c3SJocelyn Falempe 		return;
1436736692c3SJocelyn Falempe 
1437736692c3SJocelyn Falempe 	dc_plane_state = dm_plane_state->dc_state;
1438736692c3SJocelyn Falempe 
14395d945cbcSRodrigo Siqueira 	dc_plane_force_dcc_and_tiling_disable(dc_plane_state, fb->modifier ? true : false);
1440c4066d8bSRodrigo Siqueira }
1441c4066d8bSRodrigo Siqueira 
1442c4066d8bSRodrigo Siqueira static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
1443c4066d8bSRodrigo Siqueira 	.prepare_fb = amdgpu_dm_plane_helper_prepare_fb,
1444c4066d8bSRodrigo Siqueira 	.cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb,
14455d945cbcSRodrigo Siqueira 	.atomic_check = amdgpu_dm_plane_atomic_check,
14465d945cbcSRodrigo Siqueira 	.atomic_async_check = amdgpu_dm_plane_atomic_async_check,
1447736692c3SJocelyn Falempe 	.atomic_async_update = amdgpu_dm_plane_atomic_async_update
1448736692c3SJocelyn Falempe };
1449736692c3SJocelyn Falempe 
1450736692c3SJocelyn Falempe static const struct drm_plane_helper_funcs dm_primary_plane_helper_funcs = {
1451736692c3SJocelyn Falempe 	.prepare_fb = amdgpu_dm_plane_helper_prepare_fb,
1452736692c3SJocelyn Falempe 	.cleanup_fb = amdgpu_dm_plane_helper_cleanup_fb,
1453736692c3SJocelyn Falempe 	.atomic_check = amdgpu_dm_plane_atomic_check,
1454736692c3SJocelyn Falempe 	.atomic_async_check = amdgpu_dm_plane_atomic_async_check,
1455736692c3SJocelyn Falempe 	.atomic_async_update = amdgpu_dm_plane_atomic_async_update,
1456736692c3SJocelyn Falempe 	.get_scanout_buffer = amdgpu_display_get_scanout_buffer,
1457c4066d8bSRodrigo Siqueira 	.panic_flush = amdgpu_dm_plane_panic_flush,
14585d945cbcSRodrigo Siqueira };
14595d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_drm_plane_reset(struct drm_plane * plane)14605d945cbcSRodrigo Siqueira static void amdgpu_dm_plane_drm_plane_reset(struct drm_plane *plane)
14615d945cbcSRodrigo Siqueira {
14625d945cbcSRodrigo Siqueira 	struct dm_plane_state *amdgpu_state = NULL;
14635d945cbcSRodrigo Siqueira 
14645d945cbcSRodrigo Siqueira 	if (plane->state)
14655d945cbcSRodrigo Siqueira 		plane->funcs->atomic_destroy_state(plane, plane->state);
14665d945cbcSRodrigo Siqueira 
1467d5a348d9SJoshua Ashton 	amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL);
1468d5a348d9SJoshua Ashton 	WARN_ON(amdgpu_state == NULL);
1469d5a348d9SJoshua Ashton 
14705d945cbcSRodrigo Siqueira 	if (!amdgpu_state)
1471d5a348d9SJoshua Ashton 		return;
1472ec7b2a55SJoshua Ashton 
1473f545d824SMelissa Wen 	__drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
14740ef47454SJoshua Ashton 	amdgpu_state->degamma_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
14755d945cbcSRodrigo Siqueira 	amdgpu_state->hdr_mult = AMDGPU_HDR_MULT_DEFAULT;
14765d945cbcSRodrigo Siqueira 	amdgpu_state->shaper_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
1477c4066d8bSRodrigo Siqueira 	amdgpu_state->blend_tf = AMDGPU_TRANSFER_FUNCTION_DEFAULT;
14785d945cbcSRodrigo Siqueira }
14795d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_drm_plane_duplicate_state(struct drm_plane * plane)14805d945cbcSRodrigo Siqueira static struct drm_plane_state *amdgpu_dm_plane_drm_plane_duplicate_state(struct drm_plane *plane)
14815d945cbcSRodrigo Siqueira {
14825d945cbcSRodrigo Siqueira 	struct dm_plane_state *dm_plane_state, *old_dm_plane_state;
14835d945cbcSRodrigo Siqueira 
14845d945cbcSRodrigo Siqueira 	old_dm_plane_state = to_dm_plane_state(plane->state);
14855d945cbcSRodrigo Siqueira 	dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL);
14865d945cbcSRodrigo Siqueira 	if (!dm_plane_state)
14875d945cbcSRodrigo Siqueira 		return NULL;
14885d945cbcSRodrigo Siqueira 
14895d945cbcSRodrigo Siqueira 	__drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base);
14905d945cbcSRodrigo Siqueira 
14915d945cbcSRodrigo Siqueira 	if (old_dm_plane_state->dc_state) {
14925d945cbcSRodrigo Siqueira 		dm_plane_state->dc_state = old_dm_plane_state->dc_state;
14939342a9aeSMelissa Wen 		dc_plane_state_retain(dm_plane_state->dc_state);
14949342a9aeSMelissa Wen 	}
14959342a9aeSMelissa Wen 
1496b8b92c1bSMelissa Wen 	if (old_dm_plane_state->degamma_lut)
1497b8b92c1bSMelissa Wen 		dm_plane_state->degamma_lut =
1498b8b92c1bSMelissa Wen 			drm_property_blob_get(old_dm_plane_state->degamma_lut);
1499f545d824SMelissa Wen 	if (old_dm_plane_state->ctm)
1500f545d824SMelissa Wen 		dm_plane_state->ctm =
1501f545d824SMelissa Wen 			drm_property_blob_get(old_dm_plane_state->ctm);
1502671994e3SMelissa Wen 	if (old_dm_plane_state->shaper_lut)
1503671994e3SMelissa Wen 		dm_plane_state->shaper_lut =
1504671994e3SMelissa Wen 			drm_property_blob_get(old_dm_plane_state->shaper_lut);
15050ef47454SJoshua Ashton 	if (old_dm_plane_state->lut3d)
15060ef47454SJoshua Ashton 		dm_plane_state->lut3d =
15070ef47454SJoshua Ashton 			drm_property_blob_get(old_dm_plane_state->lut3d);
15089342a9aeSMelissa Wen 	if (old_dm_plane_state->blend_lut)
1509d5a348d9SJoshua Ashton 		dm_plane_state->blend_lut =
1510ec7b2a55SJoshua Ashton 			drm_property_blob_get(old_dm_plane_state->blend_lut);
1511f545d824SMelissa Wen 
15120ef47454SJoshua Ashton 	dm_plane_state->degamma_tf = old_dm_plane_state->degamma_tf;
1513d5a348d9SJoshua Ashton 	dm_plane_state->hdr_mult = old_dm_plane_state->hdr_mult;
15145d945cbcSRodrigo Siqueira 	dm_plane_state->shaper_tf = old_dm_plane_state->shaper_tf;
15155d945cbcSRodrigo Siqueira 	dm_plane_state->blend_tf = old_dm_plane_state->blend_tf;
15165d945cbcSRodrigo Siqueira 
1517c4066d8bSRodrigo Siqueira 	return &dm_plane_state->base;
15185d945cbcSRodrigo Siqueira }
15195d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_format_mod_supported(struct drm_plane * plane,uint32_t format,uint64_t modifier)15205d945cbcSRodrigo Siqueira static bool amdgpu_dm_plane_format_mod_supported(struct drm_plane *plane,
15215d945cbcSRodrigo Siqueira 						 uint32_t format,
15225d945cbcSRodrigo Siqueira 						 uint64_t modifier)
152393e28cf8SJoaquín Ignacio Aramendía {
15245d945cbcSRodrigo Siqueira 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
15255d945cbcSRodrigo Siqueira 	const struct drm_format_info *info = drm_format_info(format);
15265d945cbcSRodrigo Siqueira 	int i;
15275d945cbcSRodrigo Siqueira 
15285d945cbcSRodrigo Siqueira 	if (!info)
15295d945cbcSRodrigo Siqueira 		return false;
15305d945cbcSRodrigo Siqueira 
15315d945cbcSRodrigo Siqueira 	/*
15325d945cbcSRodrigo Siqueira 	 * We always have to allow these modifiers:
15335d945cbcSRodrigo Siqueira 	 * 1. Core DRM checks for LINEAR support if userspace does not provide modifiers.
15345d945cbcSRodrigo Siqueira 	 * 2. Not passing any modifiers is the same as explicitly passing INVALID.
15355d945cbcSRodrigo Siqueira 	 */
15365d945cbcSRodrigo Siqueira 	if (modifier == DRM_FORMAT_MOD_LINEAR ||
15375d945cbcSRodrigo Siqueira 	    modifier == DRM_FORMAT_MOD_INVALID) {
153893e28cf8SJoaquín Ignacio Aramendía 		return true;
153993e28cf8SJoaquín Ignacio Aramendía 	}
154093e28cf8SJoaquín Ignacio Aramendía 
15415d945cbcSRodrigo Siqueira 	/* Check that the modifier is on the list of the plane's supported modifiers. */
15425d945cbcSRodrigo Siqueira 	for (i = 0; i < plane->modifier_count; i++) {
154393e28cf8SJoaquín Ignacio Aramendía 		if (modifier == plane->modifiers[i])
154493e28cf8SJoaquín Ignacio Aramendía 			break;
15455d945cbcSRodrigo Siqueira 	}
1546ed17b63eSMarek Olšák 	if (i == plane->modifier_count)
1547ed17b63eSMarek Olšák 		return false;
1548ed17b63eSMarek Olšák 
1549ed17b63eSMarek Olšák 	/* GFX12 doesn't have these limitations. */
15505d945cbcSRodrigo Siqueira 	if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) <= AMD_FMT_MOD_TILE_VER_GFX11) {
15515d945cbcSRodrigo Siqueira 		enum dm_micro_swizzle microtile = amdgpu_dm_plane_modifier_gfx9_swizzle_mode(modifier) & 3;
15525d945cbcSRodrigo Siqueira 
15535d945cbcSRodrigo Siqueira 		/*
15545d945cbcSRodrigo Siqueira 		 * For D swizzle the canonical modifier depends on the bpp, so check
15555d945cbcSRodrigo Siqueira 		 * it here.
15565d945cbcSRodrigo Siqueira 		 */
15575d945cbcSRodrigo Siqueira 		if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
15585d945cbcSRodrigo Siqueira 		    adev->family >= AMDGPU_FAMILY_NV) {
15595d945cbcSRodrigo Siqueira 			if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
15605d945cbcSRodrigo Siqueira 				return false;
15615d945cbcSRodrigo Siqueira 		}
15625d945cbcSRodrigo Siqueira 
15635d945cbcSRodrigo Siqueira 		if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
1564c4066d8bSRodrigo Siqueira 		    info->cpp[0] < 8)
15655d945cbcSRodrigo Siqueira 			return false;
15665d945cbcSRodrigo Siqueira 
15675d945cbcSRodrigo Siqueira 		if (amdgpu_dm_plane_modifier_has_dcc(modifier)) {
15685d945cbcSRodrigo Siqueira 			/* Per radeonsi comments 16/64 bpp are more complicated. */
15695d945cbcSRodrigo Siqueira 			if (info->cpp[0] != 4)
15705d945cbcSRodrigo Siqueira 				return false;
15715d945cbcSRodrigo Siqueira 			/* We support multi-planar formats, but not when combined with
15725d945cbcSRodrigo Siqueira 			 * additional DCC metadata planes.
15735d945cbcSRodrigo Siqueira 			 */
1574ed17b63eSMarek Olšák 			if (info->num_planes > 1)
15755d945cbcSRodrigo Siqueira 				return false;
15765d945cbcSRodrigo Siqueira 		}
15775d945cbcSRodrigo Siqueira 	}
15785d945cbcSRodrigo Siqueira 
1579c4066d8bSRodrigo Siqueira 	return true;
15805d945cbcSRodrigo Siqueira }
15815d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane * plane,struct drm_plane_state * state)15825d945cbcSRodrigo Siqueira static void amdgpu_dm_plane_drm_plane_destroy_state(struct drm_plane *plane,
15835d945cbcSRodrigo Siqueira 						    struct drm_plane_state *state)
15849342a9aeSMelissa Wen {
15859342a9aeSMelissa Wen 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
1586b8b92c1bSMelissa Wen 
1587b8b92c1bSMelissa Wen 	if (dm_plane_state->degamma_lut)
1588671994e3SMelissa Wen 		drm_property_blob_put(dm_plane_state->degamma_lut);
1589671994e3SMelissa Wen 	if (dm_plane_state->ctm)
1590f545d824SMelissa Wen 		drm_property_blob_put(dm_plane_state->ctm);
1591f545d824SMelissa Wen 	if (dm_plane_state->lut3d)
15920ef47454SJoshua Ashton 		drm_property_blob_put(dm_plane_state->lut3d);
15930ef47454SJoshua Ashton 	if (dm_plane_state->shaper_lut)
15949342a9aeSMelissa Wen 		drm_property_blob_put(dm_plane_state->shaper_lut);
15955d945cbcSRodrigo Siqueira 	if (dm_plane_state->blend_lut)
15965d945cbcSRodrigo Siqueira 		drm_property_blob_put(dm_plane_state->blend_lut);
15975d945cbcSRodrigo Siqueira 
15985d945cbcSRodrigo Siqueira 	if (dm_plane_state->dc_state)
15995d945cbcSRodrigo Siqueira 		dc_plane_state_release(dm_plane_state->dc_state);
16005d945cbcSRodrigo Siqueira 
16019342a9aeSMelissa Wen 	drm_atomic_helper_plane_destroy_state(plane, state);
16029342a9aeSMelissa Wen }
16039342a9aeSMelissa Wen 
16049342a9aeSMelissa Wen #ifdef AMD_PRIVATE_COLOR
16059342a9aeSMelissa Wen static void
dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager * dm,struct drm_plane * plane)16069342a9aeSMelissa Wen dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
16079342a9aeSMelissa Wen 					     struct drm_plane *plane)
16089342a9aeSMelissa Wen {
16099342a9aeSMelissa Wen 	struct amdgpu_mode_info mode_info = dm->adev->mode_info;
16109342a9aeSMelissa Wen 	struct dpp_color_caps dpp_color_caps = dm->dc->caps.color.dpp;
16119342a9aeSMelissa Wen 
16129342a9aeSMelissa Wen 	/* Check HW color pipeline capabilities on DPP block (pre-blending)
16139342a9aeSMelissa Wen 	 * before exposing related properties.
16149342a9aeSMelissa Wen 	 */
16159342a9aeSMelissa Wen 	if (dpp_color_caps.dgam_ram || dpp_color_caps.gamma_corr) {
16169342a9aeSMelissa Wen 		drm_object_attach_property(&plane->base,
16179342a9aeSMelissa Wen 					   mode_info.plane_degamma_lut_property,
16189342a9aeSMelissa Wen 					   0);
1619d5a348d9SJoshua Ashton 		drm_object_attach_property(&plane->base,
1620d5a348d9SJoshua Ashton 					   mode_info.plane_degamma_lut_size_property,
1621d5a348d9SJoshua Ashton 					   MAX_COLOR_LUT_ENTRIES);
16229342a9aeSMelissa Wen 		drm_object_attach_property(&plane->base,
1623ec7b2a55SJoshua Ashton 					   dm->adev->mode_info.plane_degamma_tf_property,
1624ec7b2a55SJoshua Ashton 					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
1625ec7b2a55SJoshua Ashton 	}
1626ec7b2a55SJoshua Ashton 	/* HDR MULT is always available */
1627671994e3SMelissa Wen 	drm_object_attach_property(&plane->base,
1628b8b92c1bSMelissa Wen 				   dm->adev->mode_info.plane_hdr_mult_property,
1629b8b92c1bSMelissa Wen 				   AMDGPU_HDR_MULT_DEFAULT);
1630b8b92c1bSMelissa Wen 
1631b8b92c1bSMelissa Wen 	/* Only enable plane CTM if both DPP and MPC gamut remap is available. */
1632b8b92c1bSMelissa Wen 	if (dm->dc->caps.color.mpc.gamut_remap)
1633671994e3SMelissa Wen 		drm_object_attach_property(&plane->base,
1634671994e3SMelissa Wen 					   dm->adev->mode_info.plane_ctm_property, 0);
1635f545d824SMelissa Wen 
1636f545d824SMelissa Wen 	if (dpp_color_caps.hw_3d_lut) {
1637f545d824SMelissa Wen 		drm_object_attach_property(&plane->base,
1638f545d824SMelissa Wen 					   mode_info.plane_shaper_lut_property, 0);
1639f545d824SMelissa Wen 		drm_object_attach_property(&plane->base,
1640f545d824SMelissa Wen 					   mode_info.plane_shaper_lut_size_property,
1641f545d824SMelissa Wen 					   MAX_COLOR_LUT_ENTRIES);
1642f545d824SMelissa Wen 		drm_object_attach_property(&plane->base,
1643671994e3SMelissa Wen 					   mode_info.plane_shaper_tf_property,
1644671994e3SMelissa Wen 					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
1645671994e3SMelissa Wen 		drm_object_attach_property(&plane->base,
1646671994e3SMelissa Wen 					   mode_info.plane_lut3d_property, 0);
1647671994e3SMelissa Wen 		drm_object_attach_property(&plane->base,
16480ef47454SJoshua Ashton 					   mode_info.plane_lut3d_size_property,
16490ef47454SJoshua Ashton 					   MAX_COLOR_3DLUT_SIZE);
16500ef47454SJoshua Ashton 	}
16510ef47454SJoshua Ashton 
16520ef47454SJoshua Ashton 	if (dpp_color_caps.ogam_ram) {
16530ef47454SJoshua Ashton 		drm_object_attach_property(&plane->base,
16540ef47454SJoshua Ashton 					   mode_info.plane_blend_lut_property, 0);
16550ef47454SJoshua Ashton 		drm_object_attach_property(&plane->base,
16560ef47454SJoshua Ashton 					   mode_info.plane_blend_lut_size_property,
16570ef47454SJoshua Ashton 					   MAX_COLOR_LUT_ENTRIES);
16580ef47454SJoshua Ashton 		drm_object_attach_property(&plane->base,
16599342a9aeSMelissa Wen 					   mode_info.plane_blend_tf_property,
16609342a9aeSMelissa Wen 					   AMDGPU_TRANSFER_FUNCTION_DEFAULT);
16619342a9aeSMelissa Wen 	}
16629342a9aeSMelissa Wen }
16639342a9aeSMelissa Wen 
16649342a9aeSMelissa Wen static int
dm_atomic_plane_set_property(struct drm_plane * plane,struct drm_plane_state * state,struct drm_property * property,uint64_t val)16659342a9aeSMelissa Wen dm_atomic_plane_set_property(struct drm_plane *plane,
16669342a9aeSMelissa Wen 			     struct drm_plane_state *state,
16679342a9aeSMelissa Wen 			     struct drm_property *property,
16689342a9aeSMelissa Wen 			     uint64_t val)
16699342a9aeSMelissa Wen {
16709342a9aeSMelissa Wen 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
16719342a9aeSMelissa Wen 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
16729342a9aeSMelissa Wen 	bool replaced = false;
16739342a9aeSMelissa Wen 	int ret;
16749342a9aeSMelissa Wen 
16759342a9aeSMelissa Wen 	if (property == adev->mode_info.plane_degamma_lut_property) {
16769342a9aeSMelissa Wen 		ret = drm_property_replace_blob_from_id(plane->dev,
16779342a9aeSMelissa Wen 							&dm_plane_state->degamma_lut,
16789342a9aeSMelissa Wen 							val, -1,
16799342a9aeSMelissa Wen 							sizeof(struct drm_color_lut),
1680d5a348d9SJoshua Ashton 							&replaced);
1681d5a348d9SJoshua Ashton 		dm_plane_state->base.color_mgmt_changed |= replaced;
1682d5a348d9SJoshua Ashton 		return ret;
1683d5a348d9SJoshua Ashton 	} else if (property == adev->mode_info.plane_degamma_tf_property) {
1684d5a348d9SJoshua Ashton 		if (dm_plane_state->degamma_tf != val) {
1685ec7b2a55SJoshua Ashton 			dm_plane_state->degamma_tf = val;
1686ec7b2a55SJoshua Ashton 			dm_plane_state->base.color_mgmt_changed = 1;
1687ec7b2a55SJoshua Ashton 		}
1688ec7b2a55SJoshua Ashton 	} else if (property == adev->mode_info.plane_hdr_mult_property) {
1689ec7b2a55SJoshua Ashton 		if (dm_plane_state->hdr_mult != val) {
1690b8b92c1bSMelissa Wen 			dm_plane_state->hdr_mult = val;
1691b8b92c1bSMelissa Wen 			dm_plane_state->base.color_mgmt_changed = 1;
1692b8b92c1bSMelissa Wen 		}
1693b8b92c1bSMelissa Wen 	} else if (property == adev->mode_info.plane_ctm_property) {
16946872a189SJoshua Ashton 		ret = drm_property_replace_blob_from_id(plane->dev,
1695b8b92c1bSMelissa Wen 							&dm_plane_state->ctm,
1696b8b92c1bSMelissa Wen 							val,
1697b8b92c1bSMelissa Wen 							sizeof(struct drm_color_ctm_3x4), -1,
1698f545d824SMelissa Wen 							&replaced);
1699f545d824SMelissa Wen 		dm_plane_state->base.color_mgmt_changed |= replaced;
1700f545d824SMelissa Wen 		return ret;
1701f545d824SMelissa Wen 	} else if (property == adev->mode_info.plane_shaper_lut_property) {
1702f545d824SMelissa Wen 		ret = drm_property_replace_blob_from_id(plane->dev,
1703f545d824SMelissa Wen 							&dm_plane_state->shaper_lut,
1704f545d824SMelissa Wen 							val, -1,
1705f545d824SMelissa Wen 							sizeof(struct drm_color_lut),
1706f545d824SMelissa Wen 							&replaced);
1707f545d824SMelissa Wen 		dm_plane_state->base.color_mgmt_changed |= replaced;
1708f545d824SMelissa Wen 		return ret;
1709f545d824SMelissa Wen 	} else if (property == adev->mode_info.plane_shaper_tf_property) {
1710f545d824SMelissa Wen 		if (dm_plane_state->shaper_tf != val) {
1711671994e3SMelissa Wen 			dm_plane_state->shaper_tf = val;
1712671994e3SMelissa Wen 			dm_plane_state->base.color_mgmt_changed = 1;
1713671994e3SMelissa Wen 		}
1714671994e3SMelissa Wen 	} else if (property == adev->mode_info.plane_lut3d_property) {
1715671994e3SMelissa Wen 		ret = drm_property_replace_blob_from_id(plane->dev,
1716671994e3SMelissa Wen 							&dm_plane_state->lut3d,
1717671994e3SMelissa Wen 							val, -1,
1718671994e3SMelissa Wen 							sizeof(struct drm_color_lut),
17190ef47454SJoshua Ashton 							&replaced);
17200ef47454SJoshua Ashton 		dm_plane_state->base.color_mgmt_changed |= replaced;
17210ef47454SJoshua Ashton 		return ret;
17220ef47454SJoshua Ashton 	} else if (property == adev->mode_info.plane_blend_lut_property) {
17230ef47454SJoshua Ashton 		ret = drm_property_replace_blob_from_id(plane->dev,
17240ef47454SJoshua Ashton 							&dm_plane_state->blend_lut,
17250ef47454SJoshua Ashton 							val, -1,
17260ef47454SJoshua Ashton 							sizeof(struct drm_color_lut),
17270ef47454SJoshua Ashton 							&replaced);
17280ef47454SJoshua Ashton 		dm_plane_state->base.color_mgmt_changed |= replaced;
17290ef47454SJoshua Ashton 		return ret;
17300ef47454SJoshua Ashton 	} else if (property == adev->mode_info.plane_blend_tf_property) {
17310ef47454SJoshua Ashton 		if (dm_plane_state->blend_tf != val) {
17329342a9aeSMelissa Wen 			dm_plane_state->blend_tf = val;
17339342a9aeSMelissa Wen 			dm_plane_state->base.color_mgmt_changed = 1;
17349342a9aeSMelissa Wen 		}
17359342a9aeSMelissa Wen 	} else {
17369342a9aeSMelissa Wen 		drm_dbg_atomic(plane->dev,
17379342a9aeSMelissa Wen 			       "[PLANE:%d:%s] unknown property [PROP:%d:%s]]\n",
17389342a9aeSMelissa Wen 			       plane->base.id, plane->name,
17399342a9aeSMelissa Wen 			       property->base.id, property->name);
17409342a9aeSMelissa Wen 		return -EINVAL;
17419342a9aeSMelissa Wen 	}
17429342a9aeSMelissa Wen 
17439342a9aeSMelissa Wen 	return 0;
17449342a9aeSMelissa Wen }
17459342a9aeSMelissa Wen 
17469342a9aeSMelissa Wen static int
dm_atomic_plane_get_property(struct drm_plane * plane,const struct drm_plane_state * state,struct drm_property * property,uint64_t * val)17479342a9aeSMelissa Wen dm_atomic_plane_get_property(struct drm_plane *plane,
17489342a9aeSMelissa Wen 			     const struct drm_plane_state *state,
17499342a9aeSMelissa Wen 			     struct drm_property *property,
17509342a9aeSMelissa Wen 			     uint64_t *val)
17519342a9aeSMelissa Wen {
17529342a9aeSMelissa Wen 	struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
17539342a9aeSMelissa Wen 	struct amdgpu_device *adev = drm_to_adev(plane->dev);
17549342a9aeSMelissa Wen 
1755d5a348d9SJoshua Ashton 	if (property == adev->mode_info.plane_degamma_lut_property) {
1756d5a348d9SJoshua Ashton 		*val = (dm_plane_state->degamma_lut) ?
1757ec7b2a55SJoshua Ashton 			dm_plane_state->degamma_lut->base.id : 0;
1758ec7b2a55SJoshua Ashton 	} else if (property == adev->mode_info.plane_degamma_tf_property) {
1759b8b92c1bSMelissa Wen 		*val = dm_plane_state->degamma_tf;
1760b8b92c1bSMelissa Wen 	} else if (property == adev->mode_info.plane_hdr_mult_property) {
1761b8b92c1bSMelissa Wen 		*val = dm_plane_state->hdr_mult;
1762f545d824SMelissa Wen 	} else if (property == adev->mode_info.plane_ctm_property) {
1763f545d824SMelissa Wen 		*val = (dm_plane_state->ctm) ?
1764f545d824SMelissa Wen 			dm_plane_state->ctm->base.id : 0;
1765f545d824SMelissa Wen 	} else 	if (property == adev->mode_info.plane_shaper_lut_property) {
1766f545d824SMelissa Wen 		*val = (dm_plane_state->shaper_lut) ?
1767671994e3SMelissa Wen 			dm_plane_state->shaper_lut->base.id : 0;
1768671994e3SMelissa Wen 	} else if (property == adev->mode_info.plane_shaper_tf_property) {
1769671994e3SMelissa Wen 		*val = dm_plane_state->shaper_tf;
17700ef47454SJoshua Ashton 	} else 	if (property == adev->mode_info.plane_lut3d_property) {
17710ef47454SJoshua Ashton 		*val = (dm_plane_state->lut3d) ?
17720ef47454SJoshua Ashton 			dm_plane_state->lut3d->base.id : 0;
17730ef47454SJoshua Ashton 	} else 	if (property == adev->mode_info.plane_blend_lut_property) {
17740ef47454SJoshua Ashton 		*val = (dm_plane_state->blend_lut) ?
17750ef47454SJoshua Ashton 			dm_plane_state->blend_lut->base.id : 0;
17769342a9aeSMelissa Wen 	} else if (property == adev->mode_info.plane_blend_tf_property) {
17779342a9aeSMelissa Wen 		*val = dm_plane_state->blend_tf;
17789342a9aeSMelissa Wen 
17799342a9aeSMelissa Wen 	} else {
17809342a9aeSMelissa Wen 		return -EINVAL;
17819342a9aeSMelissa Wen 	}
17829342a9aeSMelissa Wen 
17839342a9aeSMelissa Wen 	return 0;
17845d945cbcSRodrigo Siqueira }
17855d945cbcSRodrigo Siqueira #endif
17865d945cbcSRodrigo Siqueira 
17879cf26c89SThomas Zimmermann static const struct drm_plane_funcs dm_plane_funcs = {
1788c4066d8bSRodrigo Siqueira 	.update_plane	= drm_atomic_helper_update_plane,
1789c4066d8bSRodrigo Siqueira 	.disable_plane	= drm_atomic_helper_disable_plane,
1790c4066d8bSRodrigo Siqueira 	.destroy	= drm_plane_helper_destroy,
1791c4066d8bSRodrigo Siqueira 	.reset = amdgpu_dm_plane_drm_plane_reset,
17929342a9aeSMelissa Wen 	.atomic_duplicate_state = amdgpu_dm_plane_drm_plane_duplicate_state,
17939342a9aeSMelissa Wen 	.atomic_destroy_state = amdgpu_dm_plane_drm_plane_destroy_state,
17949342a9aeSMelissa Wen 	.format_mod_supported = amdgpu_dm_plane_format_mod_supported,
17959342a9aeSMelissa Wen #ifdef AMD_PRIVATE_COLOR
17965d945cbcSRodrigo Siqueira 	.atomic_set_property = dm_atomic_plane_set_property,
17975d945cbcSRodrigo Siqueira 	.atomic_get_property = dm_atomic_plane_get_property,
17985d945cbcSRodrigo Siqueira #endif
17995d945cbcSRodrigo Siqueira };
18005d945cbcSRodrigo Siqueira 
amdgpu_dm_plane_init(struct amdgpu_display_manager * dm,struct drm_plane * plane,unsigned long possible_crtcs,const struct dc_plane_cap * plane_cap)18015d945cbcSRodrigo Siqueira int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
18025d945cbcSRodrigo Siqueira 				struct drm_plane *plane,
18035d945cbcSRodrigo Siqueira 				unsigned long possible_crtcs,
18045d945cbcSRodrigo Siqueira 				const struct dc_plane_cap *plane_cap)
18055d945cbcSRodrigo Siqueira {
18065d945cbcSRodrigo Siqueira 	uint32_t formats[32];
18075d945cbcSRodrigo Siqueira 	int num_formats;
180838e0c3dfSLeo Li 	int res = -EPERM;
18095d945cbcSRodrigo Siqueira 	unsigned int supported_rotations;
1810c4066d8bSRodrigo Siqueira 	uint64_t *modifiers = NULL;
18115d945cbcSRodrigo Siqueira 	unsigned int primary_zpos = dm->dc->caps.max_slave_planes;
18125d945cbcSRodrigo Siqueira 
1813c4066d8bSRodrigo Siqueira 	num_formats = amdgpu_dm_plane_get_plane_formats(plane, plane_cap, formats,
18145d945cbcSRodrigo Siqueira 							ARRAY_SIZE(formats));
18155d945cbcSRodrigo Siqueira 
18165d945cbcSRodrigo Siqueira 	res = amdgpu_dm_plane_get_plane_modifiers(dm->adev, plane->type, &modifiers);
1817798cd57cSDave Airlie 	if (res)
1818798cd57cSDave Airlie 		return res;
1819798cd57cSDave Airlie 
18205d945cbcSRodrigo Siqueira 	if (modifiers == NULL)
18215d945cbcSRodrigo Siqueira 		adev_to_drm(dm->adev)->mode_config.fb_modifiers_not_supported = true;
18225d945cbcSRodrigo Siqueira 
18235d945cbcSRodrigo Siqueira 	res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs,
18245d945cbcSRodrigo Siqueira 				       &dm_plane_funcs, formats, num_formats,
18255d945cbcSRodrigo Siqueira 				       modifiers, plane->type, NULL);
18265d945cbcSRodrigo Siqueira 	kfree(modifiers);
18275d945cbcSRodrigo Siqueira 	if (res)
18285d945cbcSRodrigo Siqueira 		return res;
18295d945cbcSRodrigo Siqueira 
18305d945cbcSRodrigo Siqueira 	if (plane->type == DRM_PLANE_TYPE_OVERLAY &&
18315d945cbcSRodrigo Siqueira 	    plane_cap && plane_cap->per_pixel_alpha) {
18325d945cbcSRodrigo Siqueira 		unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
18335d945cbcSRodrigo Siqueira 					  BIT(DRM_MODE_BLEND_PREMULTI) |
18345d945cbcSRodrigo Siqueira 					  BIT(DRM_MODE_BLEND_COVERAGE);
18355d945cbcSRodrigo Siqueira 
18365d945cbcSRodrigo Siqueira 		drm_plane_create_alpha_property(plane);
1837fe320639SHamza Mahfooz 		drm_plane_create_blend_mode_property(plane, blend_caps);
183838e0c3dfSLeo Li 	}
183938e0c3dfSLeo Li 
184038e0c3dfSLeo Li 	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
184138e0c3dfSLeo Li 		/*
184238e0c3dfSLeo Li 		 * Allow OVERLAY planes to be used as underlays by assigning an
1843fe320639SHamza Mahfooz 		 * immutable zpos = # of OVERLAY planes to the PRIMARY plane.
184438e0c3dfSLeo Li 		 */
184538e0c3dfSLeo Li 		drm_plane_create_zpos_immutable_property(plane, primary_zpos);
184638e0c3dfSLeo Li 	} else if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
184738e0c3dfSLeo Li 		/*
184838e0c3dfSLeo Li 		 * OVERLAY planes can be below or above the PRIMARY, but cannot
184938e0c3dfSLeo Li 		 * be above the CURSOR plane.
185038e0c3dfSLeo Li 		 */
1851fe320639SHamza Mahfooz 		unsigned int zpos = primary_zpos + 1 + drm_plane_index(plane);
1852fe320639SHamza Mahfooz 
1853fe320639SHamza Mahfooz 		drm_plane_create_zpos_property(plane, zpos, 0, 254);
1854fe320639SHamza Mahfooz 	} else if (plane->type == DRM_PLANE_TYPE_CURSOR) {
18555d945cbcSRodrigo Siqueira 		drm_plane_create_zpos_immutable_property(plane, 255);
18565d945cbcSRodrigo Siqueira 	}
18575d945cbcSRodrigo Siqueira 
18585d945cbcSRodrigo Siqueira 	if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
18595d945cbcSRodrigo Siqueira 	    plane_cap &&
18605d945cbcSRodrigo Siqueira 	    (plane_cap->pixel_format_support.nv12 ||
18615d945cbcSRodrigo Siqueira 	     plane_cap->pixel_format_support.p010)) {
18625d945cbcSRodrigo Siqueira 		/* This only affects YUV formats. */
18635d945cbcSRodrigo Siqueira 		drm_plane_create_color_properties(
18645d945cbcSRodrigo Siqueira 			plane,
18655d945cbcSRodrigo Siqueira 			BIT(DRM_COLOR_YCBCR_BT601) |
18665d945cbcSRodrigo Siqueira 			BIT(DRM_COLOR_YCBCR_BT709) |
18675d945cbcSRodrigo Siqueira 			BIT(DRM_COLOR_YCBCR_BT2020),
18685d945cbcSRodrigo Siqueira 			BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
18695d945cbcSRodrigo Siqueira 			BIT(DRM_COLOR_YCBCR_FULL_RANGE),
18705d945cbcSRodrigo Siqueira 			DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE);
18715d945cbcSRodrigo Siqueira 	}
18725d945cbcSRodrigo Siqueira 
18735d945cbcSRodrigo Siqueira 	supported_rotations =
18745d945cbcSRodrigo Siqueira 		DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
18755d945cbcSRodrigo Siqueira 		DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
18765d945cbcSRodrigo Siqueira 
18775d945cbcSRodrigo Siqueira 	if (dm->adev->asic_type >= CHIP_BONAIRE &&
18785d945cbcSRodrigo Siqueira 	    plane->type != DRM_PLANE_TYPE_CURSOR)
18794e8303cfSLijo Lazar 		drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
188030ebe415SHamza Mahfooz 						   supported_rotations);
188130ebe415SHamza Mahfooz 
188230ebe415SHamza Mahfooz 	if (amdgpu_ip_version(dm->adev, DCE_HWIP, 0) > IP_VERSION(3, 0, 1) &&
1883736692c3SJocelyn Falempe 	    plane->type != DRM_PLANE_TYPE_CURSOR)
1884736692c3SJocelyn Falempe 		drm_plane_enable_fb_damage_clips(plane);
1885736692c3SJocelyn Falempe 
18865d945cbcSRodrigo Siqueira 	if (plane->type == DRM_PLANE_TYPE_PRIMARY)
18875d945cbcSRodrigo Siqueira 		drm_plane_helper_add(plane, &dm_primary_plane_helper_funcs);
18889342a9aeSMelissa Wen 	else
18899342a9aeSMelissa Wen 		drm_plane_helper_add(plane, &dm_plane_helper_funcs);
18909342a9aeSMelissa Wen 
18915d945cbcSRodrigo Siqueira #ifdef AMD_PRIVATE_COLOR
18925d945cbcSRodrigo Siqueira 	dm_atomic_plane_attach_color_mgmt_properties(dm, plane);
18935d945cbcSRodrigo Siqueira #endif
18945d945cbcSRodrigo Siqueira 	/* Create (reset) the plane state */
18955d945cbcSRodrigo Siqueira 	if (plane->funcs->reset)
18965d945cbcSRodrigo Siqueira 		plane->funcs->reset(plane);
18975d945cbcSRodrigo Siqueira 
1898c4066d8bSRodrigo Siqueira 	return 0;
189935f33086SBhawanpreet Lakha }
190035f33086SBhawanpreet Lakha 
amdgpu_dm_plane_is_video_format(uint32_t format)190135f33086SBhawanpreet Lakha bool amdgpu_dm_plane_is_video_format(uint32_t format)
190235f33086SBhawanpreet Lakha {
190335f33086SBhawanpreet Lakha 	int i;
190435f33086SBhawanpreet Lakha 
190535f33086SBhawanpreet Lakha 	for (i = 0; i < ARRAY_SIZE(video_formats); i++)
190635f33086SBhawanpreet Lakha 		if (format == video_formats[i])
190735f33086SBhawanpreet Lakha 			return true;
190835f33086SBhawanpreet Lakha 
1909 	return false;
1910 }
1911 
1912