Merge tag 'io_uring-5.15-2021-09-11' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index d3a2a5f..9b1fc54 100644 (file)
@@ -618,6 +618,7 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params)
 }
 #endif
 
+#define DMUB_TRACE_MAX_READ 64
 /**
  * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt
  * @interrupt_params: used for determining the Outbox instance
@@ -625,7 +626,6 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params)
  * Handles the Outbox Interrupt
  * event handler.
  */
-#define DMUB_TRACE_MAX_READ 64
 static void dm_dmub_outbox1_low_irq(void *interrupt_params)
 {
        struct dmub_notification notify;
@@ -1044,10 +1044,10 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
 }
 #endif
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-static void event_mall_stutter(struct work_struct *work)
+static void vblank_control_worker(struct work_struct *work)
 {
-
-       struct vblank_workqueue *vblank_work = container_of(work, struct vblank_workqueue, mall_work);
+       struct vblank_control_work *vblank_work =
+               container_of(work, struct vblank_control_work, work);
        struct amdgpu_display_manager *dm = vblank_work->dm;
 
        mutex_lock(&dm->dc_lock);
@@ -1061,27 +1061,25 @@ static void event_mall_stutter(struct work_struct *work)
 
        DRM_DEBUG_KMS("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0);
 
-       mutex_unlock(&dm->dc_lock);
-}
-
-static struct vblank_workqueue *vblank_create_workqueue(struct amdgpu_device *adev, struct dc *dc)
-{
-
-       int max_caps = dc->caps.max_links;
-       struct vblank_workqueue *vblank_work;
-       int i = 0;
-
-       vblank_work = kcalloc(max_caps, sizeof(*vblank_work), GFP_KERNEL);
-       if (ZERO_OR_NULL_PTR(vblank_work)) {
-               kfree(vblank_work);
-               return NULL;
+       /* Control PSR based on vblank requirements from OS */
+       if (vblank_work->stream && vblank_work->stream->link) {
+               if (vblank_work->enable) {
+                       if (vblank_work->stream->link->psr_settings.psr_allow_active)
+                               amdgpu_dm_psr_disable(vblank_work->stream);
+               } else if (vblank_work->stream->link->psr_settings.psr_feature_enabled &&
+                          !vblank_work->stream->link->psr_settings.psr_allow_active &&
+                          vblank_work->acrtc->dm_irq_params.allow_psr_entry) {
+                       amdgpu_dm_psr_enable(vblank_work->stream);
+               }
        }
 
-       for (i = 0; i < max_caps; i++)
-               INIT_WORK(&vblank_work[i].mall_work, event_mall_stutter);
+       mutex_unlock(&dm->dc_lock);
+
+       dc_stream_release(vblank_work->stream);
 
-       return vblank_work;
+       kfree(vblank_work);
 }
+
 #endif
 static int amdgpu_dm_init(struct amdgpu_device *adev)
 {
@@ -1202,7 +1200,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        dc_hardware_init(adev->dm.dc);
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-       if (adev->apu_flags) {
+       if ((adev->flags & AMD_IS_APU) && (adev->asic_type >= CHIP_CARRIZO)) {
                struct dc_phy_addr_space_config pa_config;
 
                mmhub_read_system_context(adev, &pa_config);
@@ -1224,12 +1222,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        if (adev->dm.dc->caps.max_links > 0) {
-               adev->dm.vblank_workqueue = vblank_create_workqueue(adev, adev->dm.dc);
-
-               if (!adev->dm.vblank_workqueue)
+               adev->dm.vblank_control_workqueue =
+                       create_singlethread_workqueue("dm_vblank_control_workqueue");
+               if (!adev->dm.vblank_control_workqueue)
                        DRM_ERROR("amdgpu: failed to initialize vblank_workqueue.\n");
-               else
-                       DRM_DEBUG_DRIVER("amdgpu: vblank_workqueue init done %p.\n", adev->dm.vblank_workqueue);
        }
 #endif
 
@@ -1302,6 +1298,13 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
 {
        int i;
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       if (adev->dm.vblank_control_workqueue) {
+               destroy_workqueue(adev->dm.vblank_control_workqueue);
+               adev->dm.vblank_control_workqueue = NULL;
+       }
+#endif
+
        for (i = 0; i < adev->dm.display_indexes_num; i++) {
                drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
        }
@@ -1325,14 +1328,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
                dc_deinit_callbacks(adev->dm.dc);
 #endif
 
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-       if (adev->dm.vblank_workqueue) {
-               adev->dm.vblank_workqueue->dm = NULL;
-               kfree(adev->dm.vblank_workqueue);
-               adev->dm.vblank_workqueue = NULL;
-       }
-#endif
-
        dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv);
 
        if (dc_enable_dmub_notifications(adev->dm.dc)) {
@@ -1548,6 +1543,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
        }
 
        hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data;
+       adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);
 
        if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
                adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id =
@@ -1561,7 +1557,6 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
                         adev->dm.dmcub_fw_version);
        }
 
-       adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);
 
        adev->dm.dmub_srv = kzalloc(sizeof(*adev->dm.dmub_srv), GFP_KERNEL);
        dmub_srv = adev->dm.dmub_srv;
@@ -2412,6 +2407,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        static const u8 pre_computed_values[] = {
                50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
                71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
+       int i;
 
        if (!aconnector || !aconnector->dc_link)
                return;
@@ -2423,15 +2419,21 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        conn_base = &aconnector->base;
        adev = drm_to_adev(conn_base->dev);
        dm = &adev->dm;
-       caps = &dm->backlight_caps;
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if (link == dm->backlight_link[i])
+                       break;
+       }
+       if (i >= dm->num_of_edps)
+               return;
+       caps = &dm->backlight_caps[i];
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
        caps->aux_support = false;
        max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll;
        min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll;
 
-       if (caps->ext_caps->bits.oled == 1 ||
+       if (caps->ext_caps->bits.oled == 1 /*||
            caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
-           caps->ext_caps->bits.hdr_aux_backlight_control == 1)
+           caps->ext_caps->bits.hdr_aux_backlight_control == 1*/)
                caps->aux_support = true;
 
        if (amdgpu_backlight == 0)
@@ -3423,35 +3425,36 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
        defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
 
-static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm)
+static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
+                                           int bl_idx)
 {
 #if defined(CONFIG_ACPI)
        struct amdgpu_dm_backlight_caps caps;
 
        memset(&caps, 0, sizeof(caps));
 
-       if (dm->backlight_caps.caps_valid)
+       if (dm->backlight_caps[bl_idx].caps_valid)
                return;
 
        amdgpu_acpi_get_backlight_caps(&caps);
        if (caps.caps_valid) {
-               dm->backlight_caps.caps_valid = true;
+               dm->backlight_caps[bl_idx].caps_valid = true;
                if (caps.aux_support)
                        return;
-               dm->backlight_caps.min_input_signal = caps.min_input_signal;
-               dm->backlight_caps.max_input_signal = caps.max_input_signal;
+               dm->backlight_caps[bl_idx].min_input_signal = caps.min_input_signal;
+               dm->backlight_caps[bl_idx].max_input_signal = caps.max_input_signal;
        } else {
-               dm->backlight_caps.min_input_signal =
+               dm->backlight_caps[bl_idx].min_input_signal =
                                AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
-               dm->backlight_caps.max_input_signal =
+               dm->backlight_caps[bl_idx].max_input_signal =
                                AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
        }
 #else
-       if (dm->backlight_caps.aux_support)
+       if (dm->backlight_caps[bl_idx].aux_support)
                return;
 
-       dm->backlight_caps.min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
-       dm->backlight_caps.max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
+       dm->backlight_caps[bl_idx].min_input_signal = AMDGPU_DM_DEFAULT_MIN_BACKLIGHT;
+       dm->backlight_caps[bl_idx].max_input_signal = AMDGPU_DM_DEFAULT_MAX_BACKLIGHT;
 #endif
 }
 
