diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_cdclk.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_cdclk.c | 118 | 
1 files changed, 73 insertions, 45 deletions
| diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index c4839c67cb0f..c985ebb6831a 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1180,7 +1180,7 @@ sanitize:  	/* force cdclk programming */  	dev_priv->display.cdclk.hw.cdclk = 0;  	/* force full PLL disable + enable */ -	dev_priv->display.cdclk.hw.vco = -1; +	dev_priv->display.cdclk.hw.vco = ~0;  }  static void skl_cdclk_init_hw(struct drm_i915_private *dev_priv) @@ -1446,50 +1446,77 @@ static u8 bxt_calc_voltage_level(int cdclk)  	return DIV_ROUND_UP(cdclk, 25000);  } +static u8 calc_voltage_level(int cdclk, int num_voltage_levels, +			     const int voltage_level_max_cdclk[]) +{ +	int voltage_level; + +	for (voltage_level = 0; voltage_level < num_voltage_levels; voltage_level++) { +		if (cdclk <= voltage_level_max_cdclk[voltage_level]) +			return voltage_level; +	} + +	MISSING_CASE(cdclk); +	return num_voltage_levels - 1; +} +  static u8 icl_calc_voltage_level(int cdclk)  { -	if (cdclk > 556800) -		return 2; -	else if (cdclk > 312000) -		return 1; -	else -		return 0; +	static const int icl_voltage_level_max_cdclk[] = { +		[0] = 312000, +		[1] = 556800, +		[2] = 652800, +	}; + +	return calc_voltage_level(cdclk, +				  ARRAY_SIZE(icl_voltage_level_max_cdclk), +				  icl_voltage_level_max_cdclk);  }  static u8 ehl_calc_voltage_level(int cdclk)  { -	if (cdclk > 326400) -		return 3; -	else if (cdclk > 312000) -		return 2; -	else if (cdclk > 180000) -		return 1; -	else -		return 0; +	static const int ehl_voltage_level_max_cdclk[] = { +		[0] = 180000, +		[1] = 312000, +		[2] = 326400, +		/* +		 * Bspec lists the limit as 556.8 MHz, but some JSL +		 * development boards (at least) boot with 652.8 MHz +		 */ +		[3] = 652800, +	}; + +	return calc_voltage_level(cdclk, +				  ARRAY_SIZE(ehl_voltage_level_max_cdclk), +				  ehl_voltage_level_max_cdclk);  }  static u8 tgl_calc_voltage_level(int cdclk)  { -	if (cdclk > 556800) -		return 3; -	else if (cdclk > 326400) -		return 2; -	else if (cdclk > 312000) -		return 1; -	else -		return 0; +	static const int tgl_voltage_level_max_cdclk[] = { +		[0] = 312000, +		[1] = 326400, +		[2] = 556800, +		[3] = 652800, +	}; + +	return calc_voltage_level(cdclk, +				  ARRAY_SIZE(tgl_voltage_level_max_cdclk), +				  tgl_voltage_level_max_cdclk);  }  static u8 rplu_calc_voltage_level(int cdclk)  { -	if (cdclk > 556800) -		return 3; -	else if (cdclk > 480000) -		return 2; -	else if (cdclk > 312000) -		return 1; -	else -		return 0; +	static const int rplu_voltage_level_max_cdclk[] = { +		[0] = 312000, +		[1] = 480000, +		[2] = 556800, +		[3] = 652800, +	}; + +	return calc_voltage_level(cdclk, +				  ARRAY_SIZE(rplu_voltage_level_max_cdclk), +				  rplu_voltage_level_max_cdclk);  }  static void icl_readout_refclk(struct drm_i915_private *dev_priv, @@ -1800,6 +1827,8 @@ static bool cdclk_pll_is_unknown(unsigned int vco)  	return vco == ~0;  } +static const int cdclk_squash_len = 16; +  static int cdclk_squash_divider(u16 waveform)  {  	return hweight16(waveform ?: 0xffff); @@ -1811,7 +1840,6 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i91  						    struct intel_cdclk_config *mid_cdclk_config)  {  	u16 old_waveform, new_waveform, mid_waveform; -	int size = 16;  	int div = 2;  	/* Return if PLL is in an unknown state, force a complete disable and re-enable. */ @@ -1850,7 +1878,8 @@ static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i91  	}  	mid_cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_squash_divider(mid_waveform) * -						    mid_cdclk_config->vco, size * div); +						    mid_cdclk_config->vco, +						    cdclk_squash_len * div);  	/* make sure the mid clock came out sane */ @@ -1878,9 +1907,9 @@ static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,  {  	int cdclk = cdclk_config->cdclk;  	int vco = cdclk_config->vco; -	u32 val; +	int unsquashed_cdclk;  	u16 waveform; -	int clock; +	u32 val;  	if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0 &&  	    !cdclk_pll_is_unknown(dev_priv->display.cdclk.hw.vco)) { @@ -1897,15 +1926,13 @@ static void _bxt_set_cdclk(struct drm_i915_private *dev_priv,  	waveform = cdclk_squash_waveform(dev_priv, cdclk); -	if (waveform) -		clock = vco / 2; -	else -		clock = cdclk; +	unsquashed_cdclk = DIV_ROUND_CLOSEST(cdclk * cdclk_squash_len, +					     cdclk_squash_divider(waveform));  	if (HAS_CDCLK_SQUASH(dev_priv))  		dg2_cdclk_squash_program(dev_priv, waveform); -	val = bxt_cdclk_cd2x_div_sel(dev_priv, clock, vco) | +	val = bxt_cdclk_cd2x_div_sel(dev_priv, unsquashed_cdclk, vco) |  		bxt_cdclk_cd2x_pipe(dev_priv, pipe);  	/* @@ -2075,7 +2102,7 @@ sanitize:  	dev_priv->display.cdclk.hw.cdclk = 0;  	/* force full PLL disable + enable */ -	dev_priv->display.cdclk.hw.vco = -1; +	dev_priv->display.cdclk.hw.vco = ~0;  }  static void bxt_cdclk_init_hw(struct drm_i915_private *dev_priv) @@ -2597,9 +2624,10 @@ static int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state)  		 * Since PPC = 2 with bigjoiner  		 * => CDCLK >= compressed_bpp * Pixel clock  / 2 * Bigjoiner Interface bits  		 */ -		int bigjoiner_interface_bits = DISPLAY_VER(i915) > 13 ? 36 : 24; -		int min_cdclk_bj = (crtc_state->dsc.compressed_bpp * pixel_clock) / -				   (2 * bigjoiner_interface_bits); +		int bigjoiner_interface_bits = DISPLAY_VER(i915) >= 14 ? 36 : 24; +		int min_cdclk_bj = +			(to_bpp_int_roundup(crtc_state->dsc.compressed_bpp_x16) * +			 pixel_clock) / (2 * bigjoiner_interface_bits);  		min_cdclk = max(min_cdclk, min_cdclk_bj);  	} @@ -3488,7 +3516,7 @@ static const struct intel_cdclk_funcs mtl_cdclk_funcs = {  	.get_cdclk = bxt_get_cdclk,  	.set_cdclk = bxt_set_cdclk,  	.modeset_calc_cdclk = bxt_modeset_calc_cdclk, -	.calc_voltage_level = tgl_calc_voltage_level, +	.calc_voltage_level = rplu_calc_voltage_level,  };  static const struct intel_cdclk_funcs rplu_cdclk_funcs = { | 
