diff options
-rw-r--r-- | drivers/video/intelfb/intelfbhw.c | 102 | ||||
-rw-r--r-- | drivers/video/intelfb/intelfbhw.h | 15 |
2 files changed, 63 insertions, 54 deletions
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 624c4bc96f0d..a3a94642b79b 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -40,6 +40,26 @@ | |||
40 | #include "intelfb.h" | 40 | #include "intelfb.h" |
41 | #include "intelfbhw.h" | 41 | #include "intelfbhw.h" |
42 | 42 | ||
43 | struct pll_min_max { | ||
44 | int min_m, max_m; | ||
45 | int min_m1, max_m1; | ||
46 | int min_m2, max_m2; | ||
47 | int min_n, max_n; | ||
48 | int min_p, max_p; | ||
49 | int min_p1, max_p1; | ||
50 | int min_vco_freq, max_vco_freq; | ||
51 | int p_transition_clock; | ||
52 | }; | ||
53 | |||
54 | #define PLLS_I8xx 0 | ||
55 | #define PLLS_I9xx 1 | ||
56 | #define PLLS_MAX 2 | ||
57 | |||
58 | struct pll_min_max plls[PLLS_MAX] = { | ||
59 | { 108, 140, 18, 26, 6, 16, 3, 16, 4, 128, 0, 31, 930000, 1400000, 165000 }, //I8xx | ||
60 | { 75, 120, 10, 20, 5, 9, 4, 7, 5, 80, 1, 8, 930000, 2800000, 200000 } //I9xx | ||
61 | }; | ||
62 | |||
43 | int | 63 | int |
44 | intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset, | 64 | intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset, |
45 | int *mobile) | 65 | int *mobile) |
@@ -697,17 +717,17 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
697 | 717 | ||
698 | /* Split the M parameter into M1 and M2. */ | 718 | /* Split the M parameter into M1 and M2. */ |
699 | static int | 719 | static int |
700 | splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2) | 720 | splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2) |
701 | { | 721 | { |
702 | int m1, m2; | 722 | int m1, m2; |
703 | 723 | ||
704 | m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2; | 724 | m1 = (m - 2 - (plls[index].min_m1 + plls[index].max_m2) / 2) / 5 - 2; |
705 | if (m1 < MIN_M1) | 725 | if (m1 < plls[index].min_m1) |
706 | m1 = MIN_M1; | 726 | m1 = plls[index].min_m1; |
707 | if (m1 > MAX_M1) | 727 | if (m1 > plls[index].max_m1) |
708 | m1 = MAX_M1; | 728 | m1 = plls[index].max_m1; |
709 | m2 = m - 5 * (m1 + 2) - 2; | 729 | m2 = m - 5 * (m1 + 2) - 2; |
710 | if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) { | 730 | if (m2 < plls[index].min_m2 || m2 > plls[index].max_m2 || m2 >= m1) { |
711 | return 1; | 731 | return 1; |
712 | } else { | 732 | } else { |
713 | *retm1 = (unsigned int)m1; | 733 | *retm1 = (unsigned int)m1; |
@@ -718,30 +738,34 @@ splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2) | |||
718 | 738 | ||
719 | /* Split the P parameter into P1 and P2. */ | 739 | /* Split the P parameter into P1 and P2. */ |
720 | static int | 740 | static int |
721 | splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2) | 741 | splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2) |
722 | { | 742 | { |
723 | int p1, p2; | 743 | int p1, p2; |
724 | 744 | ||
725 | if (p % 4 == 0) | 745 | if (index==PLLS_I8xx) |
726 | p2 = 1; | 746 | { |
727 | else | 747 | if (p % 4 == 0) |
728 | p2 = 0; | 748 | p2 = 1; |
729 | p1 = (p / (1 << (p2 + 1))) - 2; | 749 | else |
730 | if (p % 4 == 0 && p1 < MIN_P1) { | 750 | p2 = 0; |
731 | p2 = 0; | ||
732 | p1 = (p / (1 << (p2 + 1))) - 2; | 751 | p1 = (p / (1 << (p2 + 1))) - 2; |
752 | if (p % 4 == 0 && p1 < plls[index].min_p1) { | ||
753 | p2 = 0; | ||
754 | p1 = (p / (1 << (p2 + 1))) - 2; | ||
755 | } | ||
756 | if (p1 < plls[index].min_p1 || p1 > plls[index].max_p1 || (p1 + 2) * (1 << (p2 + 1)) != p) { | ||
757 | return 1; | ||
758 | } else { | ||
759 | *retp1 = (unsigned int)p1; | ||
760 | *retp2 = (unsigned int)p2; | ||
761 | return 0; | ||
762 | } | ||
733 | } | 763 | } |
734 | if (p1 < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) { | 764 | return 1; |
735 | return 1; | ||
736 | } else { | ||
737 | *retp1 = (unsigned int)p1; | ||
738 | *retp2 = (unsigned int)p2; | ||
739 | return 0; | ||
740 | } | ||
741 | } | 765 | } |
742 | 766 | ||
743 | static int | 767 | static int |
744 | calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | 768 | calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, |
745 | u32 *retp2, u32 *retclock) | 769 | u32 *retp2, u32 *retclock) |
746 | { | 770 | { |
747 | u32 m1, m2, n, p1, p2, n1; | 771 | u32 m1, m2, n, p1, p2, n1; |
@@ -756,40 +780,40 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | |||
756 | 780 | ||
757 | DBG_MSG("Clock is %d\n", clock); | 781 | DBG_MSG("Clock is %d\n", clock); |
758 | 782 | ||
759 | div_max = MAX_VCO_FREQ / clock; | 783 | div_max = plls[index].max_vco_freq / clock; |
760 | div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock; | 784 | div_min = ROUND_UP_TO(plls[index].min_vco_freq, clock) / clock; |
761 | 785 | ||
762 | if (clock <= P_TRANSITION_CLOCK) | 786 | if (clock <= plls[index].p_transition_clock) |
763 | p_inc = 4; | 787 | p_inc = 4; |
764 | else | 788 | else |
765 | p_inc = 2; | 789 | p_inc = 2; |
766 | p_min = ROUND_UP_TO(div_min, p_inc); | 790 | p_min = ROUND_UP_TO(div_min, p_inc); |
767 | p_max = ROUND_DOWN_TO(div_max, p_inc); | 791 | p_max = ROUND_DOWN_TO(div_max, p_inc); |
768 | if (p_min < MIN_P) | 792 | if (p_min < plls[index].min_p) |
769 | p_min = 4; | 793 | p_min = 4; |
770 | if (p_max > MAX_P) | 794 | if (p_max > plls[index].max_p) |
771 | p_max = 128; | 795 | p_max = 128; |
772 | 796 | ||
773 | DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); | 797 | DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); |
774 | 798 | ||
775 | p = p_min; | 799 | p = p_min; |
776 | do { | 800 | do { |
777 | if (splitp(p, &p1, &p2)) { | 801 | if (splitp(index, p, &p1, &p2)) { |
778 | WRN_MSG("cannot split p = %d\n", p); | 802 | WRN_MSG("cannot split p = %d\n", p); |
779 | p += p_inc; | 803 | p += p_inc; |
780 | continue; | 804 | continue; |
781 | } | 805 | } |
782 | n = MIN_N; | 806 | n = plls[index].min_n; |
783 | f_vco = clock * p; | 807 | f_vco = clock * p; |
784 | 808 | ||
785 | do { | 809 | do { |
786 | m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK; | 810 | m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK; |
787 | if (m < MIN_M) | 811 | if (m < plls[index].min_m) |
788 | m = MIN_M; | 812 | m = plls[index].min_m; |
789 | if (m > MAX_M) | 813 | if (m > plls[index].max_m) |
790 | m = MAX_M; | 814 | m = plls[index].max_m; |
791 | f_out = CALC_VCLOCK3(m, n, p); | 815 | f_out = CALC_VCLOCK3(m, n, p); |
792 | if (splitm(m, &m1, &m2)) { | 816 | if (splitm(index, m, &m1, &m2)) { |
793 | WRN_MSG("cannot split m = %d\n", m); | 817 | WRN_MSG("cannot split m = %d\n", m); |
794 | n++; | 818 | n++; |
795 | continue; | 819 | continue; |
@@ -807,7 +831,7 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | |||
807 | err_best = f_err; | 831 | err_best = f_err; |
808 | } | 832 | } |
809 | n++; | 833 | n++; |
810 | } while ((n <= MAX_N) && (f_out >= clock)); | 834 | } while ((n <= plls[index].max_n) && (f_out >= clock)); |
811 | p += p_inc; | 835 | p += p_inc; |
812 | } while ((p <= p_max)); | 836 | } while ((p <= p_max)); |
813 | 837 | ||
@@ -818,8 +842,8 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | |||
818 | m = m_best; | 842 | m = m_best; |
819 | n = n_best; | 843 | n = n_best; |
820 | p = p_best; | 844 | p = p_best; |
821 | splitm(m, &m1, &m2); | 845 | splitm(index, m, &m1, &m2); |
822 | splitp(p, &p1, &p2); | 846 | splitp(index, p, &p1, &p2); |
823 | n1 = n - 2; | 847 | n1 = n - 2; |
824 | 848 | ||
825 | DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " | 849 | DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " |
@@ -929,7 +953,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
929 | /* Desired clock in kHz */ | 953 | /* Desired clock in kHz */ |
930 | clock_target = 1000000000 / var->pixclock; | 954 | clock_target = 1000000000 / var->pixclock; |
931 | 955 | ||
932 | if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) { | 956 | if (calc_pll_params(PLLS_I8xx, clock_target, &m1, &m2, &n, &p1, &p2, &clock)) { |
933 | WRN_MSG("calc_pll_params failed\n"); | 957 | WRN_MSG("calc_pll_params failed\n"); |
934 | return 1; | 958 | return 1; |
935 | } | 959 | } |
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h index ba1920159f52..e3c305c66d5c 100644 --- a/drivers/video/intelfb/intelfbhw.h +++ b/drivers/video/intelfb/intelfbhw.h | |||
@@ -155,23 +155,8 @@ | |||
155 | /* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */ | 155 | /* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */ |
156 | /* Clock values are in units of kHz */ | 156 | /* Clock values are in units of kHz */ |
157 | #define PLL_REFCLK 48000 | 157 | #define PLL_REFCLK 48000 |
158 | #define MIN_VCO_FREQ 930000 | ||
159 | #define MAX_VCO_FREQ 1400000 | ||
160 | #define MIN_CLOCK 25000 | 158 | #define MIN_CLOCK 25000 |
161 | #define MAX_CLOCK 350000 | 159 | #define MAX_CLOCK 350000 |
162 | #define P_TRANSITION_CLOCK 165000 | ||
163 | #define MIN_M 108 | ||
164 | #define MAX_M 140 | ||
165 | #define MIN_M1 18 | ||
166 | #define MAX_M1 26 | ||
167 | #define MIN_M2 6 | ||
168 | #define MAX_M2 16 | ||
169 | #define MIN_P 4 | ||
170 | #define MAX_P 128 | ||
171 | #define MIN_P1 0 | ||
172 | #define MAX_P1 31 | ||
173 | #define MIN_N 3 | ||
174 | #define MAX_N 16 | ||
175 | 160 | ||
176 | #define CALC_VCLOCK(m1, m2, n, p1, p2) \ | 161 | #define CALC_VCLOCK(m1, m2, n, p1, p2) \ |
177 | ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \ | 162 | ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \ |