Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86cb2bbf authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie
Browse files

drm/radeon/kms: use lcd pll limits when available



The bios has alternate pll output limits for LCD panels.
If available, use these for pll divider calculations.

Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent b792210e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -525,6 +525,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
				if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
					struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
					pll->algo = dig->pll_algo;
					pll->flags |= RADEON_PLL_IS_LCD;
				}
			} else {
				if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
+14 −0
Original line number Diff line number Diff line
@@ -887,6 +887,20 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
		p1pll->pll_out_max =
		    le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);

		if (crev >= 4) {
			p1pll->lcd_pll_out_min =
				le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
			if (p1pll->lcd_pll_out_min == 0)
				p1pll->lcd_pll_out_min = p1pll->pll_out_min;
			p1pll->lcd_pll_out_max =
				le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
			if (p1pll->lcd_pll_out_max == 0)
				p1pll->lcd_pll_out_max = p1pll->pll_out_max;
		} else {
			p1pll->lcd_pll_out_min = p1pll->pll_out_min;
			p1pll->lcd_pll_out_max = p1pll->pll_out_max;
		}

		if (p1pll->pll_out_min == 0) {
			if (ASIC_IS_AVIVO(rdev))
				p1pll->pll_out_min = 64800;
+2 −0
Original line number Diff line number Diff line
@@ -633,6 +633,8 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
		p1pll->reference_div = RBIOS16(pll_info + 0x10);
		p1pll->pll_out_min = RBIOS32(pll_info + 0x12);
		p1pll->pll_out_max = RBIOS32(pll_info + 0x16);
		p1pll->lcd_pll_out_min = p1pll->pll_out_min;
		p1pll->lcd_pll_out_max = p1pll->pll_out_max;

		if (rev > 9) {
			p1pll->pll_in_min = RBIOS32(pll_info + 0x36);
+32 −5
Original line number Diff line number Diff line
@@ -469,10 +469,19 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll,
	uint32_t best_error = 0xffffffff;
	uint32_t best_vco_diff = 1;
	uint32_t post_div;
	u32 pll_out_min, pll_out_max;

	DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div);
	freq = freq * 1000;

	if (pll->flags & RADEON_PLL_IS_LCD) {
		pll_out_min = pll->lcd_pll_out_min;
		pll_out_max = pll->lcd_pll_out_max;
	} else {
		pll_out_min = pll->pll_out_min;
		pll_out_max = pll->pll_out_max;
	}

	if (pll->flags & RADEON_PLL_USE_REF_DIV)
		min_ref_div = max_ref_div = pll->reference_div;
	else {
@@ -536,10 +545,10 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll,
				tmp = (uint64_t)pll->reference_freq * feedback_div;
				vco = radeon_div(tmp, ref_div);

				if (vco < pll->pll_out_min) {
				if (vco < pll_out_min) {
					min_feed_div = feedback_div + 1;
					continue;
				} else if (vco > pll->pll_out_max) {
				} else if (vco > pll_out_max) {
					max_feed_div = feedback_div;
					continue;
				}
@@ -675,6 +684,15 @@ calc_fb_ref_div(struct radeon_pll *pll,
{
	fixed20_12 ffreq, max_error, error, pll_out, a;
	u32 vco;
	u32 pll_out_min, pll_out_max;

	if (pll->flags & RADEON_PLL_IS_LCD) {
		pll_out_min = pll->lcd_pll_out_min;
		pll_out_max = pll->lcd_pll_out_max;
	} else {
		pll_out_min = pll->pll_out_min;
		pll_out_max = pll->pll_out_max;
	}

	ffreq.full = rfixed_const(freq);
	/* max_error = ffreq * 0.0025; */
@@ -686,7 +704,7 @@ calc_fb_ref_div(struct radeon_pll *pll,
			vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac));
			vco = vco / ((*ref_div) * 10);

			if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max))
			if ((vco < pll_out_min) || (vco > pll_out_max))
				continue;

			/* pll_out = vco / post_div; */
@@ -714,6 +732,15 @@ static void radeon_compute_pll_new(struct radeon_pll *pll,
{
	u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0;
	u32 best_freq = 0, vco_frequency;
	u32 pll_out_min, pll_out_max;

	if (pll->flags & RADEON_PLL_IS_LCD) {
		pll_out_min = pll->lcd_pll_out_min;
		pll_out_max = pll->lcd_pll_out_max;
	} else {
		pll_out_min = pll->pll_out_min;
		pll_out_max = pll->pll_out_max;
	}

	/* freq = freq / 10; */
	do_div(freq, 10);
@@ -724,7 +751,7 @@ static void radeon_compute_pll_new(struct radeon_pll *pll,
			goto done;

		vco_frequency = freq * post_div;
		if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
		if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max))
			goto done;

		if (pll->flags & RADEON_PLL_USE_REF_DIV) {
@@ -749,7 +776,7 @@ static void radeon_compute_pll_new(struct radeon_pll *pll,
				continue;

			vco_frequency = freq * post_div;
			if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max))
			if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max))
				continue;
			if (pll->flags & RADEON_PLL_USE_REF_DIV) {
				ref_div = pll->reference_div;
+3 −0
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ struct radeon_tmds_pll {
#define RADEON_PLL_USE_FRAC_FB_DIV      (1 << 10)
#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
#define RADEON_PLL_USE_POST_DIV         (1 << 12)
#define RADEON_PLL_IS_LCD               (1 << 13)

/* pll algo */
enum radeon_pll_algo {
@@ -149,6 +150,8 @@ struct radeon_pll {
	uint32_t pll_in_max;
	uint32_t pll_out_min;
	uint32_t pll_out_max;
	uint32_t lcd_pll_out_min;
	uint32_t lcd_pll_out_max;
	uint32_t best_vco;

	/* divider limits */