Merge tag 'amd-drm-next-6.3-2023-01-27' of https://gitlab.freedesktop.org/agd5f/linux...
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / amdgpu_dm / amdgpu_dm.c
index 8e4b668..e1d6382 100644 (file)
@@ -28,7 +28,6 @@
 
 #include "dm_services_types.h"
 #include "dc.h"
-#include "dc_link_dp.h"
 #include "link_enc_cfg.h"
 #include "dc/inc/core_types.h"
 #include "dal_asic_id.h"
@@ -39,6 +38,9 @@
 #include "dc/dc_edid_parser.h"
 #include "dc/dc_stat.h"
 #include "amdgpu_dm_trace.h"
+#include "dpcd_defs.h"
+#include "link/protocols/link_dpcd.h"
+#include "link_service_types.h"
 
 #include "vid.h"
 #include "amdgpu.h"
@@ -1225,10 +1227,25 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
        pa_config->gart_config.page_table_end_addr = page_table_end.quad_part << 12;
        pa_config->gart_config.page_table_base_addr = page_table_base.quad_part;
 
-       pa_config->is_hvm_enabled = 0;
+       pa_config->is_hvm_enabled = adev->mode_info.gpu_vm_support;
 
 }
 
+static void force_connector_state(
+       struct amdgpu_dm_connector *aconnector,
+       enum drm_connector_force force_state)
+{
+       struct drm_connector *connector = &aconnector->base;
+
+       mutex_lock(&connector->dev->mode_config.mutex);
+       aconnector->base.force = force_state;
+       mutex_unlock(&connector->dev->mode_config.mutex);
+
+       mutex_lock(&aconnector->hpd_lock);
+       drm_kms_helper_connector_hotplug_event(connector);
+       mutex_unlock(&aconnector->hpd_lock);
+}
+
 static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
 {
        struct hpd_rx_irq_offload_work *offload_work;
@@ -1237,6 +1254,9 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
        struct amdgpu_device *adev;
        enum dc_connection_type new_connection_type = dc_connection_none;
        unsigned long flags;
+       union test_response test_response;
+
+       memset(&test_response, 0, sizeof(test_response));
 
        offload_work = container_of(work, struct hpd_rx_irq_offload_work, work);
        aconnector = offload_work->offload_wq->aconnector;
@@ -1261,10 +1281,26 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
                goto skip;
 
        mutex_lock(&adev->dm.dc_lock);
-       if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST)
+       if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
                dc_link_dp_handle_automated_test(dc_link);
+
+               if (aconnector->timing_changed) {
+                       /* force connector disconnect and reconnect */
+                       force_connector_state(aconnector, DRM_FORCE_OFF);
+                       msleep(100);
+                       force_connector_state(aconnector, DRM_FORCE_UNSPECIFIED);
+               }
+
+               test_response.bits.ACK = 1;
+
+               core_link_write_dpcd(
+               dc_link,
+               DP_TEST_RESPONSE,
+               &test_response.raw,
+               sizeof(test_response));
+       }
        else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
-                       hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) &&
+                       dc_link_check_link_loss_status(dc_link, &offload_work->data) &&
                        dc_link_dp_allow_hpd_rx_irq(dc_link)) {
                dc_link_dp_handle_link_loss(dc_link);
                spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
@@ -2197,7 +2233,7 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
        drm_for_each_connector_iter(connector, &iter) {
                aconnector = to_amdgpu_dm_connector(connector);
                if (aconnector->dc_link->type != dc_connection_mst_branch ||
-                   aconnector->mst_port)
+                   aconnector->mst_root)
                        continue;
 
                mgr = &aconnector->mst_mgr;
@@ -2987,6 +3023,10 @@ void amdgpu_dm_update_connector_after_detect(
                                                    aconnector->edid);
                }
 
+               aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL);
+               if (!aconnector->timing_requested)
+                       dm_error("%s: failed to create aconnector->requested_timing\n", __func__);
+
                drm_connector_update_edid_property(connector, aconnector->edid);
                amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
                update_connector_ext_caps(aconnector);
