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