Commit | Line | Data |
---|---|---|
81dee67e SM |
1 | |
2 | #include "ddk750_help.h" | |
3 | #include "ddk750_reg.h" | |
4 | #include "ddk750_mode.h" | |
5 | #include "ddk750_chip.h" | |
6 | ||
7 | /* | |
8 | SM750LE only: | |
9 | This function takes care extra registers and bit fields required to set | |
10 | up a mode in SM750LE | |
11 | ||
12 | Explanation about Display Control register: | |
13 | HW only supports 7 predefined pixel clocks, and clock select is | |
14 | in bit 29:27 of Display Control register. | |
15 | */ | |
16 | static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl) | |
17 | { | |
18 | unsigned long x, y; | |
19 | ||
20 | x = pModeParam->horizontal_display_end; | |
21 | y = pModeParam->vertical_display_end; | |
22 | ||
78376535 JL |
23 | /* SM750LE has to set up the top-left and bottom-right |
24 | registers as well. | |
25 | Note that normal SM750/SM718 only use those two register for | |
26 | auto-centering mode. | |
27 | */ | |
85943dae | 28 | POKE32(CRT_AUTO_CENTERING_TL, 0); |
78376535 JL |
29 | |
30 | POKE32(CRT_AUTO_CENTERING_BR, | |
aed4b787 MR |
31 | (((y - 1) << CRT_AUTO_CENTERING_BR_BOTTOM_SHIFT) & |
32 | CRT_AUTO_CENTERING_BR_BOTTOM_MASK) | | |
33 | ((x - 1) & CRT_AUTO_CENTERING_BR_RIGHT_MASK)); | |
78376535 JL |
34 | |
35 | /* Assume common fields in dispControl have been properly set before | |
36 | calling this function. | |
37 | This function only sets the extra fields in dispControl. | |
38 | */ | |
81dee67e SM |
39 | |
40 | /* Clear bit 29:27 of display control register */ | |
cdce1f18 | 41 | dispControl &= ~CRT_DISPLAY_CTRL_CLK_MASK; |
81dee67e SM |
42 | |
43 | /* Set bit 29:27 of display control register for the right clock */ | |
fbb8c963 | 44 | /* Note that SM750LE only need to supported 7 resolutions. */ |
8332d94c | 45 | if (x == 800 && y == 600) |
cdce1f18 | 46 | dispControl |= CRT_DISPLAY_CTRL_CLK_PLL41; |
81dee67e | 47 | else if (x == 1024 && y == 768) |
cdce1f18 | 48 | dispControl |= CRT_DISPLAY_CTRL_CLK_PLL65; |
81dee67e | 49 | else if (x == 1152 && y == 864) |
cdce1f18 | 50 | dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80; |
81dee67e | 51 | else if (x == 1280 && y == 768) |
cdce1f18 | 52 | dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80; |
81dee67e | 53 | else if (x == 1280 && y == 720) |
cdce1f18 | 54 | dispControl |= CRT_DISPLAY_CTRL_CLK_PLL74; |
81dee67e | 55 | else if (x == 1280 && y == 960) |
cdce1f18 | 56 | dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108; |
81dee67e | 57 | else if (x == 1280 && y == 1024) |
cdce1f18 | 58 | dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108; |
81dee67e | 59 | else /* default to VGA clock */ |
cdce1f18 | 60 | dispControl |= CRT_DISPLAY_CTRL_CLK_PLL25; |
81dee67e SM |
61 | |
62 | /* Set bit 25:24 of display controller */ | |
d8264edf | 63 | dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT); |
81dee67e | 64 | |
78376535 | 65 | /* Set bit 14 of display controller */ |
992f9614 | 66 | dispControl |= DISPLAY_CTRL_CLOCK_PHASE; |
81dee67e | 67 | |
78376535 | 68 | POKE32(CRT_DISPLAY_CTRL, dispControl); |
81dee67e SM |
69 | |
70 | return dispControl; | |
71 | } | |
72 | ||
73 | ||
74 | ||
75 | /* only timing related registers will be programed */ | |
eb0f4271 | 76 | static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) |
81dee67e SM |
77 | { |
78 | int ret = 0; | |
79 | int cnt = 0; | |
c436e6ba | 80 | unsigned int tmp, reg; |
40403c1b | 81 | |
259fef35 | 82 | if (pll->clockType == SECONDARY_PLL) { |
81dee67e | 83 | /* programe secondary pixel clock */ |
195d2b64 | 84 | POKE32(CRT_PLL_CTRL, formatPllReg(pll)); |
78376535 | 85 | POKE32(CRT_HORIZONTAL_TOTAL, |
32849f85 MR |
86 | (((pModeParam->horizontal_total - 1) << |
87 | CRT_HORIZONTAL_TOTAL_TOTAL_SHIFT) & | |
88 | CRT_HORIZONTAL_TOTAL_TOTAL_MASK) | | |
89 | ((pModeParam->horizontal_display_end - 1) & | |
90 | CRT_HORIZONTAL_TOTAL_DISPLAY_END_MASK)); | |
81dee67e | 91 | |
78376535 | 92 | POKE32(CRT_HORIZONTAL_SYNC, |
1adb3c23 MR |
93 | ((pModeParam->horizontal_sync_width << |
94 | CRT_HORIZONTAL_SYNC_WIDTH_SHIFT) & | |
95 | CRT_HORIZONTAL_SYNC_WIDTH_MASK) | | |
96 | ((pModeParam->horizontal_sync_start - 1) & | |
97 | CRT_HORIZONTAL_SYNC_START_MASK)); | |
81dee67e | 98 | |
78376535 | 99 | POKE32(CRT_VERTICAL_TOTAL, |
3d5158d3 MR |
100 | (((pModeParam->vertical_total - 1) << |
101 | CRT_VERTICAL_TOTAL_TOTAL_SHIFT) & | |
102 | CRT_VERTICAL_TOTAL_TOTAL_MASK) | | |
103 | ((pModeParam->vertical_display_end - 1) & | |
104 | CRT_VERTICAL_TOTAL_DISPLAY_END_MASK)); | |
81dee67e | 105 | |
78376535 | 106 | POKE32(CRT_VERTICAL_SYNC, |
620c3912 MR |
107 | ((pModeParam->vertical_sync_height << |
108 | CRT_VERTICAL_SYNC_HEIGHT_SHIFT) & | |
109 | CRT_VERTICAL_SYNC_HEIGHT_MASK) | | |
110 | ((pModeParam->vertical_sync_start - 1) & | |
111 | CRT_VERTICAL_SYNC_START_MASK)); | |
81dee67e SM |
112 | |
113 | ||
6fba39cf MR |
114 | tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE; |
115 | if (pModeParam->vertical_sync_polarity) | |
116 | tmp |= DISPLAY_CTRL_VSYNC_PHASE; | |
117 | if (pModeParam->horizontal_sync_polarity) | |
118 | tmp |= DISPLAY_CTRL_HSYNC_PHASE; | |
81dee67e | 119 | |
8c11f5a2 | 120 | if (getChipType() == SM750LE) { |
c436e6ba | 121 | displayControlAdjust_SM750LE(pModeParam, tmp); |
6338a781 | 122 | } else { |
6fba39cf MR |
123 | reg = PEEK32(CRT_DISPLAY_CTRL) & |
124 | ~(DISPLAY_CTRL_VSYNC_PHASE | | |
125 | DISPLAY_CTRL_HSYNC_PHASE | | |
126 | DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE); | |
81dee67e | 127 | |
c436e6ba | 128 | POKE32(CRT_DISPLAY_CTRL, tmp | reg); |
81dee67e SM |
129 | } |
130 | ||
259fef35 | 131 | } else if (pll->clockType == PRIMARY_PLL) { |
c436e6ba | 132 | unsigned int reserved; |
40403c1b | 133 | |
195d2b64 | 134 | POKE32(PANEL_PLL_CTRL, formatPllReg(pll)); |
81dee67e | 135 | |
60112069 MR |
136 | reg = ((pModeParam->horizontal_total - 1) << |
137 | PANEL_HORIZONTAL_TOTAL_TOTAL_SHIFT) & | |
138 | PANEL_HORIZONTAL_TOTAL_TOTAL_MASK; | |
139 | reg |= ((pModeParam->horizontal_display_end - 1) & | |
140 | PANEL_HORIZONTAL_TOTAL_DISPLAY_END_MASK); | |
141 | POKE32(PANEL_HORIZONTAL_TOTAL, reg); | |
81dee67e | 142 | |
78376535 | 143 | POKE32(PANEL_HORIZONTAL_SYNC, |
a6f17bc4 MR |
144 | ((pModeParam->horizontal_sync_width << |
145 | PANEL_HORIZONTAL_SYNC_WIDTH_SHIFT) & | |
146 | PANEL_HORIZONTAL_SYNC_WIDTH_MASK) | | |
147 | ((pModeParam->horizontal_sync_start - 1) & | |
148 | PANEL_HORIZONTAL_SYNC_START_MASK)); | |
81dee67e | 149 | |
78376535 | 150 | POKE32(PANEL_VERTICAL_TOTAL, |
6014a31d MR |
151 | (((pModeParam->vertical_total - 1) << |
152 | PANEL_VERTICAL_TOTAL_TOTAL_SHIFT) & | |
153 | PANEL_VERTICAL_TOTAL_TOTAL_MASK) | | |
154 | ((pModeParam->vertical_display_end - 1) & | |
155 | PANEL_VERTICAL_TOTAL_DISPLAY_END_MASK)); | |
81dee67e | 156 | |
78376535 | 157 | POKE32(PANEL_VERTICAL_SYNC, |
8ffe4610 MR |
158 | ((pModeParam->vertical_sync_height << |
159 | PANEL_VERTICAL_SYNC_HEIGHT_SHIFT) & | |
160 | PANEL_VERTICAL_SYNC_HEIGHT_MASK) | | |
161 | ((pModeParam->vertical_sync_start - 1) & | |
162 | PANEL_VERTICAL_SYNC_START_MASK)); | |
81dee67e | 163 | |
6fba39cf MR |
164 | tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE; |
165 | if (pModeParam->vertical_sync_polarity) | |
166 | tmp |= DISPLAY_CTRL_VSYNC_PHASE; | |
167 | if (pModeParam->horizontal_sync_polarity) | |
168 | tmp |= DISPLAY_CTRL_HSYNC_PHASE; | |
169 | if (pModeParam->clock_phase_polarity) | |
170 | tmp |= DISPLAY_CTRL_CLOCK_PHASE; | |
78376535 | 171 | |
9bd2c86b | 172 | reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK | |
6fba39cf | 173 | PANEL_DISPLAY_CTRL_VSYNC; |
81dee67e | 174 | |
6fba39cf MR |
175 | reg = (PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) & |
176 | ~(DISPLAY_CTRL_CLOCK_PHASE | DISPLAY_CTRL_VSYNC_PHASE | | |
177 | DISPLAY_CTRL_HSYNC_PHASE | DISPLAY_CTRL_TIMING | | |
178 | DISPLAY_CTRL_PLANE); | |
81dee67e SM |
179 | |
180 | /* May a hardware bug or just my test chip (not confirmed). | |
181 | * PANEL_DISPLAY_CTRL register seems requiring few writes | |
69e98df7 | 182 | * before a value can be successfully written in. |
81dee67e SM |
183 | * Added some masks to mask out the reserved bits. |
184 | * Note: This problem happens by design. The hardware will wait for the | |
185 | * next vertical sync to turn on/off the plane. | |
186 | */ | |
187 | ||
c436e6ba | 188 | POKE32(PANEL_DISPLAY_CTRL, tmp | reg); |
cfac7d6a | 189 | |
c436e6ba MR |
190 | while ((PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) != |
191 | (tmp | reg)) { | |
81dee67e | 192 | cnt++; |
9ccc5f44 | 193 | if (cnt > 1000) |
81dee67e | 194 | break; |
c436e6ba | 195 | POKE32(PANEL_DISPLAY_CTRL, tmp | reg); |
81dee67e | 196 | } |
259fef35 | 197 | } else { |
81dee67e SM |
198 | ret = -1; |
199 | } | |
200 | return ret; | |
201 | } | |
202 | ||
eb0f4271 | 203 | int ddk750_setModeTiming(mode_parameter_t *parm, clock_type_t clock) |
81dee67e SM |
204 | { |
205 | pll_value_t pll; | |
206 | unsigned int uiActualPixelClk; | |
40403c1b | 207 | |
81dee67e SM |
208 | pll.inputFreq = DEFAULT_INPUT_CLOCK; |
209 | pll.clockType = clock; | |
210 | ||
195d2b64 | 211 | uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll); |
8c11f5a2 | 212 | if (getChipType() == SM750LE) { |
81dee67e | 213 | /* set graphic mode via IO method */ |
195d2b64 IA |
214 | outb_p(0x88, 0x3d4); |
215 | outb_p(0x06, 0x3d5); | |
81dee67e | 216 | } |
195d2b64 | 217 | programModeRegisters(parm, &pll); |
81dee67e SM |
218 | return 0; |
219 | } | |
220 | ||
221 |