All of lore.kernel.org
 help / color / mirror / Atom feed
From: ville.syrjala@linux.intel.com
To: intel-gfx@lists.freedesktop.org
Subject: [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer
Date: Mon, 18 Aug 2014 22:16:05 +0300	[thread overview]
Message-ID: <1408389369-22898-11-git-send-email-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <1408389369-22898-1-git-send-email-ville.syrjala@linux.intel.com>

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

VLV/CHV have a per-pipe panel power sequencer which locks onto the
port once used. We need to keep track wich power sequencers are
locked to which ports.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 185 ++++++++++++++++++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_drv.h |   6 ++
 2 files changed, 168 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 556e4de..4614e6e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -294,28 +294,99 @@ 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_crtc *crtc = intel_dig_port->base.base.crtc;
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	enum port port = intel_dig_port->port;
-	enum pipe pipe;
+	struct intel_encoder *encoder;
+	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
+	struct edp_power_seq power_seq;
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	/* modeset should have pipe */
-	if (crtc)
-		return to_intel_crtc(crtc)->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.
+	 */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		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);
+	}
+
+	/*
+	 * 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))
+		return PIPE_A;
+
+	intel_dp->pps_pipe = ffs(pipes) - 1;
+
+	DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n",
+		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
+
+	/* init power sequencer on this pipe and port */
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
+
+	return intel_dp->pps_pipe;
+}
+
+static enum pipe
+vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
+				 enum port port)
+{
+	enum pipe pipe;
 
-	/* init time, try to find a pipe with this port selected */
 	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
 		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
 			PANEL_PORT_SELECT_MASK;
-		if (port_sel == PANEL_PORT_SELECT_VLV(port))
-			return pipe;
+
+		if (port_sel != PANEL_PORT_SELECT_VLV(port))
+			continue;
+
+		return pipe;
+	}
+
+	return INVALID_PIPE;
+}
+
+static void
+vlv_initial_power_sequencer_setup(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 = dev->dev_private;
+	struct edp_power_seq power_seq;
+	enum port port = intel_dig_port->port;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	/* try to find a pipe with this port selected */
+	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port);
+
+	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
+	if (intel_dp->pps_pipe == INVALID_PIPE) {
+		DRM_DEBUG_KMS("no initial power sequencer for port %c\n",
+			      port_name(port));
+		return;
 	}
 
-	/* shrug */
-	return PIPE_A;
+	DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n",
+		      port_name(port), pipe_name(intel_dp->pps_pipe));
+
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
 }
 
 static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
@@ -2209,6 +2280,76 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder)
 	}
 }
 
+static void vlv_steal_power_sequencer(struct drm_device *dev,
+				      enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		struct intel_dp *intel_dp;
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		intel_dp = enc_to_intel_dp(&encoder->base);
+
+		if (intel_dp->pps_pipe != pipe)
+			continue;
+
+		DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
+			      pipe_name(pipe),
+			      port_name(dp_to_dig_port(intel_dp)->port));
+
+		/* make sure vdd is off before we steal it */
+		edp_panel_vdd_off_sync(intel_dp);
+
+		intel_dp->pps_pipe = INVALID_PIPE;
+	}
+}
+
+static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &intel_dig_port->base;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	struct edp_power_seq power_seq;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	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)
+		edp_panel_vdd_off_sync(intel_dp);
+
+	/*
+	 * We may be stealing the power
+	 * sequencer from another port.
+	 */
+	vlv_steal_power_sequencer(dev, crtc->pipe);
+
+	/* now it's all ours */
+	intel_dp->pps_pipe = crtc->pipe;
+
+	DRM_DEBUG_KMS("initializing pipe %c power sequencer for port %c\n",
+		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
+
+	/* init power sequencer on this pipe and port */
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
+}
+
 static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -2218,7 +2359,6 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	enum dpio_channel port = vlv_dport_to_channel(dport);
 	int pipe = intel_crtc->pipe;
-	struct edp_power_seq power_seq;
 	u32 val;
 
 	mutex_lock(&dev_priv->dpio_lock);
@@ -2237,11 +2377,8 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		/* init power sequencer on this pipe and port */
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-							      &power_seq);
+		vlv_init_panel_power_sequencer(intel_dp);
 		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
@@ -2286,7 +2423,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct edp_power_seq power_seq;
 	struct intel_crtc *intel_crtc =
 		to_intel_crtc(encoder->base.crtc);
 	enum dpio_channel ch = vlv_dport_to_channel(dport);
@@ -2341,11 +2477,8 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		/* init power sequencer on this pipe and port */
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-							      &power_seq);
+		vlv_init_panel_power_sequencer(intel_dp);
 		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
@@ -4691,6 +4824,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	struct edp_power_seq power_seq = { 0 };
 	int type;
 
+	intel_dp->pps_pipe = INVALID_PIPE;
+
 	/* intel_dp vfuncs */
 	if (IS_VALLEYVIEW(dev))
 		intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
