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