diff mbox

[14/31] drm/i915: display pll hw state readout and checking

Message ID 1370432073-27634-15-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Vetter June 5, 2013, 11:34 a.m. UTC
Currently still with an empty register state, this will follow in a
next step. This one here just creates the new vfunc and uses it for
cross-checking, initial state takeover and the dpll assert function.

And add a FIXME for the ddi pll readout code, which still needs to be
converted over.

v2:
- Add some hw state readout debug output.
- Also cross check the enabled crtc counting.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.h      |  7 ++++
 drivers/gpu/drm/i915/intel_display.c | 77 +++++++++++++++++++++++++++++++++---
 2 files changed, 79 insertions(+), 5 deletions(-)

Comments

Lespiau, Damien June 12, 2013, 1:31 p.m. UTC | #1
On Wed, Jun 05, 2013 at 01:34:16PM +0200, Daniel Vetter wrote:
> Currently still with an empty register state, this will follow in a
> next step. This one here just creates the new vfunc and uses it for
> cross-checking, initial state takeover and the dpll assert function.
> 
> And add a FIXME for the ddi pll readout code, which still needs to be
> converted over.
> 
> v2:
> - Add some hw state readout debug output.
> - Also cross check the enabled crtc counting.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |  7 ++++
>  drivers/gpu/drm/i915/intel_display.c | 77 +++++++++++++++++++++++++++++++++---
>  2 files changed, 79 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 8e61128..f23b033 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -143,6 +143,9 @@ enum intel_dpll_id {
>  };
>  #define I915_NUM_PLLS 2
>  
> +struct intel_dpll_hw_state {
> +};
> +
>  struct intel_shared_dpll {
>  	int refcount; /* count of number of CRTCs sharing this PLL */
>  	int active; /* count of number of active CRTCs (i.e. DPMS on) */
> @@ -150,10 +153,14 @@ struct intel_shared_dpll {
>  	const char *name;
>  	/* should match the index in the dev_priv->shared_dplls array */
>  	enum intel_dpll_id id;
> +	struct intel_dpll_hw_state hw_state;
>  	void (*enable)(struct drm_i915_private *dev_priv,
>  		       struct intel_shared_dpll *pll);
>  	void (*disable)(struct drm_i915_private *dev_priv,
>  			struct intel_shared_dpll *pll);
> +	bool (*get_hw_state)(struct drm_i915_private *dev_priv,
> +			     struct intel_shared_dpll *pll,
> +			     struct intel_dpll_hw_state *hw_state);
>  };
>  
>  /* Used by dp and fdi links */
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ea4b7a6..998ba5c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -907,8 +907,8 @@ static void assert_shared_dpll(struct drm_i915_private *dev_priv,
>  			       struct intel_shared_dpll *pll,
>  			       bool state)
>  {
> -	u32 val;
>  	bool cur_state;
> +	struct intel_dpll_hw_state hw_state;
>  
>  	if (HAS_PCH_LPT(dev_priv->dev)) {
>  		DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n");
> @@ -919,11 +919,10 @@ static void assert_shared_dpll(struct drm_i915_private *dev_priv,
>  		  "asserting DPLL %s with no DPLL\n", state_string(state)))
>  		return;
>  
> -	val = I915_READ(PCH_DPLL(pll->id));
> -	cur_state = !!(val & DPLL_VCO_ENABLE);
> +	cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
>  	WARN(cur_state != state,
> -	     "%s assertion failure (expected %s, current %s), val=%08x\n",
> -	     pll->name, state_string(state), state_string(cur_state), val);
> +	     "%s assertion failure (expected %s, current %s)\n",
> +	     pll->name, state_string(state), state_string(cur_state));
>  }
>  #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
>  #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
> @@ -8071,6 +8070,8 @@ intel_modeset_check_state(struct drm_device *dev)
>  	struct intel_encoder *encoder;
>  	struct intel_connector *connector;
>  	struct intel_crtc_config pipe_config;
> +	struct intel_dpll_hw_state dpll_hw_state;
> +	int i;
>  
>  	list_for_each_entry(connector, &dev->mode_config.connector_list,
>  			    base.head) {
> @@ -8183,6 +8184,41 @@ intel_modeset_check_state(struct drm_device *dev)
>  					       "[sw state]");
>  		}
>  	}
> +
> +	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
> +		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
> +		int enabled_crtcs = 0, active_crtcs = 0;
> +		bool active;
> +
> +		memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
> +
> +		DRM_DEBUG_KMS("%s\n", pll->name);
> +
> +		active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state);
> +
> +		WARN(pll->active > pll->refcount,
> +		     "more active pll users than references: %i vs %i\n",
> +		     pll->active, pll->refcount);
> +		WARN(pll->active && !pll->on,
> +		     "pll in active use but not on in sw tracking\n");
> +		WARN(pll->on != active,
> +		     "pll on state mismatch (expected %i, found %i)\n",
> +		     pll->on, active);
> +
> +		list_for_each_entry(crtc, &dev->mode_config.crtc_list,
> +				    base.head) {
> +			if (crtc->base.enabled && intel_crtc_to_shared_dpll(crtc) == pll)
> +				enabled_crtcs++;
> +			if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
> +				active_crtcs++;
> +		}
> +		WARN(pll->active != active_crtcs,
> +		     "pll active crtcs mismatch (expected %i, found %i)\n",
> +		     pll->active, active_crtcs);
> +		WARN(pll->refcount != enabled_crtcs,
> +		     "pll enabled crtcs mismatch (expected %i, found %i)\n",
> +		     pll->refcount, enabled_crtcs);
> +	}
>  }
>  
>  static int __intel_set_mode(struct drm_crtc *crtc,
> @@ -8621,6 +8657,17 @@ static void intel_cpu_pll_init(struct drm_device *dev)
>  		intel_ddi_pll_init(dev);
>  }
>  
> +static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
> +				      struct intel_shared_dpll *pll,
> +				      struct intel_dpll_hw_state *hw_state)
> +{
> +	uint32_t val;
> +
> +	val = I915_READ(PCH_DPLL(pll->id));
> +
> +	return val & DPLL_VCO_ENABLE;
> +}
> +

