diff options
author | David S. Miller <davem@davemloft.net> | 2011-02-19 22:17:35 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-19 22:17:35 -0500 |
commit | da935c66bacb3ed9ada984b053297f87c2dff63a (patch) | |
tree | 46278da2b312c73f1375b830d7e5912bf23abd78 /drivers/gpu/drm/radeon/radeon_display.c | |
parent | 9435eb1cf0b76b323019cebf8d16762a50a12a19 (diff) | |
parent | 2205a6ea93fea76f88b43727fea53f3ce3790d6f (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.c | 142 |
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 */ | ||
784 | static 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 | |||
803 | static 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 | |||
844 | void 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 */ | ||
783 | static inline uint32_t radeon_div(uint64_t n, uint32_t d) | 902 | static 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 | ||
793 | void radeon_compute_pll(struct radeon_pll *pll, | 912 | void 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 | ||
970 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) | 1096 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) |