Merge tag 'amd-drm-next-6.3-2023-01-06' of https://gitlab.freedesktop.org/agd5f/linux...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index 86bc23a..cabe02c 100644 (file)
@@ -210,7 +210,7 @@ static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm);
 
 static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
                                    struct amdgpu_dm_connector *amdgpu_dm_connector,
-                                   uint32_t link_index,
+                                   u32 link_index,
                                    struct amdgpu_encoder *amdgpu_encoder);
 static int amdgpu_dm_encoder_init(struct drm_device *dev,
                                  struct amdgpu_encoder *aencoder,
@@ -262,7 +262,7 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
 static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
                                  u32 *vbl, u32 *position)
 {
-       uint32_t v_blank_start, v_blank_end, h_position, v_position;
+       u32 v_blank_start, v_blank_end, h_position, v_position;
 
        if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
                return -EINVAL;
@@ -361,7 +361,7 @@ static void dm_pflip_high_irq(void *interrupt_params)
        struct amdgpu_device *adev = irq_params->adev;
        unsigned long flags;
        struct drm_pending_vblank_event *e;
-       uint32_t vpos, hpos, v_blank_start, v_blank_end;
+       u32 vpos, hpos, v_blank_start, v_blank_end;
        bool vrr_active;
 
        amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP);
@@ -648,7 +648,7 @@ static void dmub_hpd_callback(struct amdgpu_device *adev,
        struct drm_connector *connector;
        struct drm_connector_list_iter iter;
        struct dc_link *link;
-       uint8_t link_index = 0;
+       u8 link_index = 0;
        struct drm_device *dev;
 
        if (adev == NULL)
@@ -749,7 +749,7 @@ static void dm_dmub_outbox1_low_irq(void *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;
+       u32 count = 0;
        struct dmub_hpd_work *dmub_hpd_wrk;
        struct dc_link *plink = NULL;
 
@@ -1015,7 +1015,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
        struct dmub_srv_hw_params hw_params;
        enum dmub_status status;
        const unsigned char *fw_inst_const, *fw_bss_data;
-       uint32_t i, fw_inst_const_size, fw_bss_data_size;
+       u32 i, fw_inst_const_size, fw_bss_data_size;
        bool has_hw_support;
 
        if (!dmub_srv)
@@ -1176,10 +1176,10 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev)
 
 static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
 {
-       uint64_t pt_base;
-       uint32_t logical_addr_low;
-       uint32_t logical_addr_high;
-       uint32_t agp_base, agp_bot, agp_top;
+       u64 pt_base;
+       u32 logical_addr_low;
+       u32 logical_addr_high;
+       u32 agp_base, agp_bot, agp_top;
        PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base;
 
        memset(pa_config, 0, sizeof(*pa_config));
@@ -1642,7 +1642,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        }
 #endif
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-       adev->dm.crc_rd_wrk = amdgpu_dm_crtc_secure_display_create_work();
+       adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev);
+       if (!adev->dm.secure_display_ctxs) {
+               DRM_ERROR("amdgpu: failed to initialize secure_display_ctxs.\n");
+       }
 #endif
        if (dc_is_dmub_outbox_supported(adev->dm.dc)) {
                init_completion(&adev->dm.dmub_aux_transfer_done);
@@ -1737,10 +1740,15 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
        amdgpu_dm_destroy_drm_device(&adev->dm);
 
 #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-       if (adev->dm.crc_rd_wrk) {
-               flush_work(&adev->dm.crc_rd_wrk->notify_ta_work);
-               kfree(adev->dm.crc_rd_wrk);
-               adev->dm.crc_rd_wrk = NULL;
+       if (adev->dm.secure_display_ctxs) {
+               for (i = 0; i < adev->dm.dc->caps.max_links; i++) {
+                       if (adev->dm.secure_display_ctxs[i].crtc) {
+                               flush_work(&adev->dm.secure_display_ctxs[i].notify_ta_work);
+                               flush_work(&adev->dm.secure_display_ctxs[i].forward_roi_work);
+                       }
+               }
+               kfree(adev->dm.secure_display_ctxs);
+               adev->dm.secure_display_ctxs = NULL;
        }
 #endif
 #ifdef CONFIG_DRM_AMD_DC_HDCP
@@ -2080,7 +2088,9 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
         * TODO: Move this into GART.
         */
        r = amdgpu_bo_create_kernel(adev, region_info.fb_size, PAGE_SIZE,
-                                   AMDGPU_GEM_DOMAIN_VRAM, &adev->dm.dmub_bo,
+                                   AMDGPU_GEM_DOMAIN_VRAM |
+                                   AMDGPU_GEM_DOMAIN_GTT,
+                                   &adev->dm.dmub_bo,
                                    &adev->dm.dmub_bo_gpu_addr,
                                    &adev->dm.dmub_bo_cpu_addr);
        if (r)
@@ -2165,6 +2175,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
                                DRM_ERROR("DM_MST: Failed to start MST\n");
                                aconnector->dc_link->type =
                                        dc_connection_single;
+                               ret = dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx,
+                                                                    aconnector->dc_link);
                                break;
                        }
                }
@@ -2486,7 +2498,7 @@ struct amdgpu_dm_connector *
 amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
                                             struct drm_crtc *crtc)
 {
-       uint32_t i;
+       u32 i;
        struct drm_connector_state *new_con_state;
        struct drm_connector *connector;
        struct drm_crtc *crtc_from_state;
@@ -2734,12 +2746,14 @@ static int dm_resume(void *handle)
        drm_for_each_connector_iter(connector, &iter) {
                aconnector = to_amdgpu_dm_connector(connector);
 
+               if (!aconnector->dc_link)
+                       continue;
+
                /*
                 * this is the case when traversing through already created
                 * MST connectors, should be skipped
                 */
-               if (aconnector->dc_link &&
-                   aconnector->dc_link->type == dc_connection_mst_branch)
+               if (aconnector->dc_link->type == dc_connection_mst_branch)
                        continue;
 
                mutex_lock(&aconnector->hpd_lock);
@@ -3117,8 +3131,8 @@ static void handle_hpd_irq(void *param)
 
 static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
 {
-       uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
-       uint8_t dret;
+       u8 esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
+       u8 dret;
        bool new_irq_handled = false;
        int dpcd_addr;
        int dpcd_bytes_to_read;
@@ -3146,7 +3160,7 @@ static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
 
        while (dret == dpcd_bytes_to_read &&
                process_count < max_process_count) {
-               uint8_t retry;
+               u8 retry;
                dret = 0;
 
                process_count++;
@@ -3165,7 +3179,7 @@ static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
                                dpcd_bytes_to_read - 1;
 
                        for (retry = 0; retry < 3; retry++) {
-                               uint8_t wret;
+                               u8 wret;
 
                                wret = drm_dp_dpcd_write(
                                        &aconnector->dm_dp_aux.aux,
@@ -4179,12 +4193,12 @@ static void amdgpu_set_panel_orientation(struct drm_connector *connector);
 static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
 {
        struct amdgpu_display_manager *dm = &adev->dm;
-       int32_t i;
+       s32 i;
        struct amdgpu_dm_connector *aconnector = NULL;
        struct amdgpu_encoder *aencoder = NULL;
        struct amdgpu_mode_info *mode_info = &adev->mode_info;
-       uint32_t link_cnt;
-       int32_t primary_planes;
+       u32 link_cnt;
+       s32 primary_planes;
        enum dc_connection_type new_connection_type = dc_connection_none;
        const struct dc_plane_cap *plane;
        bool psr_feature_enabled = false;
@@ -4701,7 +4715,7 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
 static int
 fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
                            const struct drm_plane_state *plane_state,
-                           const uint64_t tiling_flags,
+                           const u64 tiling_flags,
                            struct dc_plane_info *plane_info,
                            struct dc_plane_address *address,
                            bool tmz_surface,
@@ -4876,7 +4890,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
 
 static inline void fill_dc_dirty_rect(struct drm_plane *plane,
                                      struct rect *dirty_rect, int32_t x,
-                                     int32_t y, int32_t width, int32_t height,
+                                     s32 y, s32 width, s32 height,
                                      int *i, bool ffu)
 {
        if (*i > DC_MAX_DIRTY_RECTS)
@@ -4932,11 +4946,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
 {
        struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
        struct rect *dirty_rects = flip_addrs->dirty_rects;
-       uint32_t num_clips;
+       u32 num_clips;
        struct drm_mode_rect *clips;
        bool bb_changed;
        bool fb_changed;
-       uint32_t i = 0;
+       u32 i = 0;
 
        /*
         * Cursor plane has it's own dirty rect update interface. See
@@ -5082,7 +5096,7 @@ static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector,
                                      bool is_y420, int requested_bpc)
 {
-       uint8_t bpc;
+       u8 bpc;
 
        if (is_y420) {
                bpc = 8;
@@ -5626,8 +5640,8 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector,
                                    uint32_t max_dsc_target_bpp_limit_override)
 {
        const struct dc_link_settings *verified_link_cap = NULL;
-       uint32_t link_bw_in_kbps;
-       uint32_t edp_min_bpp_x16, edp_max_bpp_x16;
+       u32 link_bw_in_kbps;
+       u32 edp_min_bpp_x16, edp_max_bpp_x16;
        struct dc *dc = sink->ctx->dc;
        struct dc_dsc_bw_range bw_range = {0};
        struct dc_dsc_config dsc_cfg = {0};
@@ -5684,11 +5698,11 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
                                        struct dsc_dec_dpcd_caps *dsc_caps)
 {
        struct drm_connector *drm_connector = &aconnector->base;
-       uint32_t link_bandwidth_kbps;
+       u32 link_bandwidth_kbps;
        struct dc *dc = sink->ctx->dc;
-       uint32_t max_supported_bw_in_kbps, timing_bw_in_kbps;
-       uint32_t dsc_max_supported_bw_in_kbps;
-       uint32_t max_dsc_target_bpp_limit_override =
+       u32 max_supported_bw_in_kbps, timing_bw_in_kbps;
+       u32 dsc_max_supported_bw_in_kbps;
+       u32 max_dsc_target_bpp_limit_override =
                drm_connector->display_info.max_dsc_bpp;
 
        link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
@@ -5835,7 +5849,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                 */
                DRM_DEBUG_DRIVER("No preferred mode found\n");
        } else {
-               recalculate_timing = is_freesync_video_mode(&mode, aconnector);
+               recalculate_timing = amdgpu_freesync_vid_mode &&
+                                is_freesync_video_mode(&mode, aconnector);
                if (recalculate_timing) {
                        freesync_mode = get_highest_refresh_rate_mode(aconnector, false);
                        drm_mode_copy(&saved_mode, &mode);
@@ -6909,7 +6924,7 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
        const struct drm_display_mode *m;
        struct drm_display_mode *new_mode;
        uint i;
-       uint32_t new_modes_count = 0;
+       u32 new_modes_count = 0;
 
        /* Standard FPS values
         *
@@ -6923,7 +6938,7 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
         * 60           - Commonly used
         * 48,72,96,120 - Multiples of 24
         */
-       static const uint32_t common_rates[] = {
+       static const u32 common_rates[] = {
                23976, 24000, 25000, 29970, 30000,
                48000, 50000, 60000, 72000, 96000, 120000
        };
@@ -6939,8 +6954,8 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector)
                return 0;
 
        for (i = 0; i < ARRAY_SIZE(common_rates); i++) {
-               uint64_t target_vtotal, target_vtotal_diff;
-               uint64_t num, den;
+               u64 target_vtotal, target_vtotal_diff;
+               u64 num, den;
 
                if (drm_mode_vrefresh(m) * 1000 < common_rates[i])
                        continue;
@@ -6986,7 +7001,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect
        struct amdgpu_dm_connector *amdgpu_dm_connector =
                to_amdgpu_dm_connector(connector);
 
-       if (!edid)
+       if (!(amdgpu_freesync_vid_mode && edid))
                return;
 
        if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
@@ -7182,7 +7197,7 @@ create_i2c(struct ddc_service *ddc_service,
  */
 static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
                                    struct amdgpu_dm_connector *aconnector,
-                                   uint32_t link_index,
+                                   u32 link_index,
                                    struct amdgpu_encoder *aencoder)
 {
        int res = 0;
@@ -7367,27 +7382,55 @@ is_scaling_state_different(const struct dm_connector_state *dm_state,
 }
 
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-static bool is_content_protection_different(struct drm_connector_state *state,
-                                           const struct drm_connector_state *old_state,
-                                           const struct drm_connector *connector, struct hdcp_workqueue *hdcp_w)
+static bool is_content_protection_different(struct drm_crtc_state *new_crtc_state,
+                                           struct drm_crtc_state *old_crtc_state,
+                                           struct drm_connector_state *new_conn_state,
+                                           struct drm_connector_state *old_conn_state,
+                                           const struct drm_connector *connector,
+                                           struct hdcp_workqueue *hdcp_w)
 {
        struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
        struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state);
 
-       /* Handle: Type0/1 change */
-       if (old_state->hdcp_content_type != state->hdcp_content_type &&
-           state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
-               state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+       pr_debug("[HDCP_DM] connector->index: %x connect_status: %x dpms: %x\n",
+               connector->index, connector->status, connector->dpms);
+       pr_debug("[HDCP_DM] state protection old: %x new: %x\n",
+               old_conn_state->content_protection, new_conn_state->content_protection);
+
+       if (old_crtc_state)
+               pr_debug("[HDCP_DM] old crtc en: %x a: %x m: %x a-chg: %x c-chg: %x\n",
+               old_crtc_state->enable,
+               old_crtc_state->active,
+               old_crtc_state->mode_changed,
+               old_crtc_state->active_changed,
+               old_crtc_state->connectors_changed);
+
+       if (new_crtc_state)
+               pr_debug("[HDCP_DM] NEW crtc en: %x a: %x m: %x a-chg: %x c-chg: %x\n",
+               new_crtc_state->enable,
+               new_crtc_state->active,
+               new_crtc_state->mode_changed,
+               new_crtc_state->active_changed,
+               new_crtc_state->connectors_changed);
+
+       /* hdcp content type change */
+       if (old_conn_state->hdcp_content_type != new_conn_state->hdcp_content_type &&
+           new_conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
+               new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+               pr_debug("[HDCP_DM] Type0/1 change %s :true\n", __func__);
                return true;
        }
 
-       /* CP is being re enabled, ignore this
-        *
-        * Handles:     ENABLED -> DESIRED
-        */
-       if (old_state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED &&
-           state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) {
-               state->content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+       /* CP is being re enabled, ignore this */
+       if (old_conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED &&
+           new_conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) {
+               if (new_crtc_state && new_crtc_state->mode_changed) {
+                       new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+                       pr_debug("[HDCP_DM] ENABLED->DESIRED & mode_changed %s :true\n", __func__);
+                       return true;
+               };
+               new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
+               pr_debug("[HDCP_DM] ENABLED -> DESIRED %s :false\n", __func__);
                return false;
        }
 
@@ -7395,9 +7438,9 @@ static bool is_content_protection_different(struct drm_connector_state *state,
         *
         * Handles:     UNDESIRED -> ENABLED
         */
-       if (old_state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED &&
-           state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
-               state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
+       if (old_conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED &&
+           new_conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
+               new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
 
        /* Stream removed and re-enabled
         *
@@ -7407,10 +7450,12 @@ static bool is_content_protection_different(struct drm_connector_state *state,
         *
         * Handles:     DESIRED -> DESIRED (Special case)
         */
-       if (!(old_state->crtc && old_state->crtc->enabled) &&
-               state->crtc && state->crtc->enabled &&
+       if (!(old_conn_state->crtc && old_conn_state->crtc->enabled) &&
+               new_conn_state->crtc && new_conn_state->crtc->enabled &&
                connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) {
                dm_con_state->update_hdcp = false;
+               pr_debug("[HDCP_DM] DESIRED->DESIRED (Stream removed and re-enabled) %s :true\n",
+                       __func__);
                return true;
        }
 
@@ -7422,35 +7467,42 @@ static bool is_content_protection_different(struct drm_connector_state *state,
         *
         * Handles:     DESIRED -> DESIRED (Special case)
         */
-       if (dm_con_state->update_hdcp && state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
-           connector->dpms == DRM_MODE_DPMS_ON && aconnector->dc_sink != NULL) {
+       if (dm_con_state->update_hdcp &&
+       new_conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
+       connector->dpms == DRM_MODE_DPMS_ON && aconnector->dc_sink != NULL) {
                dm_con_state->update_hdcp = false;
+               pr_debug("[HDCP_DM] DESIRED->DESIRED (Hot-plug, headless s3, dpms) %s :true\n",
+                       __func__);
                return true;
        }
 
-       /*
-        * Handles:     UNDESIRED -> UNDESIRED
-        *              DESIRED -> DESIRED
-        *              ENABLED -> ENABLED
-        */
-       if (old_state->content_protection == state->content_protection)
+       if (old_conn_state->content_protection == new_conn_state->content_protection) {
+               if (new_conn_state->content_protection >= DRM_MODE_CONTENT_PROTECTION_DESIRED) {
+                       if (new_crtc_state && new_crtc_state->mode_changed) {
+                               pr_debug("[HDCP_DM] DESIRED->DESIRED or ENABLE->ENABLE mode_change %s :true\n",
+                                       __func__);
+                               return true;
+                       };
+                       pr_debug("[HDCP_DM] DESIRED->DESIRED & ENABLE->ENABLE %s :false\n",
+                               __func__);
+                       return false;
+               };
+
+               pr_debug("[HDCP_DM] UNDESIRED->UNDESIRED %s :false\n", __func__);
                return false;
+       }
 
-       /*
-        * Handles:     UNDESIRED -> DESIRED
-        *              DESIRED -> UNDESIRED
-        *              ENABLED -> UNDESIRED
-        */
-       if (state->content_protection != DRM_MODE_CONTENT_PROTECTION_ENABLED)
+       if (new_conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+               pr_debug("[HDCP_DM] UNDESIRED->DESIRED or DESIRED->UNDESIRED or ENABLED->UNDESIRED %s :true\n",
+                       __func__);
                return true;
+       }
 
-       /*
-        * Handles:     DESIRED -> ENABLED
-        */
+       pr_debug("[HDCP_DM] DESIRED->ENABLED %s :false\n", __func__);
        return false;
 }
-
 #endif
+
 static void remove_stream(struct amdgpu_device *adev,
                          struct amdgpu_crtc *acrtc,
                          struct dc_stream_state *stream)
@@ -7666,8 +7718,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                                    struct drm_crtc *pcrtc,
                                    bool wait_for_vblank)
 {
-       uint32_t i;
-       uint64_t timestamp_ns;
+       u32 i;
+       u64 timestamp_ns;
        struct drm_plane *plane;
        struct drm_plane_state *old_plane_state, *new_plane_state;
        struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
@@ -7678,7 +7730,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                        to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
        int planes_count = 0, vpos, hpos;
        unsigned long flags;
-       uint32_t target_vblank, last_flip_vblank;
+       u32 target_vblank, last_flip_vblank;
        bool vrr_active = amdgpu_dm_vrr_active(acrtc_state);
        bool cursor_update = false;
        bool pflip_present = false;
@@ -8116,7 +8168,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
        struct amdgpu_display_manager *dm = &adev->dm;
        struct dm_atomic_state *dm_state;
        struct dc_state *dc_state = NULL, *dc_state_temp = NULL;
-       uint32_t i, j;
+       u32 i, j;
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        unsigned long flags;
@@ -8290,10 +8342,61 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
                struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
 
+               pr_debug("[HDCP_DM] -------------- i : %x ----------\n", i);
+
+               if (!connector)
+                       continue;
+
+               pr_debug("[HDCP_DM] connector->index: %x connect_status: %x dpms: %x\n",
+                       connector->index, connector->status, connector->dpms);
+               pr_debug("[HDCP_DM] state protection old: %x new: %x\n",
+                       old_con_state->content_protection, new_con_state->content_protection);
+
+               if (aconnector->dc_sink) {
+                       if (aconnector->dc_sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&
+                               aconnector->dc_sink->sink_signal != SIGNAL_TYPE_NONE) {
+                               pr_debug("[HDCP_DM] pipe_ctx dispname=%s\n",
+                               aconnector->dc_sink->edid_caps.display_name);
+                       }
+               }
+
                new_crtc_state = NULL;
+               old_crtc_state = NULL;
 
-               if (acrtc)
+               if (acrtc) {
                        new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base);
+                       old_crtc_state = drm_atomic_get_old_crtc_state(state, &acrtc->base);
+               }
+
+               if (old_crtc_state)
+                       pr_debug("old crtc en: %x a: %x m: %x a-chg: %x c-chg: %x\n",
+                       old_crtc_state->enable,
+                       old_crtc_state->active,
+                       old_crtc_state->mode_changed,
+                       old_crtc_state->active_changed,
+                       old_crtc_state->connectors_changed);
+
+               if (new_crtc_state)
+                       pr_debug("NEW crtc en: %x a: %x m: %x a-chg: %x c-chg: %x\n",
+                       new_crtc_state->enable,
+                       new_crtc_state->active,
+                       new_crtc_state->mode_changed,
+                       new_crtc_state->active_changed,
+                       new_crtc_state->connectors_changed);
+       }
+
+       for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
+               struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state);
+               struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
+               struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+               new_crtc_state = NULL;
+               old_crtc_state = NULL;
+
+               if (acrtc) {
+                       new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base);
+                       old_crtc_state = drm_atomic_get_old_crtc_state(state, &acrtc->base);
+               }
 
                dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
 
@@ -8305,11 +8408,44 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                        continue;
                }
 
-               if (is_content_protection_different(new_con_state, old_con_state, connector, adev->dm.hdcp_workqueue))
+               if (is_content_protection_different(new_crtc_state, old_crtc_state, new_con_state,
+                                                                                       old_con_state, connector, adev->dm.hdcp_workqueue)) {
+                       /* when display is unplugged from mst hub, connctor will
+                        * be destroyed within dm_dp_mst_connector_destroy. connector
+                        * hdcp perperties, like type, undesired, desired, enabled,
+                        * will be lost. So, save hdcp properties into hdcp_work within
+                        * amdgpu_dm_atomic_commit_tail. if the same display is
+                        * plugged back with same display index, its hdcp properties
+                        * will be retrieved from hdcp_work within dm_dp_mst_get_modes
+                        */
+
+                       bool enable_encryption = false;
+
+                       if (new_con_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED)
+                               enable_encryption = true;
+
+                       if (aconnector->dc_link && aconnector->dc_sink &&
+                               aconnector->dc_link->type == dc_connection_mst_branch) {
+                               struct hdcp_workqueue *hdcp_work = adev->dm.hdcp_workqueue;
+                               struct hdcp_workqueue *hdcp_w =
+                                       &hdcp_work[aconnector->dc_link->link_index];
+
+                               hdcp_w->hdcp_content_type[connector->index] =
+                                       new_con_state->hdcp_content_type;
+                               hdcp_w->content_protection[connector->index] =
+                                       new_con_state->content_protection;
+                       }
+
+                       if (new_crtc_state && new_crtc_state->mode_changed &&
+                               new_con_state->content_protection >= DRM_MODE_CONTENT_PROTECTION_DESIRED)
+                               enable_encryption = true;
+
+                       DRM_INFO("[HDCP_DM] hdcp_update_display enable_encryption = %x\n", enable_encryption);
+
                        hdcp_update_display(
                                adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector,
-                               new_con_state->hdcp_content_type,
-                               new_con_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED);
+                               new_con_state->hdcp_content_type, enable_encryption);
+               }
        }
 #endif
 
@@ -8407,9 +8543,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 #ifdef CONFIG_DEBUG_FS
                enum amdgpu_dm_pipe_crc_source cur_crc_src;
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-               struct crc_rd_work *crc_rd_wrk;
-#endif
 #endif
                /* Count number of newly disabled CRTCs for dropping PM refs later. */
                if (old_crtc_state->active && !new_crtc_state->active)
@@ -8422,9 +8555,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                update_stream_irq_parameters(dm, dm_new_crtc_state);
 
 #ifdef CONFIG_DEBUG_FS
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-               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);
@@ -8453,10 +8583,12 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                                if (amdgpu_dm_crc_window_is_activated(crtc)) {
                                        spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
                                        acrtc->dm_irq_params.window_param.update_win = true;
+
+                                       /**
+                                        * It takes 2 frames for HW to stably generate CRC when
+                                        * resuming from suspend, so we set skip_frame_cnt 2.
+                                        */
                                        acrtc->dm_irq_params.window_param.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
@@ -8679,15 +8811,22 @@ static void get_freesync_config_for_crtc(
        struct drm_display_mode *mode = &new_crtc_state->base.mode;
        int vrefresh = drm_mode_vrefresh(mode);
        bool fs_vid_mode = false;
+       bool drr_active = false;
 
        new_crtc_state->vrr_supported = new_con_state->freesync_capable &&
                                        vrefresh >= aconnector->min_vfreq &&
                                        vrefresh <= aconnector->max_vfreq;
 
-       if (new_crtc_state->vrr_supported) {
+       drr_active = new_crtc_state->vrr_supported &&
+               new_crtc_state->freesync_config.state != VRR_STATE_DISABLED &&
+               new_crtc_state->freesync_config.state != VRR_STATE_INACTIVE &&
+               new_crtc_state->freesync_config.state != VRR_STATE_UNSUPPORTED;
+
+       if (drr_active)
                new_crtc_state->stream->ignore_msa_timing_param = true;
-               fs_vid_mode = new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
 
+       if (new_crtc_state->vrr_supported) {
+               fs_vid_mode = new_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED;
                config.min_refresh_in_uhz = aconnector->min_vfreq * 1000000;
                config.max_refresh_in_uhz = aconnector->max_vfreq * 1000000;
                config.vsif_supported = true;
@@ -8747,7 +8886,7 @@ is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
 }
 
 static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) {
-       uint64_t num, den, res;
+       u64 num, den, res;
        struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
 
        dm_new_crtc_state->freesync_config.state = VRR_STATE_ACTIVE_FIXED;
@@ -8850,7 +8989,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                 * TODO: Refactor this function to allow this check to work
                 * in all conditions.
                 */
-               if (dm_new_crtc_state->stream &&
+               if (amdgpu_freesync_vid_mode &&
+                   dm_new_crtc_state->stream &&
                    is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state))
                        goto skip_modeset;
 
@@ -8885,7 +9025,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                if (!dm_old_crtc_state->stream)
                        goto skip_modeset;
 
-               if (dm_new_crtc_state->stream &&
+               if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream &&
                    is_timing_unchanged_for_freesync(new_crtc_state,
                                                     old_crtc_state)) {
                        new_crtc_state->mode_changed = false;
@@ -8897,7 +9037,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                        set_freesync_fixed_config(dm_new_crtc_state);
 
                        goto skip_modeset;
-               } else if (aconnector &&
+               } else if (amdgpu_freesync_vid_mode && aconnector &&
                           is_freesync_video_mode(&new_crtc_state->mode,
                                                  aconnector)) {
                        struct drm_display_mode *high_mode;
@@ -9883,7 +10023,7 @@ fail:
 static bool is_dp_capable_without_timing_msa(struct dc *dc,
                                             struct amdgpu_dm_connector *amdgpu_dm_connector)
 {
-       uint8_t dpcd_data;
+       u8 dpcd_data;
        bool capable = false;
 
        if (amdgpu_dm_connector->dc_link &&
@@ -9902,7 +10042,7 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc,
 static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
                unsigned int offset,
                unsigned int total_length,
-               uint8_t *data,
+               u8 *data,
                unsigned int length,
                struct amdgpu_hdmi_vsdb_info *vsdb)
 {
@@ -9957,7 +10097,7 @@ static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm,
 }
 
 static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
-               uint8_t *edid_ext, int len,
+               u8 *edid_ext, int len,
                struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
        int i;
@@ -9998,7 +10138,7 @@ static bool parse_edid_cea_dmcu(struct amdgpu_display_manager *dm,
 }
 
 static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
-               uint8_t *edid_ext, int len,
+               u8 *edid_ext, int len,
                struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
        int i;
@@ -10014,7 +10154,7 @@ static bool parse_edid_cea_dmub(struct amdgpu_display_manager *dm,
 }
 
 static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
-               uint8_t *edid_ext, int len,
+               u8 *edid_ext, int len,
                struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
        struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
@@ -10028,7 +10168,7 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
 static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
                struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
-       uint8_t *edid_ext = NULL;
+       u8 *edid_ext = NULL;
        int i;
        bool valid_vsdb_found = false;
 
@@ -10204,7 +10344,7 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev)
 }
 
 void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
-                      uint32_t value, const char *func_name)
+                      u32 value, const char *func_name)
 {
 #ifdef DM_CHECK_ADDR_0
        if (address == 0) {
@@ -10219,7 +10359,7 @@ void dm_write_reg_func(const struct dc_context *ctx, uint32_t address,
 uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
                          const char *func_name)
 {
-       uint32_t value;
+       u32 value;
 #ifdef DM_CHECK_ADDR_0
        if (address == 0) {
                DC_ERR("invalid register read; address = 0\n");