Don't we want !!(val & DPLL_VCO_ENABLE) here? we're comparing this to 0
and 1.

>  static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
>  				struct intel_shared_dpll *pll)
>  {
> @@ -8675,6 +8722,8 @@ static void ibx_pch_dpll_init(struct drm_device *dev)
>  		dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
>  		dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
>  		dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
> +		dev_priv->shared_dplls[i].get_hw_state =
> +			ibx_pch_dpll_get_hw_state;
>  	}
>  }
>  
> @@ -9592,6 +9641,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>  	struct intel_crtc *crtc;
>  	struct intel_encoder *encoder;
>  	struct intel_connector *connector;
> +	int i;
>  
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
>  			    base.head) {
> @@ -9607,9 +9657,26 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
>  			      crtc->active ? "enabled" : "disabled");
>  	}
>  
> +	/* FIXME: Smash this into the new shared dpll infrastructure. */
>  	if (HAS_DDI(dev))
>  		intel_ddi_setup_hw_pll_state(dev);
>  
> +	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
> +		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
> +
> +		pll->on = pll->get_hw_state(dev_priv, pll, &pll->hw_state);
> +		pll->active = 0;
> +		list_for_each_entry(crtc, &dev->mode_config.crtc_list,
> +				    base.head) {
> +			if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
> +				pll->active++;
> +		}
> +		pll->refcount = pll->active;
> +
> +		DRM_DEBUG_KMS("%s hw state readout: refcount %i\n",
> +			      pll->name, pll->refcount);
> +	}
> +
>  	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
>  			    base.head) {
>  		pipe = 0;
> -- 
> 1.7.11.7
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Ville Syrjala June 12, 2013, 1:39 p.m. UTC | #2
On Wed, Jun 12, 2013 at 02:31:23PM +0100, Damien Lespiau wrote:
> On Wed, Jun 05, 2013 at 01:34:16PM +0200, Daniel Vetter wrote:
> > @@ -8621,6 +8657,17 @@ static void intel_cpu_pll_init(struct drm_device *dev)
> >  		intel_ddi_pll_init(dev);
> >  }
> >  
> > +static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
> > +				      struct intel_shared_dpll *pll,
> > +				      struct intel_dpll_hw_state *hw_state)
> > +{
> > +	uint32_t val;
> > +
> > +	val = I915_READ(PCH_DPLL(pll->id));
> > +
> > +	return val & DPLL_VCO_ENABLE;
> > +}
> > +
> 
> Don't we want !!(val & DPLL_VCO_ENABLE) here? we're comparing this to 0
> and 1.