@@ -2998,6 +3038,8 @@ void amdgpu_dm_update_connector_after_detect(
                dc_sink_release(aconnector->dc_sink);
                aconnector->dc_sink = NULL;
                aconnector->edid = NULL;
+               kfree(aconnector->timing_requested);
+               aconnector->timing_requested = NULL;
 #ifdef CONFIG_DRM_AMD_DC_HDCP
                /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */
                if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)
@@ -3042,6 +3084,8 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
        if (aconnector->fake_enable)
                aconnector->fake_enable = false;
 
+       aconnector->timing_changed = false;
+
        if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
                DRM_ERROR("KMS: Failed to detect connector\n");
 
@@ -5888,6 +5932,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                        stream, &mode, &aconnector->base, con_state, old_stream,
                        requested_bpc);
 
+       if (aconnector->timing_changed) {
+               DC_LOG_DEBUG("%s: overriding timing for automated test, bpc %d, changing to %d\n",
+                               __func__,
+                               stream->timing.display_color_depth,
+                               aconnector->timing_requested->display_color_depth);
+               stream->timing = *aconnector->timing_requested;
+       }
+
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        /* SST DSC determination policy */
        update_dsc_caps(aconnector, sink, stream, &dsc_caps);
@@ -6580,11 +6632,11 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
        int clock, bpp = 0;
        bool is_y420 = false;
 
-       if (!aconnector->port || !aconnector->dc_sink)
+       if (!aconnector->mst_output_port || !aconnector->dc_sink)
                return 0;
 
-       mst_port = aconnector->port;
-       mst_mgr = &aconnector->mst_port->mst_mgr;
+       mst_port = aconnector->mst_output_port;
+       mst_mgr = &aconnector->mst_root->mst_mgr;
 
        if (!crtc_state->connectors_changed && !crtc_state->mode_changed)
                return 0;
@@ -6594,7 +6646,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
                return PTR_ERR(mst_state);
 
        if (!mst_state->pbn_div)
-               mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_port->dc_link);
+               mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_root->dc_link);
 
        if (!state->duplicated) {
                int max_bpc = conn_state->max_requested_bpc;
@@ -6640,7 +6692,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
 
                aconnector = to_amdgpu_dm_connector(connector);
 
-               if (!aconnector->port)
+               if (!aconnector->mst_output_port)
                        continue;
 
                if (!new_con_state || !new_con_state->crtc)
@@ -6680,7 +6732,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
                        dm_conn_state->pbn = pbn;
                        dm_conn_state->vcpi_slots = slot_num;
 
-                       ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port,
+                       ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->mst_output_port,
                                                           dm_conn_state->pbn, false);
                        if (ret < 0)
                                return ret;
@@ -6688,7 +6740,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,
                        continue;
                }
 
-               vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, pbn, true);
+               vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->mst_output_port, pbn, true);
                if (vcpi < 0)
                        return vcpi;
 
@@ -7102,7 +7154,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
                                adev->mode_info.underscan_vborder_property,
                                0);
 
-       if (!aconnector->mst_port)
+       if (!aconnector->mst_root)
                drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
 
        /* This defaults to the max in the range, but we want 8bpc for non-edp. */
