drm/amd/display: Add debugfs for forcing stream timing sync
[why] There's currently no method to enable multi-stream synchronization from userspace and we don't check the VSDB bits to know whether or not specific displays should have the feature enable. [how] Add a debugfs entry that controls a new DM debug option, "force_timing_sync". This debug option will set on any newly created stream following the change to the debug option. Expose a new interface from DC that performs the timing sync and a helper to the "force_timing_sync" debugfs that iterates over the current streams and modifies the current synchornization state and grouping. Example usage to force a resync (from an X based desktop): echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync xset dpms force off && xset dpms force on Signed-off-by: Victor Lu <victorchengchi.lu@amd.com> Reviewed-by: Aurabindo Jayamohanan Pillai <Aurabindo.Pillai@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Acked-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
da83b385f3
commit
3d4e52d0cf
|
@ -8034,6 +8034,13 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Check VSDB bits to decide whether this should
|
||||||
|
* be enabled or not.
|
||||||
|
*/
|
||||||
|
new_stream->triggered_crtc_reset.enabled =
|
||||||
|
dm->force_timing_sync;
|
||||||
|
|
||||||
dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
|
dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
|
||||||
|
|
||||||
ret = fill_hdr_info_packet(drm_new_conn_state,
|
ret = fill_hdr_info_packet(drm_new_conn_state,
|
||||||
|
@ -9190,3 +9197,22 @@ static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream)
|
||||||
|
|
||||||
return dc_link_set_psr_allow_active(stream->link, false, true);
|
return dc_link_set_psr_allow_active(stream->link, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void amdgpu_dm_trigger_timing_sync(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
struct amdgpu_device *adev = dev->dev_private;
|
||||||
|
struct dc *dc = adev->dm.dc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
mutex_lock(&adev->dm.dc_lock);
|
||||||
|
if (dc->current_state) {
|
||||||
|
for (i = 0; i < dc->current_state->stream_count; ++i)
|
||||||
|
dc->current_state->streams[i]
|
||||||
|
->triggered_crtc_reset.enabled =
|
||||||
|
adev->dm.force_timing_sync;
|
||||||
|
|
||||||
|
dm_enable_per_frame_crtc_master_sync(dc->current_state);
|
||||||
|
dc_trigger_sync(dc, dc->current_state);
|
||||||
|
}
|
||||||
|
mutex_unlock(&adev->dm.dc_lock);
|
||||||
|
}
|
||||||
|
|
|
@ -340,6 +340,7 @@ struct amdgpu_display_manager {
|
||||||
* fake encoders used for DP MST.
|
* fake encoders used for DP MST.
|
||||||
*/
|
*/
|
||||||
struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC];
|
struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC];
|
||||||
|
bool force_timing_sync;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dsc_preferred_settings {
|
struct dsc_preferred_settings {
|
||||||
|
@ -493,6 +494,8 @@ void dm_restore_drm_connector_state(struct drm_device *dev,
|
||||||
void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||||
struct edid *edid);
|
struct edid *edid);
|
||||||
|
|
||||||
|
void amdgpu_dm_trigger_timing_sync(struct drm_device *dev);
|
||||||
|
|
||||||
#define MAX_COLOR_LUT_ENTRIES 4096
|
#define MAX_COLOR_LUT_ENTRIES 4096
|
||||||
/* Legacy gamm LUT users such as X doesn't like large LUT sizes */
|
/* Legacy gamm LUT users such as X doesn't like large LUT sizes */
|
||||||
#define MAX_COLOR_LEGACY_LUT_ENTRIES 256
|
#define MAX_COLOR_LEGACY_LUT_ENTRIES 256
|
||||||
|
|
|
@ -2183,6 +2183,38 @@ static const struct drm_info_list amdgpu_dm_debugfs_list[] = {
|
||||||
{"amdgpu_mst_topology", &mst_topo},
|
{"amdgpu_mst_topology", &mst_topo},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets the force_timing_sync debug optino from the given string.
|
||||||
|
* All connected displays will be force synchronized immediately.
|
||||||
|
* Usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync
|
||||||
|
*/
|
||||||
|
static int force_timing_sync_set(void *data, u64 val)
|
||||||
|
{
|
||||||
|
struct amdgpu_device *adev = data;
|
||||||
|
|
||||||
|
adev->dm.force_timing_sync = (bool)val;
|
||||||
|
|
||||||
|
amdgpu_dm_trigger_timing_sync(adev->ddev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the force_timing_sync debug option value into the given buffer.
|
||||||
|
* Usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync
|
||||||
|
*/
|
||||||
|
static int force_timing_sync_get(void *data, u64 *val)
|
||||||
|
{
|
||||||
|
struct amdgpu_device *adev = data;
|
||||||
|
|
||||||
|
*val = adev->dm.force_timing_sync;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_DEBUGFS_ATTRIBUTE(force_timing_sync_ops, force_timing_sync_get,
|
||||||
|
force_timing_sync_set, "%llu\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets the DC visual confirm debug option from the given string.
|
* Sets the DC visual confirm debug option from the given string.
|
||||||
* Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm
|
* Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm
|
||||||
|
@ -2242,5 +2274,8 @@ int dtn_debugfs_init(struct amdgpu_device *adev)
|
||||||
debugfs_create_file_unsafe("amdgpu_dm_dmub_fw_state", 0644, root,
|
debugfs_create_file_unsafe("amdgpu_dm_dmub_fw_state", 0644, root,
|
||||||
adev, &dmub_fw_state_fops);
|
adev, &dmub_fw_state_fops);
|
||||||
|
|
||||||
|
debugfs_create_file_unsafe("amdgpu_dm_force_timing_sync", 0644, root,
|
||||||
|
adev, &force_timing_sync_ops);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1238,6 +1238,14 @@ bool dc_enable_stereo(
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dc_trigger_sync(struct dc *dc, struct dc_state *context)
|
||||||
|
{
|
||||||
|
if (context->stream_count > 1 && !dc->debug.disable_timing_sync) {
|
||||||
|
enable_timing_multisync(dc, context);
|
||||||
|
program_timing_sync(dc, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Applies given context to HW and copy it into current context.
|
* Applies given context to HW and copy it into current context.
|
||||||
* It's up to the user to release the src context afterwards.
|
* It's up to the user to release the src context afterwards.
|
||||||
|
@ -1297,10 +1305,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
|
||||||
if (result != DC_OK)
|
if (result != DC_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if (context->stream_count > 1 && !dc->debug.disable_timing_sync) {
|
dc_trigger_sync(dc, context);
|
||||||
enable_timing_multisync(dc, context);
|
|
||||||
program_timing_sync(dc, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Program all planes within new context*/
|
/* Program all planes within new context*/
|
||||||
if (dc->hwss.program_front_end_for_ctx) {
|
if (dc->hwss.program_front_end_for_ctx) {
|
||||||
|
|
|
@ -397,6 +397,8 @@ bool dc_enable_stereo(
|
||||||
struct dc_stream_state *streams[],
|
struct dc_stream_state *streams[],
|
||||||
uint8_t stream_count);
|
uint8_t stream_count);
|
||||||
|
|
||||||
|
/* Triggers multi-stream synchronization. */
|
||||||
|
void dc_trigger_sync(struct dc *dc, struct dc_state *context);
|
||||||
|
|
||||||
enum surface_update_type dc_check_update_surfaces_for_stream(
|
enum surface_update_type dc_check_update_surfaces_for_stream(
|
||||||
struct dc *dc,
|
struct dc *dc,
|
||||||
|
|
Loading…
Reference in New Issue