bool is always 0 or 1.
Lespiau, Damien June 12, 2013, 1:49 p.m. UTC | #3
On Wed, Jun 12, 2013 at 04:39:14PM +0300, Ville Syrjälä wrote:
> On Wed, Jun 12, 2013 at 02:31:23PM +0100, Damien Lespiau wrote:
> > On Wed, Jun 05, 2013 at 01:34:16PM +0200, Daniel Vetter wrote:
> > > @@ -8621,6 +8657,17 @@ static void intel_cpu_pll_init(struct drm_device *dev)
> > >  		intel_ddi_pll_init(dev);
> > >  }
> > >  
> > > +static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
> > > +				      struct intel_shared_dpll *pll,
> > > +				      struct intel_dpll_hw_state *hw_state)
> > > +{
> > > +	uint32_t val;
> > > +
> > > +	val = I915_READ(PCH_DPLL(pll->id));
> > > +
> > > +	return val & DPLL_VCO_ENABLE;
> > > +}
> > > +
> > 
> > Don't we want !!(val & DPLL_VCO_ENABLE) here? we're comparing this to 0
> > and 1.
> 
> bool is always 0 or 1.

Oh, of course!

Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>

then.
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8e61128..f23b033 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -143,6 +143,9 @@  enum intel_dpll_id {
 };
 #define I915_NUM_PLLS 2
 
+struct intel_dpll_hw_state {
+};
+
 struct intel_shared_dpll {
 	int refcount; /* count of number of CRTCs sharing this PLL */
 	int active; /* count of number of active CRTCs (i.e. DPMS on) */
@@ -150,10 +153,14 @@  struct intel_shared_dpll {
 	const char *name;
 	/* should match the index in the dev_priv->shared_dplls array */
 	enum intel_dpll_id id;
+	struct intel_dpll_hw_state hw_state;
 	void (*enable)(struct drm_i915_private *dev_priv,
 		       struct intel_shared_dpll *pll);
 	void (*disable)(struct drm_i915_private *dev_priv,
 			struct intel_shared_dpll *pll);
+	bool (*get_hw_state)(struct drm_i915_private *dev_priv,
+			     struct intel_shared_dpll *pll,
+			     struct intel_dpll_hw_state *hw_state);
 };
 
 /* Used by dp and fdi links */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ea4b7a6..998ba5c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -907,8 +907,8 @@  static void assert_shared_dpll(struct drm_i915_private *dev_priv,
 			       struct intel_shared_dpll *pll,
 			       bool state)
 {
-	u32 val;
 	bool cur_state;
+	struct intel_dpll_hw_state hw_state;
 
 	if (HAS_PCH_LPT(dev_priv->dev)) {
 		DRM_DEBUG_DRIVER("LPT detected: skipping PCH PLL test\n");
@@ -919,11 +919,10 @@  static void assert_shared_dpll(struct drm_i915_private *dev_priv,
 		  "asserting DPLL %s with no DPLL\n", state_string(state)))
 		return;
 
-	val = I915_READ(PCH_DPLL(pll->id));
-	cur_state = !!(val & DPLL_VCO_ENABLE);
+	cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
 	WARN(cur_state != state,
-	     "%s assertion failure (expected %s, current %s), val=%08x\n",
-	     pll->name, state_string(state), state_string(cur_state), val);
+	     "%s assertion failure (expected %s, current %s)\n",
+	     pll->name, state_string(state), state_string(cur_state));
 }
 #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
 #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
