Merge tag 'amd-drm-next-5.10-2020-09-03' of git://people.freedesktop.org/~agd5f/linux...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index df93382..ec29376 100644 (file)
@@ -127,6 +127,42 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU);
 static int amdgpu_dm_init(struct amdgpu_device *adev);
 static void amdgpu_dm_fini(struct amdgpu_device *adev);
 
+static enum drm_mode_subconnector get_subconnector_type(struct dc_link *link)
+{
+       switch (link->dpcd_caps.dongle_type) {
+       case DISPLAY_DONGLE_NONE:
+               return DRM_MODE_SUBCONNECTOR_Native;
+       case DISPLAY_DONGLE_DP_VGA_CONVERTER:
+               return DRM_MODE_SUBCONNECTOR_VGA;
+       case DISPLAY_DONGLE_DP_DVI_CONVERTER:
+       case DISPLAY_DONGLE_DP_DVI_DONGLE:
+               return DRM_MODE_SUBCONNECTOR_DVID;
+       case DISPLAY_DONGLE_DP_HDMI_CONVERTER:
+       case DISPLAY_DONGLE_DP_HDMI_DONGLE:
+               return DRM_MODE_SUBCONNECTOR_HDMIA;
+       case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE:
+       default:
+               return DRM_MODE_SUBCONNECTOR_Unknown;
+       }
+}
+
+static void update_subconnector_property(struct amdgpu_dm_connector *aconnector)
+{
+       struct dc_link *link = aconnector->dc_link;
+       struct drm_connector *connector = &aconnector->base;
+       enum drm_mode_subconnector subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
+
+       if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
+               return;
+
+       if (aconnector->dc_sink)
+               subconnector = get_subconnector_type(link);
+
+       drm_object_property_set_value(&connector->base,
+                       connector->dev->mode_config.dp_subconnector_property,
+                       subconnector);
+}
+
 /*
  * initializes drm_device display related structures, based on the information
  * provided by DAL. The drm strcutures are: drm_crtc, drm_connector,
@@ -171,7 +207,7 @@ static void amdgpu_dm_set_psr_caps(struct dc_link *link);
 static bool amdgpu_dm_psr_enable(struct dc_stream_state *stream);
 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);
 
 /*
  * dm_vblank_get_counter
@@ -268,7 +304,7 @@ static struct amdgpu_crtc *
 get_crtc_by_otg_inst(struct amdgpu_device *adev,
                     int otg_inst)
 {
-       struct drm_device *dev = adev->ddev;
+       struct drm_device *dev = adev_to_drm(adev);
        struct drm_crtc *crtc;
        struct amdgpu_crtc *amdgpu_crtc;
 
@@ -320,7 +356,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
                return;
        }
 
-       spin_lock_irqsave(&adev->ddev->event_lock, flags);
+       spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
 
        if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
                DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n",
@@ -328,7 +364,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
                                                 AMDGPU_FLIP_SUBMITTED,
                                                 amdgpu_crtc->crtc_id,
                                                 amdgpu_crtc);
-               spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+               spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
                return;
        }
 
@@ -380,7 +416,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
                e->sequence = drm_crtc_vblank_count(&amdgpu_crtc->base);
                e->pipe = amdgpu_crtc->crtc_id;
 
-               list_add_tail(&e->base.link, &adev->ddev->vblank_event_list);
+               list_add_tail(&e->base.link, &adev_to_drm(adev)->vblank_event_list);
                e = NULL;
        }
 
@@ -393,7 +429,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
                amdgpu_get_vblank_counter_kms(&amdgpu_crtc->base);
 
        amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
-       spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+       spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 
        DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_NONE, vrr[%d]-fp %d\n",
                         amdgpu_crtc->crtc_id, amdgpu_crtc,
@@ -429,7 +465,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
                        /* BTR processing for pre-DCE12 ASICs */
                        if (acrtc_state->stream &&
                            adev->family < AMDGPU_FAMILY_AI) {
-                               spin_lock_irqsave(&adev->ddev->event_lock, flags);
+                               spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
                                mod_freesync_handle_v_update(
                                    adev->dm.freesync_module,
                                    acrtc_state->stream,
@@ -439,7 +475,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
                                    adev->dm.dc,
                                    acrtc_state->stream,
                                    &acrtc_state->vrr_params.adjust);
-                               spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+                               spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
                        }
                }
        }
@@ -489,7 +525,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
        if (adev->family < AMDGPU_FAMILY_AI)
                return;
 
-       spin_lock_irqsave(&adev->ddev->event_lock, flags);
+       spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
 
        if (acrtc_state->stream && acrtc_state->vrr_params.supported &&
            acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
@@ -522,7 +558,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
                acrtc->pflip_status = AMDGPU_FLIP_NONE;
        }
 
-       spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+       spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 }
 
 static int dm_set_clockgating_state(void *handle,
@@ -544,7 +580,7 @@ static int dm_early_init(void* handle);
 static void amdgpu_dm_fbc_init(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct dm_comressor_info *compressor = &adev->dm.compressor;
        struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(connector);
        struct drm_display_mode *mode;
@@ -586,7 +622,7 @@ static int amdgpu_dm_audio_component_get_eld(struct device *kdev, int port,
                                          unsigned char *buf, int max_bytes)
 {
        struct drm_device *dev = dev_get_drvdata(kdev);
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct drm_connector *connector;
        struct drm_connector_list_iter conn_iter;
        struct amdgpu_dm_connector *aconnector;
@@ -625,7 +661,7 @@ static int amdgpu_dm_audio_component_bind(struct device *kdev,
                                       struct device *hda_kdev, void *data)
 {
        struct drm_device *dev = dev_get_drvdata(kdev);
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct drm_audio_component *acomp = data;
 
        acomp->ops = &amdgpu_dm_audio_component_ops;
@@ -639,7 +675,7 @@ static void amdgpu_dm_audio_component_unbind(struct device *kdev,
                                          struct device *hda_kdev, void *data)
 {
        struct drm_device *dev = dev_get_drvdata(kdev);
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct drm_audio_component *acomp = data;
 
        acomp->ops = NULL;
@@ -850,7 +886,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 #endif
        int r;
 
-       adev->dm.ddev = adev->ddev;
+       adev->dm.ddev = adev_to_drm(adev);
        adev->dm.adev = adev;
 
        /* Zero all the fields */
@@ -986,10 +1022,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        /* TODO: Add_display_info? */
 
        /* TODO use dynamic cursor width */
-       adev->ddev->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size;
-       adev->ddev->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size;
+       adev_to_drm(adev)->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size;
+       adev_to_drm(adev)->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size;
 
-       if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) {
+       if (drm_vblank_init(adev_to_drm(adev), adev->dm.display_indexes_num)) {
                DRM_ERROR(
                "amdgpu: failed to initialize sw for display support.\n");
                goto error;
@@ -1066,6 +1102,12 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
        const struct dmcu_firmware_header_v1_0 *hdr;
 
        switch(adev->asic_type) {
+#if defined(CONFIG_DRM_AMD_DC_SI)
+       case CHIP_TAHITI:
+       case CHIP_PITCAIRN:
+       case CHIP_VERDE:
+       case CHIP_OLAND:
+#endif
        case CHIP_BONAIRE:
        case CHIP_HAWAII:
        case CHIP_KAVERI:
@@ -1384,7 +1426,7 @@ static int dm_late_init(void *handle)
        bool ret = true;
 
        if (!adev->dm.fw_dmcu && !adev->dm.dmub_fw)
-               return detect_mst_link_for_all_connectors(adev->ddev);
+               return detect_mst_link_for_all_connectors(adev_to_drm(adev));
 
        dmcu = adev->dm.dc->res_pool->dmcu;
 
@@ -1409,12 +1451,12 @@ static int dm_late_init(void *handle)
        if (dmcu)
                ret = dmcu_load_iram(dmcu, params);
        else if (adev->dm.dc->ctx->dmub_srv)
-               ret = dmub_init_abm_config(adev->dm.dc->res_pool->abm, params);
+               ret = dmub_init_abm_config(adev->dm.dc->res_pool, params);
 
        if (!ret)
                return -EINVAL;
 
-       return detect_mst_link_for_all_connectors(adev->ddev);
+       return detect_mst_link_for_all_connectors(adev_to_drm(adev));
 }
 
 static void s3_handle_mst(struct drm_device *dev, bool suspend)
@@ -1652,7 +1694,7 @@ static int dm_suspend(void *handle)
        struct amdgpu_display_manager *dm = &adev->dm;
        int ret = 0;
 
-       if (adev->in_gpu_reset) {
+       if (amdgpu_in_reset(adev)) {
                mutex_lock(&dm->dc_lock);
                dm->cached_dc_state = dc_copy_state(dm->dc->current_state);
 
@@ -1666,9 +1708,9 @@ static int dm_suspend(void *handle)
        }
 
        WARN_ON(adev->dm.cached_state);
-       adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev);
+       adev->dm.cached_state = drm_atomic_helper_suspend(adev_to_drm(adev));
 
-       s3_handle_mst(adev->ddev, true);
+       s3_handle_mst(adev_to_drm(adev), true);
 
        amdgpu_dm_irq_suspend(adev);
 
@@ -1822,7 +1864,7 @@ cleanup:
 static int dm_resume(void *handle)
 {
        struct amdgpu_device *adev = handle;
-       struct drm_device *ddev = adev->ddev;
+       struct drm_device *ddev = adev_to_drm(adev);
        struct amdgpu_display_manager *dm = &adev->dm;
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
@@ -1838,7 +1880,7 @@ static int dm_resume(void *handle)
        struct dc_state *dc_state;
        int i, r, j;
 
-       if (adev->in_gpu_reset) {
+       if (amdgpu_in_reset(adev)) {
                dc_state = dm->cached_dc_state;
 
                r = dm_dmub_hw_init(adev);
@@ -2044,7 +2086,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
                return;
 
        conn_base = &aconnector->base;
-       adev = conn_base->dev->dev_private;
+       adev = drm_to_adev(conn_base->dev);
        dm = &adev->dm;
        caps = &dm->backlight_caps;
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
@@ -2095,7 +2137,6 @@ void amdgpu_dm_update_connector_after_detect(
        if (aconnector->mst_mgr.mst_state == true)
                return;
 
-
        sink = aconnector->dc_link->local_sink;
        if (sink)
                dc_sink_retain(sink);
@@ -2222,6 +2263,8 @@ void amdgpu_dm_update_connector_after_detect(
 
        mutex_unlock(&dev->mode_config.mutex);
 
+       update_subconnector_property(aconnector);
+
        if (sink)
                dc_sink_release(sink);
 }
@@ -2233,7 +2276,7 @@ static void handle_hpd_irq(void *param)
        struct drm_device *dev = connector->dev;
        enum dc_connection_type new_connection_type = dc_connection_none;
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
 #endif
 
        /*
@@ -2366,7 +2409,7 @@ static void handle_hpd_rx_irq(void *param)
        enum dc_connection_type new_connection_type = dc_connection_none;
 #ifdef CONFIG_DRM_AMD_DC_HDCP
        union hpd_irq_data hpd_irq_data;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
 
        memset(&hpd_irq_data, 0, sizeof(hpd_irq_data));
 #endif
@@ -2437,7 +2480,7 @@ static void handle_hpd_rx_irq(void *param)
 
 static void register_hpd_handlers(struct amdgpu_device *adev)
 {
-       struct drm_device *dev = adev->ddev;
+       struct drm_device *dev = adev_to_drm(adev);
        struct drm_connector *connector;
        struct amdgpu_dm_connector *aconnector;
        const struct dc_link *dc_link;
@@ -2474,6 +2517,89 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
        }
 }
 
+#if defined(CONFIG_DRM_AMD_DC_SI)
+/* Register IRQ sources and initialize IRQ callbacks */
+static int dce60_register_irq_handlers(struct amdgpu_device *adev)
+{
+       struct dc *dc = adev->dm.dc;
+       struct common_irq_params *c_irq_params;
+       struct dc_interrupt_params int_params = {0};
+       int r;
+       int i;
+       unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+
+       int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+       int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+
+       /*
+        * Actions of amdgpu_irq_add_id():
+        * 1. Register a set() function with base driver.
+        *    Base driver will call set() function to enable/disable an
+        *    interrupt in DC hardware.
+        * 2. Register amdgpu_dm_irq_handler().
+        *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
+        *    coming from DC hardware.
+        *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
+        *    for acknowledging and handling. */
+
+       /* Use VBLANK interrupt */
+       for (i = 0; i < adev->mode_info.num_crtc; i++) {
+               r = amdgpu_irq_add_id(adev, client_id, i+1 , &adev->crtc_irq);
+               if (r) {
+                       DRM_ERROR("Failed to add crtc irq id!\n");
+                       return r;
+               }
+
+               int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+               int_params.irq_source =
+                       dc_interrupt_to_irq_source(dc, i+1 , 0);
+
+               c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
+
+               c_irq_params->adev = adev;
+               c_irq_params->irq_src = int_params.irq_source;
+
+               amdgpu_dm_irq_register_interrupt(adev, &int_params,
+                               dm_crtc_high_irq, c_irq_params);
+       }
+
+       /* Use GRPH_PFLIP interrupt */
+       for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP;
+                       i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) {
+               r = amdgpu_irq_add_id(adev, client_id, i, &adev->pageflip_irq);
+               if (r) {
+                       DRM_ERROR("Failed to add page flip irq id!\n");
+                       return r;
+               }
+
+               int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+               int_params.irq_source =
+                       dc_interrupt_to_irq_source(dc, i, 0);
+
+               c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST];
+
+               c_irq_params->adev = adev;
+               c_irq_params->irq_src = int_params.irq_source;
+
+               amdgpu_dm_irq_register_interrupt(adev, &int_params,
+                               dm_pflip_high_irq, c_irq_params);
+
+       }
+
+       /* HPD */
+       r = amdgpu_irq_add_id(adev, client_id,
+                       VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, &adev->hpd_irq);
+       if (r) {
+               DRM_ERROR("Failed to add hpd irq id!\n");
+               return r;
+       }
+
+       register_hpd_handlers(adev);
+
+       return 0;
+}
+#endif
+
 /* Register IRQ sources and initialize IRQ callbacks */
 static int dce110_register_irq_handlers(struct amdgpu_device *adev)
 {
@@ -2704,7 +2830,7 @@ static int dm_atomic_get_state(struct drm_atomic_state *state,
                               struct dm_atomic_state **dm_state)
 {
        struct drm_device *dev = state->dev;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct amdgpu_display_manager *dm = &adev->dm;
        struct drm_private_state *priv_state;
 
@@ -2724,7 +2850,7 @@ static struct dm_atomic_state *
 dm_atomic_get_new_state(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct amdgpu_display_manager *dm = &adev->dm;
        struct drm_private_obj *obj;
        struct drm_private_state *new_obj_state;
@@ -2738,24 +2864,6 @@ dm_atomic_get_new_state(struct drm_atomic_state *state)
        return NULL;
 }
 
-static struct dm_atomic_state *
-dm_atomic_get_old_state(struct drm_atomic_state *state)
-{
-       struct drm_device *dev = state->dev;
-       struct amdgpu_device *adev = dev->dev_private;
-       struct amdgpu_display_manager *dm = &adev->dm;
-       struct drm_private_obj *obj;
-       struct drm_private_state *old_obj_state;
-       int i;
-
-       for_each_old_private_obj_in_state(state, obj, old_obj_state, i) {
-               if (obj->funcs == dm->atomic_obj.funcs)
-                       return to_dm_atomic_state(old_obj_state);
-       }
-
-       return NULL;
-}
-
 static struct drm_private_state *
 dm_atomic_duplicate_state(struct drm_private_obj *obj)
 {
@@ -2803,18 +2911,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
 
        adev->mode_info.mode_config_initialized = true;
 
-       adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs;
-       adev->ddev->mode_config.helper_private = &amdgpu_dm_mode_config_helperfuncs;
+       adev_to_drm(adev)->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs;
+       adev_to_drm(adev)->mode_config.helper_private = &amdgpu_dm_mode_config_helperfuncs;
 
-       adev->ddev->mode_config.max_width = 16384;
-       adev->ddev->mode_config.max_height = 16384;
+       adev_to_drm(adev)->mode_config.max_width = 16384;
+       adev_to_drm(adev)->mode_config.max_height = 16384;
 
-       adev->ddev->mode_config.preferred_depth = 24;
-       adev->ddev->mode_config.prefer_shadow = 1;
+       adev_to_drm(adev)->mode_config.preferred_depth = 24;
+       adev_to_drm(adev)->mode_config.prefer_shadow = 1;
        /* indicates support for immediate flip */
-       adev->ddev->mode_config.async_page_flip = true;
+       adev_to_drm(adev)->mode_config.async_page_flip = true;
 
-       adev->ddev->mode_config.fb_base = adev->gmc.aper_base;
+       adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
 
        state = kzalloc(sizeof(*state), GFP_KERNEL);
        if (!state)
@@ -2828,18 +2936,24 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
 
        dc_resource_state_copy_construct_current(adev->dm.dc, state->context);
 
-       drm_atomic_private_obj_init(adev->ddev,
+       drm_atomic_private_obj_init(adev_to_drm(adev),
                                    &adev->dm.atomic_obj,
                                    &state->base,
                                    &dm_atomic_state_funcs);
 
        r = amdgpu_display_modeset_create_props(adev);
-       if (r)
+       if (r) {
+               dc_release_state(state->context);
+               kfree(state);
                return r;
+       }
 
        r = amdgpu_dm_audio_init(adev);
-       if (r)
+       if (r) {
+               dc_release_state(state->context);
+               kfree(state);
                return r;
+       }
 
        return 0;
 }
@@ -2856,6 +2970,8 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)
 #if defined(CONFIG_ACPI)
        struct amdgpu_dm_backlight_caps caps;
 
+       memset(&caps, 0, sizeof(caps));
+
        if (dm->backlight_caps.caps_valid)
                return;
 
@@ -2894,51 +3010,50 @@ static int set_backlight_via_aux(struct dc_link *link, uint32_t brightness)
        return rc ? 0 : 1;
 }
 
-static u32 convert_brightness(const struct amdgpu_dm_backlight_caps *caps,
-                             const uint32_t user_brightness)
+static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
+                               unsigned *min, unsigned *max)
 {
-       u32 min, max, conversion_pace;
-       u32 brightness = user_brightness;
-
        if (!caps)
-               goto out;
+               return 0;
 
-       if (!caps->aux_support) {
-               max = caps->max_input_signal;
-               min = caps->min_input_signal;
-               /*
-                * The brightness input is in the range 0-255
-                * It needs to be rescaled to be between the
-                * requested min and max input signal
-                * It also needs to be scaled up by 0x101 to
-                * match the DC interface which has a range of
-                * 0 to 0xffff
-                */
-               conversion_pace = 0x101;
-               brightness =
-                       user_brightness
-                       * conversion_pace
-                       * (max - min)
-                       / AMDGPU_MAX_BL_LEVEL
-                       + min * conversion_pace;
+       if (caps->aux_support) {
+               // Firmware limits are in nits, DC API wants millinits.
+               *max = 1000 * caps->aux_max_input_signal;
+               *min = 1000 * caps->aux_min_input_signal;
        } else {
-               /* TODO
-                * We are doing a linear interpolation here, which is OK but
-                * does not provide the optimal result. We probably want
-                * something close to the Perceptual Quantizer (PQ) curve.
-                */
-               max = caps->aux_max_input_signal;
-               min = caps->aux_min_input_signal;
-
-               brightness = (AMDGPU_MAX_BL_LEVEL - user_brightness) * min
-                              + user_brightness * max;
-               // Multiple the value by 1000 since we use millinits
-               brightness *= 1000;
-               brightness = DIV_ROUND_CLOSEST(brightness, AMDGPU_MAX_BL_LEVEL);
+               // Firmware limits are 8-bit, PWM control is 16-bit.
+               *max = 0x101 * caps->max_input_signal;
+               *min = 0x101 * caps->min_input_signal;
        }
+       return 1;
+}
+
+static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
+                                       uint32_t brightness)
+{
+       unsigned min, max;
+
+       if (!get_brightness_range(caps, &min, &max))
+               return brightness;
+
+       // Rescale 0..255 to min..max
+       return min + DIV_ROUND_CLOSEST((max - min) * brightness,
+                                      AMDGPU_MAX_BL_LEVEL);
+}
+
+static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
+                                     uint32_t brightness)
+{
+       unsigned min, max;
 
-out:
-       return brightness;
+       if (!get_brightness_range(caps, &min, &max))
+               return brightness;
+
+       if (brightness < min)
+               return 0;
+       // Rescale min..max to 0..255
+       return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min),
+                                max - min);
 }
 
 static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
@@ -2954,7 +3069,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
 
        link = (struct dc_link *)dm->backlight_link;
 
-       brightness = convert_brightness(&caps, bd->props.brightness);
+       brightness = convert_brightness_from_user(&caps, bd->props.brightness);
        // Change brightness based on AUX property
        if (caps.aux_support)
                return set_backlight_via_aux(link, brightness);
@@ -2971,7 +3086,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
 
        if (ret == DC_ERROR_UNEXPECTED)
                return bd->props.brightness;
-       return ret;
+       return convert_brightness_to_user(&dm->backlight_caps, ret);
 }
 
 static const struct backlight_ops amdgpu_dm_backlight_ops = {
@@ -2993,13 +3108,13 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
        props.type = BACKLIGHT_RAW;
 
        snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
-                       dm->adev->ddev->primary->index);
+                adev_to_drm(dm->adev)->primary->index);
 
        dm->backlight_dev = backlight_device_register(bl_name,
-                       dm->adev->ddev->dev,
-                       dm,
-                       &amdgpu_dm_backlight_ops,
-                       &props);
+                                                     adev_to_drm(dm->adev)->dev,
+                                                     dm,
+                                                     &amdgpu_dm_backlight_ops,
+                                                     &props);
 
        if (IS_ERR(dm->backlight_dev))
                DRM_ERROR("DM: Backlight registration failed!\n");
@@ -3205,6 +3320,17 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
 
        /* Software is initialized. Now we can register interrupt handlers. */
        switch (adev->asic_type) {
+#if defined(CONFIG_DRM_AMD_DC_SI)
+       case CHIP_TAHITI:
+       case CHIP_PITCAIRN:
+       case CHIP_VERDE:
+       case CHIP_OLAND:
+               if (dce60_register_irq_handlers(dm->adev)) {
+                       DRM_ERROR("DM: Failed to initialize IRQ\n");
+                       goto fail;
+               }
+               break;
+#endif
        case CHIP_BONAIRE:
        case CHIP_HAWAII:
        case CHIP_KAVERI:
@@ -3305,14 +3431,14 @@ static ssize_t s3_debug_store(struct device *device,
        int ret;
        int s3_state;
        struct drm_device *drm_dev = dev_get_drvdata(device);
-       struct amdgpu_device *adev = drm_dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(drm_dev);
 
        ret = kstrtoint(buf, 0, &s3_state);
 
        if (ret == 0) {
                if (s3_state) {
                        dm_resume(adev);
-                       drm_kms_helper_hotplug_event(adev->ddev);
+                       drm_kms_helper_hotplug_event(adev_to_drm(adev));
                } else
                        dm_suspend(adev);
        }
@@ -3329,6 +3455,20 @@ static int dm_early_init(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        switch (adev->asic_type) {
+#if defined(CONFIG_DRM_AMD_DC_SI)
+       case CHIP_TAHITI:
+       case CHIP_PITCAIRN:
+       case CHIP_VERDE:
+               adev->mode_info.num_crtc = 6;
+               adev->mode_info.num_hpd = 6;
+               adev->mode_info.num_dig = 6;
+               break;
+       case CHIP_OLAND:
+               adev->mode_info.num_crtc = 2;
+               adev->mode_info.num_hpd = 2;
+               adev->mode_info.num_dig = 2;
+               break;
+#endif
        case CHIP_BONAIRE:
        case CHIP_HAWAII:
                adev->mode_info.num_crtc = 6;
@@ -3425,7 +3565,7 @@ static int dm_early_init(void *handle)
         */
 #if defined(CONFIG_DEBUG_KERNEL_DC)
        device_create_file(
-               adev->ddev->dev,
+               adev_to_drm(adev)->dev,
                &dev_attr_s3_debug);
 #endif
 
@@ -3436,21 +3576,12 @@ static bool modeset_required(struct drm_crtc_state *crtc_state,
                             struct dc_stream_state *new_stream,
                             struct dc_stream_state *old_stream)
 {
-       if (!drm_atomic_crtc_needs_modeset(crtc_state))
-               return false;
-
-       if (!crtc_state->enable)
-               return false;
-
-       return crtc_state->active;
+       return crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state);
 }
 
 static bool modereset_required(struct drm_crtc_state *crtc_state)
 {
-       if (!drm_atomic_crtc_needs_modeset(crtc_state))
-               return false;
-
-       return !crtc_state->enable || !crtc_state->active;
+       return !crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state);
 }
 
 static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder)
@@ -3523,8 +3654,17 @@ static int fill_dc_scaling_info(const struct drm_plane_state *state,
 static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,
                       uint64_t *tiling_flags, bool *tmz_surface)
 {
-       struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]);
-       int r = amdgpu_bo_reserve(rbo, false);
+       struct amdgpu_bo *rbo;
+       int r;
+
+       if (!amdgpu_fb) {
+               *tiling_flags = 0;
+               *tmz_surface = false;
+               return 0;
+       }
+
+       rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]);
+       r = amdgpu_bo_reserve(rbo, false);
 
        if (unlikely(r)) {
                /* Don't show error message when returning -ERESTARTSYS */
@@ -3947,13 +4087,10 @@ 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);
-       const struct amdgpu_framebuffer *amdgpu_fb =
-               to_amdgpu_framebuffer(plane_state->fb);
+       struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
        struct dc_scaling_info scaling_info;
        struct dc_plane_info plane_info;
