Merge tag 'amd-drm-next-5.11-2020-11-05' of git://people.freedesktop.org/~agd5f/linux...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index 86fd4420f128f31ad639d54d0163869de2ac91af..2855bb918535810a038a34524c9f408f60a0e2f4 100644 (file)
@@ -34,6 +34,7 @@
 #include "dc/inc/hw/dmcu.h"
 #include "dc/inc/hw/abm.h"
 #include "dc/dc_dmub_srv.h"
+#include "amdgpu_dm_trace.h"
 
 #include "vid.h"
 #include "amdgpu.h"
 
 #define FIRMWARE_RENOIR_DMUB "amdgpu/renoir_dmcub.bin"
 MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB);
-#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
 #define FIRMWARE_SIENNA_CICHLID_DMUB "amdgpu/sienna_cichlid_dmcub.bin"
 MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID_DMUB);
 #define FIRMWARE_NAVY_FLOUNDER_DMUB "amdgpu/navy_flounder_dmcub.bin"
 MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER_DMUB);
-#endif
+#define FIRMWARE_GREEN_SARDINE_DMUB "amdgpu/green_sardine_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_GREEN_SARDINE_DMUB);
+#define FIRMWARE_VANGOGH_DMUB "amdgpu/vangogh_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_VANGOGH_DMUB);
+#define FIRMWARE_DIMGREY_CAVEFISH_DMUB "amdgpu/dimgrey_cavefish_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB);
 
 #define FIRMWARE_RAVEN_DMCU            "amdgpu/raven_dmcu.bin"
 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
@@ -209,6 +214,9 @@ static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream);
 static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream);
 static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm);
 
+static const struct drm_format_info *
+amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd);
+
 /*
  * dm_vblank_get_counter
  *
@@ -583,7 +591,7 @@ static void amdgpu_dm_fbc_init(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
        struct amdgpu_device *adev = drm_to_adev(dev);
-       struct dm_comressor_info *compressor = &adev->dm.compressor;
+       struct dm_compressor_info *compressor = &adev->dm.compressor;
        struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(connector);
        struct drm_display_mode *mode;
        unsigned long max_size = 0;
@@ -880,44 +888,60 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
        return 0;
 }
 
-static void amdgpu_check_debugfs_connector_property_change(struct amdgpu_device *adev,
-                                                          struct drm_atomic_state *state)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
 {
-       struct drm_connector *connector;
-       struct drm_crtc *crtc;
-       struct amdgpu_dm_connector *amdgpu_dm_connector;
-       struct drm_connector_state *conn_state;
-       struct dm_crtc_state *acrtc_state;
-       struct drm_crtc_state *crtc_state;
-       struct dc_stream_state *stream;
-       struct drm_device *dev = adev_to_drm(adev);
+       uint64_t pt_base;
+       uint32_t logical_addr_low;
+       uint32_t logical_addr_high;
+       uint32_t agp_base, agp_bot, agp_top;
+       PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       logical_addr_low  = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18;
+       pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
 
-               amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
-               conn_state = connector->state;
+       if (adev->apu_flags & AMD_APU_IS_RAVEN2)
+               /*
+                * Raven2 has a HW issue that it is unable to use the vram which
+                * is out of MC_VM_SYSTEM_APERTURE_HIGH_ADDR. So here is the
+                * workaround that increase system aperture high address (add 1)
+                * to get rid of the VM fault and hardware hang.
+                */
+               logical_addr_high = max((adev->gmc.fb_end >> 18) + 0x1, adev->gmc.agp_end >> 18);
+       else
+               logical_addr_high = max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18;
 
-               if (!(conn_state && conn_state->crtc))
-                       continue;
+       agp_base = 0;
+       agp_bot = adev->gmc.agp_start >> 24;
+       agp_top = adev->gmc.agp_end >> 24;
 
-               crtc = conn_state->crtc;
-               acrtc_state = to_dm_crtc_state(crtc->state);
 
-               if (!(acrtc_state && acrtc_state->stream))
-                       continue;
+       page_table_start.high_part = (u32)(adev->gmc.gart_start >> 44) & 0xF;
+       page_table_start.low_part = (u32)(adev->gmc.gart_start >> 12);
+       page_table_end.high_part = (u32)(adev->gmc.gart_end >> 44) & 0xF;
+       page_table_end.low_part = (u32)(adev->gmc.gart_end >> 12);
+       page_table_base.high_part = upper_32_bits(pt_base) & 0xF;
+       page_table_base.low_part = lower_32_bits(pt_base);
 
-               stream = acrtc_state->stream;
+       pa_config->system_aperture.start_addr = (uint64_t)logical_addr_low << 18;
+       pa_config->system_aperture.end_addr = (uint64_t)logical_addr_high << 18;
+
+       pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24 ;
+       pa_config->system_aperture.agp_bot = (uint64_t)agp_bot << 24;
+       pa_config->system_aperture.agp_top = (uint64_t)agp_top << 24;
+
+       pa_config->system_aperture.fb_base = adev->gmc.fb_start;
+       pa_config->system_aperture.fb_offset = adev->gmc.aper_base;
+       pa_config->system_aperture.fb_top = adev->gmc.fb_end;
+
+       pa_config->gart_config.page_table_start_addr = page_table_start.quad_part << 12;
+       pa_config->gart_config.page_table_end_addr = page_table_end.quad_part << 12;
+       pa_config->gart_config.page_table_base_addr = page_table_base.quad_part;
+
+       pa_config->is_hvm_enabled = 0;
 
