diff options
Diffstat (limited to 'drivers/video/intelfb/intelfbhw.c')
-rw-r--r-- | drivers/video/intelfb/intelfbhw.c | 494 |
1 files changed, 327 insertions, 167 deletions
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 624c4bc96f0d..426b7430b125 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -40,68 +40,110 @@ | |||
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, min_m1, max_m1; | ||
45 | int min_m2, max_m2, min_n, max_n; | ||
46 | int min_p, max_p, min_p1, max_p1; | ||
47 | int min_vco, max_vco, p_transition_clk, ref_clk; | ||
48 | int p_inc_lo, p_inc_hi; | ||
49 | }; | ||
50 | |||
51 | #define PLLS_I8xx 0 | ||
52 | #define PLLS_I9xx 1 | ||
53 | #define PLLS_MAX 2 | ||
54 | |||
55 | static struct pll_min_max plls[PLLS_MAX] = { | ||
56 | { 108, 140, 18, 26, | ||
57 | 6, 16, 3, 16, | ||
58 | 4, 128, 0, 31, | ||
59 | 930000, 1400000, 165000, 48000, | ||
60 | 4, 2 }, //I8xx | ||
61 | |||
62 | { 75, 120, 10, 20, | ||
63 | 5, 9, 4, 7, | ||
64 | 5, 80, 1, 8, | ||
65 | 1400000, 2800000, 200000, 96000, | ||
66 | 10, 5 } //I9xx | ||
67 | }; | ||
68 | |||
43 | int | 69 | int |
44 | intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset, | 70 | intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo) |
45 | int *mobile) | ||
46 | { | 71 | { |
47 | u32 tmp; | 72 | u32 tmp; |
48 | 73 | if (!pdev || !dinfo) | |
49 | if (!pdev || !name || !chipset || !mobile) | ||
50 | return 1; | 74 | return 1; |
51 | 75 | ||
52 | switch (pdev->device) { | 76 | switch (pdev->device) { |
53 | case PCI_DEVICE_ID_INTEL_830M: | 77 | case PCI_DEVICE_ID_INTEL_830M: |
54 | *name = "Intel(R) 830M"; | 78 | dinfo->name = "Intel(R) 830M"; |
55 | *chipset = INTEL_830M; | 79 | dinfo->chipset = INTEL_830M; |
56 | *mobile = 1; | 80 | dinfo->mobile = 1; |
81 | dinfo->pll_index = PLLS_I8xx; | ||
57 | return 0; | 82 | return 0; |
58 | case PCI_DEVICE_ID_INTEL_845G: | 83 | case PCI_DEVICE_ID_INTEL_845G: |
59 | *name = "Intel(R) 845G"; | 84 | dinfo->name = "Intel(R) 845G"; |
60 | *chipset = INTEL_845G; | 85 | dinfo->chipset = INTEL_845G; |
61 | *mobile = 0; | 86 | dinfo->mobile = 0; |
87 | dinfo->pll_index = PLLS_I8xx; | ||
62 | return 0; | 88 | return 0; |
63 | case PCI_DEVICE_ID_INTEL_85XGM: | 89 | case PCI_DEVICE_ID_INTEL_85XGM: |
64 | tmp = 0; | 90 | tmp = 0; |
65 | *mobile = 1; | 91 | dinfo->mobile = 1; |
92 | dinfo->pll_index = PLLS_I8xx; | ||
66 | pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp); | 93 | pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp); |
67 | switch ((tmp >> INTEL_85X_VARIANT_SHIFT) & | 94 | switch ((tmp >> INTEL_85X_VARIANT_SHIFT) & |
68 | INTEL_85X_VARIANT_MASK) { | 95 | INTEL_85X_VARIANT_MASK) { |
69 | case INTEL_VAR_855GME: | 96 | case INTEL_VAR_855GME: |
70 | *name = "Intel(R) 855GME"; | 97 | dinfo->name = "Intel(R) 855GME"; |
71 | *chipset = INTEL_855GME; | 98 | dinfo->chipset = INTEL_855GME; |
72 | return 0; | 99 | return 0; |
73 | case INTEL_VAR_855GM: | 100 | case INTEL_VAR_855GM: |
74 | *name = "Intel(R) 855GM"; | 101 | dinfo->name = "Intel(R) 855GM"; |
75 | *chipset = INTEL_855GM; | 102 | dinfo->chipset = INTEL_855GM; |
76 | return 0; | 103 | return 0; |
77 | case INTEL_VAR_852GME: | 104 | case INTEL_VAR_852GME: |
78 | *name = "Intel(R) 852GME"; | 105 | dinfo->name = "Intel(R) 852GME"; |
79 | *chipset = INTEL_852GME; | 106 | dinfo->chipset = INTEL_852GME; |
80 | return 0; | 107 | return 0; |
81 | case INTEL_VAR_852GM: | 108 | case INTEL_VAR_852GM: |
82 | *name = "Intel(R) 852GM"; | 109 | dinfo->name = "Intel(R) 852GM"; |
83 | *chipset = INTEL_852GM; | 110 | dinfo->chipset = INTEL_852GM; |
84 | return 0; | 111 | return 0; |
85 | default: | 112 | default: |
86 | *name = "Intel(R) 852GM/855GM"; | 113 | dinfo->name = "Intel(R) 852GM/855GM"; |
87 | *chipset = INTEL_85XGM; | 114 | dinfo->chipset = INTEL_85XGM; |
88 | return 0; | 115 | return 0; |
89 | } | 116 | } |
90 | break; | 117 | break; |
91 | case PCI_DEVICE_ID_INTEL_865G: | 118 | case PCI_DEVICE_ID_INTEL_865G: |
92 | *name = "Intel(R) 865G"; | 119 | dinfo->name = "Intel(R) 865G"; |
93 | *chipset = INTEL_865G; | 120 | dinfo->chipset = INTEL_865G; |
94 | *mobile = 0; | 121 | dinfo->mobile = 0; |
122 | dinfo->pll_index = PLLS_I8xx; | ||
95 | return 0; | 123 | return 0; |
96 | case PCI_DEVICE_ID_INTEL_915G: | 124 | case PCI_DEVICE_ID_INTEL_915G: |
97 | *name = "Intel(R) 915G"; | 125 | dinfo->name = "Intel(R) 915G"; |
98 | *chipset = INTEL_915G; | 126 | dinfo->chipset = INTEL_915G; |
99 | *mobile = 0; | 127 | dinfo->mobile = 0; |
128 | dinfo->pll_index = PLLS_I9xx; | ||
100 | return 0; | 129 | return 0; |
101 | case PCI_DEVICE_ID_INTEL_915GM: | 130 | case PCI_DEVICE_ID_INTEL_915GM: |
102 | *name = "Intel(R) 915GM"; | 131 | dinfo->name = "Intel(R) 915GM"; |
103 | *chipset = INTEL_915GM; | 132 | dinfo->chipset = INTEL_915GM; |
104 | *mobile = 1; | 133 | dinfo->mobile = 1; |
134 | dinfo->pll_index = PLLS_I9xx; | ||
135 | return 0; | ||
136 | case PCI_DEVICE_ID_INTEL_945G: | ||
137 | dinfo->name = "Intel(R) 945G"; | ||
138 | dinfo->chipset = INTEL_945G; | ||
139 | dinfo->mobile = 0; | ||
140 | dinfo->pll_index = PLLS_I9xx; | ||
141 | return 0; | ||
142 | case PCI_DEVICE_ID_INTEL_945GM: | ||
143 | dinfo->name = "Intel(R) 945GM"; | ||
144 | dinfo->chipset = INTEL_945GM; | ||
145 | dinfo->mobile = 1; | ||
146 | dinfo->pll_index = PLLS_I9xx; | ||
105 | return 0; | 147 | return 0; |
106 | default: | 148 | default: |
107 | return 1; | 149 | return 1; |
@@ -114,6 +156,7 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | |||
114 | { | 156 | { |
115 | struct pci_dev *bridge_dev; | 157 | struct pci_dev *bridge_dev; |
116 | u16 tmp; | 158 | u16 tmp; |
159 | int stolen_overhead; | ||
117 | 160 | ||
118 | if (!pdev || !aperture_size || !stolen_size) | 161 | if (!pdev || !aperture_size || !stolen_size) |
119 | return 1; | 162 | return 1; |
@@ -128,21 +171,41 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | |||
128 | tmp = 0; | 171 | tmp = 0; |
129 | pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); | 172 | pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); |
130 | switch (pdev->device) { | 173 | switch (pdev->device) { |
131 | case PCI_DEVICE_ID_INTEL_830M: | 174 | case PCI_DEVICE_ID_INTEL_915G: |
132 | case PCI_DEVICE_ID_INTEL_845G: | 175 | case PCI_DEVICE_ID_INTEL_915GM: |
176 | case PCI_DEVICE_ID_INTEL_945G: | ||
177 | case PCI_DEVICE_ID_INTEL_945GM: | ||
178 | /* 915 and 945 chipsets support a 256MB aperture. | ||
179 | Aperture size is determined by inspected the | ||
180 | base address of the aperture. */ | ||
181 | if (pci_resource_start(pdev, 2) & 0x08000000) | ||
182 | *aperture_size = MB(128); | ||
183 | else | ||
184 | *aperture_size = MB(256); | ||
185 | break; | ||
186 | default: | ||
133 | if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) | 187 | if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) |
134 | *aperture_size = MB(64); | 188 | *aperture_size = MB(64); |
135 | else | 189 | else |
136 | *aperture_size = MB(128); | 190 | *aperture_size = MB(128); |
191 | break; | ||
192 | } | ||
193 | |||
194 | /* Stolen memory size is reduced by the GTT and the popup. | ||
195 | GTT is 1K per MB of aperture size, and popup is 4K. */ | ||
196 | stolen_overhead = (*aperture_size / MB(1)) + 4; | ||
197 | switch(pdev->device) { | ||
198 | case PCI_DEVICE_ID_INTEL_830M: | ||
199 | case PCI_DEVICE_ID_INTEL_845G: | ||
137 | switch (tmp & INTEL_830_GMCH_GMS_MASK) { | 200 | switch (tmp & INTEL_830_GMCH_GMS_MASK) { |
138 | case INTEL_830_GMCH_GMS_STOLEN_512: | 201 | case INTEL_830_GMCH_GMS_STOLEN_512: |
139 | *stolen_size = KB(512) - KB(132); | 202 | *stolen_size = KB(512) - KB(stolen_overhead); |
140 | return 0; | 203 | return 0; |
141 | case INTEL_830_GMCH_GMS_STOLEN_1024: | 204 | case INTEL_830_GMCH_GMS_STOLEN_1024: |
142 | *stolen_size = MB(1) - KB(132); | 205 | *stolen_size = MB(1) - KB(stolen_overhead); |
143 | return 0; | 206 | return 0; |
144 | case INTEL_830_GMCH_GMS_STOLEN_8192: | 207 | case INTEL_830_GMCH_GMS_STOLEN_8192: |
145 | *stolen_size = MB(8) - KB(132); | 208 | *stolen_size = MB(8) - KB(stolen_overhead); |
146 | return 0; | 209 | return 0; |
147 | case INTEL_830_GMCH_GMS_LOCAL: | 210 | case INTEL_830_GMCH_GMS_LOCAL: |
148 | ERR_MSG("only local memory found\n"); | 211 | ERR_MSG("only local memory found\n"); |
@@ -157,28 +220,27 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | |||
157 | } | 220 | } |
158 | break; | 221 | break; |
159 | default: | 222 | default: |
160 | *aperture_size = MB(128); | ||
161 | switch (tmp & INTEL_855_GMCH_GMS_MASK) { | 223 | switch (tmp & INTEL_855_GMCH_GMS_MASK) { |
162 | case INTEL_855_GMCH_GMS_STOLEN_1M: | 224 | case INTEL_855_GMCH_GMS_STOLEN_1M: |
163 | *stolen_size = MB(1) - KB(132); | 225 | *stolen_size = MB(1) - KB(stolen_overhead); |
164 | return 0; | 226 | return 0; |
165 | case INTEL_855_GMCH_GMS_STOLEN_4M: | 227 | case INTEL_855_GMCH_GMS_STOLEN_4M: |
166 | *stolen_size = MB(4) - KB(132); | 228 | *stolen_size = MB(4) - KB(stolen_overhead); |
167 | return 0; | 229 | return 0; |
168 | case INTEL_855_GMCH_GMS_STOLEN_8M: | 230 | case INTEL_855_GMCH_GMS_STOLEN_8M: |
169 | *stolen_size = MB(8) - KB(132); | 231 | *stolen_size = MB(8) - KB(stolen_overhead); |
170 | return 0; | 232 | return 0; |
171 | case INTEL_855_GMCH_GMS_STOLEN_16M: | 233 | case INTEL_855_GMCH_GMS_STOLEN_16M: |
172 | *stolen_size = MB(16) - KB(132); | 234 | *stolen_size = MB(16) - KB(stolen_overhead); |
173 | return 0; | 235 | return 0; |
174 | case INTEL_855_GMCH_GMS_STOLEN_32M: | 236 | case INTEL_855_GMCH_GMS_STOLEN_32M: |
175 | *stolen_size = MB(32) - KB(132); | 237 | *stolen_size = MB(32) - KB(stolen_overhead); |
176 | return 0; | 238 | return 0; |
177 | case INTEL_915G_GMCH_GMS_STOLEN_48M: | 239 | case INTEL_915G_GMCH_GMS_STOLEN_48M: |
178 | *stolen_size = MB(48) - KB(132); | 240 | *stolen_size = MB(48) - KB(stolen_overhead); |
179 | return 0; | 241 | return 0; |
180 | case INTEL_915G_GMCH_GMS_STOLEN_64M: | 242 | case INTEL_915G_GMCH_GMS_STOLEN_64M: |
181 | *stolen_size = MB(64) - KB(132); | 243 | *stolen_size = MB(64) - KB(stolen_overhead); |
182 | return 0; | 244 | return 0; |
183 | case INTEL_855_GMCH_GMS_DISABLED: | 245 | case INTEL_855_GMCH_GMS_DISABLED: |
184 | ERR_MSG("video memory is disabled\n"); | 246 | ERR_MSG("video memory is disabled\n"); |
@@ -529,12 +591,63 @@ intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
529 | } | 591 | } |
530 | 592 | ||
531 | 593 | ||
594 | static int calc_vclock3(int index, int m, int n, int p) | ||
595 | { | ||
596 | if (p == 0 || n == 0) | ||
597 | return 0; | ||
598 | return plls[index].ref_clk * m / n / p; | ||
599 | } | ||
600 | |||
601 | static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds) | ||
602 | { | ||
603 | struct pll_min_max *pll = &plls[index]; | ||
604 | u32 m, vco, p; | ||
605 | |||
606 | m = (5 * (m1 + 2)) + (m2 + 2); | ||
607 | n += 2; | ||
608 | vco = pll->ref_clk * m / n; | ||
609 | |||
610 | if (index == PLLS_I8xx) { | ||
611 | p = ((p1 + 2) * (1 << (p2 + 1))); | ||
612 | } else { | ||
613 | p = ((p1) * (p2 ? 5 : 10)); | ||
614 | } | ||
615 | return vco / p; | ||
616 | } | ||
617 | |||
618 | static void | ||
619 | intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2) | ||
620 | { | ||
621 | int p1, p2; | ||
622 | |||
623 | if (IS_I9XX(dinfo)) { | ||
624 | if (dpll & DPLL_P1_FORCE_DIV2) | ||
625 | p1 = 1; | ||
626 | else | ||
627 | p1 = (dpll >> DPLL_P1_SHIFT) & 0xff; | ||
628 | |||
629 | p1 = ffs(p1); | ||
630 | |||
631 | p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK; | ||
632 | } else { | ||
633 | if (dpll & DPLL_P1_FORCE_DIV2) | ||
634 | p1 = 0; | ||
635 | else | ||
636 | p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | ||
637 | p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | ||
638 | } | ||
639 | |||
640 | *o_p1 = p1; | ||
641 | *o_p2 = p2; | ||
642 | } | ||
643 | |||
644 | |||
532 | void | 645 | void |
533 | intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | 646 | intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) |
534 | { | 647 | { |
535 | #if REGDUMP | 648 | #if REGDUMP |
536 | int i, m1, m2, n, p1, p2; | 649 | int i, m1, m2, n, p1, p2; |
537 | 650 | int index = dinfo->pll_index; | |
538 | DBG_MSG("intelfbhw_print_hw_state\n"); | 651 | DBG_MSG("intelfbhw_print_hw_state\n"); |
539 | 652 | ||
540 | if (!hw || !dinfo) | 653 | if (!hw || !dinfo) |
@@ -547,26 +660,22 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
547 | n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 660 | n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
548 | m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 661 | m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
549 | m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 662 | m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
550 | if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2) | 663 | |
551 | p1 = 0; | 664 | intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2); |
552 | else | 665 | |
553 | p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK; | ||
554 | p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK; | ||
555 | printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 666 | printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
556 | m1, m2, n, p1, p2); | 667 | m1, m2, n, p1, p2); |
557 | printk(" VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); | 668 | printk(" VGA0: clock is %d\n", |
669 | calc_vclock(index, m1, m2, n, p1, p2, 0)); | ||
558 | 670 | ||
559 | n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 671 | n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
560 | m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 672 | m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
561 | m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 673 | m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
562 | if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2) | 674 | |
563 | p1 = 0; | 675 | intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2); |
564 | else | ||
565 | p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK; | ||
566 | p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK; | ||
567 | printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 676 | printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
568 | m1, m2, n, p1, p2); | 677 | m1, m2, n, p1, p2); |
569 | printk(" VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); | 678 | printk(" VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
570 | 679 | ||
571 | printk(" DPLL_A: 0x%08x\n", hw->dpll_a); | 680 | printk(" DPLL_A: 0x%08x\n", hw->dpll_a); |
572 | printk(" DPLL_B: 0x%08x\n", hw->dpll_b); | 681 | printk(" DPLL_B: 0x%08x\n", hw->dpll_b); |
@@ -578,34 +687,30 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
578 | n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 687 | n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
579 | m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 688 | m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
580 | m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 689 | m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
581 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) | 690 | |
582 | p1 = 0; | 691 | intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2); |
583 | else | 692 | |
584 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | ||
585 | p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | ||
586 | printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 693 | printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
587 | m1, m2, n, p1, p2); | 694 | m1, m2, n, p1, p2); |
588 | printk(" PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); | 695 | printk(" PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
589 | 696 | ||
590 | n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 697 | n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
591 | m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 698 | m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
592 | m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 699 | m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
593 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) | 700 | |
594 | p1 = 0; | 701 | intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2); |
595 | else | 702 | |
596 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | ||
597 | p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | ||
598 | printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 703 | printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
599 | m1, m2, n, p1, p2); | 704 | m1, m2, n, p1, p2); |
600 | printk(" PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); | 705 | printk(" PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
601 | 706 | ||
602 | #if 0 | 707 | #if 0 |
603 | printk(" PALETTE_A:\n"); | 708 | printk(" PALETTE_A:\n"); |
604 | for (i = 0; i < PALETTE_8_ENTRIES) | 709 | for (i = 0; i < PALETTE_8_ENTRIES) |
605 | printk(" %3d: 0x%08x\n", i, hw->palette_a[i]; | 710 | printk(" %3d: 0x%08x\n", i, hw->palette_a[i]); |
606 | printk(" PALETTE_B:\n"); | 711 | printk(" PALETTE_B:\n"); |
607 | for (i = 0; i < PALETTE_8_ENTRIES) | 712 | for (i = 0; i < PALETTE_8_ENTRIES) |
608 | printk(" %3d: 0x%08x\n", i, hw->palette_b[i]; | 713 | printk(" %3d: 0x%08x\n", i, hw->palette_b[i]); |
609 | #endif | 714 | #endif |
610 | 715 | ||
611 | printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a); | 716 | printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a); |
@@ -680,11 +785,11 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
680 | } | 785 | } |
681 | for (i = 0; i < 3; i++) { | 786 | for (i = 0; i < 3; i++) { |
682 | printk(" SWF3%d 0x%08x\n", i, | 787 | printk(" SWF3%d 0x%08x\n", i, |
683 | hw->swf3x[i]); | 788 | hw->swf3x[i]); |
684 | } | 789 | } |
685 | for (i = 0; i < 8; i++) | 790 | for (i = 0; i < 8; i++) |
686 | printk(" FENCE%d 0x%08x\n", i, | 791 | printk(" FENCE%d 0x%08x\n", i, |
687 | hw->fence[i]); | 792 | hw->fence[i]); |
688 | 793 | ||
689 | printk(" INSTPM 0x%08x\n", hw->instpm); | 794 | printk(" INSTPM 0x%08x\n", hw->instpm); |
690 | printk(" MEM_MODE 0x%08x\n", hw->mem_mode); | 795 | printk(" MEM_MODE 0x%08x\n", hw->mem_mode); |
@@ -695,43 +800,58 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
695 | #endif | 800 | #endif |
696 | } | 801 | } |
697 | 802 | ||
803 | |||
804 | |||
698 | /* Split the M parameter into M1 and M2. */ | 805 | /* Split the M parameter into M1 and M2. */ |
699 | static int | 806 | static int |
700 | splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2) | 807 | splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2) |
701 | { | 808 | { |
702 | int m1, m2; | 809 | int m1, m2; |
703 | 810 | int testm; | |
704 | m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2; | 811 | struct pll_min_max *pll = &plls[index]; |
705 | if (m1 < MIN_M1) | 812 | |
706 | m1 = MIN_M1; | 813 | /* no point optimising too much - brute force m */ |
707 | if (m1 > MAX_M1) | 814 | for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) { |
708 | m1 = MAX_M1; | 815 | for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) { |
709 | m2 = m - 5 * (m1 + 2) - 2; | 816 | testm = (5 * (m1 + 2)) + (m2 + 2); |
710 | if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) { | 817 | if (testm == m) { |
711 | return 1; | 818 | *retm1 = (unsigned int)m1; |
712 | } else { | 819 | *retm2 = (unsigned int)m2; |
713 | *retm1 = (unsigned int)m1; | 820 | return 0; |
714 | *retm2 = (unsigned int)m2; | 821 | } |
715 | return 0; | 822 | } |
716 | } | 823 | } |
824 | return 1; | ||
717 | } | 825 | } |
718 | 826 | ||
719 | /* Split the P parameter into P1 and P2. */ | 827 | /* Split the P parameter into P1 and P2. */ |
720 | static int | 828 | static int |
721 | splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2) | 829 | splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2) |
722 | { | 830 | { |
723 | int p1, p2; | 831 | int p1, p2; |
832 | struct pll_min_max *pll = &plls[index]; | ||
833 | |||
834 | if (index == PLLS_I9xx) { | ||
835 | p2 = (p % 10) ? 1 : 0; | ||
836 | |||
837 | p1 = p / (p2 ? 5 : 10); | ||
838 | |||
839 | *retp1 = (unsigned int)p1; | ||
840 | *retp2 = (unsigned int)p2; | ||
841 | return 0; | ||
842 | } | ||
724 | 843 | ||
725 | if (p % 4 == 0) | 844 | if (p % 4 == 0) |
726 | p2 = 1; | 845 | p2 = 1; |
727 | else | 846 | else |
728 | p2 = 0; | 847 | p2 = 0; |
729 | p1 = (p / (1 << (p2 + 1))) - 2; | 848 | p1 = (p / (1 << (p2 + 1))) - 2; |
730 | if (p % 4 == 0 && p1 < MIN_P1) { | 849 | if (p % 4 == 0 && p1 < pll->min_p1) { |
731 | p2 = 0; | 850 | p2 = 0; |
732 | p1 = (p / (1 << (p2 + 1))) - 2; | 851 | p1 = (p / (1 << (p2 + 1))) - 2; |
733 | } | 852 | } |
734 | if (p1 < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) { | 853 | if (p1 < pll->min_p1 || p1 > pll->max_p1 || |
854 | (p1 + 2) * (1 << (p2 + 1)) != p) { | ||
735 | return 1; | 855 | return 1; |
736 | } else { | 856 | } else { |
737 | *retp1 = (unsigned int)p1; | 857 | *retp1 = (unsigned int)p1; |
@@ -741,14 +861,15 @@ splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2) | |||
741 | } | 861 | } |
742 | 862 | ||
743 | static int | 863 | static int |
744 | calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | 864 | calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, |
745 | u32 *retp2, u32 *retclock) | 865 | u32 *retp2, u32 *retclock) |
746 | { | 866 | { |
747 | u32 m1, m2, n, p1, p2, n1; | 867 | u32 m1, m2, n, p1, p2, n1, testm; |
748 | u32 f_vco, p, p_best = 0, m, f_out; | 868 | u32 f_vco, p, p_best = 0, m, f_out = 0; |
749 | u32 err_max, err_target, err_best = 10000000; | 869 | u32 err_max, err_target, err_best = 10000000; |
750 | u32 n_best = 0, m_best = 0, f_best, f_err; | 870 | u32 n_best = 0, m_best = 0, f_best, f_err; |
751 | u32 p_min, p_max, p_inc, div_min, div_max; | 871 | u32 p_min, p_max, p_inc, div_max; |
872 | struct pll_min_max *pll = &plls[index]; | ||
752 | 873 | ||
753 | /* Accept 0.5% difference, but aim for 0.1% */ | 874 | /* Accept 0.5% difference, but aim for 0.1% */ |
754 | err_max = 5 * clock / 1000; | 875 | err_max = 5 * clock / 1000; |
@@ -756,58 +877,56 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | |||
756 | 877 | ||
757 | DBG_MSG("Clock is %d\n", clock); | 878 | DBG_MSG("Clock is %d\n", clock); |
758 | 879 | ||
759 | div_max = MAX_VCO_FREQ / clock; | 880 | div_max = pll->max_vco / clock; |
760 | div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock; | ||
761 | 881 | ||
762 | if (clock <= P_TRANSITION_CLOCK) | 882 | p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi; |
763 | p_inc = 4; | 883 | p_min = p_inc; |
764 | else | ||
765 | p_inc = 2; | ||
766 | p_min = ROUND_UP_TO(div_min, p_inc); | ||
767 | p_max = ROUND_DOWN_TO(div_max, p_inc); | 884 | p_max = ROUND_DOWN_TO(div_max, p_inc); |
768 | if (p_min < MIN_P) | 885 | if (p_min < pll->min_p) |
769 | p_min = 4; | 886 | p_min = pll->min_p; |
770 | if (p_max > MAX_P) | 887 | if (p_max > pll->max_p) |
771 | p_max = 128; | 888 | p_max = pll->max_p; |
772 | 889 | ||
773 | DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); | 890 | DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); |
774 | 891 | ||
775 | p = p_min; | 892 | p = p_min; |
776 | do { | 893 | do { |
777 | if (splitp(p, &p1, &p2)) { | 894 | if (splitp(index, p, &p1, &p2)) { |
778 | WRN_MSG("cannot split p = %d\n", p); | 895 | WRN_MSG("cannot split p = %d\n", p); |
779 | p += p_inc; | 896 | p += p_inc; |
780 | continue; | 897 | continue; |
781 | } | 898 | } |
782 | n = MIN_N; | 899 | n = pll->min_n; |
783 | f_vco = clock * p; | 900 | f_vco = clock * p; |
784 | 901 | ||
785 | do { | 902 | do { |
786 | m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK; | 903 | m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk; |
787 | if (m < MIN_M) | 904 | if (m < pll->min_m) |
788 | m = MIN_M; | 905 | m = pll->min_m + 1; |
789 | if (m > MAX_M) | 906 | if (m > pll->max_m) |
790 | m = MAX_M; | 907 | m = pll->max_m - 1; |
791 | f_out = CALC_VCLOCK3(m, n, p); | 908 | for (testm = m - 1; testm <= m; testm++) { |
792 | if (splitm(m, &m1, &m2)) { | 909 | f_out = calc_vclock3(index, m, n, p); |
793 | WRN_MSG("cannot split m = %d\n", m); | 910 | if (splitm(index, testm, &m1, &m2)) { |
794 | n++; | 911 | WRN_MSG("cannot split m = %d\n", m); |
795 | continue; | 912 | n++; |
796 | } | 913 | continue; |
797 | if (clock > f_out) | 914 | } |
798 | f_err = clock - f_out; | 915 | if (clock > f_out) |
799 | else | 916 | f_err = clock - f_out; |
800 | f_err = f_out - clock; | 917 | else/* slightly bias the error for bigger clocks */ |
801 | 918 | f_err = f_out - clock + 1; | |
802 | if (f_err < err_best) { | 919 | |
803 | m_best = m; | 920 | if (f_err < err_best) { |
804 | n_best = n; | 921 | m_best = testm; |
805 | p_best = p; | 922 | n_best = n; |
806 | f_best = f_out; | 923 | p_best = p; |
807 | err_best = f_err; | 924 | f_best = f_out; |
925 | err_best = f_err; | ||
926 | } | ||
808 | } | 927 | } |
809 | n++; | 928 | n++; |
810 | } while ((n <= MAX_N) && (f_out >= clock)); | 929 | } while ((n <= pll->max_n) && (f_out >= clock)); |
811 | p += p_inc; | 930 | p += p_inc; |
812 | } while ((p <= p_max)); | 931 | } while ((p <= p_max)); |
813 | 932 | ||
@@ -818,21 +937,22 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | |||
818 | m = m_best; | 937 | m = m_best; |
819 | n = n_best; | 938 | n = n_best; |
820 | p = p_best; | 939 | p = p_best; |
821 | splitm(m, &m1, &m2); | 940 | splitm(index, m, &m1, &m2); |
822 | splitp(p, &p1, &p2); | 941 | splitp(index, p, &p1, &p2); |
823 | n1 = n - 2; | 942 | n1 = n - 2; |
824 | 943 | ||
825 | DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " | 944 | DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " |
826 | "f: %d (%d), VCO: %d\n", | 945 | "f: %d (%d), VCO: %d\n", |
827 | m, m1, m2, n, n1, p, p1, p2, | 946 | m, m1, m2, n, n1, p, p1, p2, |
828 | CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2), | 947 | calc_vclock3(index, m, n, p), |
829 | CALC_VCLOCK3(m, n, p) * p); | 948 | calc_vclock(index, m1, m2, n1, p1, p2, 0), |
949 | calc_vclock3(index, m, n, p) * p); | ||
830 | *retm1 = m1; | 950 | *retm1 = m1; |
831 | *retm2 = m2; | 951 | *retm2 = m2; |
832 | *retn = n1; | 952 | *retn = n1; |
833 | *retp1 = p1; | 953 | *retp1 = p1; |
834 | *retp2 = p2; | 954 | *retp2 = p2; |
835 | *retclock = CALC_VCLOCK(m1, m2, n1, p1, p2); | 955 | *retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0); |
836 | 956 | ||
837 | return 0; | 957 | return 0; |
838 | } | 958 | } |
@@ -860,6 +980,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
860 | u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive; | 980 | u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive; |
861 | u32 vsync_pol, hsync_pol; | 981 | u32 vsync_pol, hsync_pol; |
862 | u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf; | 982 | u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf; |
983 | u32 stride_alignment; | ||
863 | 984 | ||
864 | DBG_MSG("intelfbhw_mode_to_hw\n"); | 985 | DBG_MSG("intelfbhw_mode_to_hw\n"); |
865 | 986 | ||
@@ -929,7 +1050,8 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
929 | /* Desired clock in kHz */ | 1050 | /* Desired clock in kHz */ |
930 | clock_target = 1000000000 / var->pixclock; | 1051 | clock_target = 1000000000 / var->pixclock; |
931 | 1052 | ||
932 | if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) { | 1053 | if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2, |
1054 | &n, &p1, &p2, &clock)) { | ||
933 | WRN_MSG("calc_pll_params failed\n"); | 1055 | WRN_MSG("calc_pll_params failed\n"); |
934 | return 1; | 1056 | return 1; |
935 | } | 1057 | } |
@@ -949,7 +1071,14 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
949 | *dpll &= ~DPLL_P1_FORCE_DIV2; | 1071 | *dpll &= ~DPLL_P1_FORCE_DIV2; |
950 | *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) | | 1072 | *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) | |
951 | (DPLL_P1_MASK << DPLL_P1_SHIFT)); | 1073 | (DPLL_P1_MASK << DPLL_P1_SHIFT)); |
952 | *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); | 1074 | |
1075 | if (IS_I9XX(dinfo)) { | ||
1076 | *dpll |= (p2 << DPLL_I9XX_P2_SHIFT); | ||
1077 | *dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT; | ||
1078 | } else { | ||
1079 | *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); | ||
1080 | } | ||
1081 | |||
953 | *fp0 = (n << FP_N_DIVISOR_SHIFT) | | 1082 | *fp0 = (n << FP_N_DIVISOR_SHIFT) | |
954 | (m1 << FP_M1_DIVISOR_SHIFT) | | 1083 | (m1 << FP_M1_DIVISOR_SHIFT) | |
955 | (m2 << FP_M2_DIVISOR_SHIFT); | 1084 | (m2 << FP_M2_DIVISOR_SHIFT); |
@@ -1054,7 +1183,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
1054 | *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) | | 1183 | *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) | |
1055 | (vactive << SRC_SIZE_VERT_SHIFT); | 1184 | (vactive << SRC_SIZE_VERT_SHIFT); |
1056 | 1185 | ||
1057 | hw->disp_a_stride = var->xres_virtual * var->bits_per_pixel / 8; | 1186 | hw->disp_a_stride = dinfo->pitch; |
1058 | DBG_MSG("pitch is %d\n", hw->disp_a_stride); | 1187 | DBG_MSG("pitch is %d\n", hw->disp_a_stride); |
1059 | 1188 | ||
1060 | hw->disp_a_base = hw->disp_a_stride * var->yoffset + | 1189 | hw->disp_a_base = hw->disp_a_stride * var->yoffset + |
@@ -1063,9 +1192,11 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
1063 | hw->disp_a_base += dinfo->fb.offset << 12; | 1192 | hw->disp_a_base += dinfo->fb.offset << 12; |
1064 | 1193 | ||
1065 | /* Check stride alignment. */ | 1194 | /* Check stride alignment. */ |
1066 | if (hw->disp_a_stride % STRIDE_ALIGNMENT != 0) { | 1195 | stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX : |
1196 | STRIDE_ALIGNMENT; | ||
1197 | if (hw->disp_a_stride % stride_alignment != 0) { | ||
1067 | WRN_MSG("display stride %d has bad alignment %d\n", | 1198 | WRN_MSG("display stride %d has bad alignment %d\n", |
1068 | hw->disp_a_stride, STRIDE_ALIGNMENT); | 1199 | hw->disp_a_stride, stride_alignment); |
1069 | return 1; | 1200 | return 1; |
1070 | } | 1201 | } |
1071 | 1202 | ||
@@ -1087,6 +1218,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
1087 | u32 hsync_reg, htotal_reg, hblank_reg; | 1218 | u32 hsync_reg, htotal_reg, hblank_reg; |
1088 | u32 vsync_reg, vtotal_reg, vblank_reg; | 1219 | u32 vsync_reg, vtotal_reg, vblank_reg; |
1089 | u32 src_size_reg; | 1220 | u32 src_size_reg; |
1221 | u32 count, tmp_val[3]; | ||
1090 | 1222 | ||
1091 | /* Assume single pipe, display plane A, analog CRT. */ | 1223 | /* Assume single pipe, display plane A, analog CRT. */ |
1092 | 1224 | ||
@@ -1155,6 +1287,27 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
1155 | src_size_reg = SRC_SIZE_A; | 1287 | src_size_reg = SRC_SIZE_A; |
1156 | } | 1288 | } |
1157 | 1289 | ||
1290 | /* turn off pipe */ | ||
1291 | tmp = INREG(pipe_conf_reg); | ||
1292 | tmp &= ~PIPECONF_ENABLE; | ||
1293 | OUTREG(pipe_conf_reg, tmp); | ||
1294 | |||
1295 | count = 0; | ||
1296 | do { | ||
1297 | tmp_val[count%3] = INREG(0x70000); | ||
1298 | if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2])) | ||
1299 | break; | ||
1300 | count++; | ||
1301 | udelay(1); | ||
1302 | if (count % 200 == 0) { | ||
1303 | tmp = INREG(pipe_conf_reg); | ||
1304 | tmp &= ~PIPECONF_ENABLE; | ||
1305 | OUTREG(pipe_conf_reg, tmp); | ||
1306 | } | ||
1307 | } while(count < 2000); | ||
1308 | |||
1309 | OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE); | ||
1310 | |||
1158 | /* Disable planes A and B. */ | 1311 | /* Disable planes A and B. */ |
1159 | tmp = INREG(DSPACNTR); | 1312 | tmp = INREG(DSPACNTR); |
1160 | tmp &= ~DISPPLANE_PLANE_ENABLE; | 1313 | tmp &= ~DISPPLANE_PLANE_ENABLE; |
@@ -1163,19 +1316,21 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
1163 | tmp &= ~DISPPLANE_PLANE_ENABLE; | 1316 | tmp &= ~DISPPLANE_PLANE_ENABLE; |
1164 | OUTREG(DSPBCNTR, tmp); | 1317 | OUTREG(DSPBCNTR, tmp); |
1165 | 1318 | ||
1166 | /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */ | 1319 | /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */ |
1167 | mdelay(20); | 1320 | mdelay(20); |
1168 | 1321 | ||
1322 | OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE); | ||
1323 | OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE); | ||
1324 | OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE); | ||
1325 | |||
1169 | /* Disable Sync */ | 1326 | /* Disable Sync */ |
1170 | tmp = INREG(ADPA); | 1327 | tmp = INREG(ADPA); |
1171 | tmp &= ~ADPA_DPMS_CONTROL_MASK; | 1328 | tmp &= ~ADPA_DPMS_CONTROL_MASK; |
1172 | tmp |= ADPA_DPMS_D3; | 1329 | tmp |= ADPA_DPMS_D3; |
1173 | OUTREG(ADPA, tmp); | 1330 | OUTREG(ADPA, tmp); |
1174 | 1331 | ||
1175 | /* turn off pipe */ | 1332 | /* do some funky magic - xyzzy */ |
1176 | tmp = INREG(pipe_conf_reg); | 1333 | OUTREG(0x61204, 0xabcd0000); |
1177 | tmp &= ~PIPECONF_ENABLE; | ||
1178 | OUTREG(pipe_conf_reg, tmp); | ||
1179 | 1334 | ||
1180 | /* turn off PLL */ | 1335 | /* turn off PLL */ |
1181 | tmp = INREG(dpll_reg); | 1336 | tmp = INREG(dpll_reg); |
@@ -1183,30 +1338,31 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
1183 | OUTREG(dpll_reg, tmp); | 1338 | OUTREG(dpll_reg, tmp); |
1184 | 1339 | ||
1185 | /* Set PLL parameters */ | 1340 | /* Set PLL parameters */ |
1186 | OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE); | ||
1187 | OUTREG(fp0_reg, *fp0); | 1341 | OUTREG(fp0_reg, *fp0); |
1188 | OUTREG(fp1_reg, *fp1); | 1342 | OUTREG(fp1_reg, *fp1); |
1189 | 1343 | ||
1190 | /* Set pipe parameters */ | 1344 | /* Enable PLL */ |
1191 | OUTREG(hsync_reg, *hs); | 1345 | OUTREG(dpll_reg, *dpll); |
1192 | OUTREG(hblank_reg, *hb); | ||
1193 | OUTREG(htotal_reg, *ht); | ||
1194 | OUTREG(vsync_reg, *vs); | ||
1195 | OUTREG(vblank_reg, *vb); | ||
1196 | OUTREG(vtotal_reg, *vt); | ||
1197 | OUTREG(src_size_reg, *ss); | ||
1198 | 1346 | ||
1199 | /* Set DVOs B/C */ | 1347 | /* Set DVOs B/C */ |
1200 | OUTREG(DVOB, hw->dvob); | 1348 | OUTREG(DVOB, hw->dvob); |
1201 | OUTREG(DVOC, hw->dvoc); | 1349 | OUTREG(DVOC, hw->dvoc); |
1202 | 1350 | ||
1351 | /* undo funky magic */ | ||
1352 | OUTREG(0x61204, 0x00000000); | ||
1353 | |||
1203 | /* Set ADPA */ | 1354 | /* Set ADPA */ |
1355 | OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE); | ||
1204 | OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3); | 1356 | OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3); |
1205 | 1357 | ||
1206 | /* Enable PLL */ | 1358 | /* Set pipe parameters */ |
1207 | tmp = INREG(dpll_reg); | 1359 | OUTREG(hsync_reg, *hs); |
1208 | tmp |= DPLL_VCO_ENABLE; | 1360 | OUTREG(hblank_reg, *hb); |
1209 | OUTREG(dpll_reg, tmp); | 1361 | OUTREG(htotal_reg, *ht); |
1362 | OUTREG(vsync_reg, *vs); | ||
1363 | OUTREG(vblank_reg, *vb); | ||
1364 | OUTREG(vtotal_reg, *vt); | ||
1365 | OUTREG(src_size_reg, *ss); | ||
1210 | 1366 | ||
1211 | /* Enable pipe */ | 1367 | /* Enable pipe */ |
1212 | OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE); | 1368 | OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE); |
@@ -1231,7 +1387,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
1231 | OUTREG(DSPACNTR, | 1387 | OUTREG(DSPACNTR, |
1232 | hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE); | 1388 | hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE); |
1233 | mdelay(1); | 1389 | mdelay(1); |
1234 | } | 1390 | } |
1235 | } | 1391 | } |
1236 | 1392 | ||
1237 | OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE); | 1393 | OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE); |
@@ -1616,7 +1772,7 @@ intelfbhw_cursor_init(struct intelfb_info *dinfo) | |||
1616 | DBG_MSG("intelfbhw_cursor_init\n"); | 1772 | DBG_MSG("intelfbhw_cursor_init\n"); |
1617 | #endif | 1773 | #endif |
1618 | 1774 | ||
1619 | if (dinfo->mobile) { | 1775 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
1620 | if (!dinfo->cursor.physical) | 1776 | if (!dinfo->cursor.physical) |
1621 | return; | 1777 | return; |
1622 | tmp = INREG(CURSOR_A_CONTROL); | 1778 | tmp = INREG(CURSOR_A_CONTROL); |
@@ -1649,7 +1805,7 @@ intelfbhw_cursor_hide(struct intelfb_info *dinfo) | |||
1649 | #endif | 1805 | #endif |
1650 | 1806 | ||
1651 | dinfo->cursor_on = 0; | 1807 | dinfo->cursor_on = 0; |
1652 | if (dinfo->mobile) { | 1808 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
1653 | if (!dinfo->cursor.physical) | 1809 | if (!dinfo->cursor.physical) |
1654 | return; | 1810 | return; |
1655 | tmp = INREG(CURSOR_A_CONTROL); | 1811 | tmp = INREG(CURSOR_A_CONTROL); |
@@ -1679,7 +1835,7 @@ intelfbhw_cursor_show(struct intelfb_info *dinfo) | |||
1679 | if (dinfo->cursor_blanked) | 1835 | if (dinfo->cursor_blanked) |
1680 | return; | 1836 | return; |
1681 | 1837 | ||
1682 | if (dinfo->mobile) { | 1838 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
1683 | if (!dinfo->cursor.physical) | 1839 | if (!dinfo->cursor.physical) |
1684 | return; | 1840 | return; |
1685 | tmp = INREG(CURSOR_A_CONTROL); | 1841 | tmp = INREG(CURSOR_A_CONTROL); |
@@ -1705,14 +1861,18 @@ intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y) | |||
1705 | #endif | 1861 | #endif |
1706 | 1862 | ||
1707 | /* | 1863 | /* |
1708 | * Sets the position. The coordinates are assumed to already | 1864 | * Sets the position. The coordinates are assumed to already |
1709 | * have any offset adjusted. Assume that the cursor is never | 1865 | * have any offset adjusted. Assume that the cursor is never |
1710 | * completely off-screen, and that x, y are always >= 0. | 1866 | * completely off-screen, and that x, y are always >= 0. |
1711 | */ | 1867 | */ |
1712 | 1868 | ||
1713 | tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | | 1869 | tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | |
1714 | ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); | 1870 | ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); |
1715 | OUTREG(CURSOR_A_POSITION, tmp); | 1871 | OUTREG(CURSOR_A_POSITION, tmp); |
1872 | |||
1873 | if (IS_I9XX(dinfo)) { | ||
1874 | OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical); | ||
1875 | } | ||
1716 | } | 1876 | } |
1717 | 1877 | ||
1718 | void | 1878 | void |