-       uint64_t tiling_flags;
        int ret;
-       bool tmz_surface = false;
        bool force_disable_dcc = false;
 
        ret = fill_dc_scaling_info(plane_state, &scaling_info);
@@ -3965,15 +4102,12 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
        dc_plane_state->clip_rect = scaling_info.clip_rect;
        dc_plane_state->scaling_quality = scaling_info.scaling_quality;
 
-       ret = get_fb_info(amdgpu_fb, &tiling_flags, &tmz_surface);
-       if (ret)
-               return ret;
-
        force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
-       ret = fill_dc_plane_info_and_addr(adev, plane_state, tiling_flags,
+       ret = fill_dc_plane_info_and_addr(adev, plane_state,
+                                         dm_plane_state->tiling_flags,
                                          &plane_info,
                                          &dc_plane_state->address,
-                                         tmz_surface,
+                                         dm_plane_state->tmz_surface,
                                          force_disable_dcc);
        if (ret)
                return ret;
@@ -4555,7 +4689,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                                                             dc_link_get_link_cap(aconnector->dc_link));
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-               if (dsc_caps.is_dsc_supported)
+               if (dsc_caps.is_dsc_supported) {
+                       /* Set DSC policy according to dsc_clock_en */
+                       dc_dsc_policy_set_enable_dsc_when_not_needed(aconnector->dsc_settings.dsc_clock_en);
+
                        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,
@@ -4563,6 +4700,21 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                                                  &stream->timing,
                                                  &stream->timing.dsc_cfg))
                                stream->timing.flags.DSC = 1;
