diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-03-08 12:55:16 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-03-14 19:56:46 -0400 |
commit | 86cb2bbfda2cf402aee46779ee90bbb7d915482b (patch) | |
tree | 341bcd42fe9bc49498905f97f2e61b2def21f22b /drivers/gpu | |
parent | b792210e7d1f9fb102061e2016da96cf2ad5cdbd (diff) |
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: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_combios.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 3 |
5 files changed, 52 insertions, 5 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 0c676696a0dd..a8cd637d92fa 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -525,6 +525,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
525 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { | 525 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { |
526 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 526 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
527 | pll->algo = dig->pll_algo; | 527 | pll->algo = dig->pll_algo; |
528 | pll->flags |= RADEON_PLL_IS_LCD; | ||
528 | } | 529 | } |
529 | } else { | 530 | } else { |
530 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | 531 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 93783b15c81d..e4540b2b859c 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -887,6 +887,20 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) | |||
887 | p1pll->pll_out_max = | 887 | p1pll->pll_out_max = |
888 | le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); | 888 | le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); |
889 | 889 | ||
890 | if (crev >= 4) { | ||
891 | p1pll->lcd_pll_out_min = | ||
892 | le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100; | ||
893 | if (p1pll->lcd_pll_out_min == 0) | ||
894 | p1pll->lcd_pll_out_min = p1pll->pll_out_min; | ||
895 | p1pll->lcd_pll_out_max = | ||
896 | le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100; | ||
897 | if (p1pll->lcd_pll_out_max == 0) | ||
898 | p1pll->lcd_pll_out_max = p1pll->pll_out_max; | ||
899 | } else { | ||
900 | p1pll->lcd_pll_out_min = p1pll->pll_out_min; | ||
901 | p1pll->lcd_pll_out_max = p1pll->pll_out_max; | ||
902 | } | ||
903 | |||
890 | if (p1pll->pll_out_min == 0) { | 904 | if (p1pll->pll_out_min == 0) { |
891 | if (ASIC_IS_AVIVO(rdev)) | 905 | if (ASIC_IS_AVIVO(rdev)) |
892 | p1pll->pll_out_min = 64800; | 906 | p1pll->pll_out_min = 64800; |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 69af81d9f5ae..30a84ae56811 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -633,6 +633,8 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) | |||
633 | p1pll->reference_div = RBIOS16(pll_info + 0x10); | 633 | p1pll->reference_div = RBIOS16(pll_info + 0x10); |
634 | p1pll->pll_out_min = RBIOS32(pll_info + 0x12); | 634 | p1pll->pll_out_min = RBIOS32(pll_info + 0x12); |
635 | p1pll->pll_out_max = RBIOS32(pll_info + 0x16); | 635 | p1pll->pll_out_max = RBIOS32(pll_info + 0x16); |
636 | p1pll->lcd_pll_out_min = p1pll->pll_out_min; | ||
637 | p1pll->lcd_pll_out_max = p1pll->pll_out_max; | ||
636 | 638 | ||
637 | if (rev > 9) { | 639 | if (rev > 9) { |
638 | p1pll->pll_in_min = RBIOS32(pll_info + 0x36); | 640 | p1pll->pll_in_min = RBIOS32(pll_info + 0x36); |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index ba8d806dcf39..ff5f09953c0a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -469,10 +469,19 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
469 | uint32_t best_error = 0xffffffff; | 469 | uint32_t best_error = 0xffffffff; |
470 | uint32_t best_vco_diff = 1; | 470 | uint32_t best_vco_diff = 1; |
471 | uint32_t post_div; | 471 | uint32_t post_div; |
472 | u32 pll_out_min, pll_out_max; | ||
472 | 473 | ||
473 | DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); | 474 | DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); |
474 | freq = freq * 1000; | 475 | freq = freq * 1000; |
475 | 476 | ||
477 | if (pll->flags & RADEON_PLL_IS_LCD) { | ||
478 | pll_out_min = pll->lcd_pll_out_min; | ||
479 | pll_out_max = pll->lcd_pll_out_max; | ||
480 | } else { | ||
481 | pll_out_min = pll->pll_out_min; | ||
482 | pll_out_max = pll->pll_out_max; | ||
483 | } | ||
484 | |||
476 | if (pll->flags & RADEON_PLL_USE_REF_DIV) | 485 | if (pll->flags & RADEON_PLL_USE_REF_DIV) |
477 | min_ref_div = max_ref_div = pll->reference_div; | 486 | min_ref_div = max_ref_div = pll->reference_div; |
478 | else { | 487 | else { |
@@ -536,10 +545,10 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
536 | tmp = (uint64_t)pll->reference_freq * feedback_div; | 545 | tmp = (uint64_t)pll->reference_freq * feedback_div; |
537 | vco = radeon_div(tmp, ref_div); | 546 | vco = radeon_div(tmp, ref_div); |
538 | 547 | ||
539 | if (vco < pll->pll_out_min) { | 548 | if (vco < pll_out_min) { |
540 | min_feed_div = feedback_div + 1; | 549 | min_feed_div = feedback_div + 1; |
541 | continue; | 550 | continue; |
542 | } else if (vco > pll->pll_out_max) { | 551 | } else if (vco > pll_out_max) { |
543 | max_feed_div = feedback_div; | 552 | max_feed_div = feedback_div; |
544 | continue; | 553 | continue; |
545 | } | 554 | } |
@@ -675,6 +684,15 @@ calc_fb_ref_div(struct radeon_pll *pll, | |||
675 | { | 684 | { |
676 | fixed20_12 ffreq, max_error, error, pll_out, a; | 685 | fixed20_12 ffreq, max_error, error, pll_out, a; |
677 | u32 vco; | 686 | u32 vco; |
687 | u32 pll_out_min, pll_out_max; | ||
688 | |||
689 | if (pll->flags & RADEON_PLL_IS_LCD) { | ||
690 | pll_out_min = pll->lcd_pll_out_min; | ||
691 | pll_out_max = pll->lcd_pll_out_max; | ||
692 | } else { | ||
693 | pll_out_min = pll->pll_out_min; | ||
694 | pll_out_max = pll->pll_out_max; | ||
695 | } | ||
678 | 696 | ||
679 | ffreq.full = rfixed_const(freq); | 697 | ffreq.full = rfixed_const(freq); |
680 | /* max_error = ffreq * 0.0025; */ | 698 | /* max_error = ffreq * 0.0025; */ |
@@ -686,7 +704,7 @@ calc_fb_ref_div(struct radeon_pll *pll, | |||
686 | vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac)); | 704 | vco = pll->reference_freq * (((*fb_div) * 10) + (*fb_div_frac)); |
687 | vco = vco / ((*ref_div) * 10); | 705 | vco = vco / ((*ref_div) * 10); |
688 | 706 | ||
689 | if ((vco < pll->pll_out_min) || (vco > pll->pll_out_max)) | 707 | if ((vco < pll_out_min) || (vco > pll_out_max)) |
690 | continue; | 708 | continue; |
691 | 709 | ||
692 | /* pll_out = vco / post_div; */ | 710 | /* pll_out = vco / post_div; */ |
@@ -714,6 +732,15 @@ static void radeon_compute_pll_new(struct radeon_pll *pll, | |||
714 | { | 732 | { |
715 | u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0; | 733 | u32 fb_div = 0, fb_div_frac = 0, post_div = 0, ref_div = 0; |
716 | u32 best_freq = 0, vco_frequency; | 734 | u32 best_freq = 0, vco_frequency; |
735 | u32 pll_out_min, pll_out_max; | ||
736 | |||
737 | if (pll->flags & RADEON_PLL_IS_LCD) { | ||
738 | pll_out_min = pll->lcd_pll_out_min; | ||
739 | pll_out_max = pll->lcd_pll_out_max; | ||
740 | } else { | ||
741 | pll_out_min = pll->pll_out_min; | ||
742 | pll_out_max = pll->pll_out_max; | ||
743 | } | ||
717 | 744 | ||
718 | /* freq = freq / 10; */ | 745 | /* freq = freq / 10; */ |
719 | do_div(freq, 10); | 746 | do_div(freq, 10); |
@@ -724,7 +751,7 @@ static void radeon_compute_pll_new(struct radeon_pll *pll, | |||
724 | goto done; | 751 | goto done; |
725 | 752 | ||
726 | vco_frequency = freq * post_div; | 753 | vco_frequency = freq * post_div; |
727 | if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max)) | 754 | if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max)) |
728 | goto done; | 755 | goto done; |
729 | 756 | ||
730 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { | 757 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { |
@@ -749,7 +776,7 @@ static void radeon_compute_pll_new(struct radeon_pll *pll, | |||
749 | continue; | 776 | continue; |
750 | 777 | ||
751 | vco_frequency = freq * post_div; | 778 | vco_frequency = freq * post_div; |
752 | if ((vco_frequency < pll->pll_out_min) || (vco_frequency > pll->pll_out_max)) | 779 | if ((vco_frequency < pll_out_min) || (vco_frequency > pll_out_max)) |
753 | continue; | 780 | continue; |
754 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { | 781 | if (pll->flags & RADEON_PLL_USE_REF_DIV) { |
755 | ref_div = pll->reference_div; | 782 | ref_div = pll->reference_div; |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 1702b820aa4d..b868ffad8beb 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -129,6 +129,7 @@ struct radeon_tmds_pll { | |||
129 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) | 129 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) |
130 | #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) | 130 | #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) |
131 | #define RADEON_PLL_USE_POST_DIV (1 << 12) | 131 | #define RADEON_PLL_USE_POST_DIV (1 << 12) |
132 | #define RADEON_PLL_IS_LCD (1 << 13) | ||
132 | 133 | ||
133 | /* pll algo */ | 134 | /* pll algo */ |
134 | enum radeon_pll_algo { | 135 | enum radeon_pll_algo { |
@@ -149,6 +150,8 @@ struct radeon_pll { | |||
149 | uint32_t pll_in_max; | 150 | uint32_t pll_in_max; |
150 | uint32_t pll_out_min; | 151 | uint32_t pll_out_min; |
151 | uint32_t pll_out_max; | 152 | uint32_t pll_out_max; |
153 | uint32_t lcd_pll_out_min; | ||
154 | uint32_t lcd_pll_out_max; | ||
152 | uint32_t best_vco; | 155 | uint32_t best_vco; |
153 | 156 | ||
154 | /* divider limits */ | 157 | /* divider limits */ |