diff mbox series

[v2,1/2] drm/i915/dp: Helper for checking DDI_BUF_CTL Idle status

Message ID 20200618000124.29036-1-manasi.d.navare@intel.com (mailing list archive)
State New, archived
Headers show
Series [v2,1/2] drm/i915/dp: Helper for checking DDI_BUF_CTL Idle status | expand

Commit Message

Navare, Manasi June 18, 2020, 12:01 a.m. UTC
Modify the helper to add a fixed delay or poll with timeout
based on platform specification in bothe enable and disable
cases so check for either Idle bit set (DDI_BUF_CTL is idle
for disable case) or check for Idle bit = 0 (non idle for
DDI BUF enable case)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c | 34 +++++++++++++++---------
 1 file changed, 21 insertions(+), 13 deletions(-)

Comments

Imre Deak June 22, 2020, 3:49 p.m. UTC | #1
On Wed, Jun 17, 2020 at 05:01:23PM -0700, Manasi Navare wrote:
> Modify the helper to add a fixed delay or poll with timeout
> based on platform specification in bothe enable and disable
> cases so check for either Idle bit set (DDI_BUF_CTL is idle
> for disable case) or check for Idle bit = 0 (non idle for
> DDI BUF enable case)
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c | 34 +++++++++++++++---------
>  1 file changed, 21 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index ca7bb2294d2b..e4738c3b6d44 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -1182,18 +1182,26 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
>  }
>  
>  static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
> -				    enum port port)

maybe intel_ddi_wait_for_ddi_buf(i915, port, active) ?

> +				    enum port port, bool idle)
>  {
> -	i915_reg_t reg = DDI_BUF_CTL(port);
> -	int i;
> -
> -	for (i = 0; i < 16; i++) {
> -		udelay(1);
> -		if (intel_de_read(dev_priv, reg) & DDI_BUF_IS_IDLE)
> -			return;
> +	if (idle) {
> +		if (IS_BROXTON(dev_priv))
> +			udelay(16);
> +		else
> +			if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> +					 DDI_BUF_IS_IDLE), 16))
> +				drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> +					port_name(port));
> +	} else {
> +		if (INTEL_GEN(dev_priv) < 10)
> +			udelay(600);
> +		else
> +			if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> +					  DDI_BUF_IS_IDLE), 600))
> +				drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
> +					port_name(port));
>  	}
> -	drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> -		port_name(port));
> +

since we can only guarantee a minimum delay or timeout, imo it could be just:

	if (BXT && !active || GEN <= 9 && active) {
		usleep_range(600, 1000);
		return;
	}

	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE) == active, 600))
		drm_err("Port %c: Timeout waiting for DDI BUF to get %s\n",
			port, active ? "active" : "idle"));
		

>  }
>  
>  static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
> @@ -1373,7 +1381,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
>  		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
>  		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
>  
> -		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
> +		intel_wait_ddi_buf_idle(dev_priv, PORT_E, true);
>  
>  		/* Reset FDI_RX_MISC pwrdn lanes */
>  		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
> @@ -3495,7 +3503,7 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
>  	intel_ddi_disable_fec_state(encoder, crtc_state);
>  
>  	if (wait)
> -		intel_wait_ddi_buf_idle(dev_priv, port);
> +		intel_wait_ddi_buf_idle(dev_priv, port, true);
>  }
>  
>  static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
> @@ -4004,7 +4012,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
>  		intel_de_posting_read(dev_priv, intel_dp->regs.dp_tp_ctl);
>  
>  		if (wait)
> -			intel_wait_ddi_buf_idle(dev_priv, port);
> +			intel_wait_ddi_buf_idle(dev_priv, port, true);
>  	}
>  
>  	dp_tp_ctl = DP_TP_CTL_ENABLE |

The DSI code could also use the new helper.

> -- 
> 2.19.1
>
Ville Syrjala June 22, 2020, 5:06 p.m. UTC | #2
On Mon, Jun 22, 2020 at 06:49:26PM +0300, Imre Deak wrote:
> On Wed, Jun 17, 2020 at 05:01:23PM -0700, Manasi Navare wrote:
> > Modify the helper to add a fixed delay or poll with timeout
> > based on platform specification in bothe enable and disable
> > cases so check for either Idle bit set (DDI_BUF_CTL is idle
> > for disable case) or check for Idle bit = 0 (non idle for
> > DDI BUF enable case)
> > 
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Imre Deak <imre.deak@intel.com>
> > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_ddi.c | 34 +++++++++++++++---------
> >  1 file changed, 21 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> > index ca7bb2294d2b..e4738c3b6d44 100644
> > --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> > @@ -1182,18 +1182,26 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
> >  }
> >  
> >  static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
> > -				    enum port port)
> 
> maybe intel_ddi_wait_for_ddi_buf(i915, port, active) ?