+                       /* Overwrite the stream flag if DSC is enabled through debugfs */
+                       if (aconnector->dsc_settings.dsc_clock_en)
+                               stream->timing.flags.DSC = 1;
+
+                       if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_width)
+                               stream->timing.dsc_cfg.num_slices_h = DIV_ROUND_UP(stream->timing.h_addressable,
+                                                                       aconnector->dsc_settings.dsc_slice_width);
+
+                       if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_height)
+                               stream->timing.dsc_cfg.num_slices_v = DIV_ROUND_UP(stream->timing.v_addressable,
+                                                                       aconnector->dsc_settings.dsc_slice_height);
+
+                       if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel)
+                               stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel;
+               }
 #endif
        }
 
@@ -4576,7 +4728,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
        update_stream_signal(stream, sink);
 
        if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
-               mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket, false, false);
+               mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket);
+
        if (stream->link->psr_settings.psr_feature_enabled) {
                //
                // should decide stream support vsc sdp colorimetry capability
@@ -4674,7 +4827,7 @@ static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
 {
        enum dc_irq_source irq_source;
        struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(crtc->dev);
        int rc;
 
        irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst;
@@ -4690,7 +4843,7 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
 {
        enum dc_irq_source irq_source;
        struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(crtc->dev);
        struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
        int rc = 0;
 
@@ -4757,6 +4910,8 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
        else
                connected = (aconnector->base.force == DRM_FORCE_ON);
 
+       update_subconnector_property(aconnector);
+
        return (connected ? connector_status_connected :
                        connector_status_disconnected);
 }
@@ -4767,7 +4922,7 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
                                            uint64_t val)
 {
        struct drm_device *dev = connector->dev;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct dm_connector_state *dm_old_state =
                to_dm_connector_state(connector->state);
        struct dm_connector_state *dm_new_state =
@@ -4822,7 +4977,7 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
                                            uint64_t *val)
 {
        struct drm_device *dev = connector->dev;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct dm_connector_state *dm_state =
                to_dm_connector_state(state);
        int ret = -EINVAL;
@@ -4872,9 +5027,10 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
 {
        struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
        const struct dc_link *link = aconnector->dc_link;
-       struct amdgpu_device *adev = connector->dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(connector->dev);
        struct amdgpu_display_manager *dm = &adev->dm;
 
+       drm_atomic_private_obj_fini(&aconnector->mst_mgr.base);
 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
        defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
 
@@ -5057,7 +5213,7 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                                const struct dc_stream_state *old_stream)
 {
        struct drm_connector *connector = &aconnector->base;
-       struct amdgpu_device *adev = connector->dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(connector->dev);
        struct dc_stream_state *stream;
        const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL;
        int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8;
@@ -5334,7 +5490,7 @@ static void dm_update_crtc_active_planes(struct drm_crtc *crtc,
 static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
                                       struct drm_crtc_state *state)
 {
-       struct amdgpu_device *adev = crtc->dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(crtc->dev);
        struct dc *dc = adev->dm.dc;
        struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state);
        int ret = -EINVAL;
@@ -5554,6 +5710,10 @@ 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;
 }
 
@@ -5588,14 +5748,8 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
        struct list_head list;
        struct ttm_validate_buffer tv;
        struct ww_acquire_ctx ticket;
-       uint64_t tiling_flags;
        uint32_t domain;
        int r;
-       bool tmz_surface = false;
-       bool force_disable_dcc = false;
-
-       dm_plane_state_old = to_dm_plane_state(plane->state);
-       dm_plane_state_new = to_dm_plane_state(new_state);
 
        if (!new_state->fb) {
                DRM_DEBUG_DRIVER("No FB bound\n");
@@ -5639,27 +5793,35 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
                return r;
        }
 
-       amdgpu_bo_get_tiling_flags(rbo, &tiling_flags);
-
-       tmz_surface = amdgpu_bo_encrypted(rbo);
-
        ttm_eu_backoff_reservation(&ticket, &list);
 
        afb->address = amdgpu_bo_gpu_offset(rbo);
 
        amdgpu_bo_ref(rbo);
 
+       /**
+        * We don't do surface updates on planes that have been newly created,
+        * but we also don't have the afb->address during atomic check.
+        *
+        * Fill in buffer attributes depending on the address here, but only on
+        * newly created planes since they're not being used by DC yet and this
+        * won't modify global state.
+        */
+       dm_plane_state_old = to_dm_plane_state(plane->state);
+       dm_plane_state_new = to_dm_plane_state(new_state);
+
        if (dm_plane_state_new->dc_state &&
-                       dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
-               struct dc_plane_state *plane_state = dm_plane_state_new->dc_state;
+           dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
+               struct dc_plane_state *plane_state =
+                       dm_plane_state_new->dc_state;
+               bool force_disable_dcc = !plane_state->dcc.enable;
 
-               force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
                fill_plane_buffer_attributes(
                        adev, afb, plane_state->format, plane_state->rotation,
-                       tiling_flags, &plane_state->tiling_info,
-                       &plane_state->plane_size, &plane_state->dcc,
-                       &plane_state->address, tmz_surface,
-                       force_disable_dcc);
+                       dm_plane_state_new->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);
        }
 
        return 0;
@@ -5700,7 +5862,7 @@ static int dm_plane_helper_check_state(struct drm_plane_state *state,
 static int dm_plane_atomic_check(struct drm_plane *plane,
                                 struct drm_plane_state *state)
 {
-       struct amdgpu_device *adev = plane->dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(plane->dev);
        struct dc *dc = adev->dm.dc;
        struct dm_plane_state *dm_plane_state;
        struct dc_scaling_info scaling_info;
@@ -5869,7 +6031,7 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
        num_formats = get_plane_formats(plane, plane_cap, formats,
                                        ARRAY_SIZE(formats));
 
-       res = drm_universal_plane_init(dm->adev->ddev, plane, possible_crtcs,
+       res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs,
                                       &dm_plane_funcs, formats, num_formats,
                                       NULL, plane->type, NULL);
        if (res)
@@ -5903,8 +6065,9 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
                DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
                DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
 
-       drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
-                                          supported_rotations);
+       if (dm->adev->asic_type >= CHIP_BONAIRE)
+               drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
+                                                  supported_rotations);
 
        drm_plane_helper_add(plane, &dm_plane_helper_funcs);
 
@@ -6174,7 +6337,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
                                     struct dc_link *link,
                                     int link_index)
 {
-       struct amdgpu_device *adev = dm->ddev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dm->ddev);
 
        /*
         * Some of the properties below require access to state, like bpc.
@@ -6425,7 +6588,7 @@ static int amdgpu_dm_encoder_init(struct drm_device *dev,
                                  struct amdgpu_encoder *aencoder,
                                  uint32_t link_index)
 {
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
 
        int res = drm_encoder_init(dev,
                                   &aencoder->base,
@@ -6610,7 +6773,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
 static void handle_cursor_update(struct drm_plane *plane,
                                 struct drm_plane_state *old_plane_state)
 {
-       struct amdgpu_device *adev = plane->dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(plane->dev);
        struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb);
        struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc;
        struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
@@ -6712,7 +6875,7 @@ static void update_freesync_state_on_stream(
        if (!new_stream->timing.h_total || !new_stream->timing.v_total)
                return;
 
-       spin_lock_irqsave(&adev->ddev->event_lock, flags);
+       spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
        vrr_params = new_crtc_state->vrr_params;
 
        if (surface) {
@@ -6765,7 +6928,7 @@ static void update_freesync_state_on_stream(
                              (int)new_crtc_state->base.vrr_enabled,
                              (int)vrr_params.state);
 
-       spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+       spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 }
 
 static void pre_update_freesync_state_on_stream(
@@ -6788,7 +6951,7 @@ static void pre_update_freesync_state_on_stream(
        if (!new_stream->timing.h_total || !new_stream->timing.v_total)
                return;
 
-       spin_lock_irqsave(&adev->ddev->event_lock, flags);
+       spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
        vrr_params = new_crtc_state->vrr_params;
 
        if (new_crtc_state->vrr_supported &&
@@ -6811,7 +6974,7 @@ static void pre_update_freesync_state_on_stream(
                        sizeof(vrr_params.adjust)) != 0);
 
        new_crtc_state->vrr_params = vrr_params;
-       spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+       spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 }
 
 static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
@@ -6881,8 +7044,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
        long r;
        unsigned long flags;
        struct amdgpu_bo *abo;
-       uint64_t tiling_flags;
-       bool tmz_surface = false;
        uint32_t target_vblank, last_flip_vblank;
        bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
        bool pflip_present = false;
@@ -6966,28 +7127,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                if (unlikely(r <= 0))
                        DRM_ERROR("Waiting for fences timed out!");
 
-               /*
-                * TODO This might fail and hence better not used, wait
-                * explicitly on fences instead
-                * and in general should be called for
-                * blocking commit to as per framework helpers
-                */
-               r = amdgpu_bo_reserve(abo, true);
-               if (unlikely(r != 0))
-                       DRM_ERROR("failed to reserve buffer before flip\n");
-
-               amdgpu_bo_get_tiling_flags(abo, &tiling_flags);
-
-               tmz_surface = amdgpu_bo_encrypted(abo);
-
-               amdgpu_bo_unreserve(abo);
-
                fill_dc_plane_info_and_addr(
-                       dm->adev, new_plane_state, tiling_flags,
+                       dm->adev, new_plane_state,
+                       dm_new_plane_state->tiling_flags,
                        &bundle->plane_infos[planes_count],
                        &bundle->flip_addrs[planes_count].address,
-                       tmz_surface,
-                       false);
+                       dm_new_plane_state->tmz_surface, false);
 
                DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n",
                                 new_plane_state->plane->index,
@@ -7165,9 +7310,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                 * on some ASICs).
                 */
                if (dm_old_crtc_state->active_planes != acrtc_state->active_planes)
-                       dm_update_pflip_irq_state(
-                               (struct amdgpu_device *)dev->dev_private,
-                               acrtc_attach);
+                       dm_update_pflip_irq_state(drm_to_adev(dev),
+                                                 acrtc_attach);
 
                if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
                                acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED &&
@@ -7197,7 +7341,7 @@ cleanup:
 static void amdgpu_dm_commit_audio(struct drm_device *dev,
                                   struct drm_atomic_state *state)
 {
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
        struct drm_connector_state *old_con_state, *new_con_state;
@@ -7289,7 +7433,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev,
 {
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        int i;
 
        /*
@@ -7336,7 +7480,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev,
 static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct amdgpu_display_manager *dm = &adev->dm;
        struct dm_atomic_state *dm_state;
        struct dc_state *dc_state = NULL, *dc_state_temp = NULL;
@@ -7349,6 +7493,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
        struct drm_connector_state *old_con_state, *new_con_state;
        struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
        int crtc_disable_count = 0;
+       bool mode_set_reset_required = false;
 
        drm_atomic_helper_update_legacy_modeset_state(dev, state);
 
@@ -7425,19 +7570,21 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                        acrtc->enabled = true;
                        acrtc->hw_mode = new_crtc_state->mode;
                        crtc->hwmode = new_crtc_state->mode;
+                       mode_set_reset_required = true;
                } else if (modereset_required(new_crtc_state)) {
                        DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc);
                        /* i.e. reset mode */
-                       if (dm_old_crtc_state->stream) {
-                               if (dm_old_crtc_state->stream->link->psr_settings.psr_allow_active)
-                                       amdgpu_dm_psr_disable(dm_old_crtc_state->stream);
-
+                       if (dm_old_crtc_state->stream)
                                remove_stream(adev, acrtc, dm_old_crtc_state->stream);
-                       }
+                       mode_set_reset_required = true;
                }
        } /* for_each_crtc_in_state() */
 
        if (dc_state) {
+               /* if there mode set or reset, disable eDP PSR */
+               if (mode_set_reset_required)
+                       amdgpu_dm_psr_disable_all(dm);
+
                dm_enable_per_frame_crtc_master_sync(dc_state);
                mutex_lock(&dm->dc_lock);
                WARN_ON(!dc_commit_state(dm->dc, dc_state));
@@ -7639,7 +7786,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
         * send vblank event on all events not handled in flip and
         * mark consumed event for drm_atomic_helper_commit_hw_done
         */
-       spin_lock_irqsave(&adev->ddev->event_lock, flags);
+       spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
        for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
 
                if (new_crtc_state->event)
@@ -7647,7 +7794,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 
                new_crtc_state->event = NULL;
        }