@@ -3502,41 +3505,31 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap
 }
 
 static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
+                                        int bl_idx,
                                         u32 user_brightness)
 {
        struct amdgpu_dm_backlight_caps caps;
-       struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP];
-       u32 brightness[AMDGPU_DM_MAX_NUM_EDP];
+       struct dc_link *link;
+       u32 brightness;
        bool rc;
-       int i;
 
-       amdgpu_dm_update_backlight_caps(dm);
-       caps = dm->backlight_caps;
+       amdgpu_dm_update_backlight_caps(dm, bl_idx);
+       caps = dm->backlight_caps[bl_idx];
 
-       for (i = 0; i < dm->num_of_edps; i++) {
-               dm->brightness[i] = user_brightness;
-               brightness[i] = convert_brightness_from_user(&caps, dm->brightness[i]);
-               link[i] = (struct dc_link *)dm->backlight_link[i];
-       }
+       dm->brightness[bl_idx] = user_brightness;
+       brightness = convert_brightness_from_user(&caps, dm->brightness[bl_idx]);
+       link = (struct dc_link *)dm->backlight_link[bl_idx];
 
        /* Change brightness based on AUX property */
        if (caps.aux_support) {
-               for (i = 0; i < dm->num_of_edps; i++) {
-                       rc = dc_link_set_backlight_level_nits(link[i], true, brightness[i],
-                               AUX_BL_DEFAULT_TRANSITION_TIME_MS);
-                       if (!rc) {
-                               DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", i);
-                               break;
-                       }
-               }
+               rc = dc_link_set_backlight_level_nits(link, true, brightness,
+                                                     AUX_BL_DEFAULT_TRANSITION_TIME_MS);
+               if (!rc)
+                       DRM_DEBUG("DM: Failed to update backlight via AUX on eDP[%d]\n", bl_idx);
        } else {
-               for (i = 0; i < dm->num_of_edps; i++) {
-                       rc = dc_link_set_backlight_level(dm->backlight_link[i], brightness[i], 0);
-                       if (!rc) {
-                               DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", i);
-                               break;
-                       }
-               }
+               rc = dc_link_set_backlight_level(link, brightness, 0);
+               if (!rc)
+                       DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx);
        }
 
        return rc ? 0 : 1;
