This helps speed up driver init time, and puts off the eDP stuff until
we actually need it.
Signed-off-by: Jesse Barnes jbar...@virtuousgeek.org
---
drivers/gpu/drm/i915/intel_dp.c | 103 ++-
drivers/gpu/drm/i915/intel_drv.h | 3 ++
2 files changed, 73 insertions(+), 33 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 5256c06..2abd339 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3768,6 +3768,9 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
DRM_DEBUG_KMS(DPCD: %*ph\n, (int) sizeof(intel_dp-dpcd),
intel_dp-dpcd);
+ if (intel_dp-dpcd_valid)
+ return true;
+
if (intel_dp-dpcd[DP_DPCD_REV] == 0)
return false; /* DPCD not present */
@@ -4012,6 +4015,25 @@ go_again:
return -EINVAL;
}
+static void intel_flush_edp_cache_work(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp-attached_connector-base.dev;
+
+ WARN_ON(!mutex_is_locked(dev-mode_config.mutex));
+
+ if (!is_edp(intel_dp))
+ return;
+
+ /*
+* FIXME: we need to synchronize this at a higher level, like the
+* first mode set or other display I/O activity. Maybe re-use
+* async mode setting entry points?
+*/
+ mutex_unlock(dev-mode_config.mutex);
+ flush_work(intel_dp-edp_cache_work);
+ mutex_lock(dev-mode_config.mutex);
+}
+
/*
* According to DP spec
* 5.1.2:
@@ -4044,6 +4066,8 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
return;
}
+ intel_flush_edp_cache_work(intel_dp);
+
/* Now read the DPCD to see if it's actually running */
if (!intel_dp_get_dpcd(intel_dp)) {
return;
@@ -4079,6 +4103,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
uint8_t *dpcd = intel_dp-dpcd;
uint8_t type;
+ intel_flush_edp_cache_work(intel_dp);
+
if (!intel_dp_get_dpcd(intel_dp))
return connector_status_disconnected;
@@ -4215,13 +4241,23 @@ g4x_dp_detect(struct intel_dp *intel_dp)
return intel_dp_detect_dpcd(intel_dp);
}
+static bool intel_connector_has_edid(struct intel_connector *intel_connector)
+{
+ struct intel_dp *intel_dp = intel_attached_dp(intel_connector-base);
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+ intel_flush_edp_cache_work(intel_dp);
+
+ return intel_connector-edid != NULL;
+}
+
static struct edid *
intel_dp_get_edid(struct intel_dp *intel_dp)
{
struct intel_connector *intel_connector = intel_dp-attached_connector;
/* use cached edid if we have one */
- if (intel_connector-edid) {
+ if (intel_connector_has_edid(intel_connector)) {
/* invalid edid */
if (IS_ERR(intel_connector-edid))
return NULL;
@@ -4516,6 +4552,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
intel_dp_mst_encoder_cleanup(intel_dig_port);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(intel_dp-panel_vdd_work);
+ cancel_work_sync(intel_dp-edp_cache_work);
/*
* vdd might still be enabled do to the delayed vdd off.
* Make sure vdd is actually turned off here.
@@ -5316,9 +5353,11 @@ intel_dp_drrs_init(struct intel_connector
*intel_connector,
return downclock_mode;
}
-static bool intel_edp_init_connector(struct intel_dp *intel_dp,
-struct intel_connector *intel_connector)
+static void intel_edp_cache_work(struct work_struct *work)
{
+ struct intel_dp *intel_dp = container_of(work, struct intel_dp,
+edp_cache_work);
+ struct intel_connector *intel_connector = intel_dp-attached_connector;
struct drm_connector *connector = intel_connector-base;
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *intel_encoder = intel_dig_port-base;
@@ -5329,12 +5368,10 @@ static bool intel_edp_init_connector(struct intel_dp
*intel_dp,
bool has_dpcd;
struct drm_display_mode *scan;
struct edid *edid;
- enum pipe pipe = INVALID_PIPE;
dev_priv-drrs.type = DRRS_NOT_SUPPORTED;
- if (!is_edp(intel_dp))
- return true;
+ mutex_lock(dev-mode_config.mutex);
pps_lock(intel_dp);
intel_edp_panel_vdd_sanitize(intel_dp);
@@ -5348,10 +5385,13 @@ static bool intel_edp_init_connector(struct intel_dp
*intel_dp,
dev_priv-no_aux_handshake =
intel_dp-dpcd[DP_MAX_DOWNSPREAD]
DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
+ intel_dp-dpcd_valid = true;
} else {
- /* if this fails, presume the device