[Intel-gfx] [PATCH] drm/i915: Try to initialize eDP for both ports B and C on VLV
ville.syrjala at linux.intel.com
ville.syrjala at linux.intel.com
Thu Oct 31 17:46:22 CET 2013
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
On VLV both ports B and C can support either DP or eDP. Try to
initialize eDP first on each port, and if that fails fall back to
regular DP connector.
intel_dp_init_typed() is now like the old intel_dp_init, except you pass
in the connector type. If you pass DRM_MODE_CONNECTOR_Unknown, the code
falls back to the old port/VBT based auto detection to determine the
actual type.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71051
Tested-by: Robert Hooker <robert.hooker at canonical.com>
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
drivers/gpu/drm/i915/intel_ddi.c | 3 +-
drivers/gpu/drm/i915/intel_display.c | 11 ++++--
drivers/gpu/drm/i915/intel_dp.c | 66 ++++++++++++++++++++++--------------
drivers/gpu/drm/i915/intel_drv.h | 5 ++-
4 files changed, 54 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 31f4fe2..dd2660c 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1356,7 +1356,8 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
return NULL;
intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
- if (!intel_dp_init_connector(intel_dig_port, connector)) {
+ if (!intel_dp_init_connector(intel_dig_port, connector,
+ DRM_MODE_CONNECTOR_Unknown)) {
kfree(connector);
return NULL;
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8f40ae3..16225eb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9984,15 +9984,20 @@ static void intel_setup_outputs(struct drm_device *dev)
intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB,
PORT_B);
if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED)
- intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
+ if (!intel_dp_init_typed(dev, VLV_DISPLAY_BASE + DP_B,
+ PORT_B, DRM_MODE_CONNECTOR_eDP))
+ intel_dp_init_typed(dev, VLV_DISPLAY_BASE + DP_B,
+ PORT_B, DRM_MODE_CONNECTOR_DisplayPort);
}
if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED) {
intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC,
PORT_C);
if (I915_READ(VLV_DISPLAY_BASE + DP_C) & DP_DETECTED)
- intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C,
- PORT_C);
+ if (!intel_dp_init_typed(dev, VLV_DISPLAY_BASE + DP_C,
+ PORT_C, DRM_MODE_CONNECTOR_eDP))
+ intel_dp_init_typed(dev, VLV_DISPLAY_BASE + DP_C,
+ PORT_C, DRM_MODE_CONNECTOR_DisplayPort);
}
intel_dsi_init(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b3cc333..a97f186 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3540,7 +3540,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
bool
intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
- struct intel_connector *intel_connector)
+ struct intel_connector *intel_connector,
+ int type)
{
struct drm_connector *connector = &intel_connector->base;
struct intel_dp *intel_dp = &intel_dig_port->dp;
@@ -3549,33 +3550,32 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_dig_port->port;
const char *name = NULL;
- int type, error;
+ int error;
/* Preserve the current hw state. */
intel_dp->DP = I915_READ(intel_dp->output_reg);
intel_dp->attached_connector = intel_connector;
- type = DRM_MODE_CONNECTOR_DisplayPort;
- /*
- * FIXME : We need to initialize built-in panels before external panels.
- * For X0, DP_C is fixed as eDP. Revisit this as part of VLV eDP cleanup
- */
- switch (port) {
- case PORT_A:
- type = DRM_MODE_CONNECTOR_eDP;
- break;
- case PORT_C:
- if (IS_VALLEYVIEW(dev))
- type = DRM_MODE_CONNECTOR_eDP;
- break;
- case PORT_D:
- if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev))
+ if (type == DRM_MODE_CONNECTOR_Unknown) {
+ type = DRM_MODE_CONNECTOR_DisplayPort;
+
+ switch (port) {
+ case PORT_A:
type = DRM_MODE_CONNECTOR_eDP;
- break;
- default: /* silence GCC warning */
- break;
+ break;
+ case PORT_D:
+ if (HAS_PCH_SPLIT(dev) && intel_dpd_is_edp(dev))
+ type = DRM_MODE_CONNECTOR_eDP;
+ break;
+ default: /* silence GCC warning */
+ break;
+ }
}
+ if (WARN_ON(type != DRM_MODE_CONNECTOR_DisplayPort &&
+ type != DRM_MODE_CONNECTOR_eDP))
+ return false;
+
/*
* For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
* for DP the encoder type can be set by the caller to
@@ -3598,7 +3598,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
ironlake_panel_vdd_work);
intel_connector_attach_encoder(intel_connector, intel_encoder);
- drm_sysfs_connector_add(connector);
+ error = drm_sysfs_connector_add(connector);
+ if (error) {
+ drm_connector_cleanup(connector);
+ return false;
+ }
if (HAS_DDI(dev))
intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
@@ -3680,8 +3684,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
return true;
}
-void
-intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+bool
+intel_dp_init_typed(struct drm_device *dev, int output_reg,
+ enum port port, int type)
{
struct intel_digital_port *intel_dig_port;
struct intel_encoder *intel_encoder;
@@ -3690,12 +3695,12 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port)
- return;
+ return false;
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_dig_port);
- return;
+ return false;
}
intel_encoder = &intel_dig_port->base;
@@ -3727,9 +3732,18 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_encoder->cloneable = false;
intel_encoder->hot_plug = intel_dp_hot_plug;
- if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
+ if (!intel_dp_init_connector(intel_dig_port, intel_connector, type)) {
drm_encoder_cleanup(encoder);
kfree(intel_dig_port);
kfree(intel_connector);
+ return false;
}
+
+ return true;
+}
+
+void
+intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
+{
+ intel_dp_init_typed(dev, output_reg, port, DRM_MODE_CONNECTOR_Unknown);
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9d2624f..ff982d9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -697,8 +697,11 @@ void intel_display_set_init_power(struct drm_device *dev, bool enable);
/* intel_dp.c */
void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
+bool intel_dp_init_typed(struct drm_device *dev, int output_reg,
+ enum port port, int type);
bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
- struct intel_connector *intel_connector);
+ struct intel_connector *intel_connector,
+ int type);
void intel_dp_start_link_train(struct intel_dp *intel_dp);
void intel_dp_complete_link_train(struct intel_dp *intel_dp);
void intel_dp_stop_link_train(struct intel_dp *intel_dp);
--
1.8.1.5
More information about the Intel-gfx
mailing list