@@ -3545,33 +3538,41 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
 static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
 {
        struct amdgpu_display_manager *dm = bl_get_data(bd);
+       int i;
 
-       amdgpu_dm_backlight_set_level(dm, bd->props.brightness);
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if (bd == dm->backlight_dev[i])
+                       break;
+       }
+       if (i >= AMDGPU_DM_MAX_NUM_EDP)
+               i = 0;
+       amdgpu_dm_backlight_set_level(dm, i, bd->props.brightness);
 
        return 0;
 }
 
-static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
+static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm,
+                                        int bl_idx)
 {
        struct amdgpu_dm_backlight_caps caps;
+       struct dc_link *link = (struct dc_link *)dm->backlight_link[bl_idx];
 
-       amdgpu_dm_update_backlight_caps(dm);
-       caps = dm->backlight_caps;
+       amdgpu_dm_update_backlight_caps(dm, bl_idx);
+       caps = dm->backlight_caps[bl_idx];
 
        if (caps.aux_support) {
-               struct dc_link *link = (struct dc_link *)dm->backlight_link[0];
                u32 avg, peak;
                bool rc;
 
                rc = dc_link_get_backlight_level_nits(link, &avg, &peak);
                if (!rc)
-                       return dm->brightness[0];
+                       return dm->brightness[bl_idx];
                return convert_brightness_to_user(&caps, avg);
        } else {
-               int ret = dc_link_get_backlight_level(dm->backlight_link[0]);
+               int ret = dc_link_get_backlight_level(link);
 
                if (ret == DC_ERROR_UNEXPECTED)
-                       return dm->brightness[0];
+                       return dm->brightness[bl_idx];
                return convert_brightness_to_user(&caps, ret);
        }
 }
@@ -3579,8 +3580,15 @@ static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
 static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
 {
        struct amdgpu_display_manager *dm = bl_get_data(bd);
+       int i;
 
-       return amdgpu_dm_backlight_get_level(dm);
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if (bd == dm->backlight_dev[i])
+                       break;
+       }
+       if (i >= AMDGPU_DM_MAX_NUM_EDP)
+               i = 0;
+       return amdgpu_dm_backlight_get_level(dm, i);
 }
 
 static const struct backlight_ops amdgpu_dm_backlight_ops = {
@@ -3594,31 +3602,28 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm)
 {
        char bl_name[16];
        struct backlight_properties props = { 0 };
-       int i;
 
-       amdgpu_dm_update_backlight_caps(dm);
-       for (i = 0; i < dm->num_of_edps; i++)
-               dm->brightness[i] = AMDGPU_MAX_BL_LEVEL;
+       amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps);
+       dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL;
 
        props.max_brightness = AMDGPU_MAX_BL_LEVEL;
        props.brightness = AMDGPU_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
 
        snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