-       spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
+       spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 
        /* Signal HW programming completion */
        drm_atomic_helper_commit_hw_done(state);
@@ -7919,6 +8066,13 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                        goto fail;
                }
 
+               /*
+                * TODO: Check VSDB bits to decide whether this should
+                * be enabled or not.
+                */
+               new_stream->triggered_crtc_reset.enabled =
+                       dm->force_timing_sync;
+
                dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
 
                ret = fill_hdr_info_packet(drm_new_conn_state,
@@ -8038,8 +8192,7 @@ skip_modeset:
         * We want to do dc stream updates that do not require a
         * full modeset below.
         */
-       if (!(enable && aconnector && new_crtc_state->enable &&
-             new_crtc_state->active))
+       if (!(enable && aconnector && new_crtc_state->active))
                return 0;
        /*
         * Given above conditions, the dc state cannot be NULL because:
@@ -8130,6 +8283,8 @@ 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;
+
                if (other->type == DRM_PLANE_TYPE_CURSOR)
                        continue;
 
@@ -8140,9 +8295,45 @@ static bool should_reset_plane(struct drm_atomic_state *state,
                if (old_other_state->crtc != new_other_state->crtc)
                        return true;
 
-               /* TODO: Remove this once we can handle fast format changes. */
-               if (old_other_state->fb && new_other_state->fb &&
-                   old_other_state->fb->format != new_other_state->fb->format)
+               /* Src/dst size and scaling updates. */
+               if (old_other_state->src_w != new_other_state->src_w ||
+                   old_other_state->src_h != new_other_state->src_h ||
+                   old_other_state->crtc_w != new_other_state->crtc_w ||
+                   old_other_state->crtc_h != new_other_state->crtc_h)
+                       return true;
+
+               /* Rotation / mirroring updates. */
+               if (old_other_state->rotation != new_other_state->rotation)
+                       return true;
+
+               /* Blending updates. */
+               if (old_other_state->pixel_blend_mode !=
+                   new_other_state->pixel_blend_mode)
+                       return true;
+
+               /* Alpha updates. */
+               if (old_other_state->alpha != new_other_state->alpha)
+                       return true;
+
+               /* Colorspace changes. */
+               if (old_other_state->color_range != new_other_state->color_range ||
+                   old_other_state->color_encoding != new_other_state->color_encoding)
+                       return true;
+
+               /* Framebuffer checks fall at the end. */
+               if (!old_other_state->fb || !new_other_state->fb)
+                       continue;
+
+               /* Pixel format changes can require bandwidth updates. */
+               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);
+
+               /* Tiling and DCC changes also require bandwidth updates. */
+               if (old_dm_plane_state->tiling_flags !=
+                   new_dm_plane_state->tiling_flags)
                        return true;
        }
 