@@ -7120,7 +7172,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
            connector_type == DRM_MODE_CONNECTOR_eDP) {
                drm_connector_attach_hdr_output_metadata_property(&aconnector->base);
 
-               if (!aconnector->mst_port)
+               if (!aconnector->mst_root)
                        drm_connector_attach_vrr_capable_property(&aconnector->base);
 
 #ifdef CONFIG_DRM_AMD_DC_HDCP
@@ -7604,6 +7656,7 @@ static void update_freesync_state_on_stream(
        new_crtc_state->vrr_infopacket = vrr_infopacket;
 
        new_stream->vrr_infopacket = vrr_infopacket;
+       new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params);
 
        if (new_crtc_state->freesync_vrr_info_changed)
                DRM_DEBUG_KMS("VRR packet update: crtc=%u enabled=%d state=%d",
@@ -8818,22 +8871,15 @@ 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;
 
-       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;
-
        if (new_crtc_state->vrr_supported) {
+               new_crtc_state->stream->ignore_msa_timing_param = true;
                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;
@@ -9032,6 +9078,13 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                if (!dm_old_crtc_state->stream)
                        goto skip_modeset;
 
+               /* Unset freesync video if it was active before */
+               if (dm_old_crtc_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) {
+                       dm_new_crtc_state->freesync_config.state = VRR_STATE_INACTIVE;
+                       dm_new_crtc_state->freesync_config.fixed_refresh_in_uhz = 0;
+               }
+
+               /* Now check if we should set freesync video mode */
                if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream &&
                    is_timing_unchanged_for_freesync(new_crtc_state,
                                                     old_crtc_state)) {
@@ -9593,7 +9646,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
                        continue;
 
                aconnector = to_amdgpu_dm_connector(connector);
-               if (!aconnector->port || !aconnector->mst_port)
+               if (!aconnector->mst_output_port || !aconnector->mst_root)
                        aconnector = NULL;
                else
                        break;
@@ -9602,7 +9655,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
        if (!aconnector)
                return 0;
 
-       return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_port->mst_mgr);
+       return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_root->mst_mgr);
 }
 #endif
 
@@ -9648,6 +9701,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        bool lock_and_validation_needed = false;
        struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
 #if defined(CONFIG_DRM_AMD_DC_DCN)
+       struct drm_dp_mst_topology_mgr *mgr;
+       struct drm_dp_mst_topology_state *mst_state;
        struct dsc_mst_fairness_vars vars[MAX_PIPES];
 #endif
 
@@ -9896,6 +9951,28 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
                lock_and_validation_needed = true;
        }
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+       /* set the slot info for each mst_state based on the link encoding format */
+       for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) {
+               struct amdgpu_dm_connector *aconnector;
+               struct drm_connector *connector;
+               struct drm_connector_list_iter iter;
+               u8 link_coding_cap;
+
+               drm_connector_list_iter_begin(dev, &iter);
+               drm_for_each_connector_iter(connector, &iter) {
+                       if (connector->index == mst_state->mgr->conn_base_id) {
+                               aconnector = to_amdgpu_dm_connector(connector);
+                               link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(aconnector->dc_link);
+                               drm_dp_mst_update_slots(mst_state, link_coding_cap);
+
+                               break;
+                       }
+               }
+               drm_connector_list_iter_end(&iter);
+       }
+#endif
+
        /**
         * Streams and planes are reset when there are changes that affect
         * bandwidth. Anything that affects bandwidth needs to go through
@@ -10165,11 +10242,15 @@ static bool parse_edid_cea(struct amdgpu_dm_connector *aconnector,
                struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
        struct amdgpu_device *adev = drm_to_adev(aconnector->base.dev);
+       bool ret;
 
+       mutex_lock(&adev->dm.dc_lock);
        if (adev->dm.dmub_srv)
-               return parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
+               ret = parse_edid_cea_dmub(&adev->dm, edid_ext, len, vsdb_info);
        else
-               return parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+               ret = parse_edid_cea_dmcu(&adev->dm, edid_ext, len, vsdb_info);
+       mutex_unlock(&adev->dm.dc_lock);
+       return ret;
 }
 
 static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
@@ -10445,6 +10526,7 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(
        ret = p_notify->aux_reply.length;
        *operation_result = p_notify->result;
 out:
+       reinit_completion(&adev->dm.dmub_aux_transfer_done);
        mutex_unlock(&adev->dm.dpia_aux_lock);
        return ret;
 }
@@ -10472,6 +10554,8 @@ int amdgpu_dm_process_dmub_set_config_sync(
                *operation_result = SET_CONFIG_UNKNOWN_ERROR;
        }
 
+       if (!is_cmd_complete)
+               reinit_completion(&adev->dm.dmub_aux_transfer_done);
        mutex_unlock(&adev->dm.dpia_aux_lock);
        return ret;
 }