aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/4678-drm-amd-display-Fix-Edid-emulation-for-linux.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4678-drm-amd-display-Fix-Edid-emulation-for-linux.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/4678-drm-amd-display-Fix-Edid-emulation-for-linux.patch274
1 files changed, 274 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4678-drm-amd-display-Fix-Edid-emulation-for-linux.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4678-drm-amd-display-Fix-Edid-emulation-for-linux.patch
new file mode 100644
index 00000000..db5e8287
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4678-drm-amd-display-Fix-Edid-emulation-for-linux.patch
@@ -0,0 +1,274 @@
+From 044c4f679ede41a14cb57629d58547f5a8f6bc08 Mon Sep 17 00:00:00 2001
+From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
+Date: Tue, 11 Sep 2018 15:57:28 -0400
+Subject: [PATCH 4678/5725] drm/amd/display: Fix Edid emulation for linux
+
+[Why] EDID emulation didn't work properly for linux, as we stop
+programming if nothing is connected physically.
+
+[How] We get a flag from DRM when we want to do edid emulation. We
+check if this flag is true and nothing is connected physically, if
+so we only program the front end using VIRTUAL_SIGNAL.
+
+Change-Id: I6c928dfaf1cd6fdd6b039b268e5afe091d63bb20
+Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Acked-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Kalyan Alle <kalyan.alle@amd.com>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 139 +++++++++++++++++++++-
+ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +-
+ drivers/gpu/drm/amd/display/dc/dc_link.h | 2 +
+ 3 files changed, 138 insertions(+), 7 deletions(-)
+
+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 c7b5232..913e6c1 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -638,6 +638,87 @@ amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
+ return NULL;
+ }
+
++static void emulated_link_detect(struct dc_link *link)
++{
++ struct dc_sink_init_data sink_init_data = { 0 };
++ struct display_sink_capability sink_caps = { 0 };
++ enum dc_edid_status edid_status;
++ struct dc_context *dc_ctx = link->ctx;
++ struct dc_sink *sink = NULL;
++ struct dc_sink *prev_sink = NULL;
++
++ link->type = dc_connection_none;
++ prev_sink = link->local_sink;
++
++ if (prev_sink != NULL)
++ dc_sink_retain(prev_sink);
++
++ switch (link->connector_signal) {
++ case SIGNAL_TYPE_HDMI_TYPE_A: {
++ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
++ sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
++ break;
++ }
++
++ case SIGNAL_TYPE_DVI_SINGLE_LINK: {
++ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
++ sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
++ break;
++ }
++
++ case SIGNAL_TYPE_DVI_DUAL_LINK: {
++ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
++ sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
++ break;
++ }
++
++ case SIGNAL_TYPE_LVDS: {
++ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
++ sink_caps.signal = SIGNAL_TYPE_LVDS;
++ break;
++ }
++
++ case SIGNAL_TYPE_EDP: {
++ sink_caps.transaction_type =
++ DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
++ sink_caps.signal = SIGNAL_TYPE_EDP;
++ break;
++ }
++
++ case SIGNAL_TYPE_DISPLAY_PORT: {
++ sink_caps.transaction_type =
++ DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
++ sink_caps.signal = SIGNAL_TYPE_VIRTUAL;
++ break;
++ }
++
++ default:
++ DC_ERROR("Invalid connector type! signal:%d\n",
++ link->connector_signal);
++ return;
++ }
++
++ sink_init_data.link = link;
++ sink_init_data.sink_signal = sink_caps.signal;
++
++ sink = dc_sink_create(&sink_init_data);
++ if (!sink) {
++ DC_ERROR("Failed to create sink!\n");
++ return;
++ }
++
++ link->local_sink = sink;
++
++ edid_status = dm_helpers_read_local_edid(
++ link->ctx,
++ link,
++ sink);
++
++ if (edid_status != EDID_OK)
++ DC_ERROR("Failed to read EDID");
++
++}
++
+ static int dm_resume(void *handle)
+ {
+ struct amdgpu_device *adev = handle;
+@@ -651,6 +732,7 @@ static int dm_resume(void *handle)
+ struct drm_plane *plane;
+ struct drm_plane_state *new_plane_state;
+ struct dm_plane_state *dm_new_plane_state;
++ enum dc_connection_type new_connection_type = dc_connection_none;
+ int ret;
+ int i;
+
+@@ -681,7 +763,13 @@ static int dm_resume(void *handle)
+ continue;
+
+ mutex_lock(&aconnector->hpd_lock);
+- dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
++ if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
++ DRM_ERROR("KMS: Failed to detect connector\n");
++
++ if (aconnector->base.force && new_connection_type == dc_connection_none)
++ emulated_link_detect(aconnector->dc_link);
++ else
++ dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
+
+ if (aconnector->fake_enable && aconnector->dc_link->local_sink)
+ aconnector->fake_enable = false;
+@@ -917,6 +1005,7 @@ static void handle_hpd_irq(void *param)
+ struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param;
+ struct drm_connector *connector = &aconnector->base;
+ struct drm_device *dev = connector->dev;
++ enum dc_connection_type new_connection_type = dc_connection_none;
+
+ /* In case of failure or MST no need to update connector status or notify the OS
+ * since (for MST case) MST does this in it's own context.
+@@ -926,7 +1015,21 @@ static void handle_hpd_irq(void *param)
+ if (aconnector->fake_enable)
+ aconnector->fake_enable = false;
+
+- if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) {
++ if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
++ DRM_ERROR("KMS: Failed to detect connector\n");
++
++ if (aconnector->base.force && new_connection_type == dc_connection_none) {
++ emulated_link_detect(aconnector->dc_link);
++
++
++ drm_modeset_lock_all(dev);
++ dm_restore_drm_connector_state(dev, connector);
++ drm_modeset_unlock_all(dev);
++
++ if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
++ drm_kms_helper_hotplug_event(dev);
++
++ } else if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) {
+ amdgpu_dm_update_connector_after_detect(aconnector);
+
+
+@@ -1026,6 +1129,7 @@ static void handle_hpd_rx_irq(void *param)
+ struct drm_device *dev = connector->dev;
+ struct dc_link *dc_link = aconnector->dc_link;
+ bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
++ enum dc_connection_type new_connection_type = dc_connection_none;
+
+ /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio
+ * conflict, after implement i2c helper, this mutex should be
+@@ -1037,7 +1141,24 @@ static void handle_hpd_rx_irq(void *param)
+ if (dc_link_handle_hpd_rx_irq(dc_link, NULL) &&
+ !is_mst_root_connector) {
+ /* Downstream Port status changed. */
+- if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
++ if (!dc_link_detect_sink(dc_link, &new_connection_type))
++ DRM_ERROR("KMS: Failed to detect connector\n");
++
++ if (aconnector->base.force && new_connection_type == dc_connection_none) {
++ emulated_link_detect(dc_link);
++
++ if (aconnector->fake_enable)
++ aconnector->fake_enable = false;
++
++ amdgpu_dm_update_connector_after_detect(aconnector);
++
++
++ drm_modeset_lock_all(dev);
++ dm_restore_drm_connector_state(dev, connector);
++ drm_modeset_unlock_all(dev);
++
++ drm_kms_helper_hotplug_event(dev);
++ } else if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
+
+ if (aconnector->fake_enable)
+ aconnector->fake_enable = false;
+@@ -1422,6 +1543,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+ struct amdgpu_mode_info *mode_info = &adev->mode_info;
+ uint32_t link_cnt;
+ int32_t total_overlay_planes, total_primary_planes;
++ enum dc_connection_type new_connection_type = dc_connection_none;
+
+ link_cnt = dm->dc->caps.max_links;
+ if (amdgpu_dm_mode_config_init(dm->adev)) {
+@@ -1488,7 +1610,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
+
+ link = dc_get_link_at_index(dm->dc, i);
+
+- if (dc_link_detect(link, DETECT_REASON_BOOT)) {
++ if (!dc_link_detect_sink(link, &new_connection_type))
++ DRM_ERROR("KMS: Failed to detect connector\n");
++
++ if (aconnector->base.force && new_connection_type == dc_connection_none) {
++ emulated_link_detect(link);
++ amdgpu_dm_update_connector_after_detect(aconnector);
++
++ } else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
+ amdgpu_dm_update_connector_after_detect(aconnector);
+ register_backlight_device(dm, link);
+ }
+@@ -2631,7 +2760,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
+ if (dm_state && dm_state->freesync_capable)
+ stream->ignore_msa_timing_param = true;
+ finish:
+- if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL)
++ if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL && aconnector->base.force != DRM_FORCE_ON)
+ dc_sink_release(sink);
+
+ return stream;
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+index a81ae8d..53f9db9 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+@@ -187,7 +187,7 @@ static bool program_hpd_filter(
+ return result;
+ }
+
+-static bool detect_sink(struct dc_link *link, enum dc_connection_type *type)
++bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type)
+ {
+ uint32_t is_hpd_high = 0;
+ struct gpio *hpd_pin;
+@@ -588,7 +588,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
+ if (link->connector_signal == SIGNAL_TYPE_VIRTUAL)
+ return false;
+
+- if (false == detect_sink(link, &new_connection_type)) {
++ if (false == dc_link_detect_sink(link, &new_connection_type)) {
+ BREAK_TO_DEBUGGER();
+ return false;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
+index 8a716baa..9404c6e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_link.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
+@@ -210,6 +210,8 @@ bool dc_link_dp_set_test_pattern(
+
+ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable);
+
++bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type);
++
+ /*
+ * DPCD access interfaces
+ */
+--
+2.7.4
+