@@ -8222,8 +8413,7 @@ static int dm_update_plane_state(struct dc *dc,
                                dm_old_plane_state->dc_state,
                                dm_state->context)) {
 
-                       ret = EINVAL;
-                       return ret;
+                       return -EINVAL;
                }
 
 
@@ -8264,7 +8454,7 @@ static int dm_update_plane_state(struct dc *dc,
                                plane->base.id, new_plane_crtc->base.id);
 
                ret = fill_dc_plane_attributes(
-                       new_plane_crtc->dev->dev_private,
+                       drm_to_adev(new_plane_crtc->dev),
                        dc_new_plane_state,
                        new_plane_state,
                        new_crtc_state);
@@ -8310,169 +8500,6 @@ static int dm_update_plane_state(struct dc *dc,
        return ret;
 }
 
-static int
-dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm,
-                                   struct drm_atomic_state *state,
-                                   enum surface_update_type *out_type)
-{
-       struct dc *dc = dm->dc;
-       struct dm_atomic_state *dm_state = NULL, *old_dm_state = NULL;
-       int i, j, num_plane, ret = 0;
-       struct drm_plane_state *old_plane_state, *new_plane_state;
-       struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state;
-       struct drm_crtc *new_plane_crtc;
-       struct drm_plane *plane;
-
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *new_crtc_state, *old_crtc_state;
-       struct dm_crtc_state *new_dm_crtc_state, *old_dm_crtc_state;
-       struct dc_stream_status *status = NULL;
-       enum surface_update_type update_type = UPDATE_TYPE_FAST;
-       struct surface_info_bundle {
-               struct dc_surface_update surface_updates[MAX_SURFACES];
-               struct dc_plane_info plane_infos[MAX_SURFACES];
-               struct dc_scaling_info scaling_infos[MAX_SURFACES];
-               struct dc_flip_addrs flip_addrs[MAX_SURFACES];
-               struct dc_stream_update stream_update;
-       } *bundle;
-
-       bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
-
-       if (!bundle) {
-               DRM_ERROR("Failed to allocate update bundle\n");
-               /* Set type to FULL to avoid crashing in DC*/
-               update_type = UPDATE_TYPE_FULL;
-               goto cleanup;
-       }
-
-       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
-
-               memset(bundle, 0, sizeof(struct surface_info_bundle));
-
-               new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
-               old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
-               num_plane = 0;
-
-               if (new_dm_crtc_state->stream != old_dm_crtc_state->stream) {
-                       update_type = UPDATE_TYPE_FULL;
-                       goto cleanup;
-               }
-
-               if (!new_dm_crtc_state->stream)
-                       continue;
-
-               for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) {
-                       const struct amdgpu_framebuffer *amdgpu_fb =
-                               to_amdgpu_framebuffer(new_plane_state->fb);
-                       struct dc_plane_info *plane_info = &bundle->plane_infos[num_plane];
-                       struct dc_flip_addrs *flip_addr = &bundle->flip_addrs[num_plane];
-                       struct dc_scaling_info *scaling_info = &bundle->scaling_infos[num_plane];
-                       uint64_t tiling_flags;
-                       bool tmz_surface = false;
-
-                       new_plane_crtc = new_plane_state->crtc;
-                       new_dm_plane_state = to_dm_plane_state(new_plane_state);
-                       old_dm_plane_state = to_dm_plane_state(old_plane_state);
-
-                       if (plane->type == DRM_PLANE_TYPE_CURSOR)
-                               continue;
-
-                       if (new_dm_plane_state->dc_state != old_dm_plane_state->dc_state) {
-                               update_type = UPDATE_TYPE_FULL;
-                               goto cleanup;
-                       }
-
-                       if (crtc != new_plane_crtc)
-                               continue;
-
-                       bundle->surface_updates[num_plane].surface =
-                                       new_dm_plane_state->dc_state;
-
-                       if (new_crtc_state->mode_changed) {
-                               bundle->stream_update.dst = new_dm_crtc_state->stream->dst;
-                               bundle->stream_update.src = new_dm_crtc_state->stream->src;
-                       }
-
-                       if (new_crtc_state->color_mgmt_changed) {
-                               bundle->surface_updates[num_plane].gamma =
-                                               new_dm_plane_state->dc_state->gamma_correction;
-                               bundle->surface_updates[num_plane].in_transfer_func =
-                                               new_dm_plane_state->dc_state->in_transfer_func;
-                               bundle->surface_updates[num_plane].gamut_remap_matrix =
-                                               &new_dm_plane_state->dc_state->gamut_remap_matrix;
-                               bundle->stream_update.gamut_remap =
-                                               &new_dm_crtc_state->stream->gamut_remap_matrix;
-                               bundle->stream_update.output_csc_transform =
-                                               &new_dm_crtc_state->stream->csc_color_matrix;
-                               bundle->stream_update.out_transfer_func =
-                                               new_dm_crtc_state->stream->out_transfer_func;
-                       }
-
-                       ret = fill_dc_scaling_info(new_plane_state,
-                                                  scaling_info);
-                       if (ret)
-                               goto cleanup;
-
-                       bundle->surface_updates[num_plane].scaling_info = scaling_info;
-
-                       if (amdgpu_fb) {
-                               ret = get_fb_info(amdgpu_fb, &tiling_flags, &tmz_surface);
-                               if (ret)
-                                       goto cleanup;
-
-                               ret = fill_dc_plane_info_and_addr(
-                                       dm->adev, new_plane_state, tiling_flags,
-                                       plane_info,
-                                       &flip_addr->address, tmz_surface,
-                                       false);
-                               if (ret)
-                                       goto cleanup;
-
-                               bundle->surface_updates[num_plane].plane_info = plane_info;
-                               bundle->surface_updates[num_plane].flip_addr = flip_addr;
-                       }
-
-                       num_plane++;
-               }
-
-               if (num_plane == 0)
-                       continue;
-
-               ret = dm_atomic_get_state(state, &dm_state);
-               if (ret)
-                       goto cleanup;
-
-               old_dm_state = dm_atomic_get_old_state(state);
-               if (!old_dm_state) {
-                       ret = -EINVAL;
-                       goto cleanup;
-               }
-
-               status = dc_stream_get_status_from_state(old_dm_state->context,
-                                                        new_dm_crtc_state->stream);
-               bundle->stream_update.stream = new_dm_crtc_state->stream;
-               /*
-                * TODO: DC modifies the surface during this call so we need
-                * to lock here - find a way to do this without locking.
-                */
-               mutex_lock(&dm->dc_lock);
-               update_type = dc_check_update_surfaces_for_stream(
-                               dc,     bundle->surface_updates, num_plane,
-                               &bundle->stream_update, status);
-               mutex_unlock(&dm->dc_lock);
-
-               if (update_type > UPDATE_TYPE_MED) {
-                       update_type = UPDATE_TYPE_FULL;
-                       goto cleanup;
-               }
-       }
-
-cleanup:
-       kfree(bundle);
-
-       *out_type = update_type;
-       return ret;
-}
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc)
 {
@@ -8513,8 +8540,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
  * acquired. For full updates case which removes/adds/updates streams on one
  * CRTC while flipping on another CRTC, acquiring global lock will guarantee
  * that any such full update commit will wait for completion of any outstanding
- * flip using DRMs synchronization events. See
- * dm_determine_update_type_for_commit()
+ * flip using DRMs synchronization events.
  *
  * Note that DM adds the affected connectors for all CRTCs in state, when that
  * might not seem necessary. This is because DC stream creation requires the
@@ -8526,7 +8552,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
 static int amdgpu_dm_atomic_check(struct drm_device *dev,
                                  struct drm_atomic_state *state)
 {
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        struct dm_atomic_state *dm_state = NULL;
        struct dc *dc = adev->dm.dc;
        struct drm_connector *connector;
@@ -8535,15 +8561,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_plane *plane;
        struct drm_plane_state *old_plane_state, *new_plane_state;
-       enum surface_update_type update_type = UPDATE_TYPE_FAST;
-       enum surface_update_type overall_update_type = UPDATE_TYPE_FAST;
        enum dc_status status;
        int ret, i;
-
-       /*
-        * This bool will be set for true for any modeset/reset
-        * or plane update which implies non fast surface update.
-        */
        bool lock_and_validation_needed = false;
 
        ret = drm_atomic_helper_check_modeset(dev, state);
@@ -8638,6 +8657,17 @@ 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,
@@ -8726,27 +8756,23 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state))
                        continue;
 
