|
@@ -492,14 +492,50 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
|
|
|
+{
|
|
|
+ struct intel_encoder *encoder;
|
|
|
+ unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We don't have power sequencer currently.
|
|
|
+ * Pick one that's not used by other ports.
|
|
|
+ */
|
|
|
+ for_each_intel_encoder(&dev_priv->drm, encoder) {
|
|
|
+ struct intel_dp *intel_dp;
|
|
|
+
|
|
|
+ if (encoder->type != INTEL_OUTPUT_DP &&
|
|
|
+ encoder->type != INTEL_OUTPUT_EDP)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ intel_dp = enc_to_intel_dp(&encoder->base);
|
|
|
+
|
|
|
+ if (encoder->type == INTEL_OUTPUT_EDP) {
|
|
|
+ WARN_ON(intel_dp->active_pipe != INVALID_PIPE &&
|
|
|
+ intel_dp->active_pipe != intel_dp->pps_pipe);
|
|
|
+
|
|
|
+ if (intel_dp->pps_pipe != INVALID_PIPE)
|
|
|
+ pipes &= ~(1 << intel_dp->pps_pipe);
|
|
|
+ } else {
|
|
|
+ WARN_ON(intel_dp->pps_pipe != INVALID_PIPE);
|
|
|
+
|
|
|
+ if (intel_dp->active_pipe != INVALID_PIPE)
|
|
|
+ pipes &= ~(1 << intel_dp->active_pipe);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pipes == 0)
|
|
|
+ return INVALID_PIPE;
|
|
|
+
|
|
|
+ return ffs(pipes) - 1;
|
|
|
+}
|
|
|
+
|
|
|
static enum pipe
|
|
|
vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
|
|
|
{
|
|
|
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
|
|
struct drm_device *dev = intel_dig_port->base.base.dev;
|
|
|
struct drm_i915_private *dev_priv = to_i915(dev);
|
|
|
- struct intel_encoder *encoder;
|
|
|
- unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
|
|
|
enum pipe pipe;
|
|
|
|
|
|
lockdep_assert_held(&dev_priv->pps_mutex);
|
|
@@ -507,33 +543,20 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
|
|
|
/* We should never land here with regular DP ports */
|
|
|
WARN_ON(!is_edp(intel_dp));
|
|
|
|
|
|
+ WARN_ON(intel_dp->active_pipe != INVALID_PIPE &&
|
|
|
+ intel_dp->active_pipe != intel_dp->pps_pipe);
|
|
|
+
|
|
|
if (intel_dp->pps_pipe != INVALID_PIPE)
|
|
|
return intel_dp->pps_pipe;
|
|
|
|
|
|
- /*
|
|
|
- * We don't have power sequencer currently.
|
|
|
- * Pick one that's not used by other ports.
|
|
|
- */
|
|
|
- for_each_intel_encoder(dev, encoder) {
|
|
|
- struct intel_dp *tmp;
|
|
|
-
|
|
|
- if (encoder->type != INTEL_OUTPUT_EDP)
|
|
|
- continue;
|
|
|
-
|
|
|
- tmp = enc_to_intel_dp(&encoder->base);
|
|
|
-
|
|
|
- if (tmp->pps_pipe != INVALID_PIPE)
|
|
|
- pipes &= ~(1 << tmp->pps_pipe);
|
|
|
- }
|
|
|
+ pipe = vlv_find_free_pps(dev_priv);
|
|
|
|
|
|
/*
|
|
|
* Didn't find one. This should not happen since there
|
|
|
* are two power sequencers and up to two eDP ports.
|
|
|
*/
|
|
|
- if (WARN_ON(pipes == 0))
|
|
|
+ if (WARN_ON(pipe == INVALID_PIPE))
|
|
|
pipe = PIPE_A;
|
|
|
- else
|
|
|
- pipe = ffs(pipes) - 1;
|
|
|
|
|
|
vlv_steal_power_sequencer(dev, pipe);
|
|
|
intel_dp->pps_pipe = pipe;
|
|
@@ -689,10 +712,17 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
|
|
|
for_each_intel_encoder(dev, encoder) {
|
|
|
struct intel_dp *intel_dp;
|
|
|
|
|
|
- if (encoder->type != INTEL_OUTPUT_EDP)
|
|
|
+ if (encoder->type != INTEL_OUTPUT_DP &&
|
|
|
+ encoder->type != INTEL_OUTPUT_EDP)
|
|
|
continue;
|
|
|
|
|
|
intel_dp = enc_to_intel_dp(&encoder->base);
|
|
|
+
|
|
|
+ WARN_ON(intel_dp->active_pipe != INVALID_PIPE);
|
|
|
+
|
|
|
+ if (encoder->type != INTEL_OUTPUT_EDP)
|
|
|
+ continue;
|
|
|
+
|
|
|
if (IS_GEN9_LP(dev_priv))
|
|
|
intel_dp->pps_reset = true;
|
|
|
else
|
|
@@ -2852,6 +2882,8 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
|
|
|
enum pipe pipe = intel_dp->pps_pipe;
|
|
|
i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
|
|
|
|
|
|
+ WARN_ON(intel_dp->active_pipe != INVALID_PIPE);
|
|
|
+
|
|
|
edp_panel_vdd_off_sync(intel_dp);
|
|
|
|
|
|
/*
|
|
@@ -2886,22 +2918,23 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
|
|
|
struct intel_dp *intel_dp;
|
|
|
enum port port;
|
|
|
|
|
|
- if (encoder->type != INTEL_OUTPUT_EDP)
|
|
|
+ if (encoder->type != INTEL_OUTPUT_DP &&
|
|
|
+ encoder->type != INTEL_OUTPUT_EDP)
|
|
|
continue;
|
|
|
|
|
|
intel_dp = enc_to_intel_dp(&encoder->base);
|
|
|
port = dp_to_dig_port(intel_dp)->port;
|
|
|
|
|
|
+ WARN(intel_dp->active_pipe == pipe,
|
|
|
+ "stealing pipe %c power sequencer from active (e)DP port %c\n",
|
|
|
+ pipe_name(pipe), port_name(port));
|
|
|
+
|
|
|
if (intel_dp->pps_pipe != pipe)
|
|
|
continue;
|
|
|
|
|
|
DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
|
|
|
pipe_name(pipe), port_name(port));
|
|
|
|
|
|
- WARN(encoder->base.crtc,
|
|
|
- "stealing pipe %c power sequencer from active eDP port %c\n",
|
|
|
- pipe_name(pipe), port_name(port));
|
|
|
-
|
|
|
/* make sure vdd is off before we steal it */
|
|
|
vlv_detach_power_sequencer(intel_dp);
|
|
|
}
|
|
@@ -2917,19 +2950,17 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
|
|
|
|
|
|
lockdep_assert_held(&dev_priv->pps_mutex);
|
|
|
|
|
|
- if (!is_edp(intel_dp))
|
|
|
- return;
|
|
|
+ WARN_ON(intel_dp->active_pipe != INVALID_PIPE);
|
|
|
|
|
|
- if (intel_dp->pps_pipe == crtc->pipe)
|
|
|
- return;
|
|
|
-
|
|
|
- /*
|
|
|
- * If another power sequencer was being used on this
|
|
|
- * port previously make sure to turn off vdd there while
|
|
|
- * we still have control of it.
|
|
|
- */
|
|
|
- if (intel_dp->pps_pipe != INVALID_PIPE)
|
|
|
+ if (intel_dp->pps_pipe != INVALID_PIPE &&
|
|
|
+ intel_dp->pps_pipe != crtc->pipe) {
|
|
|
+ /*
|
|
|
+ * If another power sequencer was being used on this
|
|
|
+ * port previously make sure to turn off vdd there while
|
|
|
+ * we still have control of it.
|
|
|
+ */
|
|
|
vlv_detach_power_sequencer(intel_dp);
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* We may be stealing the power
|
|
@@ -2937,6 +2968,11 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
|
|
|
*/
|
|
|
vlv_steal_power_sequencer(dev, crtc->pipe);
|
|
|
|
|
|
+ intel_dp->active_pipe = crtc->pipe;
|
|
|
+
|
|
|
+ if (!is_edp(intel_dp))
|
|
|
+ return;
|
|
|
+
|
|
|
/* now it's all ours */
|
|
|
intel_dp->pps_pipe = crtc->pipe;
|
|
|
|
|
@@ -3523,6 +3559,12 @@ intel_dp_link_down(struct intel_dp *intel_dp)
|
|
|
msleep(intel_dp->panel_power_down_delay);
|
|
|
|
|
|
intel_dp->DP = DP;
|
|
|
+
|
|
|
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
|
|
|
+ pps_lock(intel_dp);
|
|
|
+ intel_dp->active_pipe = INVALID_PIPE;
|
|
|
+ pps_unlock(intel_dp);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
bool
|
|
@@ -4791,6 +4833,19 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
|
|
|
edp_panel_vdd_schedule_off(intel_dp);
|
|
|
}
|
|
|
|
|
|
+static enum pipe vlv_active_pipe(struct intel_dp *intel_dp)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
|
|
|
+
|
|
|
+ if ((intel_dp->DP & DP_PORT_EN) == 0)
|
|
|
+ return INVALID_PIPE;
|
|
|
+
|
|
|
+ if (IS_CHERRYVIEW(dev_priv))
|
|
|
+ return DP_PORT_TO_PIPE_CHV(intel_dp->DP);
|
|
|
+ else
|
|
|
+ return PORT_TO_PIPE(intel_dp->DP);
|
|
|
+}
|
|
|
+
|
|
|
void intel_dp_encoder_reset(struct drm_encoder *encoder)
|
|
|
{
|
|
|
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
|
|
@@ -4803,14 +4858,16 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
|
|
|
if (lspcon->active)
|
|
|
lspcon_resume(lspcon);
|
|
|
|
|
|
- if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
|
|
|
- return;
|
|
|
-
|
|
|
pps_lock(intel_dp);
|
|
|
|
|
|
- /* Reinit the power sequencer, in case BIOS did something with it. */
|
|
|
- intel_dp_pps_init(encoder->dev, intel_dp);
|
|
|
- intel_edp_panel_vdd_sanitize(intel_dp);
|
|
|
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
+ intel_dp->active_pipe = vlv_active_pipe(intel_dp);
|
|
|
+
|
|
|
+ if (is_edp(intel_dp)) {
|
|
|
+ /* Reinit the power sequencer, in case BIOS did something with it. */
|
|
|
+ intel_dp_pps_init(encoder->dev, intel_dp);
|
|
|
+ intel_edp_panel_vdd_sanitize(intel_dp);
|
|
|
+ }
|
|
|
|
|
|
pps_unlock(intel_dp);
|
|
|
}
|
|
@@ -5637,10 +5694,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
|
|
* If the current pipe isn't valid, try the PPS pipe, and if that
|
|
|
* fails just assume pipe A.
|
|
|
*/
|
|
|
- if (IS_CHERRYVIEW(dev_priv))
|
|
|
- pipe = DP_PORT_TO_PIPE_CHV(intel_dp->DP);
|
|
|
- else
|
|
|
- pipe = PORT_TO_PIPE(intel_dp->DP);
|
|
|
+ pipe = vlv_active_pipe(intel_dp);
|
|
|
|
|
|
if (pipe != PIPE_A && pipe != PIPE_B)
|
|
|
pipe = intel_dp->pps_pipe;
|
|
@@ -5689,6 +5743,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|
|
return false;
|
|
|
|
|
|
intel_dp->pps_pipe = INVALID_PIPE;
|
|
|
+ intel_dp->active_pipe = INVALID_PIPE;
|
|
|
|
|
|
/* intel_dp vfuncs */
|
|
|
if (INTEL_GEN(dev_priv) >= 9)
|
|
@@ -5717,6 +5772,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|
|
else
|
|
|
type = DRM_MODE_CONNECTOR_DisplayPort;
|
|
|
|
|
|
+ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
|
|
+ intel_dp->active_pipe = vlv_active_pipe(intel_dp);
|
|
|
+
|
|
|
/*
|
|
|
* 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
|