From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Decouple the DP dual mode adaptor stuff from the HDMI code so that we can try to use it for DP branch downstream facing HDMI ports as well. Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_ddi.c | 6 +- .../drm/i915/display/intel_display_types.h | 12 ++- drivers/gpu/drm/i915/display/intel_hdmi.c | 94 ++++++++++--------- drivers/gpu/drm/i915/display/intel_hdmi.h | 9 +- 4 files changed, 72 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3d1393ff6435..92c280905f31 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3598,7 +3598,8 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, int level = intel_ddi_hdmi_level(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); + intel_dp_dual_mode_set_tmds_output(encoder, + &intel_hdmi->dp_dual_mode, true); intel_ddi_clk_select(encoder, crtc_state); intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); @@ -3778,7 +3779,8 @@ static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder, intel_ddi_clk_disable(encoder); - intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); + intel_dp_dual_mode_set_tmds_output(encoder, + &intel_hdmi->dp_dual_mode, false); } static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 00471791d772..0d135859e9d4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -46,6 +46,7 @@ #include "i915_drv.h" #include "intel_de.h" +struct i2c_adapter; struct drm_printer; struct __intel_global_objs_state; @@ -1150,15 +1151,18 @@ struct cxsr_latency { #define to_intel_plane_state(x) container_of(x, struct intel_plane_state, uapi) #define intel_fb_obj(x) ((x) ? to_intel_bo((x)->obj[0]) : NULL) +struct intel_dp_dual_mode { + struct i2c_adapter *adapter; + int max_tmds_clock; + enum drm_dp_dual_mode_type type; +}; + struct intel_hdmi { i915_reg_t hdmi_reg; int ddc_bus; - struct { - enum drm_dp_dual_mode_type type; - int max_tmds_clock; - } dp_dual_mode; bool has_hdmi_sink; bool has_audio; + struct intel_dp_dual_mode dp_dual_mode; struct intel_connector *attached_connector; struct cec_notifier *cec_notifier; }; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 9e0316f6eb3f..ad8e974585b9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1249,20 +1249,19 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, &crtc_state->infoframes.drm); } -void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) +void intel_dp_dual_mode_set_tmds_output(struct intel_encoder *encoder, + struct intel_dp_dual_mode *dp_dual_mode, + bool enable) { - struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); - struct i2c_adapter *adapter = - intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); - - if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI) + if (dp_dual_mode->type < DRM_DP_DUAL_MODE_TYPE2_DVI) return; - DRM_DEBUG_KMS("%s DP dual mode adaptor TMDS output\n", + DRM_DEBUG_KMS("[ENCODER:%d:%s] %s DP dual mode adaptor TMDS output\n", + encoder->base.base.id, encoder->base.name, enable ? "Enabling" : "Disabling"); - drm_dp_dual_mode_set_tmds_output(hdmi->dp_dual_mode.type, - adapter, enable); + drm_dp_dual_mode_set_tmds_output(dp_dual_mode->type, + dp_dual_mode->adapter, enable); } static int intel_hdmi_hdcp_read(struct intel_digital_port *intel_dig_port, @@ -1750,7 +1749,8 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; u32 hdmi_val; - intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); + intel_dp_dual_mode_set_tmds_output(encoder, + &intel_hdmi->dp_dual_mode, true); hdmi_val = SDVO_ENCODING_HDMI; if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range) @@ -2064,7 +2064,8 @@ static void intel_disable_hdmi(struct intel_encoder *encoder, false, old_crtc_state, old_conn_state); - intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); + intel_dp_dual_mode_set_tmds_output(encoder, + &intel_hdmi->dp_dual_mode, false); } static void g4x_disable_hdmi(struct intel_encoder *encoder, @@ -2519,28 +2520,24 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, } static void -intel_hdmi_unset_edid(struct drm_connector *connector) +intel_hdmi_unset_edid(struct intel_connector *connector) { - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); intel_hdmi->has_hdmi_sink = false; intel_hdmi->has_audio = false; - intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; - intel_hdmi->dp_dual_mode.max_tmds_clock = 0; + intel_dp_dual_mode_reset(&intel_hdmi->dp_dual_mode); - kfree(to_intel_connector(connector)->detect_edid); - to_intel_connector(connector)->detect_edid = NULL; + kfree(connector->detect_edid); + connector->detect_edid = NULL; } -static void -intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) +void intel_dp_dual_mode_detect(struct intel_connector *connector, + struct intel_dp_dual_mode *dp_dual_mode, + bool assume_type1_dvi) { - struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_hdmi *hdmi = intel_attached_hdmi(to_intel_connector(connector)); - enum port port = hdmi_to_dig_port(hdmi)->base.port; - struct i2c_adapter *adapter = - intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); + struct i2c_adapter *adapter = dp_dual_mode->adapter; enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(adapter); /* @@ -2559,9 +2556,9 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) /* An overridden EDID imply that we want this port for testing. * Make sure not to set limits for that port. */ - if (has_edid && !connector->override_edid && - intel_bios_is_port_dp_dual_mode(dev_priv, port)) { - DRM_DEBUG_KMS("Assuming DP dual mode adaptor presence based on VBT\n"); + if (assume_type1_dvi) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Assuming type1 DVI DP dual mode adaptor presence\n", + connector->base.base.id, connector->base.name); type = DRM_DP_DUAL_MODE_TYPE1_DVI; } else { type = DRM_DP_DUAL_MODE_NONE; @@ -2571,20 +2568,28 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid) if (type == DRM_DP_DUAL_MODE_NONE) return; - hdmi->dp_dual_mode.type = type; - hdmi->dp_dual_mode.max_tmds_clock = + dp_dual_mode->type = type; + dp_dual_mode->max_tmds_clock = drm_dp_dual_mode_max_tmds_clock(type, adapter); - DRM_DEBUG_KMS("DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n", + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n", + connector->base.base.id, connector->base.name, drm_dp_get_dual_mode_type_name(type), - hdmi->dp_dual_mode.max_tmds_clock); + dp_dual_mode->max_tmds_clock); +} + +void intel_dp_dual_mode_reset(struct intel_dp_dual_mode *dp_dual_mode) +{ + dp_dual_mode->type = DRM_DP_DUAL_MODE_NONE; + dp_dual_mode->max_tmds_clock = 0; } static bool -intel_hdmi_set_edid(struct drm_connector *connector) +intel_hdmi_set_edid(struct intel_connector *connector) { - struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector)); + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + enum port port = hdmi_to_dig_port(intel_hdmi)->base.port; intel_wakeref_t wakeref; struct edid *edid; bool connected = false; @@ -2594,20 +2599,22 @@ intel_hdmi_set_edid(struct drm_connector *connector) i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); - edid = drm_get_edid(connector, i2c); + edid = drm_get_edid(&connector->base, i2c); if (!edid && !intel_gmbus_is_forced_bit(i2c)) { DRM_DEBUG_KMS("HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n"); intel_gmbus_force_bit(i2c, true); - edid = drm_get_edid(connector, i2c); + edid = drm_get_edid(&connector->base, i2c); intel_gmbus_force_bit(i2c, false); } - intel_hdmi_dp_dual_mode_detect(connector, edid != NULL); + intel_dp_dual_mode_detect(connector, &intel_hdmi->dp_dual_mode, + edid && !connector->base.override_edid && + intel_bios_is_port_dp_dual_mode(dev_priv, port)); intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref); - to_intel_connector(connector)->detect_edid = edid; + connector->detect_edid = edid; if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { intel_hdmi->has_audio = drm_detect_monitor_audio(edid); intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid); @@ -2638,9 +2645,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) !intel_digital_port_connected(encoder)) goto out; - intel_hdmi_unset_edid(connector); + intel_hdmi_unset_edid(to_intel_connector(connector)); - if (intel_hdmi_set_edid(connector)) + if (intel_hdmi_set_edid(to_intel_connector(connector))) status = connector_status_connected; out: @@ -2664,12 +2671,12 @@ intel_hdmi_force(struct drm_connector *connector) DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); - intel_hdmi_unset_edid(connector); + intel_hdmi_unset_edid(to_intel_connector(connector)); if (connector->status != connector_status_connected) return; - intel_hdmi_set_edid(connector); + intel_hdmi_set_edid(to_intel_connector(connector)); } static int intel_hdmi_get_modes(struct drm_connector *connector) @@ -3188,6 +3195,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) connector->ycbcr_420_allowed = true; + intel_hdmi->dp_dual_mode.adapter = + intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); + intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); if (HAS_DDI(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index 52cea8beafbb..e6f7047697ff 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -18,6 +18,7 @@ struct drm_encoder; struct drm_i915_private; struct intel_connector; struct intel_digital_port; +struct intel_dp_dual_mode; struct intel_encoder; struct intel_crtc_state; struct intel_hdmi; @@ -37,7 +38,13 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, struct drm_connector *connector, bool high_tmds_clock_ratio, bool scrambling); -void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable); +void intel_dp_dual_mode_detect(struct intel_connector *connector, + struct intel_dp_dual_mode *dp_dual_mode, + bool assume_type1_dvi); +void intel_dp_dual_mode_reset(struct intel_dp_dual_mode *dp_dual_mode); +void intel_dp_dual_mode_set_tmds_output(struct intel_encoder *encodr, + struct intel_dp_dual_mode *dp_dual_mode, + bool enable); void intel_infoframe_init(struct intel_digital_port *intel_dig_port); u32 intel_hdmi_infoframes_enabled(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); -- 2.24.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel