From 1acb9372d7fb8a8adabf732fdbd676f990e06490 Mon Sep 17 00:00:00 2001 From: Mykola Lysenko 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 Acked-by: Jordan Lazare --- 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