@@ -8071,6 +8070,8 @@  intel_modeset_check_state(struct drm_device *dev)
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
 	struct intel_crtc_config pipe_config;
+	struct intel_dpll_hw_state dpll_hw_state;
+	int i;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list,
 			    base.head) {
@@ -8183,6 +8184,41 @@  intel_modeset_check_state(struct drm_device *dev)
 					       "[sw state]");
 		}
 	}
+
+	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
+		int enabled_crtcs = 0, active_crtcs = 0;
+		bool active;
+
+		memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
+
+		DRM_DEBUG_KMS("%s\n", pll->name);
+
+		active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state);
+
+		WARN(pll->active > pll->refcount,
+		     "more active pll users than references: %i vs %i\n",
+		     pll->active, pll->refcount);
+		WARN(pll->active && !pll->on,
+		     "pll in active use but not on in sw tracking\n");
+		WARN(pll->on != active,
+		     "pll on state mismatch (expected %i, found %i)\n",
+		     pll->on, active);
+
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+				    base.head) {
+			if (crtc->base.enabled && intel_crtc_to_shared_dpll(crtc) == pll)
+				enabled_crtcs++;
+			if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
+				active_crtcs++;
+		}
+		WARN(pll->active != active_crtcs,
+		     "pll active crtcs mismatch (expected %i, found %i)\n",
+		     pll->active, active_crtcs);
+		WARN(pll->refcount != enabled_crtcs,
+		     "pll enabled crtcs mismatch (expected %i, found %i)\n",
+		     pll->refcount, enabled_crtcs);
+	}
 }
 
 static int __intel_set_mode(struct drm_crtc *crtc,
@@ -8621,6 +8657,17 @@  static void intel_cpu_pll_init(struct drm_device *dev)
 		intel_ddi_pll_init(dev);
 }
 
+static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
+				      struct intel_shared_dpll *pll,
+				      struct intel_dpll_hw_state *hw_state)
+{
+	uint32_t val;
+
+	val = I915_READ(PCH_DPLL(pll->id));
+
+	return val & DPLL_VCO_ENABLE;
+}
+
 static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
 				struct intel_shared_dpll *pll)
 {
@@ -8675,6 +8722,8 @@  static void ibx_pch_dpll_init(struct drm_device *dev)
 		dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
 		dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
 		dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
+		dev_priv->shared_dplls[i].get_hw_state =
+			ibx_pch_dpll_get_hw_state;
 	}
 }
 
@@ -9592,6 +9641,7 @@  void intel_modeset_setup_hw_state(struct drm_device *dev,
 	struct intel_crtc *crtc;
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
+	int i;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
 			    base.head) {
@@ -9607,9 +9657,26 @@  void intel_modeset_setup_hw_state(struct drm_device *dev,
 			      crtc->active ? "enabled" : "disabled");
 	}
 
+	/* FIXME: Smash this into the new shared dpll infrastructure. */
 	if (HAS_DDI(dev))
 		intel_ddi_setup_hw_pll_state(dev);
 
+	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
+
+		pll->on = pll->get_hw_state(dev_priv, pll, &pll->hw_state);
+		pll->active = 0;
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+				    base.head) {
+			if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
+				pll->active++;
+		}
+		pll->refcount = pll->active;
+
+		DRM_DEBUG_KMS("%s hw state readout: refcount %i\n",
+			      pll->name, pll->refcount);
+	}
+
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
 			    base.head) {
 		pipe = 0;