[Intel-gfx] [PATCH] drm/i915/dp: move edp init to work queue
Jesse Barnes
jbarnes at virtuousgeek.org
Wed Mar 18 11:41:49 PDT 2015
This helps speed up driver init time, and puts off the eDP stuff until
we actually need it.
Signed-off-by: Jesse Barnes <jbarnes at 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 is a ghost */
- DRM_INFO("failed to retrieve link info, disabling eDP\n");
- return false;
+ cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+ edp_panel_vdd_off_sync(intel_dp);
+ drm_connector_cleanup(connector);
+ mutex_unlock(&dev->mode_config.mutex);
+ return;
}
/* We now know it's not a ghost, init power sequence regs. */
@@ -5359,7 +5399,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
pps_unlock(intel_dp);
- mutex_lock(&dev->mode_config.mutex);
edid = drm_get_edid(connector, &intel_dp->aux.ddc);
if (edid) {
if (drm_add_edid_modes(connector, edid)) {
@@ -5384,7 +5423,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
break;
}
}
-
/* fallback to VBT if available for eDP */
if (!fixed_mode && dev_priv->vbt.lfp_lvds_vbt_mode) {
fixed_mode = drm_mode_duplicate(dev,
@@ -5392,7 +5430,26 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (fixed_mode)
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
}
+
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
+ intel_connector->panel.backlight_power = intel_edp_backlight_power;
+
mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void intel_edp_init_connector(struct intel_dp *intel_dp,
+ struct intel_connector *intel_connector)
+{
+ struct drm_connector *connector = &intel_connector->base;
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+ enum pipe pipe = INVALID_PIPE;
+
+ if (!is_edp(intel_dp))
+ return;
+
+ INIT_WORK(&intel_dp->edp_cache_work, intel_edp_cache_work);
+
+ schedule_work(&intel_dp->edp_cache_work);
if (IS_VALLEYVIEW(dev)) {
intel_dp->edp_notifier.notifier_call = edp_notify_handler;
@@ -5418,11 +5475,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
pipe_name(pipe));
}
- intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
- intel_connector->panel.backlight_power = intel_edp_backlight_power;
intel_panel_setup_backlight(connector, pipe);
-
- return true;
}
bool
@@ -5488,8 +5541,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
connector->interlace_allowed = true;
connector->doublescan_allowed = 0;
- INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
- edp_panel_vdd_work);
+ INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
intel_connector_attach_encoder(intel_connector, intel_encoder);
drm_connector_register(connector);
@@ -5538,22 +5590,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
}
}
- 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_edp_init_connector(intel_dp, intel_connector);
intel_dp_add_properties(intel_dp, connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a1baaa1..8cee4a2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -656,12 +656,15 @@ struct intel_dp {
bool can_mst; /* this port supports mst */
bool is_mst;
int active_mst_links;
+ bool dpcd_valid; /* for eDP DPCD caching */
/* connector directly attached - won't be use for modeset in mst world */
struct intel_connector *attached_connector;
/* mst connector list */
struct intel_dp_mst_encoder *mst_encoders[I915_MAX_PIPES];
struct drm_dp_mst_topology_mgr mst_mgr;
+ struct work_struct edp_cache_work;
+ const char *i2c_name;
uint32_t (*get_aux_clock_divider)(struct intel_dp *dp, int index);
/*
--
1.9.1
More information about the Intel-gfx
mailing list