I'd just make it two functions. Avoids that stupid boolean
parameter.

> 
> > +				    enum port port, bool idle)
> >  {
> > -	i915_reg_t reg = DDI_BUF_CTL(port);
> > -	int i;
> > -
> > -	for (i = 0; i < 16; i++) {
> > -		udelay(1);
> > -		if (intel_de_read(dev_priv, reg) & DDI_BUF_IS_IDLE)
> > -			return;
> > +	if (idle) {
> > +		if (IS_BROXTON(dev_priv))
> > +			udelay(16);
> > +		else
> > +			if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > +					 DDI_BUF_IS_IDLE), 16))
> > +				drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > +					port_name(port));
> > +	} else {
> > +		if (INTEL_GEN(dev_priv) < 10)
> > +			udelay(600);
> > +		else
> > +			if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > +					  DDI_BUF_IS_IDLE), 600))
> > +				drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
> > +					port_name(port));
> >  	}
> > -	drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > -		port_name(port));
> > +
> 
> since we can only guarantee a minimum delay or timeout, imo it could be just:
> 
> 	if (BXT && !active || GEN <= 9 && active) {
> 		usleep_range(600, 1000);
> 		return;
> 	}
> 
> 	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE) == active, 600))
> 		drm_err("Port %c: Timeout waiting for DDI BUF to get %s\n",
> 			port, active ? "active" : "idle"));
> 		
> 
> >  }
> >  
> >  static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
> > @@ -1373,7 +1381,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
> >  		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
> >  		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
> >  
> > -		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
> > +		intel_wait_ddi_buf_idle(dev_priv, PORT_E, true);
> >  
> >  		/* Reset FDI_RX_MISC pwrdn lanes */
> >  		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
> > @@ -3495,7 +3503,7 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
> >  	intel_ddi_disable_fec_state(encoder, crtc_state);
> >  
> >  	if (wait)
> > -		intel_wait_ddi_buf_idle(dev_priv, port);
> > +		intel_wait_ddi_buf_idle(dev_priv, port, true);
> >  }
> >  
> >  static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
> > @@ -4004,7 +4012,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> >  		intel_de_posting_read(dev_priv, intel_dp->regs.dp_tp_ctl);
> >  
> >  		if (wait)
> > -			intel_wait_ddi_buf_idle(dev_priv, port);
> > +			intel_wait_ddi_buf_idle(dev_priv, port, true);
> >  	}
> >  
> >  	dp_tp_ctl = DP_TP_CTL_ENABLE |
> 
> The DSI code could also use the new helper.
> 
> > -- 
> > 2.19.1
> >
Navare, Manasi June 23, 2020, 7:26 p.m. UTC | #3
On Mon, Jun 22, 2020 at 08:06:51PM +0300, Ville Syrjälä wrote:
> On Mon, Jun 22, 2020 at 06:49:26PM +0300, Imre Deak wrote:
> > On Wed, Jun 17, 2020 at 05:01:23PM -0700, Manasi Navare wrote:
> > > Modify the helper to add a fixed delay or poll with timeout
> > > based on platform specification in bothe enable and disable
> > > cases so check for either Idle bit set (DDI_BUF_CTL is idle
> > > for disable case) or check for Idle bit = 0 (non idle for
> > > DDI BUF enable case)
> > > 
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Cc: Imre Deak <imre.deak@intel.com>
> > > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/display/intel_ddi.c | 34 +++++++++++++++---------
> > >  1 file changed, 21 insertions(+), 13 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> > > index ca7bb2294d2b..e4738c3b6d44 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> > > @@ -1182,18 +1182,26 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
> > >  }
> > >  
> > >  static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
> > > -				    enum port port)
> > 
> > maybe intel_ddi_wait_for_ddi_buf(i915, port, active) ?
> 
> I'd just make it two functions. Avoids that stupid boolean
> parameter.

Just have 2 functions: 1. intel_ddi_wait_for_ddi_buf_idle()
2. intel_ddi_wait_for_ddi_buf_active or _non_idle()?

Hmm but wouldnt it be more readable if we pass that bool and use 
the same function?

Manasi

> 
> > 
> > > +				    enum port port, bool idle)
> > >  {
> > > -	i915_reg_t reg = DDI_BUF_CTL(port);
> > > -	int i;
> > > -
> > > -	for (i = 0; i < 16; i++) {
> > > -		udelay(1);
> > > -		if (intel_de_read(dev_priv, reg) & DDI_BUF_IS_IDLE)
> > > -			return;
> > > +	if (idle) {
> > > +		if (IS_BROXTON(dev_priv))
> > > +			udelay(16);
> > > +		else
> > > +			if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > > +					 DDI_BUF_IS_IDLE), 16))
> > > +				drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > > +					port_name(port));
> > > +	} else {
> > > +		if (INTEL_GEN(dev_priv) < 10)
> > > +			udelay(600);
> > > +		else
> > > +			if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > > +					  DDI_BUF_IS_IDLE), 600))
> > > +				drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
> > > +					port_name(port));
> > >  	}
> > > -	drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > > -		port_name(port));
> > > +
> > 
> > since we can only guarantee a minimum delay or timeout, imo it could be just:
> > 
> > 	if (BXT && !active || GEN <= 9 && active) {
> > 		usleep_range(600, 1000);
> > 		return;
> > 	}
> > 
> > 	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE) == active, 600))
> > 		drm_err("Port %c: Timeout waiting for DDI BUF to get %s\n",
> > 			port, active ? "active" : "idle"));
> > 		
> > 
> > >  }
> > >  
> > >  static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
> > > @@ -1373,7 +1381,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
> > >  		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
> > >  		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
> > >  
> > > -		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
> > > +		intel_wait_ddi_buf_idle(dev_priv, PORT_E, true);
> > >  
> > >  		/* Reset FDI_RX_MISC pwrdn lanes */
> > >  		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
> > > @@ -3495,7 +3503,7 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
> > >  	intel_ddi_disable_fec_state(encoder, crtc_state);
> > >  
> > >  	if (wait)
> > > -		intel_wait_ddi_buf_idle(dev_priv, port);
> > > +		intel_wait_ddi_buf_idle(dev_priv, port, true);
> > >  }
> > >  
> > >  static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
> > > @@ -4004,7 +4012,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> > >  		intel_de_posting_read(dev_priv, intel_dp->regs.dp_tp_ctl);
> > >  
> > >  		if (wait)
> > > -			intel_wait_ddi_buf_idle(dev_priv, port);
> > > +			intel_wait_ddi_buf_idle(dev_priv, port, true);
> > >  	}
> > >  
> > >  	dp_tp_ctl = DP_TP_CTL_ENABLE |
> > 
> > The DSI code could also use the new helper.
> > 
> > > -- 
> > > 2.19.1
> > > 
> 
> -- 
> Ville Syrjälä
> Intel
Navare, Manasi June 23, 2020, 7:42 p.m. UTC | #4
On Mon, Jun 22, 2020 at 06:49:26PM +0300, Imre Deak wrote:
> On Wed, Jun 17, 2020 at 05:01:23PM -0700, Manasi Navare wrote:
> > Modify the helper to add a fixed delay or poll with timeout
> > based on platform specification in bothe enable and disable
> > cases so check for either Idle bit set (DDI_BUF_CTL is idle
> > for disable case) or check for Idle bit = 0 (non idle for
> > DDI BUF enable case)
> > 
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Imre Deak <imre.deak@intel.com>
> > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_ddi.c | 34 +++++++++++++++---------
> >  1 file changed, 21 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> > index ca7bb2294d2b..e4738c3b6d44 100644
> > --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> > @@ -1182,18 +1182,26 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
> >  }
> >  
> >  static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
> > -				    enum port port)
> 
> maybe intel_ddi_wait_for_ddi_buf(i915, port, active) ?

So here you mean active which is true if we are checking during enable for non_idle
and vice versa for disable, active will be false or checking for idel state?