-               overall_update_type = UPDATE_TYPE_FULL;
                lock_and_validation_needed = true;
        }
 
-       ret = dm_determine_update_type_for_commit(&adev->dm, state, &update_type);
-       if (ret)
-               goto fail;
-
-       if (overall_update_type < update_type)
-               overall_update_type = update_type;
-
-       /*
-        * lock_and_validation_needed was an old way to determine if we need to set
-        * the global lock. Leaving it in to check if we broke any corner cases
-        * lock_and_validation_needed true = UPDATE_TYPE_FULL or UPDATE_TYPE_MED
-        * lock_and_validation_needed false = UPDATE_TYPE_FAST
+       /**
+        * Streams and planes are reset when there are changes that affect
+        * bandwidth. Anything that affects bandwidth needs to go through
+        * DC global validation to ensure that the configuration can be applied
+        * to hardware.
+        *
+        * We have to currently stall out here in atomic_check for outstanding
+        * commits to finish in this case because our IRQ handlers reference
+        * DRM state directly - we can end up disabling interrupts too early
+        * if we don't.
+        *
+        * TODO: Remove this stall and drop DM state private objects.
         */
-       if (lock_and_validation_needed && overall_update_type <= UPDATE_TYPE_FAST)
-               WARN(1, "Global lock should be Set, overall_update_type should be UPDATE_TYPE_MED or UPDATE_TYPE_FULL");
-
-       if (overall_update_type > UPDATE_TYPE_FAST) {
+       if (lock_and_validation_needed) {
                ret = dm_atomic_get_state(state, &dm_state);
                if (ret)
                        goto fail;
@@ -8828,7 +8854,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                struct dm_crtc_state *dm_new_crtc_state =
                        to_dm_crtc_state(new_crtc_state);
 
-               dm_new_crtc_state->update_type = (int)overall_update_type;
+               dm_new_crtc_state->update_type = lock_and_validation_needed ?
+                                                        UPDATE_TYPE_FULL :
+                                                        UPDATE_TYPE_FAST;
        }
 
        /* Must be success */
@@ -8877,7 +8905,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
        struct dm_connector_state *dm_con_state = NULL;
 
        struct drm_device *dev = connector->dev;
-       struct amdgpu_device *adev = dev->dev_private;
+       struct amdgpu_device *adev = drm_to_adev(dev);
        bool freesync_capable = false;
 
        if (!connector->state) {
@@ -9076,3 +9104,34 @@ static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream)
 
        return dc_link_set_psr_allow_active(stream->link, false, true);
 }
+
+/*
+ * amdgpu_dm_psr_disable() - disable psr f/w
+ * if psr is enabled on any stream
+ *
+ * Return: true if success
+ */
+static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm)
+{
+       DRM_DEBUG_DRIVER("Disabling psr if psr is enabled on any stream\n");
+       return dc_set_psr_allow_active(dm->dc, false);
+}
+
+void amdgpu_dm_trigger_timing_sync(struct drm_device *dev)
+{
+       struct amdgpu_device *adev = drm_to_adev(dev);
+       struct dc *dc = adev->dm.dc;
+       int i;
+
+       mutex_lock(&adev->dm.dc_lock);
+       if (dc->current_state) {
+               for (i = 0; i < dc->current_state->stream_count; ++i)
+                       dc->current_state->streams[i]
+                               ->triggered_crtc_reset.enabled =
+                               adev->dm.force_timing_sync;
+
+               dm_enable_per_frame_crtc_master_sync(dc->current_state);
+               dc_trigger_sync(dc, dc->current_state);
+       }
+       mutex_unlock(&adev->dm.dc_lock);
+}