[PATCH 24/26] drm/i915: Decouple DP++ from the HDMI code
Ville Syrjala
ville.syrjala at linux.intel.com
Mon Feb 3 15:13:41 UTC 2020
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
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 at linux.intel.com>
---
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
More information about the dri-devel
mailing list