> 
> > +				    enum port port, bool idle)
> >  {
> > -	i915_reg_t reg = DDI_BUF_CTL(port);
> > -	int i;
> > -
> > -	for (i = 0; i < 16; i++) {
> > -		udelay(1);
> > -		if (intel_de_read(dev_priv, reg) & DDI_BUF_IS_IDLE)
> > -			return;
> > +	if (idle) {
> > +		if (IS_BROXTON(dev_priv))
> > +			udelay(16);
> > +		else
> > +			if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > +					 DDI_BUF_IS_IDLE), 16))
> > +				drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > +					port_name(port));
> > +	} else {
> > +		if (INTEL_GEN(dev_priv) < 10)
> > +			udelay(600);
> > +		else
> > +			if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > +					  DDI_BUF_IS_IDLE), 600))
> > +				drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
> > +					port_name(port));
> >  	}
> > -	drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > -		port_name(port));
> > +
> 
> since we can only guarantee a minimum delay or timeout, imo it could be just:
> 
> 	if (BXT && !active || GEN <= 9 && active) {
> 		usleep_range(600, 1000);
> 		return;

Didnt quite understand this logic, for BXT & !active which is BXT and idle, it shd be fixed delay of just 16usecs
or if it is !BXT and !active then we wait with a timeout
also for gen <=9 and active, it shd be fixed delay of 600 and greater than or = 10 and active should
be a timeout

Manasi

> 	}
> 
> 	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE) == active, 600))
> 		drm_err("Port %c: Timeout waiting for DDI BUF to get %s\n",
> 			port, active ? "active" : "idle"));
> 		
> 
> >  }
> >  
> >  static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
> > @@ -1373,7 +1381,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
> >  		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
> >  		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
> >  
> > -		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
> > +		intel_wait_ddi_buf_idle(dev_priv, PORT_E, true);
> >  
> >  		/* Reset FDI_RX_MISC pwrdn lanes */
> >  		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
> > @@ -3495,7 +3503,7 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
> >  	intel_ddi_disable_fec_state(encoder, crtc_state);
> >  
> >  	if (wait)
> > -		intel_wait_ddi_buf_idle(dev_priv, port);
> > +		intel_wait_ddi_buf_idle(dev_priv, port, true);
> >  }
> >  
> >  static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
> > @@ -4004,7 +4012,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> >  		intel_de_posting_read(dev_priv, intel_dp->regs.dp_tp_ctl);
> >  
> >  		if (wait)
> > -			intel_wait_ddi_buf_idle(dev_priv, port);
> > +			intel_wait_ddi_buf_idle(dev_priv, port, true);
> >  	}
> >  
> >  	dp_tp_ctl = DP_TP_CTL_ENABLE |
> 
> The DSI code could also use the new helper.
> 
> > -- 
> > 2.19.1
> >
Imre Deak June 23, 2020, 7:57 p.m. UTC | #5
On Tue, Jun 23, 2020 at 12:42:00PM -0700, Manasi Navare wrote:
> On Mon, Jun 22, 2020 at 06:49:26PM +0300, Imre Deak wrote:
> > On Wed, Jun 17, 2020 at 05:01:23PM -0700, Manasi Navare wrote:
> > > Modify the helper to add a fixed delay or poll with timeout
> > > based on platform specification in bothe enable and disable
> > > cases so check for either Idle bit set (DDI_BUF_CTL is idle
> > > for disable case) or check for Idle bit = 0 (non idle for
> > > DDI BUF enable case)
> > > 
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Cc: Imre Deak <imre.deak@intel.com>
> > > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/display/intel_ddi.c | 34 +++++++++++++++---------
> > >  1 file changed, 21 insertions(+), 13 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> > > index ca7bb2294d2b..e4738c3b6d44 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> > > @@ -1182,18 +1182,26 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
> > >  }
> > >  
> > >  static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
> > > -				    enum port port)
> > 
> > maybe intel_ddi_wait_for_ddi_buf(i915, port, active) ?
> 
> So here you mean active which is true if we are checking during enable for non_idle
> and vice versa for disable, active will be false or checking for idel state?

Maybe just use Ville's idea with two functions instead.

> 
> > 
> > > +				    enum port port, bool idle)
> > >  {
> > > -	i915_reg_t reg = DDI_BUF_CTL(port);
> > > -	int i;
> > > -
> > > -	for (i = 0; i < 16; i++) {
> > > -		udelay(1);
> > > -		if (intel_de_read(dev_priv, reg) & DDI_BUF_IS_IDLE)
> > > -			return;
> > > +	if (idle) {
> > > +		if (IS_BROXTON(dev_priv))
> > > +			udelay(16);
> > > +		else
> > > +			if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > > +					 DDI_BUF_IS_IDLE), 16))
> > > +				drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > > +					port_name(port));
> > > +	} else {
> > > +		if (INTEL_GEN(dev_priv) < 10)
> > > +			udelay(600);
> > > +		else
> > > +			if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > > +					  DDI_BUF_IS_IDLE), 600))
> > > +				drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
> > > +					port_name(port));
> > >  	}
> > > -	drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > > -		port_name(port));
> > > +
> > 
> > since we can only guarantee a minimum delay or timeout, imo it could be just:
> > 
> > 	if (BXT && !active || GEN <= 9 && active) {
> > 		usleep_range(600, 1000);
> > 		return;
> 

> Didnt quite understand this logic, for BXT & !active which is BXT and
> idle, it shd be fixed delay of just 16usecs
> or if it is !BXT and !active then we wait with a timeout
> also for gen <=9 and active, it shd be fixed delay of 600
> and greater than or = 10 and active should be a timeout

yes, the above would match what I provided. The fixed delay for all
platforms would be a minimum 600usec delay. You can't guarantee that the
delay would be only 16usec in any case, so using 600 usec on BXT too
would be ok.

> Manasi
> 
> > 	}
> > 
> > 	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE) == active, 600))
> > 		drm_err("Port %c: Timeout waiting for DDI BUF to get %s\n",
> > 			port, active ? "active" : "idle"));
> > 		
> > 
> > >  }
> > >  
> > >  static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
> > > @@ -1373,7 +1381,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
> > >  		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
> > >  		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
> > >  
> > > -		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
> > > +		intel_wait_ddi_buf_idle(dev_priv, PORT_E, true);
> > >  
> > >  		/* Reset FDI_RX_MISC pwrdn lanes */
> > >  		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
> > > @@ -3495,7 +3503,7 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
> > >  	intel_ddi_disable_fec_state(encoder, crtc_state);
> > >  
> > >  	if (wait)
> > > -		intel_wait_ddi_buf_idle(dev_priv, port);
> > > +		intel_wait_ddi_buf_idle(dev_priv, port, true);
> > >  }
> > >  
> > >  static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
> > > @@ -4004,7 +4012,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> > >  		intel_de_posting_read(dev_priv, intel_dp->regs.dp_tp_ctl);
> > >  
> > >  		if (wait)
> > > -			intel_wait_ddi_buf_idle(dev_priv, port);
> > > +			intel_wait_ddi_buf_idle(dev_priv, port, true);
> > >  	}
> > >  
> > >  	dp_tp_ctl = DP_TP_CTL_ENABLE |
> > 
> > The DSI code could also use the new helper.
> > 
> > > -- 
> > > 2.19.1
> > >
Navare, Manasi June 23, 2020, 8:32 p.m. UTC | #6
On Tue, Jun 23, 2020 at 10:57:10PM +0300, Imre Deak wrote:
> On Tue, Jun 23, 2020 at 12:42:00PM -0700, Manasi Navare wrote:
> > On Mon, Jun 22, 2020 at 06:49:26PM +0300, Imre Deak wrote:
> > > On Wed, Jun 17, 2020 at 05:01:23PM -0700, Manasi Navare wrote:
> > > > Modify the helper to add a fixed delay or poll with timeout
> > > > based on platform specification in bothe enable and disable
> > > > cases so check for either Idle bit set (DDI_BUF_CTL is idle
> > > > for disable case) or check for Idle bit = 0 (non idle for
> > > > DDI BUF enable case)
> > > > 
> > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Cc: Imre Deak <imre.deak@intel.com>
> > > > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/display/intel_ddi.c | 34 +++++++++++++++---------
> > > >  1 file changed, 21 insertions(+), 13 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> > > > index ca7bb2294d2b..e4738c3b6d44 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> > > > @@ -1182,18 +1182,26 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
> > > >  }
> > > >  
> > > >  static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
> > > > -				    enum port port)
> > > 
> > > maybe intel_ddi_wait_for_ddi_buf(i915, port, active) ?
> > 
> > So here you mean active which is true if we are checking during enable for non_idle
> > and vice versa for disable, active will be false or checking for idel state?
> 
> Maybe just use Ville's idea with two functions instead.
> 
> > 
> > > 
> > > > +				    enum port port, bool idle)
> > > >  {
> > > > -	i915_reg_t reg = DDI_BUF_CTL(port);
> > > > -	int i;
> > > > -
> > > > -	for (i = 0; i < 16; i++) {
> > > > -		udelay(1);
> > > > -		if (intel_de_read(dev_priv, reg) & DDI_BUF_IS_IDLE)
> > > > -			return;
> > > > +	if (idle) {
> > > > +		if (IS_BROXTON(dev_priv))
> > > > +			udelay(16);
> > > > +		else
> > > > +			if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > > > +					 DDI_BUF_IS_IDLE), 16))
> > > > +				drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > > > +					port_name(port));
> > > > +	} else {
> > > > +		if (INTEL_GEN(dev_priv) < 10)
> > > > +			udelay(600);
> > > > +		else
> > > > +			if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
> > > > +					  DDI_BUF_IS_IDLE), 600))
> > > > +				drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
> > > > +					port_name(port));
> > > >  	}
> > > > -	drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
> > > > -		port_name(port));
> > > > +
> > > 
> > > since we can only guarantee a minimum delay or timeout, imo it could be just:
> > > 
> > > 	if (BXT && !active || GEN <= 9 && active) {
> > > 		usleep_range(600, 1000);
> > > 		return;
> > 
> 
> > Didnt quite understand this logic, for BXT & !active which is BXT and
> > idle, it shd be fixed delay of just 16usecs
> > or if it is !BXT and !active then we wait with a timeout
> > also for gen <=9 and active, it shd be fixed delay of 600
> > and greater than or = 10 and active should be a timeout
> 
> yes, the above would match what I provided. The fixed delay for all
> platforms would be a minimum 600usec delay. You can't guarantee that the
> delay would be only 16usec in any case, so using 600 usec on BXT too
> would be ok.

still dont quite get it, how is usleep_range (600, 1000) providing a fixed delay?

Now if we split ino 2 functs, one for disable, for that:

if (BXT)
	usleep_range(600, 1000)
else
	wait_for_us(check if Idle bit set)

so in both functions, for the timeout part we still use the wait_for_us helper right?

Manasi

> 
> > Manasi
> > 
> > > 	}
> > > 
> > > 	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE) == active, 600))
> > > 		drm_err("Port %c: Timeout waiting for DDI BUF to get %s\n",
> > > 			port, active ? "active" : "idle"));
> > > 		
> > > 
> > > >  }
> > > >  
> > > >  static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
> > > > @@ -1373,7 +1381,7 @@ void hsw_fdi_link_train(struct intel_encoder *encoder,
> > > >  		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
> > > >  		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
> > > >  
> > > > -		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
> > > > +		intel_wait_ddi_buf_idle(dev_priv, PORT_E, true);
> > > >  
> > > >  		/* Reset FDI_RX_MISC pwrdn lanes */
> > > >  		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
> > > > @@ -3495,7 +3503,7 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
> > > >  	intel_ddi_disable_fec_state(encoder, crtc_state);
> > > >  
> > > >  	if (wait)
> > > > -		intel_wait_ddi_buf_idle(dev_priv, port);
> > > > +		intel_wait_ddi_buf_idle(dev_priv, port, true);
> > > >  }
> > > >  
> > > >  static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
> > > > @@ -4004,7 +4012,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> > > >  		intel_de_posting_read(dev_priv, intel_dp->regs.dp_tp_ctl);
> > > >  
> > > >  		if (wait)
> > > > -			intel_wait_ddi_buf_idle(dev_priv, port);
> > > > +			intel_wait_ddi_buf_idle(dev_priv, port, true);
> > > >  	}
> > > >  
> > > >  	dp_tp_ctl = DP_TP_CTL_ENABLE |
> > > 
> > > The DSI code could also use the new helper.
> > > 
> > > > -- 
> > > > 2.19.1
> > > >
Imre Deak June 23, 2020, 8:50 p.m. UTC | #7
On Tue, Jun 23, 2020 at 01:32:50PM -0700, Manasi Navare wrote:
> still dont quite get it, how is usleep_range (600, 1000) providing a fixed delay?

