aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_display.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-02-19 22:17:35 -0500
committerDavid S. Miller <davem@davemloft.net>2011-02-19 22:17:35 -0500
commitda935c66bacb3ed9ada984b053297f87c2dff63a (patch)
tree46278da2b312c73f1375b830d7e5912bf23abd78 /drivers/gpu/drm/radeon/radeon_display.c
parent9435eb1cf0b76b323019cebf8d16762a50a12a19 (diff)
parent2205a6ea93fea76f88b43727fea53f3ce3790d6f (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: Documentation/feature-removal-schedule.txt drivers/net/e1000e/netdev.c net/xfrm/xfrm_policy.c
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c142
1 files changed, 134 insertions, 8 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index d26dabf878d9..0e657095de7c 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -780,6 +780,125 @@ 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 if (*fb_div > pll->max_feedback_div)
798 *fb_div = pll->max_feedback_div;
799 else if (*fb_div < pll->min_feedback_div)
800 *fb_div = pll->min_feedback_div;
801}
802
803static u32 avivo_get_post_div(struct radeon_pll *pll,
804 u32 target_clock)
805{
806 u32 vco, post_div, tmp;
807
808 if (pll->flags & RADEON_PLL_USE_POST_DIV)
809 return pll->post_div;
810
811 if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
812 if (pll->flags & RADEON_PLL_IS_LCD)
813 vco = pll->lcd_pll_out_min;
814 else
815 vco = pll->pll_out_min;
816 } else {
817 if (pll->flags & RADEON_PLL_IS_LCD)
818 vco = pll->lcd_pll_out_max;
819 else
820 vco = pll->pll_out_max;
821 }
822
823 post_div = vco / target_clock;
824 tmp = vco % target_clock;
825
826 if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
827 if (tmp)
828 post_div++;
829 } else {
830 if (!tmp)
831 post_div--;
832 }
833
834 if (post_div > pll->max_post_div)
835 post_div = pll->max_post_div;
836 else if (post_div < pll->min_post_div)
837 post_div = pll->min_post_div;
838
839 return post_div;
840}
841
842#define MAX_TOLERANCE 10
843
844void radeon_compute_pll_avivo(struct radeon_pll *pll,
845 u32 freq,
846 u32 *dot_clock_p,
847 u32 *fb_div_p,
848 u32 *frac_fb_div_p,
849 u32 *ref_div_p,
850 u32 *post_div_p)
851{
852 u32 target_clock = freq / 10;
853 u32 post_div = avivo_get_post_div(pll, target_clock);
854 u32 ref_div = pll->min_ref_div;
855 u32 fb_div = 0, frac_fb_div = 0, tmp;
856
857 if (pll->flags & RADEON_PLL_USE_REF_DIV)
858 ref_div = pll->reference_div;
859
860 if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
861 avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div);
862 frac_fb_div = (100 * frac_fb_div) / pll->reference_freq;
863 if (frac_fb_div >= 5) {
864 frac_fb_div -= 5;
865 frac_fb_div = frac_fb_div / 10;
866 frac_fb_div++;
867 }
868 if (frac_fb_div >= 10) {
869 fb_div++;
870 frac_fb_div = 0;
871 }
872 } else {
873 while (ref_div <= pll->max_ref_div) {
874 avivo_get_fb_div(pll, target_clock, post_div, ref_div,
875 &fb_div, &frac_fb_div);
876 if (frac_fb_div >= (pll->reference_freq / 2))
877 fb_div++;
878 frac_fb_div = 0;
879 tmp = (pll->reference_freq * fb_div) / (post_div * ref_div);
880 tmp = (tmp * 10000) / target_clock;
881
882 if (tmp > (10000 + MAX_TOLERANCE))
883 ref_div++;
884 else if (tmp >= (10000 - MAX_TOLERANCE))
885 break;
886 else
887 ref_div++;
888 }
889 }
890
891 *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) /
892 (ref_div * post_div * 10);
893 *fb_div_p = fb_div;
894 *frac_fb_div_p = frac_fb_div;
895 *ref_div_p = ref_div;
896 *post_div_p = post_div;
897 DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n",
898 *dot_clock_p, fb_div, frac_fb_div, ref_div, post_div);
899}
900
901/* pre-avivo */
783static inline uint32_t radeon_div(uint64_t n, uint32_t d) 902static inline uint32_t radeon_div(uint64_t n, uint32_t d)
784{ 903{
785 uint64_t mod; 904 uint64_t mod;
@@ -790,13 +909,13 @@ static inline uint32_t radeon_div(uint64_t n, uint32_t d)
790 return n; 909 return n;
791} 910}
792 911
793void radeon_compute_pll(struct radeon_pll *pll, 912void radeon_compute_pll_legacy(struct radeon_pll *pll,
794 uint64_t freq, 913 uint64_t freq,
795 uint32_t *dot_clock_p, 914 uint32_t *dot_clock_p,
796 uint32_t *fb_div_p, 915 uint32_t *fb_div_p,
797 uint32_t *frac_fb_div_p, 916 uint32_t *frac_fb_div_p,
798 uint32_t *ref_div_p, 917 uint32_t *ref_div_p,
799 uint32_t *post_div_p) 918 uint32_t *post_div_p)
800{ 919{
801 uint32_t min_ref_div = pll->min_ref_div; 920 uint32_t min_ref_div = pll->min_ref_div;
802 uint32_t max_ref_div = pll->max_ref_div; 921 uint32_t max_ref_div = pll->max_ref_div;
@@ -826,6 +945,9 @@ void radeon_compute_pll(struct radeon_pll *pll,
826 pll_out_max = pll->pll_out_max; 945 pll_out_max = pll->pll_out_max;
827 } 946 }
828 947
948 if (pll_out_min > 64800)
949 pll_out_min = 64800;
950
829 if (pll->flags & RADEON_PLL_USE_REF_DIV) 951 if (pll->flags & RADEON_PLL_USE_REF_DIV)
830 min_ref_div = max_ref_div = pll->reference_div; 952 min_ref_div = max_ref_div = pll->reference_div;
831 else { 953 else {
@@ -849,7 +971,7 @@ void radeon_compute_pll(struct radeon_pll *pll,
849 max_fractional_feed_div = pll->max_frac_feedback_div; 971 max_fractional_feed_div = pll->max_frac_feedback_div;
850 } 972 }
851 973
852 for (post_div = max_post_div; post_div >= min_post_div; --post_div) { 974 for (post_div = min_post_div; post_div <= max_post_div; ++post_div) {
853 uint32_t ref_div; 975 uint32_t ref_div;
854 976
855 if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) 977 if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
@@ -965,6 +1087,10 @@ void radeon_compute_pll(struct radeon_pll *pll,
965 *frac_fb_div_p = best_frac_feedback_div; 1087 *frac_fb_div_p = best_frac_feedback_div;
966 *ref_div_p = best_ref_div; 1088 *ref_div_p = best_ref_div;
967 *post_div_p = best_post_div; 1089 *post_div_p = best_post_div;
1090 DRM_DEBUG_KMS("%d %d, pll dividers - fb: %d.%d ref: %d, post %d\n",
1091 freq, best_freq / 1000, best_feedback_div, best_frac_feedback_div,
1092 best_ref_div, best_post_div);
1093
968} 1094}
969 1095
970static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) 1096static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)