LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/amdgpu_dm - amdgpu_dm_plane.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 591 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 29 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: MIT
       2             : /*
       3             :  * Copyright 2022 Advanced Micro Devices, Inc.
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining a
       6             :  * copy of this software and associated documentation files (the "Software"),
       7             :  * to deal in the Software without restriction, including without limitation
       8             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       9             :  * and/or sell copies of the Software, and to permit persons to whom the
      10             :  * Software is furnished to do so, subject to the following conditions:
      11             :  *
      12             :  * The above copyright notice and this permission notice shall be included in
      13             :  * all copies or substantial portions of the Software.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      19             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      20             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      21             :  * OTHER DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Authors: AMD
      24             :  *
      25             :  */
      26             : 
      27             : #include <drm/drm_atomic_helper.h>
      28             : #include <drm/drm_blend.h>
      29             : #include <drm/drm_gem_atomic_helper.h>
      30             : #include <drm/drm_plane_helper.h>
      31             : #include <drm/drm_fourcc.h>
      32             : 
      33             : #include "amdgpu.h"
      34             : #include "dal_asic_id.h"
      35             : #include "amdgpu_display.h"
      36             : #include "amdgpu_dm_trace.h"
      37             : #include "amdgpu_dm_plane.h"
      38             : #include "gc/gc_11_0_0_offset.h"
      39             : #include "gc/gc_11_0_0_sh_mask.h"
      40             : 
      41             : /*
      42             :  * TODO: these are currently initialized to rgb formats only.
      43             :  * For future use cases we should either initialize them dynamically based on
      44             :  * plane capabilities, or initialize this array to all formats, so internal drm
      45             :  * check will succeed, and let DC implement proper check
      46             :  */
      47             : static const uint32_t rgb_formats[] = {
      48             :         DRM_FORMAT_XRGB8888,
      49             :         DRM_FORMAT_ARGB8888,
      50             :         DRM_FORMAT_RGBA8888,
      51             :         DRM_FORMAT_XRGB2101010,
      52             :         DRM_FORMAT_XBGR2101010,
      53             :         DRM_FORMAT_ARGB2101010,
      54             :         DRM_FORMAT_ABGR2101010,
      55             :         DRM_FORMAT_XRGB16161616,
      56             :         DRM_FORMAT_XBGR16161616,
      57             :         DRM_FORMAT_ARGB16161616,
      58             :         DRM_FORMAT_ABGR16161616,
      59             :         DRM_FORMAT_XBGR8888,
      60             :         DRM_FORMAT_ABGR8888,
      61             :         DRM_FORMAT_RGB565,
      62             : };
      63             : 
      64             : static const uint32_t overlay_formats[] = {
      65             :         DRM_FORMAT_XRGB8888,
      66             :         DRM_FORMAT_ARGB8888,
      67             :         DRM_FORMAT_RGBA8888,
      68             :         DRM_FORMAT_XBGR8888,
      69             :         DRM_FORMAT_ABGR8888,
      70             :         DRM_FORMAT_RGB565
      71             : };
      72             : 
      73             : static const u32 cursor_formats[] = {
      74             :         DRM_FORMAT_ARGB8888
      75             : };
      76             : 
      77             : enum dm_micro_swizzle {
      78             :         MICRO_SWIZZLE_Z = 0,
      79             :         MICRO_SWIZZLE_S = 1,
      80             :         MICRO_SWIZZLE_D = 2,
      81             :         MICRO_SWIZZLE_R = 3
      82             : };
      83             : 
      84           0 : const struct drm_format_info *amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
      85             : {
      86           0 :         return amdgpu_lookup_format_info(cmd->pixel_format, cmd->modifier[0]);
      87             : }
      88             : 
      89           0 : void fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
      90             :                                bool *per_pixel_alpha, bool *pre_multiplied_alpha,
      91             :                                bool *global_alpha, int *global_alpha_value)
      92             : {
      93           0 :         *per_pixel_alpha = false;
      94           0 :         *pre_multiplied_alpha = true;
      95           0 :         *global_alpha = false;
      96           0 :         *global_alpha_value = 0xff;
      97             : 
      98           0 :         if (plane_state->plane->type != DRM_PLANE_TYPE_OVERLAY)
      99             :                 return;
     100             : 
     101           0 :         if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
     102             :                 plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
     103             :                 static const uint32_t alpha_formats[] = {
     104             :                         DRM_FORMAT_ARGB8888,
     105             :                         DRM_FORMAT_RGBA8888,
     106             :                         DRM_FORMAT_ABGR8888,
     107             :                 };
     108           0 :                 uint32_t format = plane_state->fb->format->format;
     109             :                 unsigned int i;
     110             : 
     111           0 :                 for (i = 0; i < ARRAY_SIZE(alpha_formats); ++i) {
     112           0 :                         if (format == alpha_formats[i]) {
     113           0 :                                 *per_pixel_alpha = true;
     114           0 :                                 break;
     115             :                         }
     116             :                 }
     117             : 
     118           0 :                 if (*per_pixel_alpha && plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE)
     119           0 :                         *pre_multiplied_alpha = false;
     120             :         }
     121             : 
     122           0 :         if (plane_state->alpha < 0xffff) {
     123           0 :                 *global_alpha = true;
     124           0 :                 *global_alpha_value = plane_state->alpha >> 8;
     125             :         }
     126             : }
     127             : 
     128           0 : static void add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
     129             : {
     130           0 :         if (!*mods)
     131             :                 return;
     132             : 
     133           0 :         if (*cap - *size < 1) {
     134           0 :                 uint64_t new_cap = *cap * 2;
     135           0 :                 uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t), GFP_KERNEL);
     136             : 
     137           0 :                 if (!new_mods) {
     138           0 :                         kfree(*mods);
     139           0 :                         *mods = NULL;
     140           0 :                         return;
     141             :                 }
     142             : 
     143           0 :                 memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
     144           0 :                 kfree(*mods);
     145           0 :                 *mods = new_mods;
     146           0 :                 *cap = new_cap;
     147             :         }
     148             : 
     149           0 :         (*mods)[*size] = mod;
     150           0 :         *size += 1;
     151             : }
     152             : 
     153             : static bool modifier_has_dcc(uint64_t modifier)
     154             : {
     155           0 :         return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
     156             : }
     157             : 
     158             : static unsigned modifier_gfx9_swizzle_mode(uint64_t modifier)
     159             : {
     160           0 :         if (modifier == DRM_FORMAT_MOD_LINEAR)
     161             :                 return 0;
     162             : 
     163           0 :         return AMD_FMT_MOD_GET(TILE, modifier);
     164             : }
     165             : 
     166           0 : static void fill_gfx8_tiling_info_from_flags(union dc_tiling_info *tiling_info,
     167             :                                  uint64_t tiling_flags)
     168             : {
     169             :         /* Fill GFX8 params */
     170           0 :         if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) {
     171             :                 unsigned int bankw, bankh, mtaspect, tile_split, num_banks;
     172             : 
     173           0 :                 bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
     174           0 :                 bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
     175           0 :                 mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
     176           0 :                 tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
     177           0 :                 num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
     178             : 
     179             :                 /* XXX fix me for VI */
     180           0 :                 tiling_info->gfx8.num_banks = num_banks;
     181           0 :                 tiling_info->gfx8.array_mode =
     182             :                                 DC_ARRAY_2D_TILED_THIN1;
     183           0 :                 tiling_info->gfx8.tile_split = tile_split;
     184           0 :                 tiling_info->gfx8.bank_width = bankw;
     185           0 :                 tiling_info->gfx8.bank_height = bankh;
     186           0 :                 tiling_info->gfx8.tile_aspect = mtaspect;
     187           0 :                 tiling_info->gfx8.tile_mode =
     188             :                                 DC_ADDR_SURF_MICRO_TILING_DISPLAY;
     189           0 :         } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
     190             :                         == DC_ARRAY_1D_TILED_THIN1) {
     191           0 :                 tiling_info->gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1;
     192             :         }
     193             : 
     194           0 :         tiling_info->gfx8.pipe_config =
     195           0 :                         AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
     196           0 : }
     197             : 
     198             : static void fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
     199             :                                   union dc_tiling_info *tiling_info)
     200             : {
     201             :         /* Fill GFX9 params */
     202           0 :         tiling_info->gfx9.num_pipes =
     203           0 :                 adev->gfx.config.gb_addr_config_fields.num_pipes;
     204           0 :         tiling_info->gfx9.num_banks =
     205           0 :                 adev->gfx.config.gb_addr_config_fields.num_banks;
     206           0 :         tiling_info->gfx9.pipe_interleave =
     207           0 :                 adev->gfx.config.gb_addr_config_fields.pipe_interleave_size;
     208           0 :         tiling_info->gfx9.num_shader_engines =
     209           0 :                 adev->gfx.config.gb_addr_config_fields.num_se;
     210           0 :         tiling_info->gfx9.max_compressed_frags =
     211           0 :                 adev->gfx.config.gb_addr_config_fields.max_compress_frags;
     212           0 :         tiling_info->gfx9.num_rb_per_se =
     213           0 :                 adev->gfx.config.gb_addr_config_fields.num_rb_per_se;
     214           0 :         tiling_info->gfx9.shaderEnable = 1;
     215           0 :         if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
     216           0 :                 tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs;
     217             : }
     218             : 
     219           0 : static void fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
     220             :                                     union dc_tiling_info *tiling_info,
     221             :                                     uint64_t modifier)
     222             : {
     223           0 :         unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
     224           0 :         unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
     225           0 :         unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier);
     226             :         unsigned int pipes_log2;
     227             : 
     228           0 :         pipes_log2 = min(5u, mod_pipe_xor_bits);
     229             : 
     230           0 :         fill_gfx9_tiling_info_from_device(adev, tiling_info);
     231             : 
     232           0 :         if (!IS_AMD_FMT_MOD(modifier))
     233             :                 return;
     234             : 
     235           0 :         tiling_info->gfx9.num_pipes = 1u << pipes_log2;
     236           0 :         tiling_info->gfx9.num_shader_engines = 1u << (mod_pipe_xor_bits - pipes_log2);
     237             : 
     238           0 :         if (adev->family >= AMDGPU_FAMILY_NV) {
     239           0 :                 tiling_info->gfx9.num_pkrs = 1u << pkrs_log2;
     240             :         } else {
     241           0 :                 tiling_info->gfx9.num_banks = 1u << mod_bank_xor_bits;
     242             : 
     243             :                 /* for DCC we know it isn't rb aligned, so rb_per_se doesn't matter. */
     244             :         }
     245             : }
     246             : 
     247           0 : static int validate_dcc(struct amdgpu_device *adev,
     248             :              const enum surface_pixel_format format,
     249             :              const enum dc_rotation_angle rotation,
     250             :              const union dc_tiling_info *tiling_info,
     251             :              const struct dc_plane_dcc_param *dcc,
     252             :              const struct dc_plane_address *address,
     253             :              const struct plane_size *plane_size)
     254             : {
     255           0 :         struct dc *dc = adev->dm.dc;
     256             :         struct dc_dcc_surface_param input;
     257             :         struct dc_surface_dcc_cap output;
     258             : 
     259           0 :         memset(&input, 0, sizeof(input));
     260           0 :         memset(&output, 0, sizeof(output));
     261             : 
     262           0 :         if (!dcc->enable)
     263             :                 return 0;
     264             : 
     265           0 :         if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN ||
     266           0 :             !dc->cap_funcs.get_dcc_compression_cap)
     267             :                 return -EINVAL;
     268             : 
     269           0 :         input.format = format;
     270           0 :         input.surface_size.width = plane_size->surface_size.width;
     271           0 :         input.surface_size.height = plane_size->surface_size.height;
     272           0 :         input.swizzle_mode = tiling_info->gfx9.swizzle;
     273             : 
     274           0 :         if (rotation == ROTATION_ANGLE_0 || rotation == ROTATION_ANGLE_180)
     275           0 :                 input.scan = SCAN_DIRECTION_HORIZONTAL;
     276           0 :         else if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270)
     277           0 :                 input.scan = SCAN_DIRECTION_VERTICAL;
     278             : 
     279           0 :         if (!dc->cap_funcs.get_dcc_compression_cap(dc, &input, &output))
     280             :                 return -EINVAL;
     281             : 
     282           0 :         if (!output.capable)
     283             :                 return -EINVAL;
     284             : 
     285           0 :         if (dcc->independent_64b_blks == 0 &&
     286           0 :             output.grph.rgb.independent_64b_blks != 0)
     287             :                 return -EINVAL;
     288             : 
     289             :         return 0;
     290             : }
     291             : 
     292           0 : static int fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
     293             :                                           const struct amdgpu_framebuffer *afb,
     294             :                                           const enum surface_pixel_format format,
     295             :                                           const enum dc_rotation_angle rotation,
     296             :                                           const struct plane_size *plane_size,
     297             :                                           union dc_tiling_info *tiling_info,
     298             :                                           struct dc_plane_dcc_param *dcc,
     299             :                                           struct dc_plane_address *address,
     300             :                                           const bool force_disable_dcc)
     301             : {
     302           0 :         const uint64_t modifier = afb->base.modifier;
     303           0 :         int ret = 0;
     304             : 
     305           0 :         fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
     306           0 :         tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier);
     307             : 
     308           0 :         if (modifier_has_dcc(modifier) && !force_disable_dcc) {
     309           0 :                 uint64_t dcc_address = afb->address + afb->base.offsets[1];
     310           0 :                 bool independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier);
     311           0 :                 bool independent_128b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier);
     312             : 
     313           0 :                 dcc->enable = 1;
     314           0 :                 dcc->meta_pitch = afb->base.pitches[1];
     315           0 :                 dcc->independent_64b_blks = independent_64b_blks;
     316           0 :                 if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) >= AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) {
     317           0 :                         if (independent_64b_blks && independent_128b_blks)
     318           0 :                                 dcc->dcc_ind_blk = hubp_ind_block_64b_no_128bcl;
     319           0 :                         else if (independent_128b_blks)
     320           0 :                                 dcc->dcc_ind_blk = hubp_ind_block_128b;
     321           0 :                         else if (independent_64b_blks && !independent_128b_blks)
     322           0 :                                 dcc->dcc_ind_blk = hubp_ind_block_64b;
     323             :                         else
     324           0 :                                 dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
     325             :                 } else {
     326           0 :                         if (independent_64b_blks)
     327           0 :                                 dcc->dcc_ind_blk = hubp_ind_block_64b;
     328             :                         else
     329           0 :                                 dcc->dcc_ind_blk = hubp_ind_block_unconstrained;
     330             :                 }
     331             : 
     332           0 :                 address->grph.meta_addr.low_part = lower_32_bits(dcc_address);
     333           0 :                 address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
     334             :         }
     335             : 
     336           0 :         ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
     337           0 :         if (ret)
     338           0 :                 drm_dbg_kms(adev_to_drm(adev), "validate_dcc: returned error: %d\n", ret);
     339             : 
     340           0 :         return ret;
     341             : }
     342             : 
     343           0 : static void add_gfx10_1_modifiers(const struct amdgpu_device *adev,
     344             :                       uint64_t **mods, uint64_t *size, uint64_t *capacity)
     345             : {
     346           0 :         int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
     347             : 
     348           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     349             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
     350             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
     351           0 :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     352             :                     AMD_FMT_MOD_SET(DCC, 1) |
     353             :                     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
     354             :                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     355             :                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
     356             : 
     357           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     358             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
     359             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
     360             :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     361             :                     AMD_FMT_MOD_SET(DCC, 1) |
     362             :                     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
     363             :                     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
     364             :                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     365             :                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
     366             : 
     367           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     368             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
     369             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
     370             :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
     371             : 
     372           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     373             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
     374             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
     375             :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
     376             : 
     377             : 
     378             :         /* Only supported for 64bpp, will be filtered in dm_plane_format_mod_supported */
     379           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     380             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
     381             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
     382             : 
     383           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     384             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
     385             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
     386           0 : }
     387             : 
     388           0 : static void add_gfx9_modifiers(const struct amdgpu_device *adev,
     389             :                    uint64_t **mods, uint64_t *size, uint64_t *capacity)
     390             : {
     391           0 :         int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
     392           0 :         int pipe_xor_bits = min(8, pipes +
     393             :                                 ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
     394           0 :         int bank_xor_bits = min(8 - pipe_xor_bits,
     395             :                                 ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
     396           0 :         int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
     397           0 :                  ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
     398             : 
     399             : 
     400           0 :         if (adev->family == AMDGPU_FAMILY_RV) {
     401             :                 /* Raven2 and later */
     402           0 :                 bool has_constant_encode = adev->asic_type > CHIP_RAVEN || adev->external_rev_id >= 0x81;
     403             : 
     404             :                 /*
     405             :                  * No _D DCC swizzles yet because we only allow 32bpp, which
     406             :                  * doesn't support _D on DCN
     407             :                  */
     408             : 
     409           0 :                 if (has_constant_encode) {
     410           0 :                         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     411             :                                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
     412             :                                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
     413           0 :                                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     414           0 :                                     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
     415             :                                     AMD_FMT_MOD_SET(DCC, 1) |
     416             :                                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     417             :                                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
     418             :                                     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
     419             :                 }
     420             : 
     421           0 :                 add_modifier(mods, size, capacity, AMD_FMT_MOD |
     422             :                             AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
     423             :                             AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
     424           0 :                             AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     425           0 :                             AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
     426             :                             AMD_FMT_MOD_SET(DCC, 1) |
     427             :                             AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     428             :                             AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
     429             :                             AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
     430             : 
     431           0 :                 if (has_constant_encode) {
     432           0 :                         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     433             :                                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
     434             :                                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
     435             :                                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     436             :                                     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
     437             :                                     AMD_FMT_MOD_SET(DCC, 1) |
     438             :                                     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
     439             :                                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     440             :                                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
     441             : 
     442           0 :                                     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
     443           0 :                                     AMD_FMT_MOD_SET(RB, rb) |
     444           0 :                                     AMD_FMT_MOD_SET(PIPE, pipes));
     445             :                 }
     446             : 
     447           0 :                 add_modifier(mods, size, capacity, AMD_FMT_MOD |
     448             :                             AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
     449             :                             AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
     450             :                             AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     451             :                             AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
     452             :                             AMD_FMT_MOD_SET(DCC, 1) |
     453             :                             AMD_FMT_MOD_SET(DCC_RETILE, 1) |
     454             :                             AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     455             :                             AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
     456           0 :                             AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
     457           0 :                             AMD_FMT_MOD_SET(RB, rb) |
     458           0 :                             AMD_FMT_MOD_SET(PIPE, pipes));
     459             :         }
     460             : 
     461             :         /*
     462             :          * Only supported for 64bpp on Raven, will be filtered on format in
     463             :          * dm_plane_format_mod_supported.
     464             :          */
     465           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     466             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
     467             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
     468           0 :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     469           0 :                     AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
     470             : 
     471           0 :         if (adev->family == AMDGPU_FAMILY_RV) {
     472           0 :                 add_modifier(mods, size, capacity, AMD_FMT_MOD |
     473             :                             AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
     474             :                             AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
     475             :                             AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     476             :                             AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
     477             :         }
     478             : 
     479             :         /*
     480             :          * Only supported for 64bpp on Raven, will be filtered on format in
     481             :          * dm_plane_format_mod_supported.
     482             :          */
     483           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     484             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
     485             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
     486             : 
     487           0 :         if (adev->family == AMDGPU_FAMILY_RV) {
     488           0 :                 add_modifier(mods, size, capacity, AMD_FMT_MOD |
     489             :                             AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
     490             :                             AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
     491             :         }
     492           0 : }
     493             : 
     494           0 : static void add_gfx10_3_modifiers(const struct amdgpu_device *adev,
     495             :                       uint64_t **mods, uint64_t *size, uint64_t *capacity)
     496             : {
     497           0 :         int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
     498           0 :         int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
     499             : 
     500           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     501             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
     502             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
     503           0 :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     504           0 :                     AMD_FMT_MOD_SET(PACKERS, pkrs) |
     505             :                     AMD_FMT_MOD_SET(DCC, 1) |
     506             :                     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
     507             :                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     508             :                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
     509             :                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
     510             : 
     511           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     512             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
     513             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
     514             :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     515             :                     AMD_FMT_MOD_SET(PACKERS, pkrs) |
     516             :                     AMD_FMT_MOD_SET(DCC, 1) |
     517             :                     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
     518             :                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
     519             :                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
     520             : 
     521           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     522             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
     523             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
     524             :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     525             :                     AMD_FMT_MOD_SET(PACKERS, pkrs) |
     526             :                     AMD_FMT_MOD_SET(DCC, 1) |
     527             :                     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
     528             :                     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
     529             :                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     530             :                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
     531             :                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
     532             : 
     533           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     534             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
     535             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
     536             :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     537             :                     AMD_FMT_MOD_SET(PACKERS, pkrs) |
     538             :                     AMD_FMT_MOD_SET(DCC, 1) |
     539             :                     AMD_FMT_MOD_SET(DCC_RETILE, 1) |
     540             :                     AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
     541             :                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
     542             :                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
     543             : 
     544           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     545             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
     546             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
     547             :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     548             :                     AMD_FMT_MOD_SET(PACKERS, pkrs));
     549             : 
     550           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     551             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
     552             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
     553             :                     AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     554             :                     AMD_FMT_MOD_SET(PACKERS, pkrs));
     555             : 
     556             :         /* Only supported for 64bpp, will be filtered in dm_plane_format_mod_supported */
     557           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     558             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
     559             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
     560             : 
     561           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     562             :                     AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
     563             :                     AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
     564           0 : }
     565             : 
     566           0 : static void add_gfx11_modifiers(struct amdgpu_device *adev,
     567             :                       uint64_t **mods, uint64_t *size, uint64_t *capacity)
     568             : {
     569           0 :         int num_pipes = 0;
     570           0 :         int pipe_xor_bits = 0;
     571           0 :         int num_pkrs = 0;
     572           0 :         int pkrs = 0;
     573             :         u32 gb_addr_config;
     574           0 :         u8 i = 0;
     575             :         unsigned swizzle_r_x;
     576             :         uint64_t modifier_r_x;
     577             :         uint64_t modifier_dcc_best;
     578             :         uint64_t modifier_dcc_4k;
     579             : 
     580             :         /* TODO: GFX11 IP HW init hasnt finish and we get zero if we read from
     581             :          * adev->gfx.config.gb_addr_config_fields.num_{pkrs,pipes}
     582             :          */
     583           0 :         gb_addr_config = RREG32_SOC15(GC, 0, regGB_ADDR_CONFIG);
     584           0 :         ASSERT(gb_addr_config != 0);
     585             : 
     586           0 :         num_pkrs = 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS);
     587           0 :         pkrs = ilog2(num_pkrs);
     588           0 :         num_pipes = 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PIPES);
     589           0 :         pipe_xor_bits = ilog2(num_pipes);
     590             : 
     591           0 :         for (i = 0; i < 2; i++) {
     592             :                 /* Insert the best one first. */
     593             :                 /* R_X swizzle modes are the best for rendering and DCC requires them. */
     594           0 :                 if (num_pipes > 16)
     595           0 :                         swizzle_r_x = !i ? AMD_FMT_MOD_TILE_GFX11_256K_R_X : AMD_FMT_MOD_TILE_GFX9_64K_R_X;
     596             :                 else
     597           0 :                         swizzle_r_x = !i ? AMD_FMT_MOD_TILE_GFX9_64K_R_X : AMD_FMT_MOD_TILE_GFX11_256K_R_X;
     598             : 
     599           0 :                 modifier_r_x = AMD_FMT_MOD |
     600             :                                AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
     601           0 :                                AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
     602           0 :                                AMD_FMT_MOD_SET(TILE, swizzle_r_x) |
     603           0 :                                AMD_FMT_MOD_SET(PACKERS, pkrs);
     604             : 
     605             :                 /* DCC_CONSTANT_ENCODE is not set because it can't vary with gfx11 (it's implied to be 1). */
     606           0 :                 modifier_dcc_best = modifier_r_x | AMD_FMT_MOD_SET(DCC, 1) |
     607             :                                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 0) |
     608             :                                     AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
     609             :                                     AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B);
     610             : 
     611             :                 /* DCC settings for 4K and greater resolutions. (required by display hw) */
     612           0 :                 modifier_dcc_4k = modifier_r_x | AMD_FMT_MOD_SET(DCC, 1) |
     613             :                                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
     614             :                                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
     615             :                                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B);
     616             : 
     617           0 :                 add_modifier(mods, size, capacity, modifier_dcc_best);
     618           0 :                 add_modifier(mods, size, capacity, modifier_dcc_4k);
     619             : 
     620           0 :                 add_modifier(mods, size, capacity, modifier_dcc_best | AMD_FMT_MOD_SET(DCC_RETILE, 1));
     621           0 :                 add_modifier(mods, size, capacity, modifier_dcc_4k | AMD_FMT_MOD_SET(DCC_RETILE, 1));
     622             : 
     623           0 :                 add_modifier(mods, size, capacity, modifier_r_x);
     624             :         }
     625             : 
     626           0 :         add_modifier(mods, size, capacity, AMD_FMT_MOD |
     627             :                         AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX11) |
     628             :                         AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D));
     629           0 : }
     630             : 
     631           0 : static int get_plane_modifiers(struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
     632             : {
     633           0 :         uint64_t size = 0, capacity = 128;
     634           0 :         *mods = NULL;
     635             : 
     636             :         /* We have not hooked up any pre-GFX9 modifiers. */
     637           0 :         if (adev->family < AMDGPU_FAMILY_AI)
     638             :                 return 0;
     639             : 
     640           0 :         *mods = kmalloc(capacity * sizeof(uint64_t), GFP_KERNEL);
     641             : 
     642           0 :         if (plane_type == DRM_PLANE_TYPE_CURSOR) {
     643           0 :                 add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
     644           0 :                 add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
     645           0 :                 return *mods ? 0 : -ENOMEM;
     646             :         }
     647             : 
     648           0 :         switch (adev->family) {
     649             :         case AMDGPU_FAMILY_AI:
     650             :         case AMDGPU_FAMILY_RV:
     651           0 :                 add_gfx9_modifiers(adev, mods, &size, &capacity);
     652           0 :                 break;
     653             :         case AMDGPU_FAMILY_NV:
     654             :         case AMDGPU_FAMILY_VGH:
     655             :         case AMDGPU_FAMILY_YC:
     656             :         case AMDGPU_FAMILY_GC_10_3_6:
     657             :         case AMDGPU_FAMILY_GC_10_3_7:
     658           0 :                 if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
     659           0 :                         add_gfx10_3_modifiers(adev, mods, &size, &capacity);
     660             :                 else
     661           0 :                         add_gfx10_1_modifiers(adev, mods, &size, &capacity);
     662             :                 break;
     663             :         case AMDGPU_FAMILY_GC_11_0_0:
     664             :         case AMDGPU_FAMILY_GC_11_0_1:
     665           0 :                 add_gfx11_modifiers(adev, mods, &size, &capacity);
     666           0 :                 break;
     667             :         }
     668             : 
     669           0 :         add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
     670             : 
     671             :         /* INVALID marks the end of the list. */
     672           0 :         add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
     673             : 
     674           0 :         if (!*mods)
     675             :                 return -ENOMEM;
     676             : 
     677           0 :         return 0;
     678             : }
     679             : 
     680           0 : static int get_plane_formats(const struct drm_plane *plane,
     681             :                              const struct dc_plane_cap *plane_cap,
     682             :                              uint32_t *formats, int max_formats)
     683             : {
     684           0 :         int i, num_formats = 0;
     685             : 
     686             :         /*
     687             :          * TODO: Query support for each group of formats directly from
     688             :          * DC plane caps. This will require adding more formats to the
     689             :          * caps list.
     690             :          */
     691             : 
     692           0 :         switch (plane->type) {
     693             :         case DRM_PLANE_TYPE_PRIMARY:
     694           0 :                 for (i = 0; i < ARRAY_SIZE(rgb_formats); ++i) {
     695           0 :                         if (num_formats >= max_formats)
     696             :                                 break;
     697             : 
     698           0 :                         formats[num_formats++] = rgb_formats[i];
     699             :                 }
     700             : 
     701           0 :                 if (plane_cap && plane_cap->pixel_format_support.nv12)
     702           0 :                         formats[num_formats++] = DRM_FORMAT_NV12;
     703           0 :                 if (plane_cap && plane_cap->pixel_format_support.p010)
     704           0 :                         formats[num_formats++] = DRM_FORMAT_P010;
     705           0 :                 if (plane_cap && plane_cap->pixel_format_support.fp16) {
     706           0 :                         formats[num_formats++] = DRM_FORMAT_XRGB16161616F;
     707           0 :                         formats[num_formats++] = DRM_FORMAT_ARGB16161616F;
     708           0 :                         formats[num_formats++] = DRM_FORMAT_XBGR16161616F;
     709           0 :                         formats[num_formats++] = DRM_FORMAT_ABGR16161616F;
     710             :                 }
     711             :                 break;
     712             : 
     713             :         case DRM_PLANE_TYPE_OVERLAY:
     714           0 :                 for (i = 0; i < ARRAY_SIZE(overlay_formats); ++i) {
     715           0 :                         if (num_formats >= max_formats)
     716             :                                 break;
     717             : 
     718           0 :                         formats[num_formats++] = overlay_formats[i];
     719             :                 }
     720             :                 break;
     721             : 
     722             :         case DRM_PLANE_TYPE_CURSOR:
     723           0 :                 for (i = 0; i < ARRAY_SIZE(cursor_formats); ++i) {
     724           0 :                         if (num_formats >= max_formats)
     725             :                                 break;
     726             : 
     727           0 :                         formats[num_formats++] = cursor_formats[i];
     728             :                 }
     729             :                 break;
     730             :         }
     731             : 
     732           0 :         return num_formats;
     733             : }
     734             : 
     735             : #ifdef CONFIG_DRM_AMD_DC_HDR
     736             : static int attach_color_mgmt_properties(struct amdgpu_display_manager *dm, struct drm_plane *plane)
     737             : {
     738             :         drm_object_attach_property(&plane->base,
     739             :                                    dm->degamma_lut_property,
     740             :                                    0);
     741             :         drm_object_attach_property(&plane->base,
     742             :                                    dm->degamma_lut_size_property,
     743             :                                    MAX_COLOR_LUT_ENTRIES);
     744             :         drm_object_attach_property(&plane->base, dm->ctm_property,
     745             :                                    0);
     746             :         drm_object_attach_property(&plane->base, dm->sdr_boost_property,
     747             :                                    DEFAULT_SDR_BOOST);
     748             : 
     749             :         return 0;
     750             : }
     751             : #endif
     752             : 
     753           0 : int fill_plane_buffer_attributes(struct amdgpu_device *adev,
     754             :                              const struct amdgpu_framebuffer *afb,
     755             :                              const enum surface_pixel_format format,
     756             :                              const enum dc_rotation_angle rotation,
     757             :                              const uint64_t tiling_flags,
     758             :                              union dc_tiling_info *tiling_info,
     759             :                              struct plane_size *plane_size,
     760             :                              struct dc_plane_dcc_param *dcc,
     761             :                              struct dc_plane_address *address,
     762             :                              bool tmz_surface,
     763             :                              bool force_disable_dcc)
     764             : {
     765           0 :         const struct drm_framebuffer *fb = &afb->base;
     766             :         int ret;
     767             : 
     768           0 :         memset(tiling_info, 0, sizeof(*tiling_info));
     769           0 :         memset(plane_size, 0, sizeof(*plane_size));
     770           0 :         memset(dcc, 0, sizeof(*dcc));
     771           0 :         memset(address, 0, sizeof(*address));
     772             : 
     773           0 :         address->tmz_surface = tmz_surface;
     774             : 
     775           0 :         if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
     776           0 :                 uint64_t addr = afb->address + fb->offsets[0];
     777             : 
     778           0 :                 plane_size->surface_size.x = 0;
     779           0 :                 plane_size->surface_size.y = 0;
     780           0 :                 plane_size->surface_size.width = fb->width;
     781           0 :                 plane_size->surface_size.height = fb->height;
     782           0 :                 plane_size->surface_pitch =
     783           0 :                         fb->pitches[0] / fb->format->cpp[0];
     784             : 
     785           0 :                 address->type = PLN_ADDR_TYPE_GRAPHICS;
     786           0 :                 address->grph.addr.low_part = lower_32_bits(addr);
     787           0 :                 address->grph.addr.high_part = upper_32_bits(addr);
     788           0 :         } else if (format < SURFACE_PIXEL_FORMAT_INVALID) {
     789           0 :                 uint64_t luma_addr = afb->address + fb->offsets[0];
     790           0 :                 uint64_t chroma_addr = afb->address + fb->offsets[1];
     791             : 
     792           0 :                 plane_size->surface_size.x = 0;
     793           0 :                 plane_size->surface_size.y = 0;
     794           0 :                 plane_size->surface_size.width = fb->width;
     795           0 :                 plane_size->surface_size.height = fb->height;
     796           0 :                 plane_size->surface_pitch =
     797           0 :                         fb->pitches[0] / fb->format->cpp[0];
     798             : 
     799           0 :                 plane_size->chroma_size.x = 0;
     800           0 :                 plane_size->chroma_size.y = 0;
     801             :                 /* TODO: set these based on surface format */
     802           0 :                 plane_size->chroma_size.width = fb->width / 2;
     803           0 :                 plane_size->chroma_size.height = fb->height / 2;
     804             : 
     805           0 :                 plane_size->chroma_pitch =
     806           0 :                         fb->pitches[1] / fb->format->cpp[1];
     807             : 
     808           0 :                 address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
     809           0 :                 address->video_progressive.luma_addr.low_part =
     810           0 :                         lower_32_bits(luma_addr);
     811           0 :                 address->video_progressive.luma_addr.high_part =
     812           0 :                         upper_32_bits(luma_addr);
     813           0 :                 address->video_progressive.chroma_addr.low_part =
     814           0 :                         lower_32_bits(chroma_addr);
     815           0 :                 address->video_progressive.chroma_addr.high_part =
     816           0 :                         upper_32_bits(chroma_addr);
     817             :         }
     818             : 
     819           0 :         if (adev->family >= AMDGPU_FAMILY_AI) {
     820           0 :                 ret = fill_gfx9_plane_attributes_from_modifiers(adev, afb, format,
     821             :                                                                 rotation, plane_size,
     822             :                                                                 tiling_info, dcc,
     823             :                                                                 address,
     824             :                                                                 force_disable_dcc);
     825           0 :                 if (ret)
     826             :                         return ret;
     827             :         } else {
     828           0 :                 fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags);
     829             :         }
     830             : 
     831             :         return 0;
     832             : }
     833             : 
     834           0 : static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
     835             :                                       struct drm_plane_state *new_state)
     836             : {
     837             :         struct amdgpu_framebuffer *afb;
     838             :         struct drm_gem_object *obj;
     839             :         struct amdgpu_device *adev;
     840             :         struct amdgpu_bo *rbo;
     841             :         struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old;
     842             :         uint32_t domain;
     843             :         int r;
     844             : 
     845           0 :         if (!new_state->fb) {
     846           0 :                 DRM_DEBUG_KMS("No FB bound\n");
     847           0 :                 return 0;
     848             :         }
     849             : 
     850           0 :         afb = to_amdgpu_framebuffer(new_state->fb);
     851           0 :         obj = new_state->fb->obj[0];
     852           0 :         rbo = gem_to_amdgpu_bo(obj);
     853           0 :         adev = amdgpu_ttm_adev(rbo->tbo.bdev);
     854             : 
     855           0 :         r = amdgpu_bo_reserve(rbo, true);
     856           0 :         if (r) {
     857           0 :                 dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
     858           0 :                 return r;
     859             :         }
     860             : 
     861           0 :         r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
     862           0 :         if (r) {
     863           0 :                 dev_err(adev->dev, "reserving fence slot failed (%d)\n", r);
     864           0 :                 goto error_unlock;
     865             :         }
     866             : 
     867           0 :         if (plane->type != DRM_PLANE_TYPE_CURSOR)
     868           0 :                 domain = amdgpu_display_supported_domains(adev, rbo->flags);
     869             :         else
     870             :                 domain = AMDGPU_GEM_DOMAIN_VRAM;
     871             : 
     872           0 :         r = amdgpu_bo_pin(rbo, domain);
     873           0 :         if (unlikely(r != 0)) {
     874           0 :                 if (r != -ERESTARTSYS)
     875           0 :                         DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
     876             :                 goto error_unlock;
     877             :         }
     878             : 
     879           0 :         r = amdgpu_ttm_alloc_gart(&rbo->tbo);
     880           0 :         if (unlikely(r != 0)) {
     881           0 :                 DRM_ERROR("%p bind failed\n", rbo);
     882             :                 goto error_unpin;
     883             :         }
     884             : 
     885           0 :         amdgpu_bo_unreserve(rbo);
     886             : 
     887           0 :         afb->address = amdgpu_bo_gpu_offset(rbo);
     888             : 
     889           0 :         amdgpu_bo_ref(rbo);
     890             : 
     891             :         /**
     892             :          * We don't do surface updates on planes that have been newly created,
     893             :          * but we also don't have the afb->address during atomic check.
     894             :          *
     895             :          * Fill in buffer attributes depending on the address here, but only on
     896             :          * newly created planes since they're not being used by DC yet and this
     897             :          * won't modify global state.
     898             :          */
     899           0 :         dm_plane_state_old = to_dm_plane_state(plane->state);
     900           0 :         dm_plane_state_new = to_dm_plane_state(new_state);
     901             : 
     902           0 :         if (dm_plane_state_new->dc_state &&
     903           0 :             dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
     904           0 :                 struct dc_plane_state *plane_state =
     905             :                         dm_plane_state_new->dc_state;
     906           0 :                 bool force_disable_dcc = !plane_state->dcc.enable;
     907             : 
     908           0 :                 fill_plane_buffer_attributes(
     909             :                         adev, afb, plane_state->format, plane_state->rotation,
     910             :                         afb->tiling_flags,
     911             :                         &plane_state->tiling_info, &plane_state->plane_size,
     912             :                         &plane_state->dcc, &plane_state->address,
     913           0 :                         afb->tmz_surface, force_disable_dcc);
     914             :         }
     915             : 
     916             :         return 0;
     917             : 
     918             : error_unpin:
     919           0 :         amdgpu_bo_unpin(rbo);
     920             : 
     921             : error_unlock:
     922           0 :         amdgpu_bo_unreserve(rbo);
     923           0 :         return r;
     924             : }
     925             : 
     926           0 : static void dm_plane_helper_cleanup_fb(struct drm_plane *plane,
     927             :                                        struct drm_plane_state *old_state)
     928             : {
     929             :         struct amdgpu_bo *rbo;
     930             :         int r;
     931             : 
     932           0 :         if (!old_state->fb)
     933           0 :                 return;
     934             : 
     935           0 :         rbo = gem_to_amdgpu_bo(old_state->fb->obj[0]);
     936           0 :         r = amdgpu_bo_reserve(rbo, false);
     937           0 :         if (unlikely(r)) {
     938           0 :                 DRM_ERROR("failed to reserve rbo before unpin\n");
     939           0 :                 return;
     940             :         }
     941             : 
     942           0 :         amdgpu_bo_unpin(rbo);
     943           0 :         amdgpu_bo_unreserve(rbo);
     944           0 :         amdgpu_bo_unref(&rbo);
     945             : }
     946             : 
     947           0 : static void get_min_max_dc_plane_scaling(struct drm_device *dev,
     948             :                                          struct drm_framebuffer *fb,
     949             :                                          int *min_downscale, int *max_upscale)
     950             : {
     951           0 :         struct amdgpu_device *adev = drm_to_adev(dev);
     952           0 :         struct dc *dc = adev->dm.dc;
     953             :         /* Caps for all supported planes are the same on DCE and DCN 1 - 3 */
     954           0 :         struct dc_plane_cap *plane_cap = &dc->caps.planes[0];
     955             : 
     956           0 :         switch (fb->format->format) {
     957             :         case DRM_FORMAT_P010:
     958             :         case DRM_FORMAT_NV12:
     959             :         case DRM_FORMAT_NV21:
     960           0 :                 *max_upscale = plane_cap->max_upscale_factor.nv12;
     961           0 :                 *min_downscale = plane_cap->max_downscale_factor.nv12;
     962             :                 break;
     963             : 
     964             :         case DRM_FORMAT_XRGB16161616F:
     965             :         case DRM_FORMAT_ARGB16161616F:
     966             :         case DRM_FORMAT_XBGR16161616F:
     967             :         case DRM_FORMAT_ABGR16161616F:
     968           0 :                 *max_upscale = plane_cap->max_upscale_factor.fp16;
     969           0 :                 *min_downscale = plane_cap->max_downscale_factor.fp16;
     970             :                 break;
     971             : 
     972             :         default:
     973           0 :                 *max_upscale = plane_cap->max_upscale_factor.argb8888;
     974           0 :                 *min_downscale = plane_cap->max_downscale_factor.argb8888;
     975             :                 break;
     976             :         }
     977             : 
     978             :         /*
     979             :          * A factor of 1 in the plane_cap means to not allow scaling, ie. use a
     980             :          * scaling factor of 1.0 == 1000 units.
     981             :          */
     982           0 :         if (*max_upscale == 1)
     983           0 :                 *max_upscale = 1000;
     984             : 
     985           0 :         if (*min_downscale == 1)
     986           0 :                 *min_downscale = 1000;
     987           0 : }
     988             : 
     989           0 : int dm_plane_helper_check_state(struct drm_plane_state *state,
     990             :                                        struct drm_crtc_state *new_crtc_state)
     991             : {
     992           0 :         struct drm_framebuffer *fb = state->fb;
     993             :         int min_downscale, max_upscale;
     994           0 :         int min_scale = 0;
     995           0 :         int max_scale = INT_MAX;
     996             : 
     997             :         /* Plane enabled? Validate viewport and get scaling factors from plane caps. */
     998           0 :         if (fb && state->crtc) {
     999             :                 /* Validate viewport to cover the case when only the position changes */
    1000           0 :                 if (state->plane->type != DRM_PLANE_TYPE_CURSOR) {
    1001           0 :                         int viewport_width = state->crtc_w;
    1002           0 :                         int viewport_height = state->crtc_h;
    1003             : 
    1004           0 :                         if (state->crtc_x < 0)
    1005           0 :                                 viewport_width += state->crtc_x;
    1006           0 :                         else if (state->crtc_x + state->crtc_w > new_crtc_state->mode.crtc_hdisplay)
    1007           0 :                                 viewport_width = new_crtc_state->mode.crtc_hdisplay - state->crtc_x;
    1008             : 
    1009           0 :                         if (state->crtc_y < 0)
    1010           0 :                                 viewport_height += state->crtc_y;
    1011           0 :                         else if (state->crtc_y + state->crtc_h > new_crtc_state->mode.crtc_vdisplay)
    1012           0 :                                 viewport_height = new_crtc_state->mode.crtc_vdisplay - state->crtc_y;
    1013             : 
    1014           0 :                         if (viewport_width < 0 || viewport_height < 0) {
    1015           0 :                                 DRM_DEBUG_ATOMIC("Plane completely outside of screen\n");
    1016           0 :                                 return -EINVAL;
    1017           0 :                         } else if (viewport_width < MIN_VIEWPORT_SIZE*2) { /* x2 for width is because of pipe-split. */
    1018           0 :                                 DRM_DEBUG_ATOMIC("Viewport width %d smaller than %d\n", viewport_width, MIN_VIEWPORT_SIZE*2);
    1019           0 :                                 return -EINVAL;
    1020           0 :                         } else if (viewport_height < MIN_VIEWPORT_SIZE) {
    1021           0 :                                 DRM_DEBUG_ATOMIC("Viewport height %d smaller than %d\n", viewport_height, MIN_VIEWPORT_SIZE);
    1022           0 :                                 return -EINVAL;
    1023             :                         }
    1024             : 
    1025             :                 }
    1026             : 
    1027             :                 /* Get min/max allowed scaling factors from plane caps. */
    1028           0 :                 get_min_max_dc_plane_scaling(state->crtc->dev, fb,
    1029             :                                              &min_downscale, &max_upscale);
    1030             :                 /*
    1031             :                  * Convert to drm convention: 16.16 fixed point, instead of dc's
    1032             :                  * 1.0 == 1000. Also drm scaling is src/dst instead of dc's
    1033             :                  * dst/src, so min_scale = 1.0 / max_upscale, etc.
    1034             :                  */
    1035           0 :                 min_scale = (1000 << 16) / max_upscale;
    1036           0 :                 max_scale = (1000 << 16) / min_downscale;
    1037             :         }
    1038             : 
    1039           0 :         return drm_atomic_helper_check_plane_state(
    1040             :                 state, new_crtc_state, min_scale, max_scale, true, true);
    1041             : }
    1042             : 
    1043           0 : int fill_dc_scaling_info(struct amdgpu_device *adev,
    1044             :                                 const struct drm_plane_state *state,
    1045             :                                 struct dc_scaling_info *scaling_info)
    1046             : {
    1047             :         int scale_w, scale_h, min_downscale, max_upscale;
    1048             : 
    1049           0 :         memset(scaling_info, 0, sizeof(*scaling_info));
    1050             : 
    1051             :         /* Source is fixed 16.16 but we ignore mantissa for now... */
    1052           0 :         scaling_info->src_rect.x = state->src_x >> 16;
    1053           0 :         scaling_info->src_rect.y = state->src_y >> 16;
    1054             : 
    1055             :         /*
    1056             :          * For reasons we don't (yet) fully understand a non-zero
    1057             :          * src_y coordinate into an NV12 buffer can cause a
    1058             :          * system hang on DCN1x.
    1059             :          * To avoid hangs (and maybe be overly cautious)
    1060             :          * let's reject both non-zero src_x and src_y.
    1061             :          *
    1062             :          * We currently know of only one use-case to reproduce a
    1063             :          * scenario with non-zero src_x and src_y for NV12, which
    1064             :          * is to gesture the YouTube Android app into full screen
    1065             :          * on ChromeOS.
    1066             :          */
    1067           0 :         if (((adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 0)) ||
    1068           0 :             (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(1, 0, 1))) &&
    1069           0 :             (state->fb && state->fb->format->format == DRM_FORMAT_NV12 &&
    1070           0 :             (scaling_info->src_rect.x != 0 || scaling_info->src_rect.y != 0)))
    1071             :                 return -EINVAL;
    1072             : 
    1073           0 :         scaling_info->src_rect.width = state->src_w >> 16;
    1074           0 :         if (scaling_info->src_rect.width == 0)
    1075             :                 return -EINVAL;
    1076             : 
    1077           0 :         scaling_info->src_rect.height = state->src_h >> 16;
    1078           0 :         if (scaling_info->src_rect.height == 0)
    1079             :                 return -EINVAL;
    1080             : 
    1081           0 :         scaling_info->dst_rect.x = state->crtc_x;
    1082           0 :         scaling_info->dst_rect.y = state->crtc_y;
    1083             : 
    1084           0 :         if (state->crtc_w == 0)
    1085             :                 return -EINVAL;
    1086             : 
    1087           0 :         scaling_info->dst_rect.width = state->crtc_w;
    1088             : 
    1089           0 :         if (state->crtc_h == 0)
    1090             :                 return -EINVAL;
    1091             : 
    1092           0 :         scaling_info->dst_rect.height = state->crtc_h;
    1093             : 
    1094             :         /* DRM doesn't specify clipping on destination output. */
    1095           0 :         scaling_info->clip_rect = scaling_info->dst_rect;
    1096             : 
    1097             :         /* Validate scaling per-format with DC plane caps */
    1098           0 :         if (state->plane && state->plane->dev && state->fb) {
    1099           0 :                 get_min_max_dc_plane_scaling(state->plane->dev, state->fb,
    1100             :                                              &min_downscale, &max_upscale);
    1101             :         } else {
    1102           0 :                 min_downscale = 250;
    1103           0 :                 max_upscale = 16000;
    1104             :         }
    1105             : 
    1106           0 :         scale_w = scaling_info->dst_rect.width * 1000 /
    1107           0 :                   scaling_info->src_rect.width;
    1108             : 
    1109           0 :         if (scale_w < min_downscale || scale_w > max_upscale)
    1110             :                 return -EINVAL;
    1111             : 
    1112           0 :         scale_h = scaling_info->dst_rect.height * 1000 /
    1113           0 :                   scaling_info->src_rect.height;
    1114             : 
    1115           0 :         if (scale_h < min_downscale || scale_h > max_upscale)
    1116             :                 return -EINVAL;
    1117             : 
    1118             :         /*
    1119             :          * The "scaling_quality" can be ignored for now, quality = 0 has DC
    1120             :          * assume reasonable defaults based on the format.
    1121             :          */
    1122             : 
    1123           0 :         return 0;
    1124             : }
    1125             : 
    1126           0 : static int dm_plane_atomic_check(struct drm_plane *plane,
    1127             :                                  struct drm_atomic_state *state)
    1128             : {
    1129           0 :         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
    1130             :                                                                                  plane);
    1131           0 :         struct amdgpu_device *adev = drm_to_adev(plane->dev);
    1132           0 :         struct dc *dc = adev->dm.dc;
    1133             :         struct dm_plane_state *dm_plane_state;
    1134             :         struct dc_scaling_info scaling_info;
    1135             :         struct drm_crtc_state *new_crtc_state;
    1136             :         int ret;
    1137             : 
    1138             :         trace_amdgpu_dm_plane_atomic_check(new_plane_state);
    1139             : 
    1140           0 :         dm_plane_state = to_dm_plane_state(new_plane_state);
    1141             : 
    1142           0 :         if (!dm_plane_state->dc_state)
    1143             :                 return 0;
    1144             : 
    1145           0 :         new_crtc_state =
    1146           0 :                 drm_atomic_get_new_crtc_state(state,
    1147             :                                               new_plane_state->crtc);
    1148           0 :         if (!new_crtc_state)
    1149             :                 return -EINVAL;
    1150             : 
    1151           0 :         ret = dm_plane_helper_check_state(new_plane_state, new_crtc_state);
    1152           0 :         if (ret)
    1153             :                 return ret;
    1154             : 
    1155           0 :         ret = fill_dc_scaling_info(adev, new_plane_state, &scaling_info);
    1156           0 :         if (ret)
    1157             :                 return ret;
    1158             : 
    1159           0 :         if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK)
    1160             :                 return 0;
    1161             : 
    1162           0 :         return -EINVAL;
    1163             : }
    1164             : 
    1165           0 : static int dm_plane_atomic_async_check(struct drm_plane *plane,
    1166             :                                        struct drm_atomic_state *state)
    1167             : {
    1168             :         /* Only support async updates on cursor planes. */
    1169           0 :         if (plane->type != DRM_PLANE_TYPE_CURSOR)
    1170             :                 return -EINVAL;
    1171             : 
    1172           0 :         return 0;
    1173             : }
    1174             : 
    1175           0 : static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
    1176             :                                struct dc_cursor_position *position)
    1177             : {
    1178           0 :         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
    1179             :         int x, y;
    1180           0 :         int xorigin = 0, yorigin = 0;
    1181             : 
    1182           0 :         if (!crtc || !plane->state->fb)
    1183             :                 return 0;
    1184             : 
    1185           0 :         if ((plane->state->crtc_w > amdgpu_crtc->max_cursor_width) ||
    1186           0 :             (plane->state->crtc_h > amdgpu_crtc->max_cursor_height)) {
    1187           0 :                 DRM_ERROR("%s: bad cursor width or height %d x %d\n",
    1188             :                           __func__,
    1189             :                           plane->state->crtc_w,
    1190             :                           plane->state->crtc_h);
    1191             :                 return -EINVAL;
    1192             :         }
    1193             : 
    1194           0 :         x = plane->state->crtc_x;
    1195           0 :         y = plane->state->crtc_y;
    1196             : 
    1197           0 :         if (x <= -amdgpu_crtc->max_cursor_width ||
    1198           0 :             y <= -amdgpu_crtc->max_cursor_height)
    1199             :                 return 0;
    1200             : 
    1201           0 :         if (x < 0) {
    1202           0 :                 xorigin = min(-x, amdgpu_crtc->max_cursor_width - 1);
    1203           0 :                 x = 0;
    1204             :         }
    1205           0 :         if (y < 0) {
    1206           0 :                 yorigin = min(-y, amdgpu_crtc->max_cursor_height - 1);
    1207           0 :                 y = 0;
    1208             :         }
    1209           0 :         position->enable = true;
    1210           0 :         position->translate_by_source = true;
    1211           0 :         position->x = x;
    1212           0 :         position->y = y;
    1213           0 :         position->x_hotspot = xorigin;
    1214           0 :         position->y_hotspot = yorigin;
    1215             : 
    1216             :         return 0;
    1217             : }
    1218             : 
    1219           0 : void handle_cursor_update(struct drm_plane *plane,
    1220             :                                  struct drm_plane_state *old_plane_state)
    1221             : {
    1222           0 :         struct amdgpu_device *adev = drm_to_adev(plane->dev);
    1223           0 :         struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb);
    1224           0 :         struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc;
    1225           0 :         struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
    1226           0 :         struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
    1227           0 :         uint64_t address = afb ? afb->address : 0;
    1228           0 :         struct dc_cursor_position position = {0};
    1229             :         struct dc_cursor_attributes attributes;
    1230             :         int ret;
    1231             : 
    1232           0 :         if (!plane->state->fb && !old_plane_state->fb)
    1233           0 :                 return;
    1234             : 
    1235             :         DC_LOG_CURSOR("%s: crtc_id=%d with size %d to %d\n",
    1236             :                       __func__,
    1237             :                       amdgpu_crtc->crtc_id,
    1238             :                       plane->state->crtc_w,
    1239             :                       plane->state->crtc_h);
    1240             : 
    1241           0 :         ret = get_cursor_position(plane, crtc, &position);
    1242           0 :         if (ret)
    1243             :                 return;
    1244             : 
    1245           0 :         if (!position.enable) {
    1246             :                 /* turn off cursor */
    1247           0 :                 if (crtc_state && crtc_state->stream) {
    1248           0 :                         mutex_lock(&adev->dm.dc_lock);
    1249           0 :                         dc_stream_set_cursor_position(crtc_state->stream,
    1250             :                                                       &position);
    1251           0 :                         mutex_unlock(&adev->dm.dc_lock);
    1252             :                 }
    1253             :                 return;
    1254             :         }
    1255             : 
    1256           0 :         amdgpu_crtc->cursor_width = plane->state->crtc_w;
    1257           0 :         amdgpu_crtc->cursor_height = plane->state->crtc_h;
    1258             : 
    1259           0 :         memset(&attributes, 0, sizeof(attributes));
    1260           0 :         attributes.address.high_part = upper_32_bits(address);
    1261           0 :         attributes.address.low_part  = lower_32_bits(address);
    1262           0 :         attributes.width             = plane->state->crtc_w;
    1263           0 :         attributes.height            = plane->state->crtc_h;
    1264           0 :         attributes.color_format      = CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA;
    1265           0 :         attributes.rotation_angle    = 0;
    1266           0 :         attributes.attribute_flags.value = 0;
    1267             : 
    1268           0 :         attributes.pitch = afb->base.pitches[0] / afb->base.format->cpp[0];
    1269             : 
    1270           0 :         if (crtc_state->stream) {
    1271           0 :                 mutex_lock(&adev->dm.dc_lock);
    1272           0 :                 if (!dc_stream_set_cursor_attributes(crtc_state->stream,
    1273             :                                                          &attributes))
    1274           0 :                         DRM_ERROR("DC failed to set cursor attributes\n");
    1275             : 
    1276           0 :                 if (!dc_stream_set_cursor_position(crtc_state->stream,
    1277             :                                                    &position))
    1278           0 :                         DRM_ERROR("DC failed to set cursor position\n");
    1279           0 :                 mutex_unlock(&adev->dm.dc_lock);
    1280             :         }
    1281             : }
    1282             : 
    1283           0 : static void dm_plane_atomic_async_update(struct drm_plane *plane,
    1284             :                                          struct drm_atomic_state *state)
    1285             : {
    1286           0 :         struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
    1287             :                                                                            plane);
    1288           0 :         struct drm_plane_state *old_state =
    1289             :                 drm_atomic_get_old_plane_state(state, plane);
    1290             : 
    1291             :         trace_amdgpu_dm_atomic_update_cursor(new_state);
    1292             : 
    1293           0 :         swap(plane->state->fb, new_state->fb);
    1294             : 
    1295           0 :         plane->state->src_x = new_state->src_x;
    1296           0 :         plane->state->src_y = new_state->src_y;
    1297           0 :         plane->state->src_w = new_state->src_w;
    1298           0 :         plane->state->src_h = new_state->src_h;
    1299           0 :         plane->state->crtc_x = new_state->crtc_x;
    1300           0 :         plane->state->crtc_y = new_state->crtc_y;
    1301           0 :         plane->state->crtc_w = new_state->crtc_w;
    1302           0 :         plane->state->crtc_h = new_state->crtc_h;
    1303             : 
    1304           0 :         handle_cursor_update(plane, old_state);
    1305           0 : }
    1306             : 
    1307             : static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
    1308             :         .prepare_fb = dm_plane_helper_prepare_fb,
    1309             :         .cleanup_fb = dm_plane_helper_cleanup_fb,
    1310             :         .atomic_check = dm_plane_atomic_check,
    1311             :         .atomic_async_check = dm_plane_atomic_async_check,
    1312             :         .atomic_async_update = dm_plane_atomic_async_update
    1313             : };
    1314             : 
    1315           0 : static void dm_drm_plane_reset(struct drm_plane *plane)
    1316             : {
    1317           0 :         struct dm_plane_state *amdgpu_state = NULL;
    1318             : 
    1319           0 :         if (plane->state)
    1320           0 :                 plane->funcs->atomic_destroy_state(plane, plane->state);
    1321             : 
    1322           0 :         amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL);
    1323           0 :         WARN_ON(amdgpu_state == NULL);
    1324             : 
    1325           0 :         if (amdgpu_state)
    1326           0 :                 __drm_atomic_helper_plane_reset(plane, &amdgpu_state->base);
    1327             : #ifdef CONFIG_DRM_AMD_DC_HDR
    1328             :         if (amdgpu_state)
    1329             :                 amdgpu_state->sdr_boost = DEFAULT_SDR_BOOST;
    1330             : #endif
    1331           0 : }
    1332             : 
    1333             : static struct drm_plane_state *
    1334           0 : dm_drm_plane_duplicate_state(struct drm_plane *plane)
    1335             : {
    1336             :         struct dm_plane_state *dm_plane_state, *old_dm_plane_state;
    1337             : 
    1338           0 :         old_dm_plane_state = to_dm_plane_state(plane->state);
    1339           0 :         dm_plane_state = kzalloc(sizeof(*dm_plane_state), GFP_KERNEL);
    1340           0 :         if (!dm_plane_state)
    1341             :                 return NULL;
    1342             : 
    1343           0 :         __drm_atomic_helper_plane_duplicate_state(plane, &dm_plane_state->base);
    1344             : 
    1345           0 :         if (old_dm_plane_state->dc_state) {
    1346           0 :                 dm_plane_state->dc_state = old_dm_plane_state->dc_state;
    1347           0 :                 dc_plane_state_retain(dm_plane_state->dc_state);
    1348             :         }
    1349             : 
    1350             : #ifdef CONFIG_DRM_AMD_DC_HDR
    1351             :         if (dm_plane_state->degamma_lut)
    1352             :                 drm_property_blob_get(dm_plane_state->degamma_lut);
    1353             :         if (dm_plane_state->ctm)
    1354             :                 drm_property_blob_get(dm_plane_state->ctm);
    1355             : 
    1356             :         dm_plane_state->sdr_boost = old_dm_plane_state->sdr_boost;
    1357             : #endif
    1358             : 
    1359             :         return &dm_plane_state->base;
    1360             : }
    1361             : 
    1362           0 : static bool dm_plane_format_mod_supported(struct drm_plane *plane,
    1363             :                                           uint32_t format,
    1364             :                                           uint64_t modifier)
    1365             : {
    1366           0 :         struct amdgpu_device *adev = drm_to_adev(plane->dev);
    1367           0 :         const struct drm_format_info *info = drm_format_info(format);
    1368           0 :         struct hw_asic_id asic_id = adev->dm.dc->ctx->asic_id;
    1369             : 
    1370           0 :         enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3;
    1371             : 
    1372           0 :         if (!info)
    1373             :                 return false;
    1374             : 
    1375             :         /*
    1376             :          * We always have to allow these modifiers:
    1377             :          * 1. Core DRM checks for LINEAR support if userspace does not provide modifiers.
    1378             :          * 2. Not passing any modifiers is the same as explicitly passing INVALID.
    1379             :          */
    1380           0 :         if (modifier == DRM_FORMAT_MOD_LINEAR ||
    1381           0 :             modifier == DRM_FORMAT_MOD_INVALID) {
    1382             :                 return true;
    1383             :         }
    1384             : 
    1385             :         /* check if swizzle mode is supported by this version of DCN */
    1386             :         switch (asic_id.chip_family) {
    1387             :         case FAMILY_SI:
    1388             :         case FAMILY_CI:
    1389             :         case FAMILY_KV:
    1390             :         case FAMILY_CZ:
    1391             :         case FAMILY_VI:
    1392             :                 /* asics before AI does not have modifier support */
    1393             :                 return false;
    1394             :         case FAMILY_AI:
    1395             :         case FAMILY_RV:
    1396             :         case FAMILY_NV:
    1397             :         case FAMILY_VGH:
    1398             :         case FAMILY_YELLOW_CARP:
    1399             :         case AMDGPU_FAMILY_GC_10_3_6:
    1400             :         case AMDGPU_FAMILY_GC_10_3_7:
    1401           0 :                 switch (AMD_FMT_MOD_GET(TILE, modifier)) {
    1402             :                 case AMD_FMT_MOD_TILE_GFX9_64K_R_X:
    1403             :                 case AMD_FMT_MOD_TILE_GFX9_64K_D_X:
    1404             :                 case AMD_FMT_MOD_TILE_GFX9_64K_S_X:
    1405             :                 case AMD_FMT_MOD_TILE_GFX9_64K_D:
    1406             :                         return true;
    1407             :                 default:
    1408             :                         return false;
    1409             :                 }
    1410             :                 break;
    1411             :         case AMDGPU_FAMILY_GC_11_0_0:
    1412             :         case AMDGPU_FAMILY_GC_11_0_1:
    1413           0 :                 switch (AMD_FMT_MOD_GET(TILE, modifier)) {
    1414             :                 case AMD_FMT_MOD_TILE_GFX11_256K_R_X:
    1415             :                 case AMD_FMT_MOD_TILE_GFX9_64K_R_X:
    1416             :                 case AMD_FMT_MOD_TILE_GFX9_64K_D_X:
    1417             :                 case AMD_FMT_MOD_TILE_GFX9_64K_S_X:
    1418             :                 case AMD_FMT_MOD_TILE_GFX9_64K_D:
    1419             :                         return true;
    1420             :                 default:
    1421             :                         return false;
    1422             :                 }
    1423             :                 break;
    1424             :         default:
    1425           0 :                 ASSERT(0); /* Unknown asic */
    1426             :                 break;
    1427             :         }
    1428             : 
    1429             :         /*
    1430             :          * For D swizzle the canonical modifier depends on the bpp, so check
    1431             :          * it here.
    1432             :          */
    1433           0 :         if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
    1434           0 :             adev->family >= AMDGPU_FAMILY_NV) {
    1435           0 :                 if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
    1436             :                         return false;
    1437             :         }
    1438             : 
    1439           0 :         if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
    1440           0 :             info->cpp[0] < 8)
    1441             :                 return false;
    1442             : 
    1443           0 :         if (modifier_has_dcc(modifier)) {
    1444             :                 /* Per radeonsi comments 16/64 bpp are more complicated. */
    1445           0 :                 if (info->cpp[0] != 4)
    1446             :                         return false;
    1447             :                 /* We support multi-planar formats, but not when combined with
    1448             :                  * additional DCC metadata planes.
    1449             :                  */
    1450           0 :                 if (info->num_planes > 1)
    1451             :                         return false;
    1452             :         }
    1453             : 
    1454           0 :         return true;
    1455             : }
    1456             : 
    1457           0 : static void dm_drm_plane_destroy_state(struct drm_plane *plane,
    1458             :                                 struct drm_plane_state *state)
    1459             : {
    1460           0 :         struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
    1461             : 
    1462             : #ifdef CONFIG_DRM_AMD_DC_HDR
    1463             :         drm_property_blob_put(dm_plane_state->degamma_lut);
    1464             :         drm_property_blob_put(dm_plane_state->ctm);
    1465             : #endif
    1466           0 :         if (dm_plane_state->dc_state)
    1467           0 :                 dc_plane_state_release(dm_plane_state->dc_state);
    1468             : 
    1469           0 :         drm_atomic_helper_plane_destroy_state(plane, state);
    1470           0 : }
    1471             : 
    1472             : #ifdef CONFIG_DRM_AMD_DC_HDR
    1473             : /* copied from drm_atomic_uapi.c */
    1474             : static int atomic_replace_property_blob_from_id(struct drm_device *dev,
    1475             :                                          struct drm_property_blob **blob,
    1476             :                                          uint64_t blob_id,
    1477             :                                          ssize_t expected_size,
    1478             :                                          ssize_t expected_elem_size,
    1479             :                                          bool *replaced)
    1480             : {
    1481             :         struct drm_property_blob *new_blob = NULL;
    1482             : 
    1483             :         if (blob_id != 0) {
    1484             :                 new_blob = drm_property_lookup_blob(dev, blob_id);
    1485             :                 if (new_blob == NULL)
    1486             :                         return -EINVAL;
    1487             : 
    1488             :                 if (expected_size > 0 &&
    1489             :                     new_blob->length != expected_size) {
    1490             :                         drm_property_blob_put(new_blob);
    1491             :                         return -EINVAL;
    1492             :                 }
    1493             :                 if (expected_elem_size > 0 &&
    1494             :                     new_blob->length % expected_elem_size != 0) {
    1495             :                         drm_property_blob_put(new_blob);
    1496             :                         return -EINVAL;
    1497             :                 }
    1498             :         }
    1499             : 
    1500             :         *replaced |= drm_property_replace_blob(blob, new_blob);
    1501             :         drm_property_blob_put(new_blob);
    1502             : 
    1503             :         return 0;
    1504             : }
    1505             : 
    1506             : int dm_drm_plane_set_property(struct drm_plane *plane,
    1507             :                               struct drm_plane_state *state,
    1508             :                               struct drm_property *property,
    1509             :                               uint64_t val)
    1510             : {
    1511             :         struct amdgpu_device *adev = drm_to_adev(plane->dev);
    1512             :         struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
    1513             :         int ret = 0;
    1514             :         bool replaced;
    1515             : 
    1516             :         if (property == adev->dm.degamma_lut_property) {
    1517             :                 ret = atomic_replace_property_blob_from_id(adev_to_drm(adev),
    1518             :                                 &dm_plane_state->degamma_lut,
    1519             :                                 val, -1, sizeof(struct drm_color_lut),
    1520             :                                 &replaced);
    1521             :         } else if (property == adev->dm.ctm_property) {
    1522             :                 ret = atomic_replace_property_blob_from_id(adev_to_drm(adev),
    1523             :                                 &dm_plane_state->ctm,
    1524             :                                 val,
    1525             :                                 sizeof(struct drm_color_ctm), -1,
    1526             :                                 &replaced);
    1527             :         } else if (property == adev->dm.sdr_boost_property) {
    1528             :                 dm_plane_state->sdr_boost = val;
    1529             :         } else {
    1530             :                 return -EINVAL;
    1531             :         }
    1532             : 
    1533             :         return ret;
    1534             : }
    1535             : 
    1536             : int dm_drm_plane_get_property(struct drm_plane *plane,
    1537             :                               const struct drm_plane_state *state,
    1538             :                               struct drm_property *property,
    1539             :                               uint64_t *val)
    1540             : {
    1541             :         struct dm_plane_state *dm_plane_state = to_dm_plane_state(state);
    1542             :         struct amdgpu_device *adev = drm_to_adev(plane->dev);
    1543             : 
    1544             :         if (property == adev->dm.degamma_lut_property) {
    1545             :                 *val = (dm_plane_state->degamma_lut) ?
    1546             :                         dm_plane_state->degamma_lut->base.id : 0;
    1547             :         } else if (property == adev->dm.ctm_property) {
    1548             :                 *val = (dm_plane_state->ctm) ? dm_plane_state->ctm->base.id : 0;
    1549             :         } else if (property == adev->dm.sdr_boost_property) {
    1550             :                 *val = dm_plane_state->sdr_boost;
    1551             :         } else {
    1552             :                 return -EINVAL;
    1553             :         }
    1554             : 
    1555             :         return 0;
    1556             : }
    1557             : #endif
    1558             : 
    1559             : static const struct drm_plane_funcs dm_plane_funcs = {
    1560             :         .update_plane   = drm_atomic_helper_update_plane,
    1561             :         .disable_plane  = drm_atomic_helper_disable_plane,
    1562             :         .destroy        = drm_primary_helper_destroy,
    1563             :         .reset = dm_drm_plane_reset,
    1564             :         .atomic_duplicate_state = dm_drm_plane_duplicate_state,
    1565             :         .atomic_destroy_state = dm_drm_plane_destroy_state,
    1566             :         .format_mod_supported = dm_plane_format_mod_supported,
    1567             : #ifdef CONFIG_DRM_AMD_DC_HDR
    1568             :         .atomic_set_property = dm_drm_plane_set_property,
    1569             :         .atomic_get_property = dm_drm_plane_get_property,
    1570             : #endif
    1571             : };
    1572             : 
    1573           0 : int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
    1574             :                                 struct drm_plane *plane,
    1575             :                                 unsigned long possible_crtcs,
    1576             :                                 const struct dc_plane_cap *plane_cap)
    1577             : {
    1578             :         uint32_t formats[32];
    1579             :         int num_formats;
    1580           0 :         int res = -EPERM;
    1581             :         unsigned int supported_rotations;
    1582           0 :         uint64_t *modifiers = NULL;
    1583             : 
    1584           0 :         num_formats = get_plane_formats(plane, plane_cap, formats,
    1585             :                                         ARRAY_SIZE(formats));
    1586             : 
    1587           0 :         res = get_plane_modifiers(dm->adev, plane->type, &modifiers);
    1588           0 :         if (res)
    1589             :                 return res;
    1590             : 
    1591           0 :         if (modifiers == NULL)
    1592           0 :                 adev_to_drm(dm->adev)->mode_config.fb_modifiers_not_supported = true;
    1593             : 
    1594           0 :         res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs,
    1595             :                                        &dm_plane_funcs, formats, num_formats,
    1596             :                                        modifiers, plane->type, NULL);
    1597           0 :         kfree(modifiers);
    1598           0 :         if (res)
    1599             :                 return res;
    1600             : 
    1601           0 :         if (plane->type == DRM_PLANE_TYPE_OVERLAY &&
    1602           0 :             plane_cap && plane_cap->per_pixel_alpha) {
    1603           0 :                 unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
    1604             :                                           BIT(DRM_MODE_BLEND_PREMULTI) |
    1605             :                                           BIT(DRM_MODE_BLEND_COVERAGE);
    1606             : 
    1607           0 :                 drm_plane_create_alpha_property(plane);
    1608           0 :                 drm_plane_create_blend_mode_property(plane, blend_caps);
    1609             :         }
    1610             : 
    1611           0 :         if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
    1612           0 :             plane_cap &&
    1613           0 :             (plane_cap->pixel_format_support.nv12 ||
    1614             :              plane_cap->pixel_format_support.p010)) {
    1615             :                 /* This only affects YUV formats. */
    1616           0 :                 drm_plane_create_color_properties(
    1617             :                         plane,
    1618             :                         BIT(DRM_COLOR_YCBCR_BT601) |
    1619             :                         BIT(DRM_COLOR_YCBCR_BT709) |
    1620             :                         BIT(DRM_COLOR_YCBCR_BT2020),
    1621             :                         BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
    1622             :                         BIT(DRM_COLOR_YCBCR_FULL_RANGE),
    1623             :                         DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE);
    1624             :         }
    1625             : 
    1626           0 :         supported_rotations =
    1627             :                 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
    1628             :                 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
    1629             : 
    1630           0 :         if (dm->adev->asic_type >= CHIP_BONAIRE &&
    1631           0 :             plane->type != DRM_PLANE_TYPE_CURSOR)
    1632           0 :                 drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
    1633             :                                                    supported_rotations);
    1634             : 
    1635           0 :         drm_plane_helper_add(plane, &dm_plane_helper_funcs);
    1636             : 
    1637             : #ifdef CONFIG_DRM_AMD_DC_HDR
    1638             :         attach_color_mgmt_properties(dm, plane);
    1639             : #endif
    1640             :         /* Create (reset) the plane state */
    1641           0 :         if (plane->funcs->reset)
    1642           0 :                 plane->funcs->reset(plane);
    1643             : 
    1644             :         return 0;
    1645             : }
    1646             : 

Generated by: LCOV version 1.14