Not sure what you mean. udelay is busy looping, while usleep_range
sleeps instead. How to chose between udelay/usleep_range please read

Documentation/timers/timers-howto.rst

> Now if we split ino 2 functs, one for disable, for that:
> 
> if (BXT)
> 	usleep_range(600, 1000)
> else
> 	wait_for_us(check if Idle bit set)
> 
> so in both functions, for the timeout part we still use the wait_for_us helper right?

with two functions it would get:

intel_ddi_wait_for_ddi_buf_active(i915, port)
{
	if (GEN <= 9) {
		usleep_range(600, 1000);
		return;
	}

 	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE), 600))
 		drm_err("Port %c: Timeout waiting for DDI BUF to get active\n", port));
}

intel_ddi_wait_for_ddi_buf_idle(i915, port)
{
	if (BXT) {
		udelay(16);
		return;
	}

 	if (wait_for_us(read(BUF_CTL) & IS_IDLE, 600))
 		drm_err("Port %c: Timeout waiting for DDI BUF to get idle\n", port));
}

--Imre
Navare, Manasi June 23, 2020, 10:19 p.m. UTC | #8
On Tue, Jun 23, 2020 at 11:50:27PM +0300, Imre Deak wrote:
> On Tue, Jun 23, 2020 at 01:32:50PM -0700, Manasi Navare wrote:
> > still dont quite get it, how is usleep_range (600, 1000) providing a fixed delay?
> 
> Not sure what you mean. udelay is busy looping, while usleep_range
> sleeps instead. How to chose between udelay/usleep_range please read
> 
> Documentation/timers/timers-howto.rst
>

