Skip to content

Commit

Permalink
drm/radeon/kms: use lcd pll limits when available
Browse files Browse the repository at this point in the history
The bios has alternate pll output limits for LCD panels.
If available, use these for pll divider calculations.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Alex Deucher authored and Dave Airlie committed Mar 14, 2010
1 parent b792210 commit 86cb2bb
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 5 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/atombios_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 14 additions & 0 deletions drivers/gpu/drm/radeon/radeon_atombios.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/radeon_combios.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
37 changes: 32 additions & 5 deletions drivers/gpu/drm/radeon/radeon_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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; */
Expand All @@ -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; */
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/radeon/radeon_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 */
Expand Down

0 comments on commit 86cb2bb

Please sign in to comment.