[24/26] drm/i915: Decouple DP++ from the HDMI code
diff mbox series

Message ID 20200203151343.14378-25-ville.syrjala@linux.intel.com
State New
Headers show
Series
  • drm/i915: Pimp DP DFP handling
Related show

Commit Message

Ville Syrjälä Feb. 3, 2020, 3:13 p.m. UTC
From: Ville Syrjälä <ville.syrjala@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@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(-)

Patch
diff mbox series

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);