Merge tag 'amd-drm-next-5.14-2021-05-21' of https://gitlab.freedesktop.org/agd5f...
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index 15070bf..515b6d7 100644 (file)
@@ -35,6 +35,7 @@
 #include "dc/inc/hw/abm.h"
 #include "dc/dc_dmub_srv.h"
 #include "dc/dc_edid_parser.h"
+#include "dc/dc_stat.h"
 #include "amdgpu_dm_trace.h"
 
 #include "vid.h"
@@ -59,6 +60,7 @@
 
 #include "ivsrcid/ivsrcid_vislands30.h"
 
+#include "i2caux_interface.h"
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/types.h>
@@ -104,6 +106,8 @@ MODULE_FIRMWARE(FIRMWARE_GREEN_SARDINE_DMUB);
 MODULE_FIRMWARE(FIRMWARE_VANGOGH_DMUB);
 #define FIRMWARE_DIMGREY_CAVEFISH_DMUB "amdgpu/dimgrey_cavefish_dmcub.bin"
 MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB);
+#define FIRMWARE_BEIGE_GOBY_DMUB "amdgpu/beige_goby_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY_DMUB);
 
 #define FIRMWARE_RAVEN_DMCU            "amdgpu/raven_dmcu.bin"
 MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
@@ -618,6 +622,58 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params)
        amdgpu_dm_crtc_handle_crc_window_irq(&acrtc->base);
 }
 #endif
+
+/**
+ * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt
+ * @interrupt_params: used for determining the Outbox instance
+ *
+ * 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;
+       struct common_irq_params *irq_params = interrupt_params;
+       struct amdgpu_device *adev = irq_params->adev;
+       struct amdgpu_display_manager *dm = &adev->dm;
+       struct dmcub_trace_buf_entry entry = { 0 };
+       uint32_t count = 0;
+
+       if (dc_enable_dmub_notifications(adev->dm.dc)) {
+               if (irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) {
+                       do {
+                               dc_stat_get_dmub_notification(adev->dm.dc, &notify);
+                       } while (notify.pending_notification);
+
+                       if (adev->dm.dmub_notify)
+                               memcpy(adev->dm.dmub_notify, &notify, sizeof(struct dmub_notification));
+                       if (notify.type == DMUB_NOTIFICATION_AUX_REPLY)
+                               complete(&adev->dm.dmub_aux_transfer_done);
+                       // TODO : HPD Implementation
+
+               } else {
+                       DRM_ERROR("DM: Failed to receive correct outbox IRQ !");
+               }
+       }
+
+
+       do {
+               if (dc_dmub_srv_get_dmub_outbox0_msg(dm->dc, &entry)) {
+                       trace_amdgpu_dmub_trace_high_irq(entry.trace_code, entry.tick_count,
+                                                       entry.param0, entry.param1);
+
+                       DRM_DEBUG_DRIVER("trace_code:%u, tick_count:%u, param0:%u, param1:%u\n",
+                                entry.trace_code, entry.tick_count, entry.param0, entry.param1);
+               } else
+                       break;
+
+               count++;
+
+       } while (count <= DMUB_TRACE_MAX_READ);
+
+       ASSERT(count <= DMUB_TRACE_MAX_READ);
+}
 #endif
 
 static int dm_set_clockgating_state(void *handle,
@@ -938,32 +994,6 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
 }
 
 #if defined(CONFIG_DRM_AMD_DC_DCN)
-#define DMUB_TRACE_MAX_READ 64
-static void dm_dmub_trace_high_irq(void *interrupt_params)
-{
-       struct common_irq_params *irq_params = interrupt_params;
-       struct amdgpu_device *adev = irq_params->adev;
-       struct amdgpu_display_manager *dm = &adev->dm;
-       struct dmcub_trace_buf_entry entry = { 0 };
-       uint32_t count = 0;
-
-       do {
-               if (dc_dmub_srv_get_dmub_outbox0_msg(dm->dc, &entry)) {
-                       trace_amdgpu_dmub_trace_high_irq(entry.trace_code, entry.tick_count,
-                                                       entry.param0, entry.param1);
-
-                       DRM_DEBUG_DRIVER("trace_code:%u, tick_count:%u, param0:%u, param1:%u\n",
-                                entry.trace_code, entry.tick_count, entry.param0, entry.param1);
-               } else
-                       break;
-
-               count++;
-
-       } while (count <= DMUB_TRACE_MAX_READ);
-
-       ASSERT(count <= DMUB_TRACE_MAX_READ);
-}
-
 static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
 {
        uint64_t pt_base;
@@ -1220,6 +1250,16 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
        adev->dm.crc_rd_wrk = amdgpu_dm_crtc_secure_display_create_work();
 #endif
+       if (dc_enable_dmub_notifications(adev->dm.dc)) {
+               init_completion(&adev->dm.dmub_aux_transfer_done);
+               adev->dm.dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_KERNEL);
+               if (!adev->dm.dmub_notify) {
+                       DRM_INFO("amdgpu: fail to allocate adev->dm.dmub_notify");
+                       goto error;
+               }
+               amdgpu_dm_outbox_init(adev);
+       }
+
        if (amdgpu_dm_initialize_drm_device(adev)) {
                DRM_ERROR(
                "amdgpu: failed to initialize sw for display support.\n");
@@ -1293,6 +1333,11 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
                adev->dm.dc->ctx->dmub_srv = NULL;
        }
 
+       if (dc_enable_dmub_notifications(adev->dm.dc)) {
+               kfree(adev->dm.dmub_notify);
+               adev->dm.dmub_notify = NULL;
+       }
+
        if (adev->dm.dmub_bo)
                amdgpu_bo_free_kernel(&adev->dm.dmub_bo,
                                      &adev->dm.dmub_bo_gpu_addr,
@@ -1357,6 +1402,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
        case CHIP_SIENNA_CICHLID:
        case CHIP_NAVY_FLOUNDER:
        case CHIP_DIMGREY_CAVEFISH:
+       case CHIP_BEIGE_GOBY:
        case CHIP_VANGOGH:
                return 0;
        case CHIP_NAVI12:
@@ -1472,6 +1518,10 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
                dmub_asic = DMUB_ASIC_DCN302;
                fw_name_dmub = FIRMWARE_DIMGREY_CAVEFISH_DMUB;
                break;
+       case CHIP_BEIGE_GOBY:
+               dmub_asic = DMUB_ASIC_DCN303;
+               fw_name_dmub = FIRMWARE_BEIGE_GOBY_DMUB;
+               break;
 
        default:
                /* ASIC doesn't support DMUB. */
@@ -1944,9 +1994,6 @@ static int dm_suspend(void *handle)
                return ret;
        }
 
-#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
-       amdgpu_dm_crtc_secure_display_suspend(adev);
-#endif
        WARN_ON(adev->dm.cached_state);
        adev->dm.cached_state = drm_atomic_helper_suspend(adev_to_drm(adev));
 
@@ -2271,10 +2318,6 @@ static int dm_resume(void *handle)
 
        dm->cached_state = NULL;
 
-#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
-       amdgpu_dm_crtc_secure_display_resume(adev);
-#endif
-
        amdgpu_dm_irq_resume_late(adev);
 
        amdgpu_dm_smu_write_watermarks_table(adev);
@@ -2725,15 +2768,15 @@ static void handle_hpd_rx_irq(void *param)
                }
        }
 
-       if (!amdgpu_in_reset(adev))
+       if (!amdgpu_in_reset(adev)) {
                mutex_lock(&adev->dm.dc_lock);
 #ifdef CONFIG_DRM_AMD_DC_HDCP
        result = dc_link_handle_hpd_rx_irq(dc_link, &hpd_irq_data, NULL);
 #else
        result = dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL);
 #endif
-       if (!amdgpu_in_reset(adev))
                mutex_unlock(&adev->dm.dc_lock);
+       }
 
 out:
        if (result && !is_mst_root_connector) {
@@ -3152,38 +3195,51 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
 
        }
 
-       if (dc->ctx->dmub_srv) {
-               i = DCN_1_0__SRCID__DMCUB_OUTBOX_HIGH_PRIORITY_READY_INT;
-               r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->dmub_trace_irq);
+       /* HPD */
+       r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT,
+                       &adev->hpd_irq);
+       if (r) {
+               DRM_ERROR("Failed to add hpd irq id!\n");
+               return r;
+       }
 
-               if (r) {
-                       DRM_ERROR("Failed to add dmub trace irq id!\n");
-                       return r;
-               }
+       register_hpd_handlers(adev);
 
-               int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+       return 0;
+}
+/* Register Outbox IRQ sources and initialize IRQ callbacks */
+static int register_outbox_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, i;
+
+       int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
+       int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
+
+       r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT,
+                       &adev->dmub_outbox_irq);
+       if (r) {
+               DRM_ERROR("Failed to add outbox irq id!\n");
+               return r;
+       }
+
+       if (dc->ctx->dmub_srv) {
+               i = DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT;
+               int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
                int_params.irq_source =
-                       dc_interrupt_to_irq_source(dc, i, 0);
+               dc_interrupt_to_irq_source(dc, i, 0);
 
-               c_irq_params = &adev->dm.dmub_trace_params[0];
+               c_irq_params = &adev->dm.dmub_outbox_params[0];
 
                c_irq_params->adev = adev;
                c_irq_params->irq_src = int_params.irq_source;
 
                amdgpu_dm_irq_register_interrupt(adev, &int_params,
-                               dm_dmub_trace_high_irq, c_irq_params);
-       }
-
-       /* HPD */
-       r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, DCN_1_0__SRCID__DC_HPD1_INT,
-                       &adev->hpd_irq);
-       if (r) {
-               DRM_ERROR("Failed to add hpd irq id!\n");
-               return r;
+                               dm_dmub_outbox1_low_irq, c_irq_params);
        }
 
-       register_hpd_handlers(adev);
-
        return 0;
 }
 #endif
@@ -3411,56 +3467,88 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap
                                 max - min);
 }
 
-static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
+static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
+                                        u32 user_brightness)
 {
-       struct amdgpu_display_manager *dm = bl_get_data(bd);
        struct amdgpu_dm_backlight_caps caps;
-       struct dc_link *link = NULL;
-       u32 brightness;
+       struct dc_link *link[AMDGPU_DM_MAX_NUM_EDP];
+       u32 brightness[AMDGPU_DM_MAX_NUM_EDP];
        bool rc;
+       int i;
 
        amdgpu_dm_update_backlight_caps(dm);
        caps = dm->backlight_caps;
 
-       link = (struct dc_link *)dm->backlight_link;
+       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];
+       }
 
-       brightness = convert_brightness_from_user(&caps, bd->props.brightness);
-       // Change brightness based on AUX property
-       if (caps.aux_support)
-               rc = dc_link_set_backlight_level_nits(link, true, brightness,
-                                                     AUX_BL_DEFAULT_TRANSITION_TIME_MS);
-       else
-               rc = dc_link_set_backlight_level(dm->backlight_link, brightness, 0);
+       /* 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_ERROR("DM: Failed to update backlight via AUX on eDP[%d]\n", i);
+                               break;
+                       }
+               }
+       } 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_ERROR("DM: Failed to update backlight on eDP[%d]\n", i);
+                               break;
+                       }
+               }
+       }
 
        return rc ? 0 : 1;
 }
 
-static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
+static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
 {
        struct amdgpu_display_manager *dm = bl_get_data(bd);
+
+       amdgpu_dm_backlight_set_level(dm, bd->props.brightness);
+
+       return 0;
+}
+
+static u32 amdgpu_dm_backlight_get_level(struct amdgpu_display_manager *dm)
+{
        struct amdgpu_dm_backlight_caps caps;
 
        amdgpu_dm_update_backlight_caps(dm);
        caps = dm->backlight_caps;
 
        if (caps.aux_support) {
-               struct dc_link *link = (struct dc_link *)dm->backlight_link;
+               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 bd->props.brightness;
+                       return dm->brightness[0];
                return convert_brightness_to_user(&caps, avg);
        } else {
-               int ret = dc_link_get_backlight_level(dm->backlight_link);
+               int ret = dc_link_get_backlight_level(dm->backlight_link[0]);
 
                if (ret == DC_ERROR_UNEXPECTED)
-                       return bd->props.brightness;
+                       return dm->brightness[0];
                return convert_brightness_to_user(&caps, ret);
        }
 }
 
+static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd)
+{
+       struct amdgpu_display_manager *dm = bl_get_data(bd);
+
+       return amdgpu_dm_backlight_get_level(dm);
+}
+
 static const struct backlight_ops amdgpu_dm_backlight_ops = {
        .options = BL_CORE_SUSPENDRESUME,
        .get_brightness = amdgpu_dm_backlight_get_brightness,
@@ -3472,8 +3560,11 @@ 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;
 
        props.max_brightness = AMDGPU_MAX_BL_LEVEL;
        props.brightness = AMDGPU_MAX_BL_LEVEL;
@@ -3550,10 +3641,13 @@ static void register_backlight_device(struct amdgpu_display_manager *dm,
                 * DM initialization because not having a backlight control
                 * is better then a black screen.
                 */
-               amdgpu_dm_register_backlight_device(dm);
+               if (!dm->backlight_dev)
+                       amdgpu_dm_register_backlight_device(dm);
 
-               if (dm->backlight_dev)
-                       dm->backlight_link = link;
+               if (dm->backlight_dev) {
+                       dm->backlight_link[dm->num_of_edps] = link;
+                       dm->num_of_edps++;
+               }
        }
 #endif
 }
@@ -3644,6 +3738,22 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
                        goto fail;
                }
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       /* Use Outbox interrupt */
+       switch (adev->asic_type) {
+       case CHIP_SIENNA_CICHLID:
+       case CHIP_NAVY_FLOUNDER:
+       case CHIP_RENOIR:
+               if (register_outbox_irq_handlers(dm->adev)) {
+                       DRM_ERROR("DM: Failed to initialize IRQ\n");
+                       goto fail;
+               }
+               break;
+       default:
+               DRM_DEBUG_KMS("Unsupported ASIC type for outbox: 0x%X\n", adev->asic_type);
+       }
+#endif
+
        /* loops over all connectors on the board */
        for (i = 0; i < link_cnt; i++) {
                struct dc_link *link = NULL;
@@ -3735,6 +3845,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
        case CHIP_SIENNA_CICHLID:
        case CHIP_NAVY_FLOUNDER:
        case CHIP_DIMGREY_CAVEFISH:
+       case CHIP_BEIGE_GOBY:
        case CHIP_VANGOGH:
                if (dcn10_register_irq_handlers(dm->adev)) {
                        DRM_ERROR("DM: Failed to initialize IRQ\n");
@@ -3914,6 +4025,11 @@ static int dm_early_init(void *handle)
                adev->mode_info.num_hpd = 5;
                adev->mode_info.num_dig = 5;
                break;
+       case CHIP_BEIGE_GOBY:
+               adev->mode_info.num_crtc = 2;
+               adev->mode_info.num_hpd = 2;
+               adev->mode_info.num_dig = 2;
+               break;
 #endif
        default:
                DRM_ERROR("Unsupported ASIC type: 0x%X\n", adev->asic_type);
@@ -4139,6 +4255,7 @@ fill_gfx9_tiling_info_from_device(const struct amdgpu_device *adev,
        if (adev->asic_type == CHIP_SIENNA_CICHLID ||
            adev->asic_type == CHIP_NAVY_FLOUNDER ||
            adev->asic_type == CHIP_DIMGREY_CAVEFISH ||
+           adev->asic_type == CHIP_BEIGE_GOBY ||
            adev->asic_type == CHIP_VANGOGH)
                tiling_info->gfx9.num_pkrs = adev->gfx.config.gb_addr_config_fields.num_pkrs;
 }
@@ -6309,25 +6426,6 @@ static int fill_hdr_info_packet(const struct drm_connector_state *state,
        return 0;
 }
 
-static bool
-is_hdr_metadata_different(const struct drm_connector_state *old_state,
-                         const struct drm_connector_state *new_state)
-{
-       struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
-       struct drm_property_blob *new_blob = new_state->hdr_output_metadata;
-
-       if (old_blob != new_blob) {
-               if (old_blob && new_blob &&
-                   old_blob->length == new_blob->length)
-                       return memcmp(old_blob->data, new_blob->data,
-                                     old_blob->length);
-
-               return true;
-       }
-
-       return false;
-}
-
 static int
 amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
                                 struct drm_atomic_state *state)
@@ -6345,7 +6443,7 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
        if (!crtc)
                return 0;
 
-       if (is_hdr_metadata_different(old_con_state, new_con_state)) {
+       if (!drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state)) {
                struct dc_info_packet hdr_infopacket;
 
                ret = fill_hdr_info_packet(new_con_state, &hdr_infopacket);
@@ -7532,9 +7630,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
            connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
            connector_type == DRM_MODE_CONNECTOR_eDP) {
-               drm_object_attach_property(
-                       &aconnector->base.base,
-                       dm->ddev->mode_config.hdr_output_metadata_property, 0);
+               drm_connector_attach_hdr_output_metadata_property(&aconnector->base);
 
                if (!aconnector->mst_port)
                        drm_connector_attach_vrr_capable_property(&aconnector->base);
@@ -8838,7 +8934,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                              dm_old_crtc_state->abm_level;
 
                hdr_changed =
-                       is_hdr_metadata_different(old_con_state, new_con_state);
+                       !drm_connector_atomic_hdr_metadata_equal(old_con_state, new_con_state);
 
                if (!scaling_changed && !abm_changed && !hdr_changed)
                        continue;
@@ -8914,6 +9010,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
 #ifdef CONFIG_DEBUG_FS
                bool configure_crc = false;
                enum amdgpu_dm_pipe_crc_source cur_crc_src;
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+               struct crc_rd_work *crc_rd_wrk = dm->crc_rd_wrk;
+#endif
+               spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
+               cur_crc_src = acrtc->dm_irq_params.crc_src;
+               spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 #endif
                dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
 
@@ -8930,21 +9032,26 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                         * settings for the stream.
                         */
                        dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
-                       spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
-                       cur_crc_src = acrtc->dm_irq_params.crc_src;
-                       spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
 
                        if (amdgpu_dm_is_valid_crc_source(cur_crc_src)) {
                                configure_crc = true;
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-                               if (amdgpu_dm_crc_window_is_activated(crtc))
-                                       configure_crc = false;
+                               if (amdgpu_dm_crc_window_is_activated(crtc)) {
+                                       spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
+                                       acrtc->dm_irq_params.crc_window.update_win = true;
+                                       acrtc->dm_irq_params.crc_window.skip_frame_cnt = 2;
+                                       spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock);
+                                       crc_rd_wrk->crtc = crtc;
+                                       spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock);
+                                       spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
+                               }
 #endif
                        }
 
                        if (configure_crc)
-                               amdgpu_dm_crtc_configure_crc_source(
-                                       crtc, dm_new_crtc_state, cur_crc_src);
+                               if (amdgpu_dm_crtc_configure_crc_source(
+                                       crtc, dm_new_crtc_state, cur_crc_src))
+                                       DRM_DEBUG_DRIVER("Failed to configure crc source");
 #endif
                }
        }
@@ -8965,6 +9072,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
        /* Update audio instances for each connector. */
        amdgpu_dm_commit_audio(dev, state);
 
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||          \
+       defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+       /* restore the backlight level */
+       if (dm->backlight_dev)
+               amdgpu_dm_backlight_set_level(dm, dm->brightness[0]);
+#endif
        /*
         * send vblank event on all events not handled in flip and
         * mark consumed event for drm_atomic_helper_commit_hw_done
@@ -10689,3 +10802,30 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
 
        return value;
 }
+
+int amdgpu_dm_process_dmub_aux_transfer_sync(struct dc_context *ctx, unsigned int linkIndex,
+                               struct aux_payload *payload, enum aux_return_code_type *operation_result)
+{
+       struct amdgpu_device *adev = ctx->driver_context;
+       int ret = 0;
+
+       dc_process_dmub_aux_transfer_async(ctx->dc, linkIndex, payload);
+       ret = wait_for_completion_interruptible_timeout(&adev->dm.dmub_aux_transfer_done, 10*HZ);
+       if (ret == 0) {
+               *operation_result = AUX_RET_ERROR_TIMEOUT;
+               return -1;
+       }
+       *operation_result = (enum aux_return_code_type)adev->dm.dmub_notify->result;
+
+       if (adev->dm.dmub_notify->result == AUX_RET_SUCCESS) {
+               (*payload->reply) = adev->dm.dmub_notify->aux_reply.command;
+
+               // For read case, Copy data to payload
+               if (!payload->write && adev->dm.dmub_notify->aux_reply.length &&
+               (*payload->reply == AUX_TRANSACTION_REPLY_AUX_ACK))
+                       memcpy(payload->data, adev->dm.dmub_notify->aux_reply.data,
+                       adev->dm.dmub_notify->aux_reply.length);
+       }
+
+       return adev->dm.dmub_notify->aux_reply.length;
+}