-               if (amdgpu_dm_connector->dsc_settings.dsc_force_enable ||
-                   amdgpu_dm_connector->dsc_settings.dsc_num_slices_v ||
-                   amdgpu_dm_connector->dsc_settings.dsc_num_slices_h ||
-                   amdgpu_dm_connector->dsc_settings.dsc_bits_per_pixel) {
-                       conn_state = drm_atomic_get_connector_state(state, connector);
-                       crtc_state = drm_atomic_get_crtc_state(state, crtc);
-                       crtc_state->mode_changed = true;
-               }
-       }
 }
+#endif
 
 static int amdgpu_dm_init(struct amdgpu_device *adev)
 {
@@ -973,6 +997,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        case CHIP_RAVEN:
        case CHIP_RENOIR:
                init_data.flags.gpu_vm_support = true;
+               if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
+                       init_data.flags.disable_dmcu = true;
                break;
        default:
                break;
@@ -1026,6 +1052,17 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 
        dc_hardware_init(adev->dm.dc);
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       if (adev->asic_type == CHIP_RENOIR) {
+               struct dc_phy_addr_space_config pa_config;
+
+               mmhub_read_system_context(adev, &pa_config);
+
+               // Call the DC init_memory func
+               dc_setup_system_context(adev->dm.dc, &pa_config);
+       }
+#endif
+
        adev->dm.freesync_module = mod_freesync_create(adev->dm.dc);
        if (!adev->dm.freesync_module) {
                DRM_ERROR(
@@ -1072,6 +1109,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
                goto error;
        }
 
+
        DRM_DEBUG_DRIVER("KMS initialized.\n");
 
        return 0;
@@ -1168,10 +1206,10 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
        case CHIP_NAVI10:
        case CHIP_NAVI14:
        case CHIP_RENOIR:
-#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
        case CHIP_SIENNA_CICHLID:
        case CHIP_NAVY_FLOUNDER:
-#endif
+       case CHIP_DIMGREY_CAVEFISH:
+       case CHIP_VANGOGH:
                return 0;
        case CHIP_NAVI12:
                fw_name_dmcu = FIRMWARE_NAVI12_DMCU;
@@ -1267,8 +1305,9 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
        case CHIP_RENOIR:
                dmub_asic = DMUB_ASIC_DCN21;
                fw_name_dmub = FIRMWARE_RENOIR_DMUB;
+               if (ASICREV_IS_GREEN_SARDINE(adev->external_rev_id))
+                       fw_name_dmub = FIRMWARE_GREEN_SARDINE_DMUB;
                break;
-#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
        case CHIP_SIENNA_CICHLID:
                dmub_asic = DMUB_ASIC_DCN30;
                fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB;
@@ -1277,7 +1316,14 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
                dmub_asic = DMUB_ASIC_DCN30;
                fw_name_dmub = FIRMWARE_NAVY_FLOUNDER_DMUB;
                break;
-#endif
+       case CHIP_VANGOGH:
+               dmub_asic = DMUB_ASIC_DCN301;
+               fw_name_dmub = FIRMWARE_VANGOGH_DMUB;
+               break;
+       case CHIP_DIMGREY_CAVEFISH:
+               dmub_asic = DMUB_ASIC_DCN302;
+               fw_name_dmub = FIRMWARE_DIMGREY_CAVEFISH_DMUB;
+               break;
 
        default:
                /* ASIC doesn't support DMUB. */
@@ -2095,6 +2141,7 @@ const struct amdgpu_ip_block_version dm_ip_block =
 
 static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
        .fb_create = amdgpu_display_user_framebuffer_create,
+       .get_format_info = amd_get_format_info,
        .output_poll_changed = drm_fb_helper_output_poll_changed,
        .atomic_check = amdgpu_dm_atomic_check,
        .atomic_commit = amdgpu_dm_atomic_commit,
@@ -3396,10 +3443,10 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
        case CHIP_NAVI10:
        case CHIP_NAVI14:
        case CHIP_RENOIR:
-#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
        case CHIP_SIENNA_CICHLID:
        case CHIP_NAVY_FLOUNDER:
-#endif
+       case CHIP_DIMGREY_CAVEFISH:
+       case CHIP_VANGOGH:
                if (dcn10_register_irq_handlers(dm->adev)) {
                        DRM_ERROR("DM: Failed to initialize IRQ\n");
                        goto fail;
@@ -3558,31 +3605,27 @@ static int dm_early_init(void *handle)
                break;
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        case CHIP_RAVEN:
+       case CHIP_RENOIR:
+       case CHIP_VANGOGH:
                adev->mode_info.num_crtc = 4;
                adev->mode_info.num_hpd = 4;
                adev->mode_info.num_dig = 4;
                break;
-#endif
        case CHIP_NAVI10:
        case CHIP_NAVI12:
-#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
        case CHIP_SIENNA_CICHLID:
        case CHIP_NAVY_FLOUNDER:
-#endif
                adev->mode_info.num_crtc = 6;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 6;
                break;
        case CHIP_NAVI14:
+       case CHIP_DIMGREY_CAVEFISH:
                adev->mode_info.num_crtc = 5;
                adev->mode_info.num_hpd = 5;
                adev->mode_info.num_dig = 5;
                break;
-       case CHIP_RENOIR:
-               adev->mode_info.num_crtc = 4;
-               adev->mode_info.num_hpd = 4;
-               adev->mode_info.num_dig = 4;
-               break;
+#endif
        default:
                DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);
                return -EINVAL;
@@ -3686,78 +3729,84 @@ static int fill_dc_scaling_info(const struct drm_plane_state *state,
        return 0;
 }
 
-static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,
-                      uint64_t *tiling_flags, bool *tmz_surface)
+static void
+fill_gfx8_tiling_info_from_flags(union dc_tiling_info *tiling_info,
+                                uint64_t tiling_flags)
 {
-       struct amdgpu_bo *rbo;
-       int r;
-
-       if (!amdgpu_fb) {
-               *tiling_flags = 0;
-               *tmz_surface = false;
-               return 0;
-       }
+       /* Fill GFX8 params */
+       if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) {
+               unsigned int bankw, bankh, mtaspect, tile_split, num_banks;
 
-       rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]);
-       r = amdgpu_bo_reserve(rbo, false);
+               bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
+               bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
+               mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
+               tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
+               num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
 
-       if (unlikely(r)) {
-               /* Don't show error message when returning -ERESTARTSYS */
-               if (r != -ERESTARTSYS)
-                       DRM_ERROR("Unable to reserve buffer: %d\n", r);
-               return r;
+               /* XXX fix me for VI */
+               tiling_info->gfx8.num_banks = num_banks;
+               tiling_info->gfx8.array_mode =
+                               DC_ARRAY_2D_TILED_THIN1;
+               tiling_info->gfx8.tile_split = tile_split;
+               tiling_info->gfx8.bank_width = bankw;
+               tiling_info->gfx8.bank_height = bankh;
+               tiling_info->gfx8.tile_aspect = mtaspect;
+               tiling_info->gfx8.tile_mode =
+                               DC_ADDR_SURF_MICRO_TILING_DISPLAY;
+       } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
+                       == DC_ARRAY_1D_TILED_THIN1) {
+               tiling_info->gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1;
        }
 
-       if (tiling_flags)
-               amdgpu_bo_get_tiling_flags(rbo, tiling_flags);
-
-       if (tmz_surface)
-               *tmz_surface = amdgpu_bo_encrypted(rbo);
-
-       amdgpu_bo_unreserve(rbo);
-
-       return r;
+       tiling_info->gfx8.pipe_config =
+                       AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
 }
 
-static inline uint64_t get_dcc_address(uint64_t address, uint64_t tiling_flags)
-{
-       uint32_t offset = AMDGPU_TILING_GET(tiling_flags, DCC_OFFSET_256B);
-
-       return offset ? (address + offset * 256) : 0;
+static void
+fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
+                                 union dc_tiling_info *tiling_info)
+{
+       tiling_info->gfx9.num_pipes =
+               adev->gfx.config.gb_addr_config_fields.num_pipes;
+       tiling_info->gfx9.num_banks =
+               adev->gfx.config.gb_addr_config_fields.num_banks;
+       tiling_info->gfx9.pipe_interleave =
+               adev->gfx.config.gb_addr_config_fields.pipe_interleave_size;
+       tiling_info->gfx9.num_shader_engines =
+               adev->gfx.config.gb_addr_config_fields.num_se;
+       tiling_info->gfx9.max_compressed_frags =
+               adev->gfx.config.gb_addr_config_fields.max_compress_frags;
+       tiling_info->gfx9.num_rb_per_se =
+               adev->gfx.config.gb_addr_config_fields.num_rb_per_se;
+       tiling_info->gfx9.shaderEnable = 1;
+       if (adev->asic_type == CHIP_SIENNA_CICHLID ||
+           adev->asic_type == CHIP_NAVY_FLOUNDER ||
+           adev->asic_type == CHIP_DIMGREY_CAVEFISH ||
+           adev->asic_type == CHIP_VANGOGH)
+               tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs;
 }
 
 static int
-fill_plane_dcc_attributes(struct amdgpu_device *adev,
-                         const struct amdgpu_framebuffer *afb,
-                         const enum surface_pixel_format format,
-                         const enum dc_rotation_angle rotation,
-                         const struct plane_size *plane_size,
-                         const union dc_tiling_info *tiling_info,
-                         const uint64_t info,
-                         struct dc_plane_dcc_param *dcc,
-                         struct dc_plane_address *address,
-                         bool force_disable_dcc)
+validate_dcc(struct amdgpu_device *adev,
+            const enum surface_pixel_format format,
+            const enum dc_rotation_angle rotation,
+            const union dc_tiling_info *tiling_info,
+            const struct dc_plane_dcc_param *dcc,
+            const struct dc_plane_address *address,
+            const struct plane_size *plane_size)
 {
        struct dc *dc = adev->dm.dc;
        struct dc_dcc_surface_param input;
        struct dc_surface_dcc_cap output;
-       uint32_t offset = AMDGPU_TILING_GET(info, DCC_OFFSET_256B);
-       uint32_t i64b = AMDGPU_TILING_GET(info, DCC_INDEPENDENT_64B) != 0;
-       uint64_t dcc_address;
 
        memset(&input, 0, sizeof(input));
        memset(&output, 0, sizeof(output));
 
-       if (force_disable_dcc)
+       if (!dcc->enable)
                return 0;
 
-       if (!offset)
-               return 0;
-
-       if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
-               return 0;
-
-       if (!dc->cap_funcs.get_dcc_compression_cap)
+       if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN ||
+           !dc->cap_funcs.get_dcc_compression_cap)
                return -EINVAL;
 
        input.format = format;
@@ -3776,17 +3825,508 @@ fill_plane_dcc_attributes(struct amdgpu_device *adev,
        if (!output.capable)
                return -EINVAL;
 
-       if (i64b == 0 && output.grph.rgb.independent_64b_blks != 0)
+       if (dcc->independent_64b_blks == 0 &&
+           output.grph.rgb.independent_64b_blks != 0)
                return -EINVAL;
 
-       dcc->enable = 1;
-       dcc->meta_pitch =
-               AMDGPU_TILING_GET(info, DCC_PITCH_MAX) + 1;
-       dcc->independent_64b_blks = i64b;
+       return 0;
+}
+
+static bool
+modifier_has_dcc(uint64_t modifier)
+{
+       return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
+}
+
+static unsigned
+modifier_gfx9_swizzle_mode(uint64_t modifier)
+{
+       if (modifier == DRM_FORMAT_MOD_LINEAR)
+               return 0;
+
+       return AMD_FMT_MOD_GET(TILE, modifier);
+}
+
+static const struct drm_format_info dcc_formats[] = {
+       { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+        { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+       { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+          .has_alpha = true, },
+       { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+         .has_alpha = true, },
+       { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+         .has_alpha = true, },
+       { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+       { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+       { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+         .has_alpha = true, },
+       { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 2,
+         .cpp = { 4, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+         .has_alpha = true, },
+       { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 2,
+         .cpp = { 2, 0, }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+};
+
+static const struct drm_format_info dcc_retile_formats[] = {
+       { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+        { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+       { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+          .has_alpha = true, },
+       { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+         .has_alpha = true, },
+       { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+         .has_alpha = true, },
+       { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+       { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+       { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+         .has_alpha = true, },
+       { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 3,
+         .cpp = { 4, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1,
+         .has_alpha = true, },
+       { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 3,
+         .cpp = { 2, 0, 0 }, .block_w = {1, 1, 1}, .block_h = {1, 1, 1}, .hsub = 1, .vsub = 1, },
+};
+
+
+static const struct drm_format_info *
+lookup_format_info(const struct drm_format_info formats[],
+                 int num_formats, u32 format)
+{
+       int i;
+
+       for (i = 0; i < num_formats; i++) {
+               if (formats[i].format == format)
+                       return &formats[i];
+       }
+
+       return NULL;
+}
+
+static const struct drm_format_info *
+amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
+{
+       uint64_t modifier = cmd->modifier[0];
+
+       if (!IS_AMD_FMT_MOD(modifier))
+               return NULL;
+
+       if (AMD_FMT_MOD_GET(DCC_RETILE, modifier))
+               return lookup_format_info(dcc_retile_formats,
+                                         ARRAY_SIZE(dcc_retile_formats),
+                                         cmd->pixel_format);
 
-       dcc_address = get_dcc_address(afb->address, info);
-       address->grph.meta_addr.low_part = lower_32_bits(dcc_address);
-       address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
+       if (AMD_FMT_MOD_GET(DCC, modifier))
+               return lookup_format_info(dcc_formats, ARRAY_SIZE(dcc_formats),
+                                         cmd->pixel_format);
+
+       /* returning NULL will cause the default format structs to be used. */
+       return NULL;
+}
+
+static void
+fill_gfx9_tiling_info_from_modifier(const struct amdgpu_device *adev,
+                                   union dc_tiling_info *tiling_info,
+                                   uint64_t modifier)
+{
+       unsigned int mod_bank_xor_bits = AMD_FMT_MOD_GET(BANK_XOR_BITS, modifier);
+       unsigned int mod_pipe_xor_bits = AMD_FMT_MOD_GET(PIPE_XOR_BITS, modifier);
+       unsigned int pkrs_log2 = AMD_FMT_MOD_GET(PACKERS, modifier);
+       unsigned int pipes_log2 = min(4u, mod_pipe_xor_bits);
+
+       fill_gfx9_tiling_info_from_device(adev, tiling_info);
+
+       if (!IS_AMD_FMT_MOD(modifier))
+               return;
+
+       tiling_info->gfx9.num_pipes = 1u << pipes_log2;
+       tiling_info->gfx9.num_shader_engines = 1u << (mod_pipe_xor_bits - pipes_log2);
+
+       if (adev->family >= AMDGPU_FAMILY_NV) {
+               tiling_info->gfx9.num_pkrs = 1u << pkrs_log2;
+       } else {
+               tiling_info->gfx9.num_banks = 1u << mod_bank_xor_bits;
+
+               /* for DCC we know it isn't rb aligned, so rb_per_se doesn't matter. */
+       }
+}
+
+enum dm_micro_swizzle {
+       MICRO_SWIZZLE_Z = 0,
+       MICRO_SWIZZLE_S = 1,
+       MICRO_SWIZZLE_D = 2,
+       MICRO_SWIZZLE_R = 3
+};
+
+static bool dm_plane_format_mod_supported(struct drm_plane *plane,
+                                         uint32_t format,
+                                         uint64_t modifier)
+{
+       struct amdgpu_device *adev = drm_to_adev(plane->dev);
+       const struct drm_format_info *info = drm_format_info(format);
+
+       enum dm_micro_swizzle microtile = modifier_gfx9_swizzle_mode(modifier) & 3;
+
+       if (!info)
+               return false;
+
+       /*
+        * We always have to allow this modifier, because core DRM still
+        * checks LINEAR support if userspace does not provide modifers.
+        */
+       if (modifier == DRM_FORMAT_MOD_LINEAR)
+               return true;
+
+       /*
+        * The arbitrary tiling support for multiplane formats has not been hooked
+        * up.
+        */
+       if (info->num_planes > 1)
+               return false;
+
+       /*
+        * For D swizzle the canonical modifier depends on the bpp, so check
+        * it here.
+        */
+       if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX9 &&
+           adev->family >= AMDGPU_FAMILY_NV) {
+               if (microtile == MICRO_SWIZZLE_D && info->cpp[0] == 4)
+                       return false;
+       }
+
+       if (adev->family >= AMDGPU_FAMILY_RV && microtile == MICRO_SWIZZLE_D &&
+           info->cpp[0] < 8)
+               return false;
+
+       if (modifier_has_dcc(modifier)) {
+               /* Per radeonsi comments 16/64 bpp are more complicated. */
+               if (info->cpp[0] != 4)
+                       return false;
+       }
+
+       return true;
+}
+
+static void
+add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_t mod)
+{
+       if (!*mods)
+               return;
+
+       if (*cap - *size < 1) {
+               uint64_t new_cap = *cap * 2;
+               uint64_t *new_mods = kmalloc(new_cap * sizeof(uint64_t), GFP_KERNEL);
+
+               if (!new_mods) {
+                       kfree(*mods);
+                       *mods = NULL;
+                       return;
+               }
+
+               memcpy(new_mods, *mods, sizeof(uint64_t) * *size);
+               kfree(*mods);
+               *mods = new_mods;
+               *cap = new_cap;
+       }
+
+       (*mods)[*size] = mod;
+       *size += 1;
+}
+
+static void
+add_gfx9_modifiers(const struct amdgpu_device *adev,
+                  uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
+       int pipes = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
+       int pipe_xor_bits = min(8, pipes +
+                               ilog2(adev->gfx.config.gb_addr_config_fields.num_se));
+       int bank_xor_bits = min(8 - pipe_xor_bits,
+                               ilog2(adev->gfx.config.gb_addr_config_fields.num_banks));
+       int rb = ilog2(adev->gfx.config.gb_addr_config_fields.num_se) +
+                ilog2(adev->gfx.config.gb_addr_config_fields.num_rb_per_se);
+
+
+       if (adev->family == AMDGPU_FAMILY_RV) {
+               /* Raven2 and later */
+               bool has_constant_encode = adev->asic_type > CHIP_RAVEN || adev->external_rev_id >= 0x81;
+
+               /*
+                * No _D DCC swizzles yet because we only allow 32bpp, which
+                * doesn't support _D on DCN
+                */
+
+               if (has_constant_encode) {
+                       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+                                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+                                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                                   AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+                                   AMD_FMT_MOD_SET(DCC, 1) |
+                                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+                                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+                                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1));
+               }
+
+               add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+                           AMD_FMT_MOD_SET(DCC, 1) |
+                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0));
+
+               if (has_constant_encode) {
+                       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+                                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+                                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                                   AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+                                   AMD_FMT_MOD_SET(DCC, 1) |
+                                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+                                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+                                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+
+                                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+                                   AMD_FMT_MOD_SET(RB, rb) |
+                                   AMD_FMT_MOD_SET(PIPE, pipes));
+               }
+
+               add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits) |
+                           AMD_FMT_MOD_SET(DCC, 1) |
+                           AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+                           AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+                           AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B) |
+                           AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 0) |
+                           AMD_FMT_MOD_SET(RB, rb) |
+                           AMD_FMT_MOD_SET(PIPE, pipes));
+       }
+
+       /*
+        * Only supported for 64bpp on Raven, will be filtered on format in
+        * dm_plane_format_mod_supported.
+        */
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                   AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
+
+       if (adev->family == AMDGPU_FAMILY_RV) {
+               add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9) |
+                           AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                           AMD_FMT_MOD_SET(BANK_XOR_BITS, bank_xor_bits));
+       }
+
+       /*
+        * Only supported for 64bpp on Raven, will be filtered on format in
+        * dm_plane_format_mod_supported.
+        */
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+       if (adev->family == AMDGPU_FAMILY_RV) {
+               add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                           AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+                           AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+       }
+}
+
+static void
+add_gfx10_1_modifiers(const struct amdgpu_device *adev,
+                     uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
+       int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                   AMD_FMT_MOD_SET(DCC, 1) |
+                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                   AMD_FMT_MOD_SET(DCC, 1) |
+                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B));
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits));
+
+
+       /* Only supported for 64bpp, will be filtered in dm_plane_format_mod_supported */
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+}
+
+static void
+add_gfx10_3_modifiers(const struct amdgpu_device *adev,
+                     uint64_t **mods, uint64_t *size, uint64_t *capacity)
+{
+       int pipe_xor_bits = ilog2(adev->gfx.config.gb_addr_config_fields.num_pipes);
+       int pkrs = ilog2(adev->gfx.config.gb_addr_config_fields.num_pkrs);
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                   AMD_FMT_MOD_SET(PACKERS, pkrs) |
+                   AMD_FMT_MOD_SET(DCC, 1) |
+                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
+                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                   AMD_FMT_MOD_SET(PACKERS, pkrs) |
+                   AMD_FMT_MOD_SET(DCC, 1) |
+                   AMD_FMT_MOD_SET(DCC_RETILE, 1) |
+                   AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) |
+                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_64B, 1) |
+                   AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) |
+                   AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B));
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                   AMD_FMT_MOD_SET(PACKERS, pkrs));
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S_X) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) |
+                   AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) |
+                   AMD_FMT_MOD_SET(PACKERS, pkrs));
+
+       /* Only supported for 64bpp, will be filtered in dm_plane_format_mod_supported */
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_D) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+
+       add_modifier(mods, size, capacity, AMD_FMT_MOD |
+                   AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_S) |
+                   AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX9));
+}
+
+static int
+get_plane_modifiers(const struct amdgpu_device *adev, unsigned int plane_type, uint64_t **mods)
+{
+       uint64_t size = 0, capacity = 128;
+       *mods = NULL;
+
+       /* We have not hooked up any pre-GFX9 modifiers. */
+       if (adev->family < AMDGPU_FAMILY_AI)
+               return 0;
+
+       *mods = kmalloc(capacity * sizeof(uint64_t), GFP_KERNEL);
+
+       if (plane_type == DRM_PLANE_TYPE_CURSOR) {
+               add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
+               add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
+               return *mods ? 0 : -ENOMEM;
+       }
+
+       switch (adev->family) {
+       case AMDGPU_FAMILY_AI:
+       case AMDGPU_FAMILY_RV:
+               add_gfx9_modifiers(adev, mods, &size, &capacity);
+               break;
+       case AMDGPU_FAMILY_NV:
+       case AMDGPU_FAMILY_VGH:
+               if (adev->asic_type >= CHIP_SIENNA_CICHLID)
+                       add_gfx10_3_modifiers(adev, mods, &size, &capacity);
+               else
+                       add_gfx10_1_modifiers(adev, mods, &size, &capacity);
+               break;
+       }
+
+       add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_LINEAR);
+
+       /* INVALID marks the end of the list. */
+       add_modifier(mods, &size, &capacity, DRM_FORMAT_MOD_INVALID);
+
+       if (!*mods)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int
+fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
+                                         const struct amdgpu_framebuffer *afb,
+                                         const enum surface_pixel_format format,
+                                         const enum dc_rotation_angle rotation,
+                                         const struct plane_size *plane_size,
+                                         union dc_tiling_info *tiling_info,
+                                         struct dc_plane_dcc_param *dcc,
+                                         struct dc_plane_address *address,
+                                         const bool force_disable_dcc)
+{
+       const uint64_t modifier = afb->base.modifier;
+       int ret;
+
+       fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
+       tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier);
+
+       if (modifier_has_dcc(modifier) && !force_disable_dcc) {
+               uint64_t dcc_address = afb->address + afb->base.offsets[1];
+
+               dcc->enable = 1;
+               dcc->meta_pitch = afb->base.pitches[1];
+               dcc->independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier);
+
+               address->grph.meta_addr.low_part = lower_32_bits(dcc_address);
+               address->grph.meta_addr.high_part = upper_32_bits(dcc_address);
+       }
+
+       ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
+       if (ret)
+               return ret;
 
        return 0;
 }
@@ -3815,6 +4355,8 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
        address->tmz_surface = tmz_surface;
 
        if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
+               uint64_t addr = afb->address + fb->offsets[0];
+
                plane_size->surface_size.x = 0;
                plane_size->surface_size.y = 0;
                plane_size->surface_size.width = fb->width;
@@ -3823,9 +4365,10 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
                        fb->pitches[0] / fb->format->cpp[0];
 
                address->type = PLN_ADDR_TYPE_GRAPHICS;
-               address->grph.addr.low_part = lower_32_bits(afb->address);
-               address->grph.addr.high_part = upper_32_bits(afb->address);
+               address->grph.addr.low_part = lower_32_bits(addr);
+               address->grph.addr.high_part = upper_32_bits(addr);
        } else if (format < SURFACE_PIXEL_FORMAT_INVALID) {
+               uint64_t luma_addr = afb->address + fb->offsets[0];
                uint64_t chroma_addr = afb->address + fb->offsets[1];
 
                plane_size->surface_size.x = 0;
@@ -3846,83 +4389,25 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
 
                address->type = PLN_ADDR_TYPE_VIDEO_PROGRESSIVE;
                address->video_progressive.luma_addr.low_part =
-                       lower_32_bits(afb->address);
+                       lower_32_bits(luma_addr);
                address->video_progressive.luma_addr.high_part =
-                       upper_32_bits(afb->address);
+                       upper_32_bits(luma_addr);
                address->video_progressive.chroma_addr.low_part =
                        lower_32_bits(chroma_addr);
                address->video_progressive.chroma_addr.high_part =
                        upper_32_bits(chroma_addr);
        }
 
