aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2011-01-31 16:48:52 -0500
committerDave Airlie <airlied@redhat.com>2011-02-01 21:49:41 -0500
commitf523f74eac1897b13c05c88ce6e5de0a7c34578b (patch)
tree54c2a3f66eae2c094fb2fe7ed37dbd04ac47f949 /drivers/gpu
parent51d4bf840a27fe02c883ddc6d9708af056773769 (diff)
drm/radeon/kms: add new pll algo for avivo asics
Based on the vbios code. This should hopefully fix the pll problems on a number of avivo asics once it's enabled. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Cc: stable@kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c123
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h23
4 files changed, 137 insertions, 19 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 842954fe74c5..4374168b75b8 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -951,8 +951,8 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
951 /* adjust pixel clock as needed */ 951 /* adjust pixel clock as needed */
952 adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss); 952 adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss);
953 953
954 radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, 954 radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
955 &ref_div, &post_div); 955 &ref_div, &post_div);
956 956
957 atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss); 957 atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
958 958
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 367365652e9a..5fda820959ed 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -780,6 +780,115 @@ static int radeon_ddc_dump(struct drm_connector *connector)
780 return ret; 780 return ret;
781} 781}
782 782
783/* avivo */
784static void avivo_get_fb_div(struct radeon_pll *pll,
785 u32 target_clock,
786 u32 post_div,
787 u32 ref_div,
788 u32 *fb_div,
789 u32 *frac_fb_div)
790{
791 u32 tmp = post_div * ref_div;
792
793 tmp *= target_clock;
794 *fb_div = tmp / pll->reference_freq;
795 *frac_fb_div = tmp % pll->reference_freq;
796}
797
798static u32 avivo_get_post_div(struct radeon_pll *pll,
799 u32 target_clock)
800{
801 u32 vco, post_div, tmp;
802
803 if (pll->flags & RADEON_PLL_USE_POST_DIV)
804 return pll->post_div;
805
806 if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
807 if (pll->flags & RADEON_PLL_IS_LCD)
808 vco = pll->lcd_pll_out_min;
809 else
810 vco = pll->pll_out_min;
811 } else {
812 if (pll->flags & RADEON_PLL_IS_LCD)
813 vco = pll->lcd_pll_out_max;
814 else
815 vco = pll->pll_out_max;
816 }
817
818 post_div = vco / target_clock;
819 tmp = vco % target_clock;
820
821 if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
822 if (tmp)
823 post_div++;
824 } else {
825 if (!tmp)
826 post_div--;
827 }
828
829 return post_div;
830}
831
832#define MAX_TOLERANCE 10
833
834void radeon_compute_pll_avivo(struct radeon_pll *pll,
835 u32 freq,
836 u32 *dot_clock_p,
837 u32 *fb_div_p,
838 u32 *frac_fb_div_p,
839 u32 *ref_div_p,
840 u32 *post_div_p)
841{
842 u32 target_clock = freq / 10;
843 u32 post_div = avivo_get_post_div(pll, target_clock);
844 u32 ref_div = pll->min_ref_div;
845 u32 fb_div = 0, frac_fb_div = 0, tmp;
846
847 if (pll->flags & RADEON_PLL_USE_REF_DIV)
848 ref_div = pll->reference_div;
849
850 if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
851 avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div);
852 frac_fb_div = (100 * frac_fb_div) / pll->reference_freq;
853 if (frac_fb_div >= 5) {
854 frac_fb_div -= 5;
855 frac_fb_div = frac_fb_div / 10;
856 frac_fb_div++;
857 }
858 if (frac_fb_div >= 10) {
859 fb_div++;
860 frac_fb_div = 0;
861 }
862 } else {
863 while (ref_div <= pll->max_ref_div) {
864 avivo_get_fb_div(pll, target_clock, post_div, ref_div,
865 &fb_div, &frac_fb_div);
866 if (frac_fb_div >= (pll->reference_freq / 2))
867 fb_div++;
868 frac_fb_div = 0;
869 tmp = (pll->reference_freq * fb_div) / (post_div * ref_div);
870 tmp = (tmp * 10000) / target_clock;
871
872 if (tmp > (10000 + MAX_TOLERANCE))
873 ref_div++;
874 else if (tmp >= (10000 - MAX_TOLERANCE))
875 break;
876 else
877 ref_div++;
878 }
879 }
880
881 *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) /
882 (ref_div * post_div * 10);
883 *fb_div_p = fb_div;
884 *frac_fb_div_p = frac_fb_div;
885 *ref_div_p = ref_div;
886 *post_div_p = post_div;
887 DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n",
888 *dot_clock_p, fb_div, frac_fb_div, ref_div, post_div);
889}
890
891/* pre-avivo */
783static inline uint32_t radeon_div(uint64_t n, uint32_t d) 892static inline uint32_t radeon_div(uint64_t n, uint32_t d)
784{ 893{
785 uint64_t mod; 894 uint64_t mod;
@@ -790,13 +899,13 @@ static inline uint32_t radeon_div(uint64_t n, uint32_t d)
790 return n; 899 return n;
791} 900}
792 901
793void radeon_compute_pll(struct radeon_pll *pll, 902void radeon_compute_pll_legacy(struct radeon_pll *pll,
794 uint64_t freq, 903 uint64_t freq,
795 uint32_t *dot_clock_p, 904 uint32_t *dot_clock_p,
796 uint32_t *fb_div_p, 905 uint32_t *fb_div_p,
797 uint32_t *frac_fb_div_p, 906 uint32_t *frac_fb_div_p,
798 uint32_t *ref_div_p, 907 uint32_t *ref_div_p,
799 uint32_t *post_div_p) 908 uint32_t *post_div_p)
800{ 909{
801 uint32_t min_ref_div = pll->min_ref_div; 910 uint32_t min_ref_div = pll->min_ref_div;
802 uint32_t max_ref_div = pll->max_ref_div; 911 uint32_t max_ref_div = pll->max_ref_div;
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index ace2e6384d40..cf0638c3b7c7 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -778,9 +778,9 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
778 DRM_DEBUG_KMS("\n"); 778 DRM_DEBUG_KMS("\n");
779 779
780 if (!use_bios_divs) { 780 if (!use_bios_divs) {
781 radeon_compute_pll(pll, mode->clock, 781 radeon_compute_pll_legacy(pll, mode->clock,
782 &freq, &feedback_div, &frac_fb_div, 782 &freq, &feedback_div, &frac_fb_div,
783 &reference_div, &post_divider); 783 &reference_div, &post_divider);
784 784
785 for (post_div = &post_divs[0]; post_div->divider; ++post_div) { 785 for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
786 if (post_div->divider == post_divider) 786 if (post_div->divider == post_divider)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 12bdeab91c86..6794cdf91f28 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -149,6 +149,7 @@ struct radeon_tmds_pll {
149#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) 149#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
150#define RADEON_PLL_USE_POST_DIV (1 << 12) 150#define RADEON_PLL_USE_POST_DIV (1 << 12)
151#define RADEON_PLL_IS_LCD (1 << 13) 151#define RADEON_PLL_IS_LCD (1 << 13)
152#define RADEON_PLL_PREFER_MINM_OVER_MAXP (1 << 14)
152 153
153struct radeon_pll { 154struct radeon_pll {
154 /* reference frequency */ 155 /* reference frequency */
@@ -510,13 +511,21 @@ extern bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
510 struct radeon_atom_ss *ss, 511 struct radeon_atom_ss *ss,
511 int id, u32 clock); 512 int id, u32 clock);
512 513
513extern void radeon_compute_pll(struct radeon_pll *pll, 514extern void radeon_compute_pll_legacy(struct radeon_pll *pll,
514 uint64_t freq, 515 uint64_t freq,
515 uint32_t *dot_clock_p, 516 uint32_t *dot_clock_p,
516 uint32_t *fb_div_p, 517 uint32_t *fb_div_p,
517 uint32_t *frac_fb_div_p, 518 uint32_t *frac_fb_div_p,
518 uint32_t *ref_div_p, 519 uint32_t *ref_div_p,
519 uint32_t *post_div_p); 520 uint32_t *post_div_p);
521
522extern void radeon_compute_pll_avivo(struct radeon_pll *pll,
523 u32 freq,
524 u32 *dot_clock_p,
525 u32 *fb_div_p,
526 u32 *frac_fb_div_p,
527 u32 *ref_div_p,
528 u32 *post_div_p);
520 529
521extern void radeon_setup_encoder_clones(struct drm_device *dev); 530extern void radeon_setup_encoder_clones(struct drm_device *dev);
522 531