Yes thanks for pointing me to the documentation.
I guess I thought you were suggesting to use just usleep_range for both
fixed delay and delay with timeout so got confused.
 
> > Now if we split ino 2 functs, one for disable, for that:
> > 
> > if (BXT)
> > 	usleep_range(600, 1000)
> > else
> > 	wait_for_us(check if Idle bit set)
> > 
> > so in both functions, for the timeout part we still use the wait_for_us helper right?
> 
> with two functions it would get:
> 
> intel_ddi_wait_for_ddi_buf_active(i915, port)
> {
> 	if (GEN <= 9) {
> 		usleep_range(600, 1000);

The doumentation however does suggest that we use udelay to avoid the overhead
of setting up hrtimers needed for usleep_range in atomic context. But then
checkpatch also suggests using usleep_range, why is that?

so still not clear in the context of i915 how we decide where to use jiffie based
delay through udelay and when to use hrtimers (usleep)?

Manasi


> 		return;
> 	}
> 
>  	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE), 600))
>  		drm_err("Port %c: Timeout waiting for DDI BUF to get active\n", port));
> }
> 
> intel_ddi_wait_for_ddi_buf_idle(i915, port)
> {
> 	if (BXT) {
> 		udelay(16);
> 		return;
> 	}
> 
>  	if (wait_for_us(read(BUF_CTL) & IS_IDLE, 600))
>  		drm_err("Port %c: Timeout waiting for DDI BUF to get idle\n", port));
> }
> 
> --Imre
Imre Deak June 23, 2020, 10:50 p.m. UTC | #9
On Tue, Jun 23, 2020 at 03:19:41PM -0700, Manasi Navare wrote:
> On Tue, Jun 23, 2020 at 11:50:27PM +0300, Imre Deak wrote:
> > On Tue, Jun 23, 2020 at 01:32:50PM -0700, Manasi Navare wrote:
> > 
> > with two functions it would get:
> > 
> > intel_ddi_wait_for_ddi_buf_active(i915, port)
> > {
> > 	if (GEN <= 9) {
> > 		usleep_range(600, 1000);
> 
> The doumentation however does suggest that we use udelay to avoid the overhead
> of setting up hrtimers needed for usleep_range in atomic context.

The relevant part here is "NON-ATOMIC CONTEXT":

SLEEPING FOR "A FEW" USECS ( < ~10us? ):
	* Use udelay

	- Why not usleep?
                        On slower systems, (embedded, OR perhaps a speed-
                        stepped PC!) the overhead of setting up the hrtimers
                        for usleep *may* not be worth it. Such an evaluation
                        will obviously depend on your specific situation, but
                        it is something to be aware of.

SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms):
        * Use usleep_range

So, can use udelay() for 16usec and should use usleep_range() for 600 usec.

> But then checkpatch also suggests using usleep_range, why is that?
> 
> so still not clear in the context of i915 how we decide where to use jiffie based
> delay through udelay and when to use hrtimers (usleep)?

The above document should be followed.

> 
> Manasi
> 
> 
> > 		return;
> > 	}
> > 
> >  	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE), 600))
> >  		drm_err("Port %c: Timeout waiting for DDI BUF to get active\n", port));
> > }
> > 
> > intel_ddi_wait_for_ddi_buf_idle(i915, port)
> > {
> > 	if (BXT) {
> > 		udelay(16);
> > 		return;
> > 	}
> > 
> >  	if (wait_for_us(read(BUF_CTL) & IS_IDLE, 600))
> >  		drm_err("Port %c: Timeout waiting for DDI BUF to get idle\n", port));
> > }
> > 
> > --Imre
Navare, Manasi June 23, 2020, 10:59 p.m. UTC | #10
On Wed, Jun 24, 2020 at 01:50:06AM +0300, Imre Deak wrote:
> On Tue, Jun 23, 2020 at 03:19:41PM -0700, Manasi Navare wrote:
> > On Tue, Jun 23, 2020 at 11:50:27PM +0300, Imre Deak wrote:
> > > On Tue, Jun 23, 2020 at 01:32:50PM -0700, Manasi Navare wrote:
> > > 
> > > with two functions it would get:
> > > 
> > > intel_ddi_wait_for_ddi_buf_active(i915, port)
> > > {
> > > 	if (GEN <= 9) {
> > > 		usleep_range(600, 1000);
> > 
> > The doumentation however does suggest that we use udelay to avoid the overhead
> > of setting up hrtimers needed for usleep_range in atomic context.
> 
> The relevant part here is "NON-ATOMIC CONTEXT":
> 
> SLEEPING FOR "A FEW" USECS ( < ~10us? ):
> 	* Use udelay
> 
> 	- Why not usleep?
>                         On slower systems, (embedded, OR perhaps a speed-
>                         stepped PC!) the overhead of setting up the hrtimers
>                         for usleep *may* not be worth it. Such an evaluation
>                         will obviously depend on your specific situation, but
>                         it is something to be aware of.
> 
> SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms):
>         * Use usleep_range
> 
> So, can use udelay() for 16usec and should use usleep_range() for 600 usec.

Got it thanks will update and send the next rev

Regards
Manasi

> 
> > But then checkpatch also suggests using usleep_range, why is that?
> > 
> > so still not clear in the context of i915 how we decide where to use jiffie based
> > delay through udelay and when to use hrtimers (usleep)?
> 
> The above document should be followed.
> 
> > 
> > Manasi
> > 
> > 
> > > 		return;
> > > 	}
> > > 
> > >  	if (wait_for_us(!(read(BUF_CTL) & IS_IDLE), 600))
> > >  		drm_err("Port %c: Timeout waiting for DDI BUF to get active\n", port));
> > > }
> > > 
> > > intel_ddi_wait_for_ddi_buf_idle(i915, port)
> > > {
> > > 	if (BXT) {
> > > 		udelay(16);
> > > 		return;
> > > 	}
> > > 
> > >  	if (wait_for_us(read(BUF_CTL) & IS_IDLE, 600))
> > >  		drm_err("Port %c: Timeout waiting for DDI BUF to get idle\n", port));
> > > }
> > > 
> > > --Imre
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index ca7bb2294d2b..e4738c3b6d44 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -1182,18 +1182,26 @@  static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
 }
 
 static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