-       /* Fill GFX8 params */
-       if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == DC_ARRAY_2D_TILED_THIN1) {
-               unsigned int bankw, bankh, mtaspect, tile_split, num_banks;
-
-               bankw = AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
-               bankh = AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
-               mtaspect = AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
-               tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
-               num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
-
-               /* XXX fix me for VI */
-               tiling_info->gfx8.num_banks = num_banks;
-               tiling_info->gfx8.array_mode =
-                               DC_ARRAY_2D_TILED_THIN1;
-               tiling_info->gfx8.tile_split = tile_split;
-               tiling_info->gfx8.bank_width = bankw;
-               tiling_info->gfx8.bank_height = bankh;
-               tiling_info->gfx8.tile_aspect = mtaspect;
-               tiling_info->gfx8.tile_mode =
-                               DC_ADDR_SURF_MICRO_TILING_DISPLAY;
-       } else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE)
-                       == DC_ARRAY_1D_TILED_THIN1) {
-               tiling_info->gfx8.array_mode = DC_ARRAY_1D_TILED_THIN1;
-       }
-
-       tiling_info->gfx8.pipe_config =
-                       AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
-
-       if (adev->asic_type == CHIP_VEGA10 ||
-           adev->asic_type == CHIP_VEGA12 ||
-           adev->asic_type == CHIP_VEGA20 ||
-           adev->asic_type == CHIP_NAVI10 ||
-           adev->asic_type == CHIP_NAVI14 ||
-           adev->asic_type == CHIP_NAVI12 ||
-#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
-               adev->asic_type == CHIP_SIENNA_CICHLID ||
-               adev->asic_type == CHIP_NAVY_FLOUNDER ||
-#endif
-           adev->asic_type == CHIP_RENOIR ||
-           adev->asic_type == CHIP_RAVEN) {
-               /* Fill GFX9 params */
-               tiling_info->gfx9.num_pipes =
-                       adev->gfx.config.gb_addr_config_fields.num_pipes;
-               tiling_info->gfx9.num_banks =
-                       adev->gfx.config.gb_addr_config_fields.num_banks;
-               tiling_info->gfx9.pipe_interleave =
-                       adev->gfx.config.gb_addr_config_fields.pipe_interleave_size;
-               tiling_info->gfx9.num_shader_engines =
-                       adev->gfx.config.gb_addr_config_fields.num_se;
-               tiling_info->gfx9.max_compressed_frags =
-                       adev->gfx.config.gb_addr_config_fields.max_compress_frags;
-               tiling_info->gfx9.num_rb_per_se =
-                       adev->gfx.config.gb_addr_config_fields.num_rb_per_se;
-               tiling_info->gfx9.swizzle =
-                       AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE);
-               tiling_info->gfx9.shaderEnable = 1;
-
-#ifdef CONFIG_DRM_AMD_DC_DCN3_0
-               if (adev->asic_type == CHIP_SIENNA_CICHLID ||
-                   adev->asic_type == CHIP_NAVY_FLOUNDER)
-                       tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs;
-#endif
-               ret = fill_plane_dcc_attributes(adev, afb, format, rotation,
-                                               plane_size, tiling_info,
-                                               tiling_flags, dcc, address,
-                                               force_disable_dcc);
+       if (adev->family >= AMDGPU_FAMILY_AI) {
+               ret = fill_gfx9_plane_attributes_from_modifiers(adev, afb, format,
+                                                               rotation, plane_size,
+                                                               tiling_info, dcc,
+                                                               address,
+                                                               force_disable_dcc);
                if (ret)
                        return ret;
+       } else {
+               fill_gfx8_tiling_info_from_flags(tiling_info, tiling_flags);
        }
 
        return 0;
