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)) / \ |