-				    enum port port)
+				    enum port port, bool idle)
 {
-	i915_reg_t reg = DDI_BUF_CTL(port);
-	int i;
-
-	for (i = 0; i < 16; i++) {
-		udelay(1);
-		if (intel_de_read(dev_priv, reg) & DDI_BUF_IS_IDLE)
-			return;
+	if (idle) {
+		if (IS_BROXTON(dev_priv))
+			udelay(16);
+		else
+			if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
+					 DDI_BUF_IS_IDLE), 16))
+				drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
+					port_name(port));
+	} else {
+		if (INTEL_GEN(dev_priv) < 10)
+			udelay(600);
+		else
+			if (wait_for_us(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
+					  DDI_BUF_IS_IDLE), 600))
+				drm_err(&dev_priv->drm, "DDI port:%c buffer idle\n",
+					port_name(port));
 	}
-	drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c idle bit\n",
-		port_name(port));
+
 }
 
 static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
@@ -1373,7 +1381,7 @@  void hsw_fdi_link_train(struct intel_encoder *encoder,
 		intel_de_write(dev_priv, DP_TP_CTL(PORT_E), temp);
 		intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));
 
-		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
+		intel_wait_ddi_buf_idle(dev_priv, PORT_E, true);
 
 		/* Reset FDI_RX_MISC pwrdn lanes */
 		temp = intel_de_read(dev_priv, FDI_RX_MISC(PIPE_A));
@@ -3495,7 +3503,7 @@  static void intel_disable_ddi_buf(struct intel_encoder *encoder,
 	intel_ddi_disable_fec_state(encoder, crtc_state);
 
 	if (wait)
-		intel_wait_ddi_buf_idle(dev_priv, port);
+		intel_wait_ddi_buf_idle(dev_priv, port, true);
 }
 
 static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
@@ -4004,7 +4012,7 @@  static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
 		intel_de_posting_read(dev_priv, intel_dp->regs.dp_tp_ctl);
 
 		if (wait)
-			intel_wait_ddi_buf_idle(dev_priv, port);
+			intel_wait_ddi_buf_idle(dev_priv, port, true);
 	}
 
 	dp_tp_ctl = DP_TP_CTL_ENABLE |