@@ -4122,7 +4607,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
                                    struct drm_crtc_state *crtc_state)
 {
        struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
-       struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
+       struct amdgpu_framebuffer *afb = (struct amdgpu_framebuffer *)plane_state->fb;
        struct dc_scaling_info scaling_info;
        struct dc_plane_info plane_info;
        int ret;
@@ -4139,10 +4624,10 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
 
        force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
        ret = fill_dc_plane_info_and_addr(adev, plane_state,
-                                         dm_plane_state->tiling_flags,
+                                         afb->tiling_flags,
                                          &plane_info,
                                          &dc_plane_state->address,
-                                         dm_plane_state->tmz_surface,
+                                         afb->tmz_surface,
                                          force_disable_dcc);
        if (ret)
                return ret;
@@ -4732,6 +5217,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                        if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0],
                                                  &dsc_caps,
                                                  aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override,
+                                                 0,
                                                  link_bandwidth_kbps,
                                                  &stream->timing,
                                                  &stream->timing.dsc_cfg))
@@ -5310,7 +5796,8 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
 
        dc_sink = to_amdgpu_dm_connector(connector)->dc_sink;
 
-       if (dc_sink == NULL) {
+       if (dc_sink == NULL && aconnector->base.force != DRM_FORCE_ON_DIGITAL &&
+                               aconnector->base.force != DRM_FORCE_ON) {
                DRM_ERROR("dc_sink is NULL!\n");
                goto fail;
        }
@@ -5416,6 +5903,8 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
        struct drm_crtc_state *new_crtc_state;
        int ret;
 
+       trace_amdgpu_dm_connector_atomic_check(new_con_state);
+
        if (!crtc)
                return 0;
 
@@ -5523,6 +6012,8 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
        struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
        int ret = -EINVAL;
 
+       trace_amdgpu_dm_crtc_atomic_check(crtc_state);
+
        dm_update_crtc_active_planes(crtc, crtc_state);
 
        if (unlikely(!dm_crtc_state->stream &&
@@ -5739,10 +6230,6 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane)
                dc_plane_state_retain(dm_plane_state->dc_state);
        }
 
-       /* Framebuffer hasn't been updated yet, so retain old flags. */
-       dm_plane_state->tiling_flags = old_dm_plane_state->tiling_flags;
-       dm_plane_state->tmz_surface = old_dm_plane_state->tmz_surface;
-
        return &dm_plane_state->base;
 }
 
@@ -5764,6 +6251,7 @@ static const struct drm_plane_funcs dm_plane_funcs = {
        .reset = dm_drm_plane_reset,
        .atomic_duplicate_state = dm_drm_plane_duplicate_state,
        .atomic_destroy_state = dm_drm_plane_destroy_state,
+       .format_mod_supported = dm_plane_format_mod_supported,
 };
 
 static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
@@ -5847,10 +6335,10 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
 
                fill_plane_buffer_attributes(
                        adev, afb, plane_state->format, plane_state->rotation,
-                       dm_plane_state_new->tiling_flags,
+                       afb->tiling_flags,
                        &plane_state->tiling_info, &plane_state->plane_size,
                        &plane_state->dcc, &plane_state->address,
-                       dm_plane_state_new->tmz_surface, force_disable_dcc);
+                       afb->tmz_surface, force_disable_dcc);
        }
 
        return 0;
@@ -5898,6 +6386,8 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
        struct drm_crtc_state *new_crtc_state;
        int ret;
 
+       trace_amdgpu_dm_plane_atomic_check(state);
+
        dm_plane_state = to_dm_plane_state(state);
 
        if (!dm_plane_state->dc_state)
@@ -5938,6 +6428,8 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane,
        struct drm_plane_state *old_state =
                drm_atomic_get_old_plane_state(new_state->state, plane);
 
+       trace_amdgpu_dm_atomic_update_cursor(new_state);
+
        swap(plane->state->fb, new_state->fb);
 
        plane->state->src_x = new_state->src_x;
@@ -6056,13 +6548,19 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
        int num_formats;
        int res = -EPERM;
        unsigned int supported_rotations;
+       uint64_t *modifiers = NULL;
 
        num_formats = get_plane_formats(plane, plane_cap, formats,
                                        ARRAY_SIZE(formats));
 
+       res = get_plane_modifiers(dm->adev, plane->type, &modifiers);
+       if (res)
+               return res;
+
        res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs,
                                       &dm_plane_funcs, formats, num_formats,