-                adev_to_drm(dm->adev)->primary->index);
+                adev_to_drm(dm->adev)->primary->index + dm->num_of_edps);
 
-       dm->backlight_dev = backlight_device_register(bl_name,
-                                                     adev_to_drm(dm->adev)->dev,
-                                                     dm,
-                                                     &amdgpu_dm_backlight_ops,
-                                                     &props);
+       dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name,
+                                                                      adev_to_drm(dm->adev)->dev,
+                                                                      dm,
+                                                                      &amdgpu_dm_backlight_ops,
+                                                                      &props);
 
-       if (IS_ERR(dm->backlight_dev))
+       if (IS_ERR(dm->backlight_dev[dm->num_of_edps]))
                DRM_ERROR("DM: Backlight registration failed!\n");
        else
                DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name);
 }
-
 #endif
 
 static int initialize_plane(struct amdgpu_display_manager *dm,
@@ -3675,10 +3680,10 @@ static void register_backlight_device(struct amdgpu_display_manager *dm,
                 * DM initialization because not having a backlight control
                 * is better then a black screen.
                 */
-               if (!dm->backlight_dev)
+               if (!dm->backlight_dev[dm->num_of_edps])
                        amdgpu_dm_register_backlight_device(dm);
 
-               if (dm->backlight_dev) {
+               if (dm->backlight_dev[dm->num_of_edps]) {
                        dm->backlight_link[dm->num_of_edps] = link;
                        dm->num_of_edps++;
                }
@@ -4747,7 +4752,7 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
                                          const bool force_disable_dcc)
 {
        const uint64_t modifier = afb->base.modifier;
-       int ret;
+       int ret = 0;
 
        fill_gfx9_tiling_info_from_modifier(adev, tiling_info, modifier);
        tiling_info->gfx9.swizzle = modifier_gfx9_swizzle_mode(modifier);
@@ -4765,9 +4770,9 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev,
 
        ret = validate_dcc(adev, format, rotation, tiling_info, dcc, address, plane_size);
        if (ret)
-               return ret;
+               drm_dbg_kms(adev_to_drm(adev), "validate_dcc: returned error: %d\n", ret);
 
-       return 0;
+       return ret;
 }
 
 static int
@@ -5994,7 +5999,7 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
        struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        struct amdgpu_display_manager *dm = &adev->dm;
-       unsigned long flags;
+       struct vblank_control_work *work;
 #endif
        int rc = 0;
 
@@ -6019,12 +6024,21 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
                return 0;
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-       spin_lock_irqsave(&dm->vblank_lock, flags);
-       dm->vblank_workqueue->dm = dm;
-       dm->vblank_workqueue->otg_inst = acrtc->otg_inst;
-       dm->vblank_workqueue->enable = enable;
-       spin_unlock_irqrestore(&dm->vblank_lock, flags);
-       schedule_work(&dm->vblank_workqueue->mall_work);
+       work = kzalloc(sizeof(*work), GFP_ATOMIC);
+       if (!work)
+               return -ENOMEM;
+
+       INIT_WORK(&work->work, vblank_control_worker);
+       work->dm = dm;
+       work->acrtc = acrtc;
+       work->enable = enable;
+
+       if (acrtc_state->stream) {
+               dc_stream_retain(acrtc_state->stream);
+               work->stream = acrtc_state->stream;
+       }
+
+       queue_work(dm->vblank_control_workqueue, &work->work);
 #endif
 
        return 0;
@@ -6198,6 +6212,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
        const struct dc_link *link = aconnector->dc_link;
        struct amdgpu_device *adev = drm_to_adev(connector->dev);
        struct amdgpu_display_manager *dm = &adev->dm;
+       int i;
 
        /*
         * Call only if mst_mgr was iniitalized before since it's not done
@@ -6208,12 +6223,11 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
 
 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
        defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
-
-       if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) &&
-           link->type != dc_connection_none &&
-           dm->backlight_dev) {
-               backlight_device_unregister(dm->backlight_dev);
-               dm->backlight_dev = NULL;
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) {
+                       backlight_device_unregister(dm->backlight_dev[i]);
+                       dm->backlight_dev[i] = NULL;
+               }
        }
 #endif
 
@@ -7570,8 +7584,10 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
         * 60       - Commonly used
         * 48,72,96 - Multiples of 24
         */
-       const uint32_t common_rates[] = { 23976, 24000, 25000, 29970, 30000,
-                                        48000, 50000, 60000, 72000, 96000 };
+       static const uint32_t common_rates[] = {
+               23976, 24000, 25000, 29970, 30000,
+               48000, 50000, 60000, 72000, 96000
+       };
 
        /*
         * Find mode with highest refresh rate with the same resolution
@@ -8627,6 +8643,14 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
        /* Update the planes if changed or disable if we don't have any. */
        if ((planes_count || acrtc_state->active_planes == 0) &&
                acrtc_state->stream) {
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+               /*
+                * If PSR or idle optimizations are enabled then flush out
+                * any pending work before hardware programming.
+                */
+               flush_workqueue(dm->vblank_control_workqueue);
+#endif
+
                bundle->stream_update.stream = acrtc_state->stream;
                if (new_pcrtc_state->mode_changed) {
                        bundle->stream_update.src = acrtc_state->stream->src;
@@ -8695,16 +8719,20 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                                acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED &&
                                !acrtc_state->stream->link->psr_settings.psr_feature_enabled)
                        amdgpu_dm_link_setup_psr(acrtc_state->stream);
-               else if ((acrtc_state->update_type == UPDATE_TYPE_FAST) &&
-                               acrtc_state->stream->link->psr_settings.psr_feature_enabled &&
-                               !acrtc_state->stream->link->psr_settings.psr_allow_active) {
-                       struct amdgpu_dm_connector *aconn = (struct amdgpu_dm_connector *)
-                                       acrtc_state->stream->dm_stream_context;
+
+               /* Decrement skip count when PSR is enabled and we're doing fast updates. */
+               if (acrtc_state->update_type == UPDATE_TYPE_FAST &&
+                   acrtc_state->stream->link->psr_settings.psr_feature_enabled) {
+                       struct amdgpu_dm_connector *aconn =
+                               (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context;
 
                        if (aconn->psr_skip_count > 0)
                                aconn->psr_skip_count--;
-                       else
-                               amdgpu_dm_psr_enable(acrtc_state->stream);
+
+                       /* Allow PSR when skip count is 0. */
+                       acrtc_attach->dm_irq_params.allow_psr_entry = !aconn->psr_skip_count;
+               } else {
+                       acrtc_attach->dm_irq_params.allow_psr_entry = false;
                }
 
                mutex_unlock(&dm->dc_lock);
@@ -8953,8 +8981,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 
        if (dc_state) {
                /* if there mode set or reset, disable eDP PSR */
-               if (mode_set_reset_required)
+               if (mode_set_reset_required) {
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+                       flush_workqueue(dm->vblank_control_workqueue);
+#endif
                        amdgpu_dm_psr_disable_all(dm);
+               }
 
                dm_enable_per_frame_crtc_master_sync(dc_state);
                mutex_lock(&dm->dc_lock);
@@ -9191,8 +9223,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||          \
        defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
        /* restore the backlight level */
-       if (dm->backlight_dev && (amdgpu_dm_backlight_get_level(dm) != dm->brightness[0]))
-               amdgpu_dm_backlight_set_level(dm, dm->brightness[0]);
+       for (i = 0; i < dm->num_of_edps; i++) {
+               if (dm->backlight_dev[i] &&
+                   (amdgpu_dm_backlight_get_level(dm, i) != dm->brightness[i]))
+                       amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
+       }
 #endif
        /*
         * send vblank event on all events not handled in flip and
@@ -9605,7 +9640,12 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                } else if (amdgpu_freesync_vid_mode && aconnector &&
                           is_freesync_video_mode(&new_crtc_state->mode,
                                                  aconnector)) {
-                       set_freesync_fixed_config(dm_new_crtc_state);
+                       struct drm_display_mode *high_mode;
+
+                       high_mode = get_highest_refresh_rate_mode(aconnector, false);
+                       if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
+                               set_freesync_fixed_config(dm_new_crtc_state);
+                       }
                }
 
                ret = dm_atomic_get_state(state, &dm_state);
@@ -10549,13 +10589,68 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc,
        return capable;
 }
 
-static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
+static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
+               unsigned int offset,
+               unsigned int total_length,
+               uint8_t *data,
+               unsigned int length,
+               struct amdgpu_hdmi_vsdb_info *vsdb)
+{
+       bool res;
+       union dmub_rb_cmd cmd;
+       struct dmub_cmd_send_edid_cea *input;
+       struct dmub_cmd_edid_cea_output *output;
+
+       if (length > DMUB_EDID_CEA_DATA_CHUNK_BYTES)
+               return false;
+
+       memset(&cmd, 0, sizeof(cmd));
+
+       input = &cmd.edid_cea.data.input;
+
+       cmd.edid_cea.header.type = DMUB_CMD__EDID_CEA;
+       cmd.edid_cea.header.sub_type = 0;
+       cmd.edid_cea.header.payload_bytes =
+               sizeof(cmd.edid_cea) - sizeof(cmd.edid_cea.header);
+       input->offset = offset;
+       input->length = length;
+       input->total_length = total_length;
+       memcpy(input->payload, data, length);
+
+       res = dc_dmub_srv_cmd_with_reply_data(dm->dc->ctx->dmub_srv, &cmd);
+       if (!res) {
+               DRM_ERROR("EDID CEA parser failed\n");
+               return false;
+       }
+
+       output = &cmd.edid_cea.data.output;
+
+       if (output->type == DMUB_CMD__EDID_CEA_ACK) {
+               if (!output->ack.success) {
+                       DRM_ERROR("EDID CEA ack failed at offset %d\n",
+                                       output->ack.offset);
+               }
+       } else if (output->type == DMUB_CMD__EDID_CEA_AMD_VSDB) {
+               if (!output->amd_vsdb.vsdb_found)
+                       return false;
+
+               vsdb->freesync_supported = output->amd_vsdb.freesync_supported;
+               vsdb->amd_vsdb_version = output->amd_vsdb.amd_vsdb_version;
+               vsdb->min_refresh_rate_hz = output->amd_vsdb.min_frame_rate;
+               vsdb->max_refresh_rate_hz = output->amd_vsdb.max_frame_rate;
+       } else {
+               DRM_WARN("Unknown EDID CEA parser results\n");
+               return false;
+       }
+
+       return true;
+}
+
+static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
                uint8_t *edid_ext, int len,
                struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
        int i;
-       struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
-       struct dc *dc = adev->dm.dc;
 
        /* send extension block to DMCU for parsing */
        for (i = 0; i < len; i += 8) {
@@ -10563,14 +10658,14 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
                int offset;
 
                /* send 8 bytes a time */
-               if (!dc_edid_parser_send_cea(dc, i, len, &edid_ext[i], 8))
+               if (!dc_edid_parser_send_cea(dm->dc, i, len, &edid_ext[i], 8))
                        return false;
 
                if (i+8 == len) {
                        /* EDID block sent completed, expect result */
                        int version, min_rate, max_rate;
 
-                       res = dc_edid_parser_recv_amd_vsdb(dc, &version, &min_rate, &max_rate);
+                       res = dc_edid_parser_recv_amd_vsdb(dm->dc, &version, &min_rate, &max_rate);
                        if (res) {
                                /* amd vsdb found */
                                vsdb_info->freesync_supported = 1;
@@ -10584,7 +10679,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
                }
 
                /* check for ack*/
-               res = dc_edid_parser_recv_cea_ack(dc, &offset);
+               res = dc_edid_parser_recv_cea_ack(dm->dc, &offset);
                if (!res)
                        return false;
        }
@@ -10592,6 +10687,34 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
        return false;
 }
 
+static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
+               uint8_t *edid_ext, int len,
+               struct amdgpu_hdmi_vsdb_info *vsdb_info)
+{
+       int i;
+
+       /* send extension block to DMCU for parsing */
+       for (i = 0; i < len; i += 8) {
+               /* send 8 bytes a time */
+               if (!dm_edid_parser_send_cea(dm, i, len, &edid_ext[i], 8, vsdb_info))
+                       return false;
+       }
+
+       return vsdb_info->freesync_supported;
+}
+
+static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
+               uint8_t *edid_ext, int len,
+               struct amdgpu_hdmi_vsdb_info *vsdb_info)
+{
+       struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
+
+       if (adev->dm.dmub_srv)
+               return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
+       else
+               return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+}
+
 static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
                struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {