From ed1984b362e5acb94bdfeb0c932f14b41ffcdecd Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 17 Aug 2017 14:58:07 -0400 Subject: [PATCH 1076/4131] drm/amd/display: Create fake sink if needed when commit stream The problem we're trying to fix is this (and similar): 1) X Desktop with single display 2) VT switch 3) Unplug display 4) VT switch back to X 5) re-plug same display Before this we'd fail at step 4 when trying to create a dc_stream_state because of a missing sink. This change will fake a sink in this case. The same scenario applies to S3 resume. Change-Id: I7bbaefc889f91021abb36e3caa6906390ab6678b Signed-off-by: Harry Wentland --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 30 ++++++++++++++++++++++- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 ++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index de19d11..4fc57e6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -978,6 +978,10 @@ static void handle_hpd_irq(void *param) * since (for MST case) MST does this in it's own context. */ mutex_lock(&aconnector->hpd_lock); + + if (aconnector->fake_enable) + aconnector->fake_enable = false; + if (dc_link_detect(aconnector->dc_link, false)) { amdgpu_dm_update_connector_after_detect(aconnector); @@ -2411,6 +2415,25 @@ static void decide_crtc_timing_for_drm_display_mode( } } +static void create_fake_sink(struct amdgpu_dm_connector *aconnector) +{ + struct dc_sink *sink = NULL; + struct dc_sink_init_data sink_init_data = { 0 }; + + sink_init_data.link = aconnector->dc_link; + sink_init_data.sink_signal = aconnector->dc_link->connector_signal; + + sink = dc_sink_create(&sink_init_data); + if (!sink) + DRM_ERROR("Failed to create sink!\n"); + + sink->sink_signal = SIGNAL_TYPE_VIRTUAL; + aconnector->fake_enable = true; + + aconnector->dc_sink = sink; + aconnector->dc_link->local_sink = sink; +} + static struct dc_stream_state *create_stream_for_sink( struct amdgpu_dm_connector *aconnector, const struct drm_display_mode *drm_mode, @@ -2433,6 +2456,10 @@ static struct dc_stream_state *create_stream_for_sink( } drm_connector = &aconnector->base; + + if (!aconnector->dc_sink) + create_fake_sink(aconnector); + stream = dc_create_stream_for_sink(aconnector->dc_sink); if (stream == NULL) { @@ -4733,7 +4760,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } else { - + + /* TODO This hack should go away */ if (aconnector) { conn_state = drm_atomic_get_connector_state(state, &aconnector->base); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 158e6b2e..8f8ef5e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -183,6 +183,8 @@ struct amdgpu_dm_connector { struct mod_freesync_caps caps; struct mutex hpd_lock; + + bool fake_enable; }; #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) -- 2.7.4