@@ -4762,8 +4897,12 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 
 	if (is_edp(intel_dp)) {
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_timestamps(intel_dp);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+		if (IS_VALLEYVIEW(dev)) {
+			vlv_initial_power_sequencer_setup(intel_dp);
+		} else {
+			intel_dp_init_panel_power_timestamps(intel_dp);
+			intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+		}
 		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ad4e69b..d36299b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -560,6 +560,12 @@ struct intel_dp {
 
 	struct notifier_block edp_notifier;
 
+	/*
+	 * Pipe whose power sequencer is currently locked into
+	 * this port. Only relevant on VLV/CHV.
+	 */
+	enum pipe pps_pipe;
+
 	bool use_tps3;
 	bool can_mst; /* this port supports mst */
 	bool is_mst;
-- 
1.8.5.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2014-08-18 19:21 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
2014-08-18 19:15 ` [PATCH 01/14] drm/i915: Parametrize PANEL_PORT_SELECT_VLV ville.syrjala
2014-08-19  6:58   ` Jani Nikula
2014-08-18 19:15 ` [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier ville.syrjala
2014-08-18 21:28   ` Clint Taylor
2014-08-19  7:00   ` Jani Nikula
2014-08-26 12:58     ` Ville Syrjälä
2014-08-26 13:21       ` Jani Nikula
2014-08-26 13:30         ` Ville Syrjälä
2014-08-26 13:36         ` Daniel Vetter
2014-08-26 14:06           ` Ville Syrjälä
2014-09-04 17:47             ` Clint Taylor
2014-09-05  8:23               ` Ville Syrjälä
2014-08-18 19:15 ` [PATCH 03/14] drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst() ville.syrjala
2014-08-19  7:12   ` Jani Nikula
2014-08-18 19:15 ` [PATCH 04/14] drm/i915: Rename edp vdd funcs for consistency ville.syrjala
2014-08-19  7:20   ` Jani Nikula
2014-08-19 10:24     ` [PATCH v2 " ville.syrjala
2014-08-18 19:16 ` [PATCH 05/14] drm/i915: Add a note explaining vdd on/off handling in intel_dp_aux_ch() ville.syrjala
2014-08-19  7:07   ` Jani Nikula
2014-08-18 19:16 ` [PATCH 06/14] drm/i915: Replace big nested if block with early return ville.syrjala
2014-08-19  7:24   ` Jani Nikula
2014-08-18 19:16 ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() ville.syrjala
2014-08-19  7:36   ` Jani Nikula
2014-08-19 10:39     ` Ville Syrjälä
2014-08-19 13:37       ` Jani Nikula
2014-08-19 17:47         ` [PATCH 15/14] drm/i915: Add comments explaining the vdd on/off functions ville.syrjala
2014-09-03 11:52           ` Imre Deak
2014-09-04 11:55             ` [PATCH v2 " ville.syrjala
2014-09-04 13:02               ` Daniel Vetter
2014-08-26  9:21         ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() Daniel Vetter
2014-08-18 19:16 ` [PATCH 08/14] drm/i915: Flatten intel_edp_panel_vdd_on() ville.syrjala
2014-08-19  7:30   ` Jani Nikula
2014-08-19 10:49     ` Ville Syrjälä
2014-08-18 19:16 ` [PATCH 09/14] drm/i915: Fix edp vdd locking ville.syrjala
2014-08-19 17:32   ` [PATCH v2 " ville.syrjala
2014-09-02 13:07     ` Imre Deak
2014-09-04 11:53       ` [PATCH v3 " ville.syrjala
2014-08-18 19:16 ` ville.syrjala [this message]
2014-08-19 17:45   ` [PATCH 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off ville.syrjala
2014-08-22 14:21     ` [PATCH v2 " ville.syrjala
2014-09-02 13:47       ` Imre Deak
2014-09-04 11:54         ` [PATCH v3 " ville.syrjala
2014-09-01 11:19   ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer Antti Koskipää
2014-09-04 11:54   ` [PATCH v2 " ville.syrjala
2014-08-18 19:16 ` [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe ville.syrjala
2014-09-02 13:52   ` Imre Deak
2014-09-04 12:59   ` Daniel Vetter
2014-08-18 19:16 ` [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers ville.syrjala
2014-08-19  7:33   ` Jani Nikula
2014-08-19 10:57     ` Ville Syrjälä
2014-08-26 12:41       ` Daniel Vetter
2014-09-02 14:02   ` Imre Deak
2014-08-18 19:16 ` [PATCH 13/14] drm/i915: Enable DP port earlier ville.syrjala
2014-09-03 11:02   ` Imre Deak
2014-08-18 19:16 ` [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms ville.syrjala
2014-08-26  9:43   ` Daniel Vetter
2014-09-03 11:20   ` Imre Deak
2014-08-19  7:45 ` [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick Jani Nikula
2014-08-26  9:37   ` Daniel Vetter
2014-08-19  8:08 ` Jani Nikula
2014-08-19 10:46   ` Ville Syrjälä
2014-08-26  9:35     ` Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1408389369-22898-11-git-send-email-ville.syrjala@linux.intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.