aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0664-drm-amd-dal-save-MST-connection-type-in-link.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0664-drm-amd-dal-save-MST-connection-type-in-link.patch')
-rw-r--r--common/recipes-kernel/linux/files/0664-drm-amd-dal-save-MST-connection-type-in-link.patch356
1 files changed, 356 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0664-drm-amd-dal-save-MST-connection-type-in-link.patch b/common/recipes-kernel/linux/files/0664-drm-amd-dal-save-MST-connection-type-in-link.patch
new file mode 100644
index 00000000..aa588c2b
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0664-drm-amd-dal-save-MST-connection-type-in-link.patch
@@ -0,0 +1,356 @@
+From 1acb9372d7fb8a8adabf732fdbd676f990e06490 Mon Sep 17 00:00:00 2001
+From: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Date: Mon, 4 Jan 2016 10:53:15 +0800
+Subject: [PATCH 0664/1110] drm/amd/dal: save MST connection type in link
+
+Use existing connection type field in public instead
+of adding new fields. MST connection type already provided
+
+This is follow-up change for
+commit ece83f70387e2b6638d8e099e328599b233de4f5
+("drm/amd/dal: Properly handle sink removal")
+
+Signed-off-by: Mykola Lysenko <Mykola.Lysenko@amd.com>
+Acked-by: Jordan Lazare <Jordan.Lazare@amd.com>
+---
+ drivers/gpu/drm/amd/dal/dc/core/dc_link.c | 214 +++++++++++----------
+ drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 2 -
+ .../gpu/drm/amd/dal/include/ddc_service_types.h | 3 +
+ 3 files changed, 115 insertions(+), 104 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
+index 3347174..94990b9 100644
+--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c
+@@ -132,7 +132,7 @@ static bool program_hpd_filter(
+ return result;
+ }
+
+-static bool detect_sink(struct core_link *link)
++static bool detect_sink(struct core_link *link, enum dc_connection_type *type)
+ {
+ uint32_t is_hpd_high = 0;
+ struct irq *hpd_pin;
+@@ -152,10 +152,10 @@ static bool detect_sink(struct core_link *link)
+ hpd_pin);
+
+ if (is_hpd_high) {
+- link->public.type = dc_connection_single;
++ *type = dc_connection_single;
+ /* TODO: need to do the actual detection */
+ } else {
+- link->public.type = dc_connection_none;
++ *type = dc_connection_none;
+ }
+
+ return true;
+@@ -470,14 +470,87 @@ static enum dc_edid_status read_edid(
+ return edid_status;
+ }
+
++static void dc_link_detect_dp(
++ struct core_link *link,
++ struct display_sink_capability *sink_caps,
++ bool *converter_disable_audio,
++ union audio_support *audio_support)
++{
++ sink_caps->signal = link_detect_sink(link);
++ sink_caps->transaction_type =
++ get_ddc_transaction_type(sink_caps->signal);
++
++ if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
++ sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
++ detect_dp_sink_caps(link);
++
++ /* DP active dongles */
++ if (is_dp_active_dongle(link->dpcd_caps.dongle_type)) {
++ if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
++ link->public.type = dc_connection_none;
++ /*
++ * active dongle unplug processing for short irq
++ */
++ link_disconnect_all_sinks(link);
++ return;
++ }
++
++ if (link->dpcd_caps.dongle_type !=
++ DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
++ *converter_disable_audio = true;
++ }
++ }
++ if (is_mst_supported(link)) {
++ sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
++
++ /*
++ * This call will initiate MST topology discovery. Which
++ * will detect MST ports and add new DRM connector DRM
++ * framework. Then read EDID via remote i2c over aux. In
++ * the end, will notify DRM detect result and save EDID
++ * into DRM framework.
++ *
++ * .detect is called by .fill_modes.
++ * .fill_modes is called by user mode ioctl
++ * DRM_IOCTL_MODE_GETCONNECTOR.
++ *
++ * .get_modes is called by .fill_modes.
++ *
++ * call .get_modes, AMDGPU DM implementation will create
++ * new dc_sink and add to dc_link. For long HPD plug
++ * in/out, MST has its own handle.
++ *
++ * Therefore, just after dc_create, link->sink is not
++ * created for MST until user mode app calls
++ * DRM_IOCTL_MODE_GETCONNECTOR.
++ *
++ * Need check ->sink usages in case ->sink = NULL
++ * TODO: s3 resume check
++ */
++
++ if (dc_helpers_dp_mst_start_top_mgr(
++ link->ctx,
++ &link->public)) {
++ link->public.type = dc_connection_mst_branch;
++ } else {
++ /* MST not supported */
++ sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
++ }
++ }
++ } else {
++ /* DP passive dongles */
++ sink_caps->signal = dp_passive_dongle_detection(link->ddc,
++ sink_caps,
++ audio_support);
++ }
++}
++
+ void dc_link_detect(const struct dc_link *dc_link)
+ {
+ struct core_link *link = DC_LINK_TO_LINK(dc_link);
+ struct sink_init_data sink_init_data = { 0 };
+- enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE;
+ struct display_sink_capability sink_caps = { 0 };
+ uint8_t i;
+- enum signal_type signal = SIGNAL_TYPE_NONE;
+ bool converter_disable_audio = false;
+ union audio_support audio_support =
+ dal_adapter_service_get_audio_support(
+@@ -486,123 +559,57 @@ void dc_link_detect(const struct dc_link *dc_link)
+ struct dc_context *dc_ctx = link->ctx;
+ struct dc_sink *dc_sink;
+ struct core_sink *sink = NULL;
++ enum dc_connection_type new_connection_type = dc_connection_none;
+
+- if (false == detect_sink(link)) {
++ if (false == detect_sink(link, &new_connection_type)) {
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+
+- if (link->public.type != dc_connection_none) {
++ if (new_connection_type != dc_connection_none) {
++ link->public.type = new_connection_type;
++
+ /* From Disconnected-to-Connected. */
+ switch (link->public.connector_signal) {
+ case SIGNAL_TYPE_HDMI_TYPE_A: {
+- transaction_type = DDC_TRANSACTION_TYPE_I2C;
++ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+ if (audio_support.bits.HDMI_AUDIO_NATIVE)
+- signal = SIGNAL_TYPE_HDMI_TYPE_A;
++ sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+ else
+- signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
++ sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+ break;
+ }
+
+ case SIGNAL_TYPE_DVI_SINGLE_LINK: {
+- transaction_type = DDC_TRANSACTION_TYPE_I2C;
+- signal = 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: {
+- transaction_type = DDC_TRANSACTION_TYPE_I2C;
+- signal = 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_EDP: {
+ detect_dp_sink_caps(link);
+- transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+- signal = 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: {
+- signal = link_detect_sink(link);
+- transaction_type = get_ddc_transaction_type(
+- signal);
+-
+- if (transaction_type ==
+- DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
+- signal =
+- SIGNAL_TYPE_DISPLAY_PORT;
+- detect_dp_sink_caps(link);
+-
+- /* DP active dongles */
+- if (is_dp_active_dongle(
+- link->dpcd_caps.dongle_type)) {
+- if (!link->dpcd_caps.
+- sink_count.bits.SINK_COUNT) {
+- link->public.type =
+- dc_connection_none;
+- /* active dongle unplug
+- * processing for short irq
+- */
+- link_disconnect_all_sinks(link);
+- return;
+- }
+-
+- if (link->dpcd_caps.dongle_type !=
+- DISPLAY_DONGLE_DP_HDMI_CONVERTER) {
+- converter_disable_audio = true;
+- }
+- }
+- if (is_mst_supported(link)) {
+- signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
+-
+- /*
+- * This call will initiate MST topology
+- * discovery. Which will detect
+- * MST ports and add new DRM connector
+- * DRM framework. Then read EDID via
+- * remote i2c over aux.In the end, will
+- * notify DRM detect result and save
+- * EDID into DRM framework.
+- *
+- * .detect is called by .fill_modes.
+- * .fill_modes is called by user mode
+- * ioctl DRM_IOCTL_MODE_GETCONNECTOR.
+- *
+- * .get_modes is called by .fill_modes.
+- *
+- * call .get_modes, AMDGPU DM
+- * implementation will create new
+- * dc_sink and add to dc_link.
+- * For long HPD plug in/out, MST has its
+- * own handle.
+- *
+- * Therefore, just after dc_create,
+- * link->sink is not created for MST
+- * until user mode app calls
+- * DRM_IOCTL_MODE_GETCONNECTOR.
+- *
+- * Need check ->sink usages in case
+- * ->sink = NULL
+- * TODO: s3 resume check*/
+-
+- if (dc_helpers_dp_mst_start_top_mgr(
+- link->ctx,
+- &link->public)) {
+- link->mst_enabled = true;
+- return;
+- } else {
+- /* MST not supported */
+- signal = SIGNAL_TYPE_DISPLAY_PORT;
+- }
+- }
+- }
+- else {
+- /* DP passive dongles */
+- signal = dp_passive_dongle_detection(link->ddc,
+- &sink_caps,
+- &audio_support);
+- }
++ dc_link_detect_dp(
++ link,
++ &sink_caps,
++ &converter_disable_audio,
++ &audio_support);
++
++ if (link->public.type == dc_connection_mst_branch)
++ return;
++
+ break;
+ }
+
+@@ -621,14 +628,14 @@ void dc_link_detect(const struct dc_link *dc_link)
+
+ dal_ddc_service_set_transaction_type(
+ link->ddc,
+- transaction_type);
++ sink_caps.transaction_type);
+
+ sink_init_data.link = &link->public;
+- sink_init_data.sink_signal = signal;
++ sink_init_data.sink_signal = sink_caps.signal;
+ sink_init_data.dongle_max_pix_clk =
+ sink_caps.max_hdmi_pixel_clock;
+ sink_init_data.converter_disable_audio =
+- converter_disable_audio;
++ converter_disable_audio;
+
+ dc_sink = sink_create(&sink_init_data);
+ if (!dc_sink) {
+@@ -704,16 +711,19 @@ void dc_link_detect(const struct dc_link *dc_link)
+
+ } else {
+ /* From Connected-to-Disconnected. */
+- if (link->mst_enabled) {
++ if (link->public.type == dc_connection_mst_branch)
+ dc_helpers_dp_mst_stop_top_mgr(link->ctx, &link->public);
+- link->mst_enabled = false;
+- } else
++ else
+ link_disconnect_all_sinks(link);
++
++ link->public.type = dc_connection_none;
++ sink_caps.signal = SIGNAL_TYPE_NONE;
+ }
+
+ LINK_INFO("link=%d, dc_sink_in=%p is now %s\n",
+ link->public.link_index, &sink->public,
+- (signal == SIGNAL_TYPE_NONE ? "Disconnected":"Connected"));
++ (sink_caps.signal == SIGNAL_TYPE_NONE ?
++ "Disconnected":"Connected"));
+
+ return;
+ }
+diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
+index 26f5002..2b97d4d 100644
+--- a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
++++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h
+@@ -226,8 +226,6 @@ struct core_link {
+ /* MST record stream using this link */
+ const struct core_stream *enabled_streams[MAX_SINKS_PER_LINK];
+ uint8_t enabled_stream_count;
+-
+- bool mst_enabled;
+ };
+
+ #define DC_LINK_TO_LINK(dc_link) container_of(dc_link, struct core_link, public)
+diff --git a/drivers/gpu/drm/amd/dal/include/ddc_service_types.h b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
+index 21fd17e..cbdb6df 100644
+--- a/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
++++ b/drivers/gpu/drm/amd/dal/include/ddc_service_types.h
+@@ -125,6 +125,9 @@ struct display_sink_capability {
+ /* to check if we have queried the display capability
+ * for eDP panel already. */
+ bool is_edp_sink_cap_valid;
++
++ enum ddc_transaction_type transaction_type;
++ enum signal_type signal;
+ };
+
+ struct dp_receiver_id_info {
+--
+2.7.4
+