-                                      NULL, plane->type, NULL);
+                                      modifiers, plane->type, NULL);
+       kfree(modifiers);
        if (res)
                return res;
 
@@ -7109,6 +7607,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                struct drm_crtc *crtc = new_plane_state->crtc;
                struct drm_crtc_state *new_crtc_state;
                struct drm_framebuffer *fb = new_plane_state->fb;
+               struct amdgpu_framebuffer *afb = (struct amdgpu_framebuffer *)fb;
                bool plane_needs_flip;
                struct dc_plane_state *dc_plane;
                struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state);
@@ -7163,10 +7662,10 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 
                fill_dc_plane_info_and_addr(
                        dm->adev, new_plane_state,
-                       dm_new_plane_state->tiling_flags,
+                       afb->tiling_flags,
                        &bundle->plane_infos[planes_count],
                        &bundle->flip_addrs[planes_count].address,
-                       dm_new_plane_state->tmz_surface, false);
+                       afb->tmz_surface, false);
 
                DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n",
                                 new_plane_state->plane->index,
@@ -7501,6 +8000,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
        int crtc_disable_count = 0;
        bool mode_set_reset_required = false;
 
+       trace_amdgpu_dm_atomic_commit_tail_begin(state);
+
        drm_atomic_helper_update_legacy_modeset_state(dev, state);
        drm_atomic_helper_calc_timestamping_constants(state);
 
@@ -8306,8 +8807,7 @@ static bool should_reset_plane(struct drm_atomic_state *state,
         * TODO: Come up with a more elegant solution for this.
         */
        for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) {
-               struct dm_plane_state *old_dm_plane_state, *new_dm_plane_state;
-
+               struct amdgpu_framebuffer *old_afb, *new_afb;
                if (other->type == DRM_PLANE_TYPE_CURSOR)
                        continue;
 
@@ -8351,12 +8851,12 @@ static bool should_reset_plane(struct drm_atomic_state *state,
                if (old_other_state->fb->format != new_other_state->fb->format)
                        return true;
 
-               old_dm_plane_state = to_dm_plane_state(old_other_state);
-               new_dm_plane_state = to_dm_plane_state(new_other_state);
+               old_afb = (struct amdgpu_framebuffer *)old_other_state->fb;
+               new_afb = (struct amdgpu_framebuffer *)new_other_state->fb;
 
                /* Tiling and DCC changes also require bandwidth updates. */
-               if (old_dm_plane_state->tiling_flags !=
-                   new_dm_plane_state->tiling_flags)
+               if (old_afb->tiling_flags != new_afb->tiling_flags ||
+                   old_afb->base.modifier != new_afb->base.modifier)
                        return true;
        }
 
@@ -8587,8 +9087,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        enum dc_status status;
        int ret, i;
        bool lock_and_validation_needed = false;
+       struct dm_crtc_state *dm_old_crtc_state;
 
-       amdgpu_check_debugfs_connector_property_change(adev, state);
+       trace_amdgpu_dm_atomic_check_begin(state);
 
        ret = drm_atomic_helper_check_modeset(dev, state);
        if (ret)
@@ -8629,9 +9130,12 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        }
 #endif
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
+
                if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
                    !new_crtc_state->color_mgmt_changed &&
-                   old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)
+                   old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled &&
+                       dm_old_crtc_state->dsc_force_changed == false)
                        continue;
 
                if (!new_crtc_state->enable)
@@ -8682,17 +9186,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                }
        }
 
-       /* Prepass for updating tiling flags on new planes. */
-       for_each_new_plane_in_state(state, plane, new_plane_state, i) {
-               struct dm_plane_state *new_dm_plane_state = to_dm_plane_state(new_plane_state);
-               struct amdgpu_framebuffer *new_afb = to_amdgpu_framebuffer(new_plane_state->fb);
-
-               ret = get_fb_info(new_afb, &new_dm_plane_state->tiling_flags,
-                                 &new_dm_plane_state->tmz_surface);
-               if (ret)
-                       goto fail;
-       }
-
        /* Remove exiting planes if they are modified */
        for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
                ret = dm_update_plane_state(dc, state, plane,
@@ -8886,6 +9379,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
        /* Must be success */
        WARN_ON(ret);
+
+       trace_amdgpu_dm_atomic_check_finish(state, ret);
+
        return ret;
 
 fail:
@@ -8896,6 +9392,8 @@ fail:
        else
                DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
 
+       trace_amdgpu_dm_atomic_check_finish(state, ret);
+
        return ret;
 }
 
@@ -9160,3 +9658,41 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev)
        }
        mutex_unlock(&adev->dm.dc_lock);
 }
+
+void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
+                      uint32_t value, const char *func_name)
+{
+#ifdef DM_CHECK_ADDR_0
+       if (address == 0) {
+               DC_ERR("invalid register write. address = 0");
+               return;
+       }
+#endif
+       cgs_write_register(ctx->cgs_device, address, value);
+       trace_amdgpu_dc_wreg(&ctx->perf_trace->write_count, address, value);
+}
+
+uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
+                         const char *func_name)
+{
+       uint32_t value;
+#ifdef DM_CHECK_ADDR_0
+       if (address == 0) {
+               DC_ERR("invalid register read; address = 0\n");
+               return 0;
+       }
+#endif
+
+       if (ctx->dmub_srv &&
+           ctx->dmub_srv->reg_helper_offload.gather_in_progress &&
+           !ctx->dmub_srv->reg_helper_offload.should_burst_write) {
+               ASSERT(false);
+               return 0;
+       }
+
+       value = cgs_read_register(ctx->cgs_device, address);
+
+       trace_amdgpu_dc_rreg(&ctx->perf_trace->read_count, address, value);
+
+       return value;
+}