mirror of
https://github.com/torvalds/linux.git
synced 2026-04-24 09:35:52 -04:00
Merge tag 'amd-drm-next-6.3-2023-01-27' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-6.3-2023-01-27: amdgpu: - GC11 fixes - SMU13 fixes - Freesync fixes - DP MST fixes - DP MST code rework and cleanup - AV1 fixes for VCN4 - DCN 3.2.x fixes - PSR fixes - DML optimizations - DC link code rework Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230127225917.2419162-1-alexander.deucher@amd.com
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user