[Intel-gfx] [PATCH 4/6] drm/i915: Make the LPT iclkip 20MHz case more generic

Imre Deak imre.deak at intel.com
Fri Feb 19 14:04:11 UTC 2016


On ke, 2016-02-17 at 21:41 +0200, ville.syrjala at linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> 
> The reason for spcial casing 20MHz in the iclkip calculations is that
> it would overflow the 7 bit divisor value. Let's rewrite the special
> case to check for just that, and bump up auxdiv when needed. This
> makes
> the code work for freqeuencies close to but not exactly 20MHz. The
> real
> lower limit for auxdiv=0 is actually:
> 172800000/(0x7f+2)*64)=~20930 kHz, and below that we must resort to
> auxdiv=1.
> 
> Actually this is all very theoretical since we limit the dotclock to
> min 25MHz with CRT on all platforms. 25Mhz is actually the documented
> limit in Bspec, so it seems we ought to never need to worry about the
> auxdiv=1 case. But no harm in having it.
> 
> Cc: Paulo Zanoni <paulo.r.zanoni at intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

Yep, fewer special casing is better. Btw, the spec could have just as
well describe how to calculate aux_div instead of providing special
cases and tables, I wonder why this is done at places. The patch looks
good:
Reviewed-by: Imre Deak <imre.deak at intel.com>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 40 +++++++++++++++++---------
> ----------
>  1 file changed, 19 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index a3c959cd8b3b..5e7b22a31098 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3957,37 +3957,35 @@ static void lpt_disable_iclkip(struct
> drm_i915_private *dev_priv)
>  /* Program iCLKIP clock to the desired frequency */
>  static void lpt_program_iclkip(struct drm_crtc *crtc)
>  {
> -	struct drm_device *dev = crtc->dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
>  	int clock = to_intel_crtc(crtc)->config-
> >base.adjusted_mode.crtc_clock;
>  	u32 divsel, phaseinc, auxdiv, phasedir = 0;
>  	u32 temp;
>  
>  	lpt_disable_iclkip(dev_priv);
>  
> -	/* 20MHz is a corner case which is out of range for the 7-
> bit divisor */
> -	if (clock == 20000) {
> -		auxdiv = 1;
> -		divsel = 0x41;
> -		phaseinc = 0x20;
> -	} else {
> -		/* The iCLK virtual clock root frequency is in MHz,
> -		 * but the adjusted_mode->crtc_clock in in KHz. To
> get the
> -		 * divisors, it is necessary to divide one by
> another, so we
> -		 * convert the virtual clock precision to KHz here
> for higher
> -		 * precision.
> -		 */
> +	/* The iCLK virtual clock root frequency is in MHz,
> +	 * but the adjusted_mode->crtc_clock in in KHz. To get the
> +	 * divisors, it is necessary to divide one by another, so we
> +	 * convert the virtual clock precision to KHz here for
> higher
> +	 * precision.
> +	 */
> +	for (auxdiv = 0; auxdiv < 2; auxdiv++) {
>  		u32 iclk_virtual_root_freq = 172800 * 1000;
>  		u32 iclk_pi_range = 64;
> -		u32 desired_divisor, msb_divisor_value, pi_value;
> +		u32 desired_divisor;
>  
> -		desired_divisor =
> DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock);
> -		msb_divisor_value = desired_divisor / iclk_pi_range;
> -		pi_value = desired_divisor % iclk_pi_range;
> +		desired_divisor =
> DIV_ROUND_CLOSEST(iclk_virtual_root_freq,
> +						    clock <<
> auxdiv);
> +		divsel = (desired_divisor / iclk_pi_range) - 2;
> +		phaseinc = desired_divisor % iclk_pi_range;
>  
> -		auxdiv = 0;
> -		divsel = msb_divisor_value - 2;
> -		phaseinc = pi_value;
> +		/*
> +		 * Near 20MHz is a corner case which is
> +		 * out of range for the 7-bit divisor
> +		 */
> +		if (divsel <= 0x7f)
> +			break;
>  	}
>  
>  	/* This should not happen with any sane values */


More information about the Intel-gfx mailing list