Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=88331
The existing code seems very carefully crafted, taking into account the
differences betweem various GPU generations etc, shuffling that around
might risk breakage. FWIW, I'm wondering if just adding a quirk for this single
Dell workstation might be justified?
Best regards,
Lukas
Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
Cc: Jesse Barnes <jbarnes@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/i915/intel_display.c | 27 ++++----
drivers/gpu/drm/i915/intel_dp.c | 127
+++++++++++++++++------------------
drivers/gpu/drm/i915/intel_drv.h | 6 +-
3 files changed, 79 insertions(+), 81 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c
b/drivers/gpu/drm/i915/intel_display.c
index 0bcd1b1aba4f..aab8dfd1f8a5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13941,7 +13941,6 @@ static void intel_setup_outputs(struct
drm_device *dev) {
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *encoder;
- bool dpd_is_edp = false;
intel_lvds_init(dev);
@@ -13983,31 +13982,33 @@ static void intel_setup_outputs(struct
drm_device *dev)
intel_ddi_init(dev, PORT_D);
} else if (HAS_PCH_SPLIT(dev)) {
int found;
- dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
if (has_edp_a(dev))
intel_dp_init(dev, DP_A, PORT_A);
+ found = 0;
+ /* PCH SDVOB multiplex with HDMIB */
if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
- /* PCH SDVOB multiplex with HDMIB */
found = intel_sdvo_init(dev, PCH_SDVOB, true);
if (!found)
intel_hdmi_init(dev, PCH_HDMIB, PORT_B);
- if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
- intel_dp_init(dev, PCH_DP_B, PORT_B);
}
+ if (!found && I915_READ(PCH_DP_B) & DP_DETECTED)
+ intel_dp_init(dev, PCH_DP_B, PORT_B);
- if (I915_READ(PCH_HDMIC) & SDVO_DETECTED)
- intel_hdmi_init(dev, PCH_HDMIC, PORT_C);
-
- if (!dpd_is_edp && I915_READ(PCH_HDMID) & SDVO_DETECTED)
- intel_hdmi_init(dev, PCH_HDMID, PORT_D);
-
+ found = 0;
if (I915_READ(PCH_DP_C) & DP_DETECTED)
- intel_dp_init(dev, PCH_DP_C, PORT_C);
+ found = intel_dp_init(dev, PCH_DP_C, PORT_C);
+ if (found != DRM_MODE_CONNECTOR_eDP &&
+ I915_READ(PCH_HDMIC) & SDVO_DETECTED)
+ intel_hdmi_init(dev, PCH_HDMIC, PORT_C);
+ found = 0;
if (I915_READ(PCH_DP_D) & DP_DETECTED)
- intel_dp_init(dev, PCH_DP_D, PORT_D);
+ found = intel_dp_init(dev, PCH_DP_D, PORT_D);
+ if (found != DRM_MODE_CONNECTOR_eDP &&
+ I915_READ(PCH_HDMID) & SDVO_DETECTED)
+ intel_hdmi_init(dev, PCH_HDMID, PORT_D);
} else if (IS_VALLEYVIEW(dev)) {
/*
* The DP_DETECTED bit is the latched state of the DDC diff --git
a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1e64a8c1e7cb..8adf500f3989 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1031,14 +1031,13 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg)
return ret;
}
-static void
+static int
intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector
*connector) {
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
enum port port = intel_dig_port->port;
const char *name = NULL;
- int ret;
switch (port) {
case PORT_A:
@@ -1080,20 +1079,7 @@ intel_dp_aux_init(struct intel_dp *intel_dp,
struct intel_connector *connector)
DRM_DEBUG_KMS("registering %s bus for %s\n", name,
connector->base.kdev->kobj.name);
- ret = drm_dp_aux_register(&intel_dp->aux);
- if (ret < 0) {
- DRM_ERROR("drm_dp_aux_register() for %s failed (%d)\n",
- name, ret);
- return;
- }
-
- ret = sysfs_create_link(&connector->base.kdev->kobj,
- &intel_dp->aux.ddc.dev.kobj,
- intel_dp->aux.ddc.dev.kobj.name);
- if (ret < 0) {
- DRM_ERROR("sysfs_create_link() for %s failed (%d)\n", name, ret);
- drm_dp_aux_unregister(&intel_dp->aux);
- }
+ return drm_dp_aux_register(&intel_dp->aux);
}
static void
@@ -5019,6 +5005,10 @@ bool intel_dp_is_edp(struct drm_device *dev,
enum port port)
[PORT_D] = PORT_IDPD,
};
+ /* eDP only on port B and/or C on vlv/chv */
+ if (IS_VALLEYVIEW(dev_priv) && !(port == PORT_B || port == PORT_C))
+ return false;
+
if (port == PORT_A)
return true;
@@ -5670,9 +5660,6 @@ static bool intel_edp_init_connector(struct
intel_dp *intel_dp,
struct edid *edid;
enum pipe pipe = INVALID_PIPE;
- if (!is_edp(intel_dp))
- return true;
-
pps_lock(intel_dp);
intel_edp_panel_vdd_sanitize(intel_dp);
pps_unlock(intel_dp);
@@ -5762,7 +5749,7 @@ static bool intel_edp_init_connector(struct
intel_dp *intel_dp,
return true;
}
-bool
+int
intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector) { @@ -5772,6
+5759,7 @@
intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_dig_port->port;
+ int ret;
int type;
intel_dp->pps_pipe = INVALID_PIPE;
@@ -5802,34 +5790,14 @@ intel_dp_init_connector(struct
intel_digital_port *intel_dig_port,
else
type = DRM_MODE_CONNECTOR_DisplayPort;
- /*
- * 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
- * INTEL_OUTPUT_UNKNOWN for DDI, so don't rewrite it.
- */
- if (type == DRM_MODE_CONNECTOR_eDP)
- intel_encoder->type = INTEL_OUTPUT_EDP;
-
- /* eDP only on port B and/or C on vlv/chv */
- if (WARN_ON(IS_VALLEYVIEW(dev) && is_edp(intel_dp) &&
- port != PORT_B && port != PORT_C))
- return false;
-
DRM_DEBUG_KMS("Adding %s connector on port %c\n",
type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP",
port_name(port));
- drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
- drm_connector_helper_add(connector,
&intel_dp_connector_helper_funcs);
-
connector->interlace_allowed = true;
connector->doublescan_allowed = 0;
- INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
- edp_panel_vdd_work);
-
- intel_connector_attach_encoder(intel_connector, intel_encoder);
- drm_connector_register(connector);
+ INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
edp_panel_vdd_work);
if (HAS_DDI(dev))
intel_connector->get_hw_state =
intel_ddi_connector_get_hw_state;
@@ -5855,7 +5823,7 @@ intel_dp_init_connector(struct intel_digital_port
*intel_dig_port,
BUG();
}
- if (is_edp(intel_dp)) {
+ if (type == DRM_MODE_CONNECTOR_eDP) {
pps_lock(intel_dp);
intel_dp_init_panel_power_timestamps(intel_dp);
if (IS_VALLEYVIEW(dev))
@@ -5865,7 +5833,49 @@ intel_dp_init_connector(struct
intel_digital_port *intel_dig_port,
pps_unlock(intel_dp);
}
- intel_dp_aux_init(intel_dp, intel_connector);
+ ret = intel_dp_aux_init(intel_dp, intel_connector);
+ if (ret < 0) {
+ DRM_ERROR("registering DP-AUX channel for %s failed (%d)\n",
+ intel_dp->aux.name, ret);
+ return 0;
+ }
+
+ if (type == DRM_MODE_CONNECTOR_eDP &&
+ !intel_edp_init_connector(intel_dp, intel_connector)) {
+ drm_dp_aux_unregister(&intel_dp->aux);
+ cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+ /*
+ * vdd might still be enabled do to the delayed vdd off.
+ * Make sure vdd is actually turned off here.
+ */
+ pps_lock(intel_dp);
+ edp_panel_vdd_off_sync(intel_dp);
+ pps_unlock(intel_dp);
+
+ /* Downgrade to a normal DP link */
+ type = DRM_MODE_CONNECTOR_DisplayPort;
+ }
+
+ /*
+ * 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
+ * INTEL_OUTPUT_UNKNOWN for DDI, so don't rewrite it.
+ */
+ if (type == DRM_MODE_CONNECTOR_eDP)
+ intel_encoder->type = INTEL_OUTPUT_EDP;
+
+ drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
+ drm_connector_helper_add(connector,
+&intel_dp_connector_helper_funcs);
+
+ intel_connector_attach_encoder(intel_connector, intel_encoder);
+ drm_connector_register(connector);
+
+ ret = sysfs_create_link(&connector->kdev->kobj,
+ &intel_dp->aux.ddc.dev.kobj,
+ intel_dp->aux.ddc.dev.kobj.name);
+ if (ret < 0)
+ DRM_ERROR("sysfs_create_link() for %s failed (%d)\n",
+ intel_dp->aux.name, ret);
/* init MST on ports that can support it */
if (HAS_DP_MST(dev) &&
@@ -5873,23 +5883,6 @@ intel_dp_init_connector(struct
intel_digital_port *intel_dig_port,
intel_dp_mst_encoder_init(intel_dig_port,
intel_connector->base.base.id);
- if (!intel_edp_init_connector(intel_dp, intel_connector)) {
- drm_dp_aux_unregister(&intel_dp->aux);
- if (is_edp(intel_dp)) {
- cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
- /*
- * vdd might still be enabled do to the delayed vdd off.
- * Make sure vdd is actually turned off here.
- */
- pps_lock(intel_dp);
- edp_panel_vdd_off_sync(intel_dp);
- pps_unlock(intel_dp);
- }
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
- return false;
- }
-
intel_dp_add_properties(intel_dp, connector);
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
@@ -5903,10 +5896,10 @@ intel_dp_init_connector(struct
intel_digital_port *intel_dig_port,
i915_debugfs_connector_add(connector);
- return true;
+ return type;
}
-void
+int
intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
{
struct drm_i915_private *dev_priv = dev->dev_private; @@ -5914,15
+5907,16 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum
port port)
struct intel_encoder *intel_encoder;
struct drm_encoder *encoder;
struct intel_connector *intel_connector;
+ int ret;
intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port)
- return;
+ return 0;
intel_connector = intel_connector_alloc();
if (!intel_connector) {
kfree(intel_dig_port);
- return;
+ return 0;
}
intel_encoder = &intel_dig_port->base; @@ -5970,11 +5964,14 @@
intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
dev_priv->hotplug.irq_port[port] = intel_dig_port;
- if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
+ ret = intel_dp_init_connector(intel_dig_port, intel_connector);
+ if (ret == 0) {
drm_encoder_cleanup(encoder);
kfree(intel_dig_port);
kfree(intel_connector);
}
+
+ return ret;
}
void intel_dp_mst_suspend(struct drm_device *dev) diff --git
a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 18fe6d8b7d93..ade1ce853583 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1179,9 +1179,9 @@ void intel_csr_ucode_fini(struct drm_device
*dev); void assert_csr_loaded(struct drm_i915_private *dev_priv);
/* intel_dp.c */
-void intel_dp_init(struct drm_device *dev, int output_reg, enum port
port); -bool intel_dp_init_connector(struct intel_digital_port
*intel_dig_port,
- struct intel_connector *intel_connector);
+int intel_dp_init(struct drm_device *dev, int output_reg, enum port
+port); int intel_dp_init_connector(struct intel_digital_port
*intel_dig_port,
+ struct intel_connector *intel_connector);
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);
--
2.5.0
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx