diff options
Diffstat (limited to 'drivers/video/fbdev/via/hw.c')
-rw-r--r-- | drivers/video/fbdev/via/hw.c | 2134 |
1 files changed, 2134 insertions, 0 deletions
diff --git a/drivers/video/fbdev/via/hw.c b/drivers/video/fbdev/via/hw.c new file mode 100644 index 000000000000..22450908306c --- /dev/null +++ b/drivers/video/fbdev/via/hw.c | |||
@@ -0,0 +1,2134 @@ | |||
1 | /* | ||
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | ||
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | ||
4 | |||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public | ||
7 | * License as published by the Free Software Foundation; | ||
8 | * either version 2, or (at your option) any later version. | ||
9 | |||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | ||
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | ||
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | ||
14 | * for more details. | ||
15 | |||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., | ||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/via-core.h> | ||
23 | #include <asm/olpc.h> | ||
24 | #include "global.h" | ||
25 | #include "via_clock.h" | ||
26 | |||
27 | static struct pll_limit cle266_pll_limits[] = { | ||
28 | {19, 19, 4, 0}, | ||
29 | {26, 102, 5, 0}, | ||
30 | {53, 112, 6, 0}, | ||
31 | {41, 100, 7, 0}, | ||
32 | {83, 108, 8, 0}, | ||
33 | {87, 118, 9, 0}, | ||
34 | {95, 115, 12, 0}, | ||
35 | {108, 108, 13, 0}, | ||
36 | {83, 83, 17, 0}, | ||
37 | {67, 98, 20, 0}, | ||
38 | {121, 121, 24, 0}, | ||
39 | {99, 99, 29, 0}, | ||
40 | {33, 33, 3, 1}, | ||
41 | {15, 23, 4, 1}, | ||
42 | {37, 121, 5, 1}, | ||
43 | {82, 82, 6, 1}, | ||
44 | {31, 84, 7, 1}, | ||
45 | {83, 83, 8, 1}, | ||
46 | {76, 127, 9, 1}, | ||
47 | {33, 121, 4, 2}, | ||
48 | {91, 118, 5, 2}, | ||
49 | {83, 109, 6, 2}, | ||
50 | {90, 90, 7, 2}, | ||
51 | {93, 93, 2, 3}, | ||
52 | {53, 53, 3, 3}, | ||
53 | {73, 117, 4, 3}, | ||
54 | {101, 127, 5, 3}, | ||
55 | {99, 99, 7, 3} | ||
56 | }; | ||
57 | |||
58 | static struct pll_limit k800_pll_limits[] = { | ||
59 | {22, 22, 2, 0}, | ||
60 | {28, 28, 3, 0}, | ||
61 | {81, 112, 3, 1}, | ||
62 | {86, 166, 4, 1}, | ||
63 | {109, 153, 5, 1}, | ||
64 | {66, 116, 3, 2}, | ||
65 | {93, 137, 4, 2}, | ||
66 | {117, 208, 5, 2}, | ||
67 | {30, 30, 2, 3}, | ||
68 | {69, 125, 3, 3}, | ||
69 | {89, 161, 4, 3}, | ||
70 | {121, 208, 5, 3}, | ||
71 | {66, 66, 2, 4}, | ||
72 | {85, 85, 3, 4}, | ||
73 | {141, 161, 4, 4}, | ||
74 | {177, 177, 5, 4} | ||
75 | }; | ||
76 | |||
77 | static struct pll_limit cx700_pll_limits[] = { | ||
78 | {98, 98, 3, 1}, | ||
79 | {86, 86, 4, 1}, | ||
80 | {109, 208, 5, 1}, | ||
81 | {68, 68, 2, 2}, | ||
82 | {95, 116, 3, 2}, | ||
83 | {93, 166, 4, 2}, | ||
84 | {110, 206, 5, 2}, | ||
85 | {174, 174, 7, 2}, | ||
86 | {82, 109, 3, 3}, | ||
87 | {117, 161, 4, 3}, | ||
88 | {112, 208, 5, 3}, | ||
89 | {141, 202, 5, 4} | ||
90 | }; | ||
91 | |||
92 | static struct pll_limit vx855_pll_limits[] = { | ||
93 | {86, 86, 4, 1}, | ||
94 | {108, 208, 5, 1}, | ||
95 | {110, 208, 5, 2}, | ||
96 | {83, 112, 3, 3}, | ||
97 | {103, 161, 4, 3}, | ||
98 | {112, 209, 5, 3}, | ||
99 | {142, 161, 4, 4}, | ||
100 | {141, 176, 5, 4} | ||
101 | }; | ||
102 | |||
103 | /* according to VIA Technologies these values are based on experiment */ | ||
104 | static struct io_reg scaling_parameters[] = { | ||
105 | {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */ | ||
106 | {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */ | ||
107 | {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */ | ||
108 | {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */ | ||
109 | {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */ | ||
110 | {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */ | ||
111 | {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */ | ||
112 | {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */ | ||
113 | {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */ | ||
114 | {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */ | ||
115 | {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */ | ||
116 | {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */ | ||
117 | {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */ | ||
118 | {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */ | ||
119 | }; | ||
120 | |||
121 | static struct io_reg common_vga[] = { | ||
122 | {VIACR, CR07, 0x10, 0x10}, /* [0] vertical total (bit 8) | ||
123 | [1] vertical display end (bit 8) | ||
124 | [2] vertical retrace start (bit 8) | ||
125 | [3] start vertical blanking (bit 8) | ||
126 | [4] line compare (bit 8) | ||
127 | [5] vertical total (bit 9) | ||
128 | [6] vertical display end (bit 9) | ||
129 | [7] vertical retrace start (bit 9) */ | ||
130 | {VIACR, CR08, 0xFF, 0x00}, /* [0-4] preset row scan | ||
131 | [5-6] byte panning */ | ||
132 | {VIACR, CR09, 0xDF, 0x40}, /* [0-4] max scan line | ||
133 | [5] start vertical blanking (bit 9) | ||
134 | [6] line compare (bit 9) | ||
135 | [7] scan doubling */ | ||
136 | {VIACR, CR0A, 0xFF, 0x1E}, /* [0-4] cursor start | ||
137 | [5] cursor disable */ | ||
138 | {VIACR, CR0B, 0xFF, 0x00}, /* [0-4] cursor end | ||
139 | [5-6] cursor skew */ | ||
140 | {VIACR, CR0E, 0xFF, 0x00}, /* [0-7] cursor location (high) */ | ||
141 | {VIACR, CR0F, 0xFF, 0x00}, /* [0-7] cursor location (low) */ | ||
142 | {VIACR, CR11, 0xF0, 0x80}, /* [0-3] vertical retrace end | ||
143 | [6] memory refresh bandwidth | ||
144 | [7] CRTC register protect enable */ | ||
145 | {VIACR, CR14, 0xFF, 0x00}, /* [0-4] underline location | ||
146 | [5] divide memory address clock by 4 | ||
147 | [6] double word addressing */ | ||
148 | {VIACR, CR17, 0xFF, 0x63}, /* [0-1] mapping of display address 13-14 | ||
149 | [2] divide scan line clock by 2 | ||
150 | [3] divide memory address clock by 2 | ||
151 | [5] address wrap | ||
152 | [6] byte mode select | ||
153 | [7] sync enable */ | ||
154 | {VIACR, CR18, 0xFF, 0xFF}, /* [0-7] line compare */ | ||
155 | }; | ||
156 | |||
157 | static struct fifo_depth_select display_fifo_depth_reg = { | ||
158 | /* IGA1 FIFO Depth_Select */ | ||
159 | {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } }, | ||
160 | /* IGA2 FIFO Depth_Select */ | ||
161 | {IGA2_FIFO_DEPTH_SELECT_REG_NUM, | ||
162 | {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } } | ||
163 | }; | ||
164 | |||
165 | static struct fifo_threshold_select fifo_threshold_select_reg = { | ||
166 | /* IGA1 FIFO Threshold Select */ | ||
167 | {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } }, | ||
168 | /* IGA2 FIFO Threshold Select */ | ||
169 | {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } } | ||
170 | }; | ||
171 | |||
172 | static struct fifo_high_threshold_select fifo_high_threshold_select_reg = { | ||
173 | /* IGA1 FIFO High Threshold Select */ | ||
174 | {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } }, | ||
175 | /* IGA2 FIFO High Threshold Select */ | ||
176 | {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } } | ||
177 | }; | ||
178 | |||
179 | static struct display_queue_expire_num display_queue_expire_num_reg = { | ||
180 | /* IGA1 Display Queue Expire Num */ | ||
181 | {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } }, | ||
182 | /* IGA2 Display Queue Expire Num */ | ||
183 | {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } } | ||
184 | }; | ||
185 | |||
186 | /* Definition Fetch Count Registers*/ | ||
187 | static struct fetch_count fetch_count_reg = { | ||
188 | /* IGA1 Fetch Count Register */ | ||
189 | {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } }, | ||
190 | /* IGA2 Fetch Count Register */ | ||
191 | {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } } | ||
192 | }; | ||
193 | |||
194 | static struct rgbLUT palLUT_table[] = { | ||
195 | /* {R,G,B} */ | ||
196 | /* Index 0x00~0x03 */ | ||
197 | {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00, | ||
198 | 0x2A, | ||
199 | 0x2A}, | ||
200 | /* Index 0x04~0x07 */ | ||
201 | {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A, | ||
202 | 0x2A, | ||
203 | 0x2A}, | ||
204 | /* Index 0x08~0x0B */ | ||
205 | {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15, | ||
206 | 0x3F, | ||
207 | 0x3F}, | ||
208 | /* Index 0x0C~0x0F */ | ||
209 | {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F, | ||
210 | 0x3F, | ||
211 | 0x3F}, | ||
212 | /* Index 0x10~0x13 */ | ||
213 | {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B, | ||
214 | 0x0B, | ||
215 | 0x0B}, | ||
216 | /* Index 0x14~0x17 */ | ||
217 | {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18, | ||
218 | 0x18, | ||
219 | 0x18}, | ||
220 | /* Index 0x18~0x1B */ | ||
221 | {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28, | ||
222 | 0x28, | ||
223 | 0x28}, | ||
224 | /* Index 0x1C~0x1F */ | ||
225 | {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F, | ||
226 | 0x3F, | ||
227 | 0x3F}, | ||
228 | /* Index 0x20~0x23 */ | ||
229 | {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F, | ||
230 | 0x00, | ||
231 | 0x3F}, | ||
232 | /* Index 0x24~0x27 */ | ||
233 | {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F, | ||
234 | 0x00, | ||
235 | 0x10}, | ||
236 | /* Index 0x28~0x2B */ | ||
237 | {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F, | ||
238 | 0x2F, | ||
239 | 0x00}, | ||
240 | /* Index 0x2C~0x2F */ | ||
241 | {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10, | ||
242 | 0x3F, | ||
243 | 0x00}, | ||
244 | /* Index 0x30~0x33 */ | ||
245 | {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00, | ||
246 | 0x3F, | ||
247 | 0x2F}, | ||
248 | /* Index 0x34~0x37 */ | ||
249 | {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00, | ||
250 | 0x10, | ||
251 | 0x3F}, | ||
252 | /* Index 0x38~0x3B */ | ||
253 | {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37, | ||
254 | 0x1F, | ||
255 | 0x3F}, | ||
256 | /* Index 0x3C~0x3F */ | ||
257 | {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F, | ||
258 | 0x1F, | ||
259 | 0x27}, | ||
260 | /* Index 0x40~0x43 */ | ||
261 | {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F, | ||
262 | 0x3F, | ||
263 | 0x1F}, | ||
264 | /* Index 0x44~0x47 */ | ||
265 | {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27, | ||
266 | 0x3F, | ||
267 | 0x1F}, | ||
268 | /* Index 0x48~0x4B */ | ||
269 | {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F, | ||
270 | 0x3F, | ||
271 | 0x37}, | ||
272 | /* Index 0x4C~0x4F */ | ||
273 | {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F, | ||
274 | 0x27, | ||
275 | 0x3F}, | ||
276 | /* Index 0x50~0x53 */ | ||
277 | {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A, | ||
278 | 0x2D, | ||
279 | 0x3F}, | ||
280 | /* Index 0x54~0x57 */ | ||
281 | {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F, | ||
282 | 0x2D, | ||
283 | 0x31}, | ||
284 | /* Index 0x58~0x5B */ | ||
285 | {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F, | ||
286 | 0x3A, | ||
287 | 0x2D}, | ||
288 | /* Index 0x5C~0x5F */ | ||
289 | {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31, | ||
290 | 0x3F, | ||
291 | 0x2D}, | ||
292 | /* Index 0x60~0x63 */ | ||
293 | {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D, | ||
294 | 0x3F, | ||
295 | 0x3A}, | ||
296 | /* Index 0x64~0x67 */ | ||
297 | {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D, | ||
298 | 0x31, | ||
299 | 0x3F}, | ||
300 | /* Index 0x68~0x6B */ | ||
301 | {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15, | ||
302 | 0x00, | ||
303 | 0x1C}, | ||
304 | /* Index 0x6C~0x6F */ | ||
305 | {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C, | ||
306 | 0x00, | ||
307 | 0x07}, | ||
308 | /* Index 0x70~0x73 */ | ||
309 | {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C, | ||
310 | 0x15, | ||
311 | 0x00}, | ||
312 | /* Index 0x74~0x77 */ | ||
313 | {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07, | ||
314 | 0x1C, | ||
315 | 0x00}, | ||
316 | /* Index 0x78~0x7B */ | ||
317 | {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00, | ||
318 | 0x1C, | ||
319 | 0x15}, | ||
320 | /* Index 0x7C~0x7F */ | ||
321 | {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00, | ||
322 | 0x07, | ||
323 | 0x1C}, | ||
324 | /* Index 0x80~0x83 */ | ||
325 | {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18, | ||
326 | 0x0E, | ||
327 | 0x1C}, | ||
328 | /* Index 0x84~0x87 */ | ||
329 | {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C, | ||
330 | 0x0E, | ||
331 | 0x11}, | ||
332 | /* Index 0x88~0x8B */ | ||
333 | {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C, | ||
334 | 0x18, | ||
335 | 0x0E}, | ||
336 | /* Index 0x8C~0x8F */ | ||
337 | {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11, | ||
338 | 0x1C, | ||
339 | 0x0E}, | ||
340 | /* Index 0x90~0x93 */ | ||
341 | {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E, | ||
342 | 0x1C, | ||
343 | 0x18}, | ||
344 | /* Index 0x94~0x97 */ | ||
345 | {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E, | ||
346 | 0x11, | ||
347 | 0x1C}, | ||
348 | /* Index 0x98~0x9B */ | ||
349 | {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A, | ||
350 | 0x14, | ||
351 | 0x1C}, | ||
352 | /* Index 0x9C~0x9F */ | ||
353 | {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C, | ||
354 | 0x14, | ||
355 | 0x16}, | ||
356 | /* Index 0xA0~0xA3 */ | ||
357 | {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C, | ||
358 | 0x1A, | ||
359 | 0x14}, | ||
360 | /* Index 0xA4~0xA7 */ | ||
361 | {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16, | ||
362 | 0x1C, | ||
363 | 0x14}, | ||
364 | /* Index 0xA8~0xAB */ | ||
365 | {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14, | ||
366 | 0x1C, | ||
367 | 0x1A}, | ||
368 | /* Index 0xAC~0xAF */ | ||
369 | {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14, | ||
370 | 0x16, | ||
371 | 0x1C}, | ||
372 | /* Index 0xB0~0xB3 */ | ||
373 | {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C, | ||
374 | 0x00, | ||
375 | 0x10}, | ||
376 | /* Index 0xB4~0xB7 */ | ||
377 | {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10, | ||
378 | 0x00, | ||
379 | 0x04}, | ||
380 | /* Index 0xB8~0xBB */ | ||
381 | {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10, | ||
382 | 0x0C, | ||
383 | 0x00}, | ||
384 | /* Index 0xBC~0xBF */ | ||
385 | {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04, | ||
386 | 0x10, | ||
387 | 0x00}, | ||
388 | /* Index 0xC0~0xC3 */ | ||
389 | {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00, | ||
390 | 0x10, | ||
391 | 0x0C}, | ||
392 | /* Index 0xC4~0xC7 */ | ||
393 | {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00, | ||
394 | 0x04, | ||
395 | 0x10}, | ||
396 | /* Index 0xC8~0xCB */ | ||
397 | {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E, | ||
398 | 0x08, | ||
399 | 0x10}, | ||
400 | /* Index 0xCC~0xCF */ | ||
401 | {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10, | ||
402 | 0x08, | ||
403 | 0x0A}, | ||
404 | /* Index 0xD0~0xD3 */ | ||
405 | {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10, | ||
406 | 0x0E, | ||
407 | 0x08}, | ||
408 | /* Index 0xD4~0xD7 */ | ||
409 | {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A, | ||
410 | 0x10, | ||
411 | 0x08}, | ||
412 | /* Index 0xD8~0xDB */ | ||
413 | {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08, | ||
414 | 0x10, | ||
415 | 0x0E}, | ||
416 | /* Index 0xDC~0xDF */ | ||
417 | {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08, | ||
418 | 0x0A, | ||
419 | 0x10}, | ||
420 | /* Index 0xE0~0xE3 */ | ||
421 | {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F, | ||
422 | 0x0B, | ||
423 | 0x10}, | ||
424 | /* Index 0xE4~0xE7 */ | ||
425 | {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10, | ||
426 | 0x0B, | ||
427 | 0x0C}, | ||
428 | /* Index 0xE8~0xEB */ | ||
429 | {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10, | ||
430 | 0x0F, | ||
431 | 0x0B}, | ||
432 | /* Index 0xEC~0xEF */ | ||
433 | {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C, | ||
434 | 0x10, | ||
435 | 0x0B}, | ||
436 | /* Index 0xF0~0xF3 */ | ||
437 | {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B, | ||
438 | 0x10, | ||
439 | 0x0F}, | ||
440 | /* Index 0xF4~0xF7 */ | ||
441 | {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B, | ||
442 | 0x0C, | ||
443 | 0x10}, | ||
444 | /* Index 0xF8~0xFB */ | ||
445 | {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, | ||
446 | 0x00, | ||
447 | 0x00}, | ||
448 | /* Index 0xFC~0xFF */ | ||
449 | {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, | ||
450 | 0x00, | ||
451 | 0x00} | ||
452 | }; | ||
453 | |||
454 | static struct via_device_mapping device_mapping[] = { | ||
455 | {VIA_LDVP0, "LDVP0"}, | ||
456 | {VIA_LDVP1, "LDVP1"}, | ||
457 | {VIA_DVP0, "DVP0"}, | ||
458 | {VIA_CRT, "CRT"}, | ||
459 | {VIA_DVP1, "DVP1"}, | ||
460 | {VIA_LVDS1, "LVDS1"}, | ||
461 | {VIA_LVDS2, "LVDS2"} | ||
462 | }; | ||
463 | |||
464 | /* structure with function pointers to support clock control */ | ||
465 | static struct via_clock clock; | ||
466 | |||
467 | static void load_fix_bit_crtc_reg(void); | ||
468 | static void init_gfx_chip_info(int chip_type); | ||
469 | static void init_tmds_chip_info(void); | ||
470 | static void init_lvds_chip_info(void); | ||
471 | static void device_screen_off(void); | ||
472 | static void device_screen_on(void); | ||
473 | static void set_display_channel(void); | ||
474 | static void device_off(void); | ||
475 | static void device_on(void); | ||
476 | static void enable_second_display_channel(void); | ||
477 | static void disable_second_display_channel(void); | ||
478 | |||
479 | void viafb_lock_crt(void) | ||
480 | { | ||
481 | viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7); | ||
482 | } | ||
483 | |||
484 | void viafb_unlock_crt(void) | ||
485 | { | ||
486 | viafb_write_reg_mask(CR11, VIACR, 0, BIT7); | ||
487 | viafb_write_reg_mask(CR47, VIACR, 0, BIT0); | ||
488 | } | ||
489 | |||
490 | static void write_dac_reg(u8 index, u8 r, u8 g, u8 b) | ||
491 | { | ||
492 | outb(index, LUT_INDEX_WRITE); | ||
493 | outb(r, LUT_DATA); | ||
494 | outb(g, LUT_DATA); | ||
495 | outb(b, LUT_DATA); | ||
496 | } | ||
497 | |||
498 | static u32 get_dvi_devices(int output_interface) | ||
499 | { | ||
500 | switch (output_interface) { | ||
501 | case INTERFACE_DVP0: | ||
502 | return VIA_DVP0 | VIA_LDVP0; | ||
503 | |||
504 | case INTERFACE_DVP1: | ||
505 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
506 | return VIA_LDVP1; | ||
507 | else | ||
508 | return VIA_DVP1; | ||
509 | |||
510 | case INTERFACE_DFP_HIGH: | ||
511 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
512 | return 0; | ||
513 | else | ||
514 | return VIA_LVDS2 | VIA_DVP0; | ||
515 | |||
516 | case INTERFACE_DFP_LOW: | ||
517 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
518 | return 0; | ||
519 | else | ||
520 | return VIA_DVP1 | VIA_LVDS1; | ||
521 | |||
522 | case INTERFACE_TMDS: | ||
523 | return VIA_LVDS1; | ||
524 | } | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static u32 get_lcd_devices(int output_interface) | ||
530 | { | ||
531 | switch (output_interface) { | ||
532 | case INTERFACE_DVP0: | ||
533 | return VIA_DVP0; | ||
534 | |||
535 | case INTERFACE_DVP1: | ||
536 | return VIA_DVP1; | ||
537 | |||
538 | case INTERFACE_DFP_HIGH: | ||
539 | return VIA_LVDS2 | VIA_DVP0; | ||
540 | |||
541 | case INTERFACE_DFP_LOW: | ||
542 | return VIA_LVDS1 | VIA_DVP1; | ||
543 | |||
544 | case INTERFACE_DFP: | ||
545 | return VIA_LVDS1 | VIA_LVDS2; | ||
546 | |||
547 | case INTERFACE_LVDS0: | ||
548 | case INTERFACE_LVDS0LVDS1: | ||
549 | return VIA_LVDS1; | ||
550 | |||
551 | case INTERFACE_LVDS1: | ||
552 | return VIA_LVDS2; | ||
553 | } | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | /*Set IGA path for each device*/ | ||
559 | void viafb_set_iga_path(void) | ||
560 | { | ||
561 | int crt_iga_path = 0; | ||
562 | |||
563 | if (viafb_SAMM_ON == 1) { | ||
564 | if (viafb_CRT_ON) { | ||
565 | if (viafb_primary_dev == CRT_Device) | ||
566 | crt_iga_path = IGA1; | ||
567 | else | ||
568 | crt_iga_path = IGA2; | ||
569 | } | ||
570 | |||
571 | if (viafb_DVI_ON) { | ||
572 | if (viafb_primary_dev == DVI_Device) | ||
573 | viaparinfo->tmds_setting_info->iga_path = IGA1; | ||
574 | else | ||
575 | viaparinfo->tmds_setting_info->iga_path = IGA2; | ||
576 | } | ||
577 | |||
578 | if (viafb_LCD_ON) { | ||
579 | if (viafb_primary_dev == LCD_Device) { | ||
580 | if (viafb_dual_fb && | ||
581 | (viaparinfo->chip_info->gfx_chip_name == | ||
582 | UNICHROME_CLE266)) { | ||
583 | viaparinfo-> | ||
584 | lvds_setting_info->iga_path = IGA2; | ||
585 | crt_iga_path = IGA1; | ||
586 | viaparinfo-> | ||
587 | tmds_setting_info->iga_path = IGA1; | ||
588 | } else | ||
589 | viaparinfo-> | ||
590 | lvds_setting_info->iga_path = IGA1; | ||
591 | } else { | ||
592 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
593 | } | ||
594 | } | ||
595 | if (viafb_LCD2_ON) { | ||
596 | if (LCD2_Device == viafb_primary_dev) | ||
597 | viaparinfo->lvds_setting_info2->iga_path = IGA1; | ||
598 | else | ||
599 | viaparinfo->lvds_setting_info2->iga_path = IGA2; | ||
600 | } | ||
601 | } else { | ||
602 | viafb_SAMM_ON = 0; | ||
603 | |||
604 | if (viafb_CRT_ON && viafb_LCD_ON) { | ||
605 | crt_iga_path = IGA1; | ||
606 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
607 | } else if (viafb_CRT_ON && viafb_DVI_ON) { | ||
608 | crt_iga_path = IGA1; | ||
609 | viaparinfo->tmds_setting_info->iga_path = IGA2; | ||
610 | } else if (viafb_LCD_ON && viafb_DVI_ON) { | ||
611 | viaparinfo->tmds_setting_info->iga_path = IGA1; | ||
612 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
613 | } else if (viafb_LCD_ON && viafb_LCD2_ON) { | ||
614 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
615 | viaparinfo->lvds_setting_info2->iga_path = IGA2; | ||
616 | } else if (viafb_CRT_ON) { | ||
617 | crt_iga_path = IGA1; | ||
618 | } else if (viafb_LCD_ON) { | ||
619 | viaparinfo->lvds_setting_info->iga_path = IGA2; | ||
620 | } else if (viafb_DVI_ON) { | ||
621 | viaparinfo->tmds_setting_info->iga_path = IGA1; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | viaparinfo->shared->iga1_devices = 0; | ||
626 | viaparinfo->shared->iga2_devices = 0; | ||
627 | if (viafb_CRT_ON) { | ||
628 | if (crt_iga_path == IGA1) | ||
629 | viaparinfo->shared->iga1_devices |= VIA_CRT; | ||
630 | else | ||
631 | viaparinfo->shared->iga2_devices |= VIA_CRT; | ||
632 | } | ||
633 | |||
634 | if (viafb_DVI_ON) { | ||
635 | if (viaparinfo->tmds_setting_info->iga_path == IGA1) | ||
636 | viaparinfo->shared->iga1_devices |= get_dvi_devices( | ||
637 | viaparinfo->chip_info-> | ||
638 | tmds_chip_info.output_interface); | ||
639 | else | ||
640 | viaparinfo->shared->iga2_devices |= get_dvi_devices( | ||
641 | viaparinfo->chip_info-> | ||
642 | tmds_chip_info.output_interface); | ||
643 | } | ||
644 | |||
645 | if (viafb_LCD_ON) { | ||
646 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) | ||
647 | viaparinfo->shared->iga1_devices |= get_lcd_devices( | ||
648 | viaparinfo->chip_info-> | ||
649 | lvds_chip_info.output_interface); | ||
650 | else | ||
651 | viaparinfo->shared->iga2_devices |= get_lcd_devices( | ||
652 | viaparinfo->chip_info-> | ||
653 | lvds_chip_info.output_interface); | ||
654 | } | ||
655 | |||
656 | if (viafb_LCD2_ON) { | ||
657 | if (viaparinfo->lvds_setting_info2->iga_path == IGA1) | ||
658 | viaparinfo->shared->iga1_devices |= get_lcd_devices( | ||
659 | viaparinfo->chip_info-> | ||
660 | lvds_chip_info2.output_interface); | ||
661 | else | ||
662 | viaparinfo->shared->iga2_devices |= get_lcd_devices( | ||
663 | viaparinfo->chip_info-> | ||
664 | lvds_chip_info2.output_interface); | ||
665 | } | ||
666 | |||
667 | /* looks like the OLPC has its display wired to DVP1 and LVDS2 */ | ||
668 | if (machine_is_olpc()) | ||
669 | viaparinfo->shared->iga2_devices = VIA_DVP1 | VIA_LVDS2; | ||
670 | } | ||
671 | |||
672 | static void set_color_register(u8 index, u8 red, u8 green, u8 blue) | ||
673 | { | ||
674 | outb(0xFF, 0x3C6); /* bit mask of palette */ | ||
675 | outb(index, 0x3C8); | ||
676 | outb(red, 0x3C9); | ||
677 | outb(green, 0x3C9); | ||
678 | outb(blue, 0x3C9); | ||
679 | } | ||
680 | |||
681 | void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue) | ||
682 | { | ||
683 | viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01); | ||
684 | set_color_register(index, red, green, blue); | ||
685 | } | ||
686 | |||
687 | void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue) | ||
688 | { | ||
689 | viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01); | ||
690 | set_color_register(index, red, green, blue); | ||
691 | } | ||
692 | |||
693 | static void set_source_common(u8 index, u8 offset, u8 iga) | ||
694 | { | ||
695 | u8 value, mask = 1 << offset; | ||
696 | |||
697 | switch (iga) { | ||
698 | case IGA1: | ||
699 | value = 0x00; | ||
700 | break; | ||
701 | case IGA2: | ||
702 | value = mask; | ||
703 | break; | ||
704 | default: | ||
705 | printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga); | ||
706 | return; | ||
707 | } | ||
708 | |||
709 | via_write_reg_mask(VIACR, index, value, mask); | ||
710 | } | ||
711 | |||
712 | static void set_crt_source(u8 iga) | ||
713 | { | ||
714 | u8 value; | ||
715 | |||
716 | switch (iga) { | ||
717 | case IGA1: | ||
718 | value = 0x00; | ||
719 | break; | ||
720 | case IGA2: | ||
721 | value = 0x40; | ||
722 | break; | ||
723 | default: | ||
724 | printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga); | ||
725 | return; | ||
726 | } | ||
727 | |||
728 | via_write_reg_mask(VIASR, 0x16, value, 0x40); | ||
729 | } | ||
730 | |||
731 | static inline void set_ldvp0_source(u8 iga) | ||
732 | { | ||
733 | set_source_common(0x6C, 7, iga); | ||
734 | } | ||
735 | |||
736 | static inline void set_ldvp1_source(u8 iga) | ||
737 | { | ||
738 | set_source_common(0x93, 7, iga); | ||
739 | } | ||
740 | |||
741 | static inline void set_dvp0_source(u8 iga) | ||
742 | { | ||
743 | set_source_common(0x96, 4, iga); | ||
744 | } | ||
745 | |||
746 | static inline void set_dvp1_source(u8 iga) | ||
747 | { | ||
748 | set_source_common(0x9B, 4, iga); | ||
749 | } | ||
750 | |||
751 | static inline void set_lvds1_source(u8 iga) | ||
752 | { | ||
753 | set_source_common(0x99, 4, iga); | ||
754 | } | ||
755 | |||
756 | static inline void set_lvds2_source(u8 iga) | ||
757 | { | ||
758 | set_source_common(0x97, 4, iga); | ||
759 | } | ||
760 | |||
761 | void via_set_source(u32 devices, u8 iga) | ||
762 | { | ||
763 | if (devices & VIA_LDVP0) | ||
764 | set_ldvp0_source(iga); | ||
765 | if (devices & VIA_LDVP1) | ||
766 | set_ldvp1_source(iga); | ||
767 | if (devices & VIA_DVP0) | ||
768 | set_dvp0_source(iga); | ||
769 | if (devices & VIA_CRT) | ||
770 | set_crt_source(iga); | ||
771 | if (devices & VIA_DVP1) | ||
772 | set_dvp1_source(iga); | ||
773 | if (devices & VIA_LVDS1) | ||
774 | set_lvds1_source(iga); | ||
775 | if (devices & VIA_LVDS2) | ||
776 | set_lvds2_source(iga); | ||
777 | } | ||
778 | |||
779 | static void set_crt_state(u8 state) | ||
780 | { | ||
781 | u8 value; | ||
782 | |||
783 | switch (state) { | ||
784 | case VIA_STATE_ON: | ||
785 | value = 0x00; | ||
786 | break; | ||
787 | case VIA_STATE_STANDBY: | ||
788 | value = 0x10; | ||
789 | break; | ||
790 | case VIA_STATE_SUSPEND: | ||
791 | value = 0x20; | ||
792 | break; | ||
793 | case VIA_STATE_OFF: | ||
794 | value = 0x30; | ||
795 | break; | ||
796 | default: | ||
797 | return; | ||
798 | } | ||
799 | |||
800 | via_write_reg_mask(VIACR, 0x36, value, 0x30); | ||
801 | } | ||
802 | |||
803 | static void set_dvp0_state(u8 state) | ||
804 | { | ||
805 | u8 value; | ||
806 | |||
807 | switch (state) { | ||
808 | case VIA_STATE_ON: | ||
809 | value = 0xC0; | ||
810 | break; | ||
811 | case VIA_STATE_OFF: | ||
812 | value = 0x00; | ||
813 | break; | ||
814 | default: | ||
815 | return; | ||
816 | } | ||
817 | |||
818 | via_write_reg_mask(VIASR, 0x1E, value, 0xC0); | ||
819 | } | ||
820 | |||
821 | static void set_dvp1_state(u8 state) | ||
822 | { | ||
823 | u8 value; | ||
824 | |||
825 | switch (state) { | ||
826 | case VIA_STATE_ON: | ||
827 | value = 0x30; | ||
828 | break; | ||
829 | case VIA_STATE_OFF: | ||
830 | value = 0x00; | ||
831 | break; | ||
832 | default: | ||
833 | return; | ||
834 | } | ||
835 | |||
836 | via_write_reg_mask(VIASR, 0x1E, value, 0x30); | ||
837 | } | ||
838 | |||
839 | static void set_lvds1_state(u8 state) | ||
840 | { | ||
841 | u8 value; | ||
842 | |||
843 | switch (state) { | ||
844 | case VIA_STATE_ON: | ||
845 | value = 0x03; | ||
846 | break; | ||
847 | case VIA_STATE_OFF: | ||
848 | value = 0x00; | ||
849 | break; | ||
850 | default: | ||
851 | return; | ||
852 | } | ||
853 | |||
854 | via_write_reg_mask(VIASR, 0x2A, value, 0x03); | ||
855 | } | ||
856 | |||
857 | static void set_lvds2_state(u8 state) | ||
858 | { | ||
859 | u8 value; | ||
860 | |||
861 | switch (state) { | ||
862 | case VIA_STATE_ON: | ||
863 | value = 0x0C; | ||
864 | break; | ||
865 | case VIA_STATE_OFF: | ||
866 | value = 0x00; | ||
867 | break; | ||
868 | default: | ||
869 | return; | ||
870 | } | ||
871 | |||
872 | via_write_reg_mask(VIASR, 0x2A, value, 0x0C); | ||
873 | } | ||
874 | |||
875 | void via_set_state(u32 devices, u8 state) | ||
876 | { | ||
877 | /* | ||
878 | TODO: Can we enable/disable these devices? How? | ||
879 | if (devices & VIA_LDVP0) | ||
880 | if (devices & VIA_LDVP1) | ||
881 | */ | ||
882 | if (devices & VIA_DVP0) | ||
883 | set_dvp0_state(state); | ||
884 | if (devices & VIA_CRT) | ||
885 | set_crt_state(state); | ||
886 | if (devices & VIA_DVP1) | ||
887 | set_dvp1_state(state); | ||
888 | if (devices & VIA_LVDS1) | ||
889 | set_lvds1_state(state); | ||
890 | if (devices & VIA_LVDS2) | ||
891 | set_lvds2_state(state); | ||
892 | } | ||
893 | |||
894 | void via_set_sync_polarity(u32 devices, u8 polarity) | ||
895 | { | ||
896 | if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) { | ||
897 | printk(KERN_WARNING "viafb: Unsupported polarity: %d\n", | ||
898 | polarity); | ||
899 | return; | ||
900 | } | ||
901 | |||
902 | if (devices & VIA_CRT) | ||
903 | via_write_misc_reg_mask(polarity << 6, 0xC0); | ||
904 | if (devices & VIA_DVP1) | ||
905 | via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60); | ||
906 | if (devices & VIA_LVDS1) | ||
907 | via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60); | ||
908 | if (devices & VIA_LVDS2) | ||
909 | via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60); | ||
910 | } | ||
911 | |||
912 | u32 via_parse_odev(char *input, char **end) | ||
913 | { | ||
914 | char *ptr = input; | ||
915 | u32 odev = 0; | ||
916 | bool next = true; | ||
917 | int i, len; | ||
918 | |||
919 | while (next) { | ||
920 | next = false; | ||
921 | for (i = 0; i < ARRAY_SIZE(device_mapping); i++) { | ||
922 | len = strlen(device_mapping[i].name); | ||
923 | if (!strncmp(ptr, device_mapping[i].name, len)) { | ||
924 | odev |= device_mapping[i].device; | ||
925 | ptr += len; | ||
926 | if (*ptr == ',') { | ||
927 | ptr++; | ||
928 | next = true; | ||
929 | } | ||
930 | } | ||
931 | } | ||
932 | } | ||
933 | |||
934 | *end = ptr; | ||
935 | return odev; | ||
936 | } | ||
937 | |||
938 | void via_odev_to_seq(struct seq_file *m, u32 odev) | ||
939 | { | ||
940 | int i, count = 0; | ||
941 | |||
942 | for (i = 0; i < ARRAY_SIZE(device_mapping); i++) { | ||
943 | if (odev & device_mapping[i].device) { | ||
944 | if (count > 0) | ||
945 | seq_putc(m, ','); | ||
946 | |||
947 | seq_puts(m, device_mapping[i].name); | ||
948 | count++; | ||
949 | } | ||
950 | } | ||
951 | |||
952 | seq_putc(m, '\n'); | ||
953 | } | ||
954 | |||
955 | static void load_fix_bit_crtc_reg(void) | ||
956 | { | ||
957 | viafb_unlock_crt(); | ||
958 | |||
959 | /* always set to 1 */ | ||
960 | viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7); | ||
961 | /* line compare should set all bits = 1 (extend modes) */ | ||
962 | viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4); | ||
963 | /* line compare should set all bits = 1 (extend modes) */ | ||
964 | viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2); | ||
965 | /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */ | ||
966 | |||
967 | viafb_lock_crt(); | ||
968 | |||
969 | /* If K8M800, enable Prefetch Mode. */ | ||
970 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) | ||
971 | || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890)) | ||
972 | viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3); | ||
973 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) | ||
974 | && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX)) | ||
975 | viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1); | ||
976 | |||
977 | } | ||
978 | |||
979 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, | ||
980 | struct io_register *reg, | ||
981 | int io_type) | ||
982 | { | ||
983 | int reg_mask; | ||
984 | int bit_num = 0; | ||
985 | int data; | ||
986 | int i, j; | ||
987 | int shift_next_reg; | ||
988 | int start_index, end_index, cr_index; | ||
989 | u16 get_bit; | ||
990 | |||
991 | for (i = 0; i < viafb_load_reg_num; i++) { | ||
992 | reg_mask = 0; | ||
993 | data = 0; | ||
994 | start_index = reg[i].start_bit; | ||
995 | end_index = reg[i].end_bit; | ||
996 | cr_index = reg[i].io_addr; | ||
997 | |||
998 | shift_next_reg = bit_num; | ||
999 | for (j = start_index; j <= end_index; j++) { | ||
1000 | /*if (bit_num==8) timing_value = timing_value >>8; */ | ||
1001 | reg_mask = reg_mask | (BIT0 << j); | ||
1002 | get_bit = (timing_value & (BIT0 << bit_num)); | ||
1003 | data = | ||
1004 | data | ((get_bit >> shift_next_reg) << start_index); | ||
1005 | bit_num++; | ||
1006 | } | ||
1007 | if (io_type == VIACR) | ||
1008 | viafb_write_reg_mask(cr_index, VIACR, data, reg_mask); | ||
1009 | else | ||
1010 | viafb_write_reg_mask(cr_index, VIASR, data, reg_mask); | ||
1011 | } | ||
1012 | |||
1013 | } | ||
1014 | |||
1015 | /* Write Registers */ | ||
1016 | void viafb_write_regx(struct io_reg RegTable[], int ItemNum) | ||
1017 | { | ||
1018 | int i; | ||
1019 | |||
1020 | /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */ | ||
1021 | |||
1022 | for (i = 0; i < ItemNum; i++) | ||
1023 | via_write_reg_mask(RegTable[i].port, RegTable[i].index, | ||
1024 | RegTable[i].value, RegTable[i].mask); | ||
1025 | } | ||
1026 | |||
1027 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) | ||
1028 | { | ||
1029 | int reg_value; | ||
1030 | int viafb_load_reg_num; | ||
1031 | struct io_register *reg = NULL; | ||
1032 | |||
1033 | switch (set_iga) { | ||
1034 | case IGA1: | ||
1035 | reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte); | ||
1036 | viafb_load_reg_num = fetch_count_reg. | ||
1037 | iga1_fetch_count_reg.reg_num; | ||
1038 | reg = fetch_count_reg.iga1_fetch_count_reg.reg; | ||
1039 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1040 | break; | ||
1041 | case IGA2: | ||
1042 | reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte); | ||
1043 | viafb_load_reg_num = fetch_count_reg. | ||
1044 | iga2_fetch_count_reg.reg_num; | ||
1045 | reg = fetch_count_reg.iga2_fetch_count_reg.reg; | ||
1046 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1047 | break; | ||
1048 | } | ||
1049 | |||
1050 | } | ||
1051 | |||
1052 | void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active) | ||
1053 | { | ||
1054 | int reg_value; | ||
1055 | int viafb_load_reg_num; | ||
1056 | struct io_register *reg = NULL; | ||
1057 | int iga1_fifo_max_depth = 0, iga1_fifo_threshold = | ||
1058 | 0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0; | ||
1059 | int iga2_fifo_max_depth = 0, iga2_fifo_threshold = | ||
1060 | 0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0; | ||
1061 | |||
1062 | if (set_iga == IGA1) { | ||
1063 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { | ||
1064 | iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH; | ||
1065 | iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD; | ||
1066 | iga1_fifo_high_threshold = | ||
1067 | K800_IGA1_FIFO_HIGH_THRESHOLD; | ||
1068 | /* If resolution > 1280x1024, expire length = 64, else | ||
1069 | expire length = 128 */ | ||
1070 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1071 | iga1_display_queue_expire_num = 16; | ||
1072 | else | ||
1073 | iga1_display_queue_expire_num = | ||
1074 | K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1075 | |||
1076 | } | ||
1077 | |||
1078 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) { | ||
1079 | iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH; | ||
1080 | iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD; | ||
1081 | iga1_fifo_high_threshold = | ||
1082 | P880_IGA1_FIFO_HIGH_THRESHOLD; | ||
1083 | iga1_display_queue_expire_num = | ||
1084 | P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1085 | |||
1086 | /* If resolution > 1280x1024, expire length = 64, else | ||
1087 | expire length = 128 */ | ||
1088 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1089 | iga1_display_queue_expire_num = 16; | ||
1090 | else | ||
1091 | iga1_display_queue_expire_num = | ||
1092 | P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1093 | } | ||
1094 | |||
1095 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) { | ||
1096 | iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH; | ||
1097 | iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD; | ||
1098 | iga1_fifo_high_threshold = | ||
1099 | CN700_IGA1_FIFO_HIGH_THRESHOLD; | ||
1100 | |||
1101 | /* If resolution > 1280x1024, expire length = 64, | ||
1102 | else expire length = 128 */ | ||
1103 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1104 | iga1_display_queue_expire_num = 16; | ||
1105 | else | ||
1106 | iga1_display_queue_expire_num = | ||
1107 | CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1108 | } | ||
1109 | |||
1110 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
1111 | iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH; | ||
1112 | iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD; | ||
1113 | iga1_fifo_high_threshold = | ||
1114 | CX700_IGA1_FIFO_HIGH_THRESHOLD; | ||
1115 | iga1_display_queue_expire_num = | ||
1116 | CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1117 | } | ||
1118 | |||
1119 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) { | ||
1120 | iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH; | ||
1121 | iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD; | ||
1122 | iga1_fifo_high_threshold = | ||
1123 | K8M890_IGA1_FIFO_HIGH_THRESHOLD; | ||
1124 | iga1_display_queue_expire_num = | ||
1125 | K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1126 | } | ||
1127 | |||
1128 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) { | ||
1129 | iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH; | ||
1130 | iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD; | ||
1131 | iga1_fifo_high_threshold = | ||
1132 | P4M890_IGA1_FIFO_HIGH_THRESHOLD; | ||
1133 | iga1_display_queue_expire_num = | ||
1134 | P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1135 | } | ||
1136 | |||
1137 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) { | ||
1138 | iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH; | ||
1139 | iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD; | ||
1140 | iga1_fifo_high_threshold = | ||
1141 | P4M900_IGA1_FIFO_HIGH_THRESHOLD; | ||
1142 | iga1_display_queue_expire_num = | ||
1143 | P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1144 | } | ||
1145 | |||
1146 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) { | ||
1147 | iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH; | ||
1148 | iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD; | ||
1149 | iga1_fifo_high_threshold = | ||
1150 | VX800_IGA1_FIFO_HIGH_THRESHOLD; | ||
1151 | iga1_display_queue_expire_num = | ||
1152 | VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1153 | } | ||
1154 | |||
1155 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) { | ||
1156 | iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH; | ||
1157 | iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD; | ||
1158 | iga1_fifo_high_threshold = | ||
1159 | VX855_IGA1_FIFO_HIGH_THRESHOLD; | ||
1160 | iga1_display_queue_expire_num = | ||
1161 | VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1162 | } | ||
1163 | |||
1164 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) { | ||
1165 | iga1_fifo_max_depth = VX900_IGA1_FIFO_MAX_DEPTH; | ||
1166 | iga1_fifo_threshold = VX900_IGA1_FIFO_THRESHOLD; | ||
1167 | iga1_fifo_high_threshold = | ||
1168 | VX900_IGA1_FIFO_HIGH_THRESHOLD; | ||
1169 | iga1_display_queue_expire_num = | ||
1170 | VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1171 | } | ||
1172 | |||
1173 | /* Set Display FIFO Depath Select */ | ||
1174 | reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth); | ||
1175 | viafb_load_reg_num = | ||
1176 | display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num; | ||
1177 | reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg; | ||
1178 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1179 | |||
1180 | /* Set Display FIFO Threshold Select */ | ||
1181 | reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold); | ||
1182 | viafb_load_reg_num = | ||
1183 | fifo_threshold_select_reg. | ||
1184 | iga1_fifo_threshold_select_reg.reg_num; | ||
1185 | reg = | ||
1186 | fifo_threshold_select_reg. | ||
1187 | iga1_fifo_threshold_select_reg.reg; | ||
1188 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1189 | |||
1190 | /* Set FIFO High Threshold Select */ | ||
1191 | reg_value = | ||
1192 | IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold); | ||
1193 | viafb_load_reg_num = | ||
1194 | fifo_high_threshold_select_reg. | ||
1195 | iga1_fifo_high_threshold_select_reg.reg_num; | ||
1196 | reg = | ||
1197 | fifo_high_threshold_select_reg. | ||
1198 | iga1_fifo_high_threshold_select_reg.reg; | ||
1199 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1200 | |||
1201 | /* Set Display Queue Expire Num */ | ||
1202 | reg_value = | ||
1203 | IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA | ||
1204 | (iga1_display_queue_expire_num); | ||
1205 | viafb_load_reg_num = | ||
1206 | display_queue_expire_num_reg. | ||
1207 | iga1_display_queue_expire_num_reg.reg_num; | ||
1208 | reg = | ||
1209 | display_queue_expire_num_reg. | ||
1210 | iga1_display_queue_expire_num_reg.reg; | ||
1211 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR); | ||
1212 | |||
1213 | } else { | ||
1214 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { | ||
1215 | iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH; | ||
1216 | iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD; | ||
1217 | iga2_fifo_high_threshold = | ||
1218 | K800_IGA2_FIFO_HIGH_THRESHOLD; | ||
1219 | |||
1220 | /* If resolution > 1280x1024, expire length = 64, | ||
1221 | else expire length = 128 */ | ||
1222 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1223 | iga2_display_queue_expire_num = 16; | ||
1224 | else | ||
1225 | iga2_display_queue_expire_num = | ||
1226 | K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1227 | } | ||
1228 | |||
1229 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) { | ||
1230 | iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH; | ||
1231 | iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD; | ||
1232 | iga2_fifo_high_threshold = | ||
1233 | P880_IGA2_FIFO_HIGH_THRESHOLD; | ||
1234 | |||
1235 | /* If resolution > 1280x1024, expire length = 64, | ||
1236 | else expire length = 128 */ | ||
1237 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1238 | iga2_display_queue_expire_num = 16; | ||
1239 | else | ||
1240 | iga2_display_queue_expire_num = | ||
1241 | P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1242 | } | ||
1243 | |||
1244 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) { | ||
1245 | iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH; | ||
1246 | iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD; | ||
1247 | iga2_fifo_high_threshold = | ||
1248 | CN700_IGA2_FIFO_HIGH_THRESHOLD; | ||
1249 | |||
1250 | /* If resolution > 1280x1024, expire length = 64, | ||
1251 | else expire length = 128 */ | ||
1252 | if ((hor_active > 1280) && (ver_active > 1024)) | ||
1253 | iga2_display_queue_expire_num = 16; | ||
1254 | else | ||
1255 | iga2_display_queue_expire_num = | ||
1256 | CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1257 | } | ||
1258 | |||
1259 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
1260 | iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH; | ||
1261 | iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD; | ||
1262 | iga2_fifo_high_threshold = | ||
1263 | CX700_IGA2_FIFO_HIGH_THRESHOLD; | ||
1264 | iga2_display_queue_expire_num = | ||
1265 | CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1266 | } | ||
1267 | |||
1268 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) { | ||
1269 | iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH; | ||
1270 | iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD; | ||
1271 | iga2_fifo_high_threshold = | ||
1272 | K8M890_IGA2_FIFO_HIGH_THRESHOLD; | ||
1273 | iga2_display_queue_expire_num = | ||
1274 | K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1275 | } | ||
1276 | |||
1277 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) { | ||
1278 | iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH; | ||
1279 | iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD; | ||
1280 | iga2_fifo_high_threshold = | ||
1281 | P4M890_IGA2_FIFO_HIGH_THRESHOLD; | ||
1282 | iga2_display_queue_expire_num = | ||
1283 | P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1284 | } | ||
1285 | |||
1286 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) { | ||
1287 | iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH; | ||
1288 | iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD; | ||
1289 | iga2_fifo_high_threshold = | ||
1290 | P4M900_IGA2_FIFO_HIGH_THRESHOLD; | ||
1291 | iga2_display_queue_expire_num = | ||
1292 | P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1293 | } | ||
1294 | |||
1295 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) { | ||
1296 | iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH; | ||
1297 | iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD; | ||
1298 | iga2_fifo_high_threshold = | ||
1299 | VX800_IGA2_FIFO_HIGH_THRESHOLD; | ||
1300 | iga2_display_queue_expire_num = | ||
1301 | VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1302 | } | ||
1303 | |||
1304 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) { | ||
1305 | iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH; | ||
1306 | iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD; | ||
1307 | iga2_fifo_high_threshold = | ||
1308 | VX855_IGA2_FIFO_HIGH_THRESHOLD; | ||
1309 | iga2_display_queue_expire_num = | ||
1310 | VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1311 | } | ||
1312 | |||
1313 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) { | ||
1314 | iga2_fifo_max_depth = VX900_IGA2_FIFO_MAX_DEPTH; | ||
1315 | iga2_fifo_threshold = VX900_IGA2_FIFO_THRESHOLD; | ||
1316 | iga2_fifo_high_threshold = | ||
1317 | VX900_IGA2_FIFO_HIGH_THRESHOLD; | ||
1318 | iga2_display_queue_expire_num = | ||
1319 | VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM; | ||
1320 | } | ||
1321 | |||
1322 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) { | ||
1323 | /* Set Display FIFO Depath Select */ | ||
1324 | reg_value = | ||
1325 | IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth) | ||
1326 | - 1; | ||
1327 | /* Patch LCD in IGA2 case */ | ||
1328 | viafb_load_reg_num = | ||
1329 | display_fifo_depth_reg. | ||
1330 | iga2_fifo_depth_select_reg.reg_num; | ||
1331 | reg = | ||
1332 | display_fifo_depth_reg. | ||
1333 | iga2_fifo_depth_select_reg.reg; | ||
1334 | viafb_load_reg(reg_value, | ||
1335 | viafb_load_reg_num, reg, VIACR); | ||
1336 | } else { | ||
1337 | |||
1338 | /* Set Display FIFO Depath Select */ | ||
1339 | reg_value = | ||
1340 | IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth); | ||
1341 | viafb_load_reg_num = | ||
1342 | display_fifo_depth_reg. | ||
1343 | iga2_fifo_depth_select_reg.reg_num; | ||
1344 | reg = | ||
1345 | display_fifo_depth_reg. | ||
1346 | iga2_fifo_depth_select_reg.reg; | ||
1347 | viafb_load_reg(reg_value, | ||
1348 | viafb_load_reg_num, reg, VIACR); | ||
1349 | } | ||
1350 | |||
1351 | /* Set Display FIFO Threshold Select */ | ||
1352 | reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold); | ||
1353 | viafb_load_reg_num = | ||
1354 | fifo_threshold_select_reg. | ||
1355 | iga2_fifo_threshold_select_reg.reg_num; | ||
1356 | reg = | ||
1357 | fifo_threshold_select_reg. | ||
1358 | iga2_fifo_threshold_select_reg.reg; | ||
1359 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1360 | |||
1361 | /* Set FIFO High Threshold Select */ | ||
1362 | reg_value = | ||
1363 | IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold); | ||
1364 | viafb_load_reg_num = | ||
1365 | fifo_high_threshold_select_reg. | ||
1366 | iga2_fifo_high_threshold_select_reg.reg_num; | ||
1367 | reg = | ||
1368 | fifo_high_threshold_select_reg. | ||
1369 | iga2_fifo_high_threshold_select_reg.reg; | ||
1370 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1371 | |||
1372 | /* Set Display Queue Expire Num */ | ||
1373 | reg_value = | ||
1374 | IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA | ||
1375 | (iga2_display_queue_expire_num); | ||
1376 | viafb_load_reg_num = | ||
1377 | display_queue_expire_num_reg. | ||
1378 | iga2_display_queue_expire_num_reg.reg_num; | ||
1379 | reg = | ||
1380 | display_queue_expire_num_reg. | ||
1381 | iga2_display_queue_expire_num_reg.reg; | ||
1382 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
1383 | |||
1384 | } | ||
1385 | |||
1386 | } | ||
1387 | |||
1388 | static struct via_pll_config get_pll_config(struct pll_limit *limits, int size, | ||
1389 | int clk) | ||
1390 | { | ||
1391 | struct via_pll_config cur, up, down, best = {0, 1, 0}; | ||
1392 | const u32 f0 = 14318180; /* X1 frequency */ | ||
1393 | int i, f; | ||
1394 | |||
1395 | for (i = 0; i < size; i++) { | ||
1396 | cur.rshift = limits[i].rshift; | ||
1397 | cur.divisor = limits[i].divisor; | ||
1398 | cur.multiplier = clk / ((f0 / cur.divisor)>>cur.rshift); | ||
1399 | f = abs(get_pll_output_frequency(f0, cur) - clk); | ||
1400 | up = down = cur; | ||
1401 | up.multiplier++; | ||
1402 | down.multiplier--; | ||
1403 | if (abs(get_pll_output_frequency(f0, up) - clk) < f) | ||
1404 | cur = up; | ||
1405 | else if (abs(get_pll_output_frequency(f0, down) - clk) < f) | ||
1406 | cur = down; | ||
1407 | |||
1408 | if (cur.multiplier < limits[i].multiplier_min) | ||
1409 | cur.multiplier = limits[i].multiplier_min; | ||
1410 | else if (cur.multiplier > limits[i].multiplier_max) | ||
1411 | cur.multiplier = limits[i].multiplier_max; | ||
1412 | |||
1413 | f = abs(get_pll_output_frequency(f0, cur) - clk); | ||
1414 | if (f < abs(get_pll_output_frequency(f0, best) - clk)) | ||
1415 | best = cur; | ||
1416 | } | ||
1417 | |||
1418 | return best; | ||
1419 | } | ||
1420 | |||
1421 | static struct via_pll_config get_best_pll_config(int clk) | ||
1422 | { | ||
1423 | struct via_pll_config config; | ||
1424 | |||
1425 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1426 | case UNICHROME_CLE266: | ||
1427 | case UNICHROME_K400: | ||
1428 | config = get_pll_config(cle266_pll_limits, | ||
1429 | ARRAY_SIZE(cle266_pll_limits), clk); | ||
1430 | break; | ||
1431 | case UNICHROME_K800: | ||
1432 | case UNICHROME_PM800: | ||
1433 | case UNICHROME_CN700: | ||
1434 | config = get_pll_config(k800_pll_limits, | ||
1435 | ARRAY_SIZE(k800_pll_limits), clk); | ||
1436 | break; | ||
1437 | case UNICHROME_CX700: | ||
1438 | case UNICHROME_CN750: | ||
1439 | case UNICHROME_K8M890: | ||
1440 | case UNICHROME_P4M890: | ||
1441 | case UNICHROME_P4M900: | ||
1442 | case UNICHROME_VX800: | ||
1443 | config = get_pll_config(cx700_pll_limits, | ||
1444 | ARRAY_SIZE(cx700_pll_limits), clk); | ||
1445 | break; | ||
1446 | case UNICHROME_VX855: | ||
1447 | case UNICHROME_VX900: | ||
1448 | config = get_pll_config(vx855_pll_limits, | ||
1449 | ARRAY_SIZE(vx855_pll_limits), clk); | ||
1450 | break; | ||
1451 | } | ||
1452 | |||
1453 | return config; | ||
1454 | } | ||
1455 | |||
1456 | /* Set VCLK*/ | ||
1457 | void viafb_set_vclock(u32 clk, int set_iga) | ||
1458 | { | ||
1459 | struct via_pll_config config = get_best_pll_config(clk); | ||
1460 | |||
1461 | if (set_iga == IGA1) | ||
1462 | clock.set_primary_pll(config); | ||
1463 | if (set_iga == IGA2) | ||
1464 | clock.set_secondary_pll(config); | ||
1465 | |||
1466 | /* Fire! */ | ||
1467 | via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ | ||
1468 | } | ||
1469 | |||
1470 | struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var, | ||
1471 | u16 cxres, u16 cyres) | ||
1472 | { | ||
1473 | struct via_display_timing timing; | ||
1474 | u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2; | ||
1475 | |||
1476 | timing.hor_addr = cxres; | ||
1477 | timing.hor_sync_start = timing.hor_addr + var->right_margin + dx; | ||
1478 | timing.hor_sync_end = timing.hor_sync_start + var->hsync_len; | ||
1479 | timing.hor_total = timing.hor_sync_end + var->left_margin + dx; | ||
1480 | timing.hor_blank_start = timing.hor_addr + dx; | ||
1481 | timing.hor_blank_end = timing.hor_total - dx; | ||
1482 | timing.ver_addr = cyres; | ||
1483 | timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy; | ||
1484 | timing.ver_sync_end = timing.ver_sync_start + var->vsync_len; | ||
1485 | timing.ver_total = timing.ver_sync_end + var->upper_margin + dy; | ||
1486 | timing.ver_blank_start = timing.ver_addr + dy; | ||
1487 | timing.ver_blank_end = timing.ver_total - dy; | ||
1488 | return timing; | ||
1489 | } | ||
1490 | |||
1491 | void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, | ||
1492 | u16 cxres, u16 cyres, int iga) | ||
1493 | { | ||
1494 | struct via_display_timing crt_reg = var_to_timing(var, | ||
1495 | cxres ? cxres : var->xres, cyres ? cyres : var->yres); | ||
1496 | |||
1497 | if (iga == IGA1) | ||
1498 | via_set_primary_timing(&crt_reg); | ||
1499 | else if (iga == IGA2) | ||
1500 | via_set_secondary_timing(&crt_reg); | ||
1501 | |||
1502 | viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga); | ||
1503 | if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266 | ||
1504 | && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400) | ||
1505 | viafb_load_FIFO_reg(iga, var->xres, var->yres); | ||
1506 | |||
1507 | viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga); | ||
1508 | } | ||
1509 | |||
1510 | void viafb_init_chip_info(int chip_type) | ||
1511 | { | ||
1512 | via_clock_init(&clock, chip_type); | ||
1513 | init_gfx_chip_info(chip_type); | ||
1514 | init_tmds_chip_info(); | ||
1515 | init_lvds_chip_info(); | ||
1516 | |||
1517 | /*Set IGA path for each device */ | ||
1518 | viafb_set_iga_path(); | ||
1519 | |||
1520 | viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method; | ||
1521 | viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode; | ||
1522 | viaparinfo->lvds_setting_info2->display_method = | ||
1523 | viaparinfo->lvds_setting_info->display_method; | ||
1524 | viaparinfo->lvds_setting_info2->lcd_mode = | ||
1525 | viaparinfo->lvds_setting_info->lcd_mode; | ||
1526 | } | ||
1527 | |||
1528 | void viafb_update_device_setting(int hres, int vres, int bpp, int flag) | ||
1529 | { | ||
1530 | if (flag == 0) { | ||
1531 | viaparinfo->tmds_setting_info->h_active = hres; | ||
1532 | viaparinfo->tmds_setting_info->v_active = vres; | ||
1533 | } else { | ||
1534 | |||
1535 | if (viaparinfo->tmds_setting_info->iga_path == IGA2) { | ||
1536 | viaparinfo->tmds_setting_info->h_active = hres; | ||
1537 | viaparinfo->tmds_setting_info->v_active = vres; | ||
1538 | } | ||
1539 | |||
1540 | } | ||
1541 | } | ||
1542 | |||
1543 | static void init_gfx_chip_info(int chip_type) | ||
1544 | { | ||
1545 | u8 tmp; | ||
1546 | |||
1547 | viaparinfo->chip_info->gfx_chip_name = chip_type; | ||
1548 | |||
1549 | /* Check revision of CLE266 Chip */ | ||
1550 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | ||
1551 | /* CR4F only define in CLE266.CX chip */ | ||
1552 | tmp = viafb_read_reg(VIACR, CR4F); | ||
1553 | viafb_write_reg(CR4F, VIACR, 0x55); | ||
1554 | if (viafb_read_reg(VIACR, CR4F) != 0x55) | ||
1555 | viaparinfo->chip_info->gfx_chip_revision = | ||
1556 | CLE266_REVISION_AX; | ||
1557 | else | ||
1558 | viaparinfo->chip_info->gfx_chip_revision = | ||
1559 | CLE266_REVISION_CX; | ||
1560 | /* restore orignal CR4F value */ | ||
1561 | viafb_write_reg(CR4F, VIACR, tmp); | ||
1562 | } | ||
1563 | |||
1564 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { | ||
1565 | tmp = viafb_read_reg(VIASR, SR43); | ||
1566 | DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp); | ||
1567 | if (tmp & 0x02) { | ||
1568 | viaparinfo->chip_info->gfx_chip_revision = | ||
1569 | CX700_REVISION_700M2; | ||
1570 | } else if (tmp & 0x40) { | ||
1571 | viaparinfo->chip_info->gfx_chip_revision = | ||
1572 | CX700_REVISION_700M; | ||
1573 | } else { | ||
1574 | viaparinfo->chip_info->gfx_chip_revision = | ||
1575 | CX700_REVISION_700; | ||
1576 | } | ||
1577 | } | ||
1578 | |||
1579 | /* Determine which 2D engine we have */ | ||
1580 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1581 | case UNICHROME_VX800: | ||
1582 | case UNICHROME_VX855: | ||
1583 | case UNICHROME_VX900: | ||
1584 | viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1; | ||
1585 | break; | ||
1586 | case UNICHROME_K8M890: | ||
1587 | case UNICHROME_P4M900: | ||
1588 | viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5; | ||
1589 | break; | ||
1590 | default: | ||
1591 | viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2; | ||
1592 | break; | ||
1593 | } | ||
1594 | } | ||
1595 | |||
1596 | static void init_tmds_chip_info(void) | ||
1597 | { | ||
1598 | viafb_tmds_trasmitter_identify(); | ||
1599 | |||
1600 | if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info. | ||
1601 | output_interface) { | ||
1602 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1603 | case UNICHROME_CX700: | ||
1604 | { | ||
1605 | /* we should check support by hardware layout.*/ | ||
1606 | if ((viafb_display_hardware_layout == | ||
1607 | HW_LAYOUT_DVI_ONLY) | ||
1608 | || (viafb_display_hardware_layout == | ||
1609 | HW_LAYOUT_LCD_DVI)) { | ||
1610 | viaparinfo->chip_info->tmds_chip_info. | ||
1611 | output_interface = INTERFACE_TMDS; | ||
1612 | } else { | ||
1613 | viaparinfo->chip_info->tmds_chip_info. | ||
1614 | output_interface = | ||
1615 | INTERFACE_NONE; | ||
1616 | } | ||
1617 | break; | ||
1618 | } | ||
1619 | case UNICHROME_K8M890: | ||
1620 | case UNICHROME_P4M900: | ||
1621 | case UNICHROME_P4M890: | ||
1622 | /* TMDS on PCIE, we set DFPLOW as default. */ | ||
1623 | viaparinfo->chip_info->tmds_chip_info.output_interface = | ||
1624 | INTERFACE_DFP_LOW; | ||
1625 | break; | ||
1626 | default: | ||
1627 | { | ||
1628 | /* set DVP1 default for DVI */ | ||
1629 | viaparinfo->chip_info->tmds_chip_info | ||
1630 | .output_interface = INTERFACE_DVP1; | ||
1631 | } | ||
1632 | } | ||
1633 | } | ||
1634 | |||
1635 | DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n", | ||
1636 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); | ||
1637 | viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info, | ||
1638 | &viaparinfo->shared->tmds_setting_info); | ||
1639 | } | ||
1640 | |||
1641 | static void init_lvds_chip_info(void) | ||
1642 | { | ||
1643 | viafb_lvds_trasmitter_identify(); | ||
1644 | viafb_init_lcd_size(); | ||
1645 | viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info, | ||
1646 | viaparinfo->lvds_setting_info); | ||
1647 | if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { | ||
1648 | viafb_init_lvds_output_interface(&viaparinfo->chip_info-> | ||
1649 | lvds_chip_info2, viaparinfo->lvds_setting_info2); | ||
1650 | } | ||
1651 | /*If CX700,two singel LCD, we need to reassign | ||
1652 | LCD interface to different LVDS port */ | ||
1653 | if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name) | ||
1654 | && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) { | ||
1655 | if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info. | ||
1656 | lvds_chip_name) && (INTEGRATED_LVDS == | ||
1657 | viaparinfo->chip_info-> | ||
1658 | lvds_chip_info2.lvds_chip_name)) { | ||
1659 | viaparinfo->chip_info->lvds_chip_info.output_interface = | ||
1660 | INTERFACE_LVDS0; | ||
1661 | viaparinfo->chip_info->lvds_chip_info2. | ||
1662 | output_interface = | ||
1663 | INTERFACE_LVDS1; | ||
1664 | } | ||
1665 | } | ||
1666 | |||
1667 | DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n", | ||
1668 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name); | ||
1669 | DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n", | ||
1670 | viaparinfo->chip_info->lvds_chip_info.output_interface); | ||
1671 | DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n", | ||
1672 | viaparinfo->chip_info->lvds_chip_info.output_interface); | ||
1673 | } | ||
1674 | |||
1675 | void viafb_init_dac(int set_iga) | ||
1676 | { | ||
1677 | int i; | ||
1678 | u8 tmp; | ||
1679 | |||
1680 | if (set_iga == IGA1) { | ||
1681 | /* access Primary Display's LUT */ | ||
1682 | viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0); | ||
1683 | /* turn off LCK */ | ||
1684 | viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6); | ||
1685 | for (i = 0; i < 256; i++) { | ||
1686 | write_dac_reg(i, palLUT_table[i].red, | ||
1687 | palLUT_table[i].green, | ||
1688 | palLUT_table[i].blue); | ||
1689 | } | ||
1690 | /* turn on LCK */ | ||
1691 | viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6); | ||
1692 | } else { | ||
1693 | tmp = viafb_read_reg(VIACR, CR6A); | ||
1694 | /* access Secondary Display's LUT */ | ||
1695 | viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6); | ||
1696 | viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0); | ||
1697 | for (i = 0; i < 256; i++) { | ||
1698 | write_dac_reg(i, palLUT_table[i].red, | ||
1699 | palLUT_table[i].green, | ||
1700 | palLUT_table[i].blue); | ||
1701 | } | ||
1702 | /* set IGA1 DAC for default */ | ||
1703 | viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0); | ||
1704 | viafb_write_reg(CR6A, VIACR, tmp); | ||
1705 | } | ||
1706 | } | ||
1707 | |||
1708 | static void device_screen_off(void) | ||
1709 | { | ||
1710 | /* turn off CRT screen (IGA1) */ | ||
1711 | viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5); | ||
1712 | } | ||
1713 | |||
1714 | static void device_screen_on(void) | ||
1715 | { | ||
1716 | /* turn on CRT screen (IGA1) */ | ||
1717 | viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5); | ||
1718 | } | ||
1719 | |||
1720 | static void set_display_channel(void) | ||
1721 | { | ||
1722 | /*If viafb_LCD2_ON, on cx700, internal lvds's information | ||
1723 | is keeped on lvds_setting_info2 */ | ||
1724 | if (viafb_LCD2_ON && | ||
1725 | viaparinfo->lvds_setting_info2->device_lcd_dualedge) { | ||
1726 | /* For dual channel LCD: */ | ||
1727 | /* Set to Dual LVDS channel. */ | ||
1728 | viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5); | ||
1729 | } else if (viafb_LCD_ON && viafb_DVI_ON) { | ||
1730 | /* For LCD+DFP: */ | ||
1731 | /* Set to LVDS1 + TMDS channel. */ | ||
1732 | viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5); | ||
1733 | } else if (viafb_DVI_ON) { | ||
1734 | /* Set to single TMDS channel. */ | ||
1735 | viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5); | ||
1736 | } else if (viafb_LCD_ON) { | ||
1737 | if (viaparinfo->lvds_setting_info->device_lcd_dualedge) { | ||
1738 | /* For dual channel LCD: */ | ||
1739 | /* Set to Dual LVDS channel. */ | ||
1740 | viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5); | ||
1741 | } else { | ||
1742 | /* Set to LVDS0 + LVDS1 channel. */ | ||
1743 | viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5); | ||
1744 | } | ||
1745 | } | ||
1746 | } | ||
1747 | |||
1748 | static u8 get_sync(struct fb_var_screeninfo *var) | ||
1749 | { | ||
1750 | u8 polarity = 0; | ||
1751 | |||
1752 | if (!(var->sync & FB_SYNC_HOR_HIGH_ACT)) | ||
1753 | polarity |= VIA_HSYNC_NEGATIVE; | ||
1754 | if (!(var->sync & FB_SYNC_VERT_HIGH_ACT)) | ||
1755 | polarity |= VIA_VSYNC_NEGATIVE; | ||
1756 | return polarity; | ||
1757 | } | ||
1758 | |||
1759 | static void hw_init(void) | ||
1760 | { | ||
1761 | int i; | ||
1762 | |||
1763 | inb(VIAStatus); | ||
1764 | outb(0x00, VIAAR); | ||
1765 | |||
1766 | /* Write Common Setting for Video Mode */ | ||
1767 | viafb_write_regx(common_vga, ARRAY_SIZE(common_vga)); | ||
1768 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1769 | case UNICHROME_CLE266: | ||
1770 | viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs); | ||
1771 | break; | ||
1772 | |||
1773 | case UNICHROME_K400: | ||
1774 | viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs); | ||
1775 | break; | ||
1776 | |||
1777 | case UNICHROME_K800: | ||
1778 | case UNICHROME_PM800: | ||
1779 | viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs); | ||
1780 | break; | ||
1781 | |||
1782 | case UNICHROME_CN700: | ||
1783 | case UNICHROME_K8M890: | ||
1784 | case UNICHROME_P4M890: | ||
1785 | case UNICHROME_P4M900: | ||
1786 | viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs); | ||
1787 | break; | ||
1788 | |||
1789 | case UNICHROME_CX700: | ||
1790 | case UNICHROME_VX800: | ||
1791 | viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs); | ||
1792 | break; | ||
1793 | |||
1794 | case UNICHROME_VX855: | ||
1795 | case UNICHROME_VX900: | ||
1796 | viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs); | ||
1797 | break; | ||
1798 | } | ||
1799 | |||
1800 | /* magic required on VX900 for correct modesetting on IGA1 */ | ||
1801 | via_write_reg_mask(VIACR, 0x45, 0x00, 0x01); | ||
1802 | |||
1803 | /* probably this should go to the scaling code one day */ | ||
1804 | via_write_reg_mask(VIACR, 0xFD, 0, 0x80); /* VX900 hw scale on IGA2 */ | ||
1805 | viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters)); | ||
1806 | |||
1807 | /* Fill VPIT Parameters */ | ||
1808 | /* Write Misc Register */ | ||
1809 | outb(VPIT.Misc, VIA_MISC_REG_WRITE); | ||
1810 | |||
1811 | /* Write Sequencer */ | ||
1812 | for (i = 1; i <= StdSR; i++) | ||
1813 | via_write_reg(VIASR, i, VPIT.SR[i - 1]); | ||
1814 | |||
1815 | viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2); | ||
1816 | |||
1817 | /* Write Graphic Controller */ | ||
1818 | for (i = 0; i < StdGR; i++) | ||
1819 | via_write_reg(VIAGR, i, VPIT.GR[i]); | ||
1820 | |||
1821 | /* Write Attribute Controller */ | ||
1822 | for (i = 0; i < StdAR; i++) { | ||
1823 | inb(VIAStatus); | ||
1824 | outb(i, VIAAR); | ||
1825 | outb(VPIT.AR[i], VIAAR); | ||
1826 | } | ||
1827 | |||
1828 | inb(VIAStatus); | ||
1829 | outb(0x20, VIAAR); | ||
1830 | |||
1831 | load_fix_bit_crtc_reg(); | ||
1832 | } | ||
1833 | |||
1834 | int viafb_setmode(void) | ||
1835 | { | ||
1836 | int j, cxres = 0, cyres = 0; | ||
1837 | int port; | ||
1838 | u32 devices = viaparinfo->shared->iga1_devices | ||
1839 | | viaparinfo->shared->iga2_devices; | ||
1840 | u8 value, index, mask; | ||
1841 | struct fb_var_screeninfo var2; | ||
1842 | |||
1843 | device_screen_off(); | ||
1844 | device_off(); | ||
1845 | via_set_state(devices, VIA_STATE_OFF); | ||
1846 | |||
1847 | hw_init(); | ||
1848 | |||
1849 | /* Update Patch Register */ | ||
1850 | |||
1851 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 | ||
1852 | || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) | ||
1853 | && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) { | ||
1854 | for (j = 0; j < res_patch_table[0].table_length; j++) { | ||
1855 | index = res_patch_table[0].io_reg_table[j].index; | ||
1856 | port = res_patch_table[0].io_reg_table[j].port; | ||
1857 | value = res_patch_table[0].io_reg_table[j].value; | ||
1858 | mask = res_patch_table[0].io_reg_table[j].mask; | ||
1859 | viafb_write_reg_mask(index, port, value, mask); | ||
1860 | } | ||
1861 | } | ||
1862 | |||
1863 | via_set_primary_pitch(viafbinfo->fix.line_length); | ||
1864 | via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length | ||
1865 | : viafbinfo->fix.line_length); | ||
1866 | via_set_primary_color_depth(viaparinfo->depth); | ||
1867 | via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth | ||
1868 | : viaparinfo->depth); | ||
1869 | via_set_source(viaparinfo->shared->iga1_devices, IGA1); | ||
1870 | via_set_source(viaparinfo->shared->iga2_devices, IGA2); | ||
1871 | if (viaparinfo->shared->iga2_devices) | ||
1872 | enable_second_display_channel(); | ||
1873 | else | ||
1874 | disable_second_display_channel(); | ||
1875 | |||
1876 | /* Update Refresh Rate Setting */ | ||
1877 | |||
1878 | /* Clear On Screen */ | ||
1879 | |||
1880 | if (viafb_dual_fb) { | ||
1881 | var2 = viafbinfo1->var; | ||
1882 | } else if (viafb_SAMM_ON) { | ||
1883 | viafb_fill_var_timing_info(&var2, viafb_get_best_mode( | ||
1884 | viafb_second_xres, viafb_second_yres, viafb_refresh1)); | ||
1885 | cxres = viafbinfo->var.xres; | ||
1886 | cyres = viafbinfo->var.yres; | ||
1887 | var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; | ||
1888 | } | ||
1889 | |||
1890 | /* CRT set mode */ | ||
1891 | if (viafb_CRT_ON) { | ||
1892 | if (viaparinfo->shared->iga2_devices & VIA_CRT | ||
1893 | && viafb_SAMM_ON) | ||
1894 | viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2); | ||
1895 | else | ||
1896 | viafb_fill_crtc_timing(&viafbinfo->var, 0, 0, | ||
1897 | (viaparinfo->shared->iga1_devices & VIA_CRT) | ||
1898 | ? IGA1 : IGA2); | ||
1899 | |||
1900 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode | ||
1901 | to 8 alignment (1368),there is several pixels (2 pixels) | ||
1902 | on right side of screen. */ | ||
1903 | if (viafbinfo->var.xres % 8) { | ||
1904 | viafb_unlock_crt(); | ||
1905 | viafb_write_reg(CR02, VIACR, | ||
1906 | viafb_read_reg(VIACR, CR02) - 1); | ||
1907 | viafb_lock_crt(); | ||
1908 | } | ||
1909 | } | ||
1910 | |||
1911 | if (viafb_DVI_ON) { | ||
1912 | if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 | ||
1913 | && viafb_SAMM_ON) | ||
1914 | viafb_dvi_set_mode(&var2, cxres, cyres, IGA2); | ||
1915 | else | ||
1916 | viafb_dvi_set_mode(&viafbinfo->var, 0, 0, | ||
1917 | viaparinfo->tmds_setting_info->iga_path); | ||
1918 | } | ||
1919 | |||
1920 | if (viafb_LCD_ON) { | ||
1921 | if (viafb_SAMM_ON && | ||
1922 | (viaparinfo->lvds_setting_info->iga_path == IGA2)) { | ||
1923 | viafb_lcd_set_mode(&var2, cxres, cyres, | ||
1924 | viaparinfo->lvds_setting_info, | ||
1925 | &viaparinfo->chip_info->lvds_chip_info); | ||
1926 | } else { | ||
1927 | /* IGA1 doesn't have LCD scaling, so set it center. */ | ||
1928 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { | ||
1929 | viaparinfo->lvds_setting_info->display_method = | ||
1930 | LCD_CENTERING; | ||
1931 | } | ||
1932 | viafb_lcd_set_mode(&viafbinfo->var, 0, 0, | ||
1933 | viaparinfo->lvds_setting_info, | ||
1934 | &viaparinfo->chip_info->lvds_chip_info); | ||
1935 | } | ||
1936 | } | ||
1937 | if (viafb_LCD2_ON) { | ||
1938 | if (viafb_SAMM_ON && | ||
1939 | (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { | ||
1940 | viafb_lcd_set_mode(&var2, cxres, cyres, | ||
1941 | viaparinfo->lvds_setting_info2, | ||
1942 | &viaparinfo->chip_info->lvds_chip_info2); | ||
1943 | } else { | ||
1944 | /* IGA1 doesn't have LCD scaling, so set it center. */ | ||
1945 | if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { | ||
1946 | viaparinfo->lvds_setting_info2->display_method = | ||
1947 | LCD_CENTERING; | ||
1948 | } | ||
1949 | viafb_lcd_set_mode(&viafbinfo->var, 0, 0, | ||
1950 | viaparinfo->lvds_setting_info2, | ||
1951 | &viaparinfo->chip_info->lvds_chip_info2); | ||
1952 | } | ||
1953 | } | ||
1954 | |||
1955 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) | ||
1956 | && (viafb_LCD_ON || viafb_DVI_ON)) | ||
1957 | set_display_channel(); | ||
1958 | |||
1959 | /* If set mode normally, save resolution information for hot-plug . */ | ||
1960 | if (!viafb_hotplug) { | ||
1961 | viafb_hotplug_Xres = viafbinfo->var.xres; | ||
1962 | viafb_hotplug_Yres = viafbinfo->var.yres; | ||
1963 | viafb_hotplug_bpp = viafbinfo->var.bits_per_pixel; | ||
1964 | viafb_hotplug_refresh = viafb_refresh; | ||
1965 | |||
1966 | if (viafb_DVI_ON) | ||
1967 | viafb_DeviceStatus = DVI_Device; | ||
1968 | else | ||
1969 | viafb_DeviceStatus = CRT_Device; | ||
1970 | } | ||
1971 | device_on(); | ||
1972 | if (!viafb_SAMM_ON) | ||
1973 | via_set_sync_polarity(devices, get_sync(&viafbinfo->var)); | ||
1974 | else { | ||
1975 | via_set_sync_polarity(viaparinfo->shared->iga1_devices, | ||
1976 | get_sync(&viafbinfo->var)); | ||
1977 | via_set_sync_polarity(viaparinfo->shared->iga2_devices, | ||
1978 | get_sync(&var2)); | ||
1979 | } | ||
1980 | |||
1981 | clock.set_engine_pll_state(VIA_STATE_ON); | ||
1982 | clock.set_primary_clock_source(VIA_CLKSRC_X1, true); | ||
1983 | clock.set_secondary_clock_source(VIA_CLKSRC_X1, true); | ||
1984 | |||
1985 | #ifdef CONFIG_FB_VIA_X_COMPATIBILITY | ||
1986 | clock.set_primary_pll_state(VIA_STATE_ON); | ||
1987 | clock.set_primary_clock_state(VIA_STATE_ON); | ||
1988 | clock.set_secondary_pll_state(VIA_STATE_ON); | ||
1989 | clock.set_secondary_clock_state(VIA_STATE_ON); | ||
1990 | #else | ||
1991 | if (viaparinfo->shared->iga1_devices) { | ||
1992 | clock.set_primary_pll_state(VIA_STATE_ON); | ||
1993 | clock.set_primary_clock_state(VIA_STATE_ON); | ||
1994 | } else { | ||
1995 | clock.set_primary_pll_state(VIA_STATE_OFF); | ||
1996 | clock.set_primary_clock_state(VIA_STATE_OFF); | ||
1997 | } | ||
1998 | |||
1999 | if (viaparinfo->shared->iga2_devices) { | ||
2000 | clock.set_secondary_pll_state(VIA_STATE_ON); | ||
2001 | clock.set_secondary_clock_state(VIA_STATE_ON); | ||
2002 | } else { | ||
2003 | clock.set_secondary_pll_state(VIA_STATE_OFF); | ||
2004 | clock.set_secondary_clock_state(VIA_STATE_OFF); | ||
2005 | } | ||
2006 | #endif /*CONFIG_FB_VIA_X_COMPATIBILITY*/ | ||
2007 | |||
2008 | via_set_state(devices, VIA_STATE_ON); | ||
2009 | device_screen_on(); | ||
2010 | return 1; | ||
2011 | } | ||
2012 | |||
2013 | int viafb_get_refresh(int hres, int vres, u32 long_refresh) | ||
2014 | { | ||
2015 | const struct fb_videomode *best; | ||
2016 | |||
2017 | best = viafb_get_best_mode(hres, vres, long_refresh); | ||
2018 | if (!best) | ||
2019 | return 60; | ||
2020 | |||
2021 | if (abs(best->refresh - long_refresh) > 3) { | ||
2022 | if (hres == 1200 && vres == 900) | ||
2023 | return 49; /* OLPC DCON only supports 50 Hz */ | ||
2024 | else | ||
2025 | return 60; | ||
2026 | } | ||
2027 | |||
2028 | return best->refresh; | ||
2029 | } | ||
2030 | |||
2031 | static void device_off(void) | ||
2032 | { | ||
2033 | viafb_dvi_disable(); | ||
2034 | viafb_lcd_disable(); | ||
2035 | } | ||
2036 | |||
2037 | static void device_on(void) | ||
2038 | { | ||
2039 | if (viafb_DVI_ON == 1) | ||
2040 | viafb_dvi_enable(); | ||
2041 | if (viafb_LCD_ON == 1) | ||
2042 | viafb_lcd_enable(); | ||
2043 | } | ||
2044 | |||
2045 | static void enable_second_display_channel(void) | ||
2046 | { | ||
2047 | /* to enable second display channel. */ | ||
2048 | viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6); | ||
2049 | viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7); | ||
2050 | viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); | ||
2051 | } | ||
2052 | |||
2053 | static void disable_second_display_channel(void) | ||
2054 | { | ||
2055 | /* to disable second display channel. */ | ||
2056 | viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6); | ||
2057 | viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7); | ||
2058 | viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); | ||
2059 | } | ||
2060 | |||
2061 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | ||
2062 | *p_gfx_dpa_setting) | ||
2063 | { | ||
2064 | switch (output_interface) { | ||
2065 | case INTERFACE_DVP0: | ||
2066 | { | ||
2067 | /* DVP0 Clock Polarity and Adjust: */ | ||
2068 | viafb_write_reg_mask(CR96, VIACR, | ||
2069 | p_gfx_dpa_setting->DVP0, 0x0F); | ||
2070 | |||
2071 | /* DVP0 Clock and Data Pads Driving: */ | ||
2072 | viafb_write_reg_mask(SR1E, VIASR, | ||
2073 | p_gfx_dpa_setting->DVP0ClockDri_S, BIT2); | ||
2074 | viafb_write_reg_mask(SR2A, VIASR, | ||
2075 | p_gfx_dpa_setting->DVP0ClockDri_S1, | ||
2076 | BIT4); | ||
2077 | viafb_write_reg_mask(SR1B, VIASR, | ||
2078 | p_gfx_dpa_setting->DVP0DataDri_S, BIT1); | ||
2079 | viafb_write_reg_mask(SR2A, VIASR, | ||
2080 | p_gfx_dpa_setting->DVP0DataDri_S1, BIT5); | ||
2081 | break; | ||
2082 | } | ||
2083 | |||
2084 | case INTERFACE_DVP1: | ||
2085 | { | ||
2086 | /* DVP1 Clock Polarity and Adjust: */ | ||
2087 | viafb_write_reg_mask(CR9B, VIACR, | ||
2088 | p_gfx_dpa_setting->DVP1, 0x0F); | ||
2089 | |||
2090 | /* DVP1 Clock and Data Pads Driving: */ | ||
2091 | viafb_write_reg_mask(SR65, VIASR, | ||
2092 | p_gfx_dpa_setting->DVP1Driving, 0x0F); | ||
2093 | break; | ||
2094 | } | ||
2095 | |||
2096 | case INTERFACE_DFP_HIGH: | ||
2097 | { | ||
2098 | viafb_write_reg_mask(CR97, VIACR, | ||
2099 | p_gfx_dpa_setting->DFPHigh, 0x0F); | ||
2100 | break; | ||
2101 | } | ||
2102 | |||
2103 | case INTERFACE_DFP_LOW: | ||
2104 | { | ||
2105 | viafb_write_reg_mask(CR99, VIACR, | ||
2106 | p_gfx_dpa_setting->DFPLow, 0x0F); | ||
2107 | break; | ||
2108 | } | ||
2109 | |||
2110 | case INTERFACE_DFP: | ||
2111 | { | ||
2112 | viafb_write_reg_mask(CR97, VIACR, | ||
2113 | p_gfx_dpa_setting->DFPHigh, 0x0F); | ||
2114 | viafb_write_reg_mask(CR99, VIACR, | ||
2115 | p_gfx_dpa_setting->DFPLow, 0x0F); | ||
2116 | break; | ||
2117 | } | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, | ||
2122 | const struct fb_videomode *mode) | ||
2123 | { | ||
2124 | var->pixclock = mode->pixclock; | ||
2125 | var->xres = mode->xres; | ||
2126 | var->yres = mode->yres; | ||
2127 | var->left_margin = mode->left_margin; | ||
2128 | var->right_margin = mode->right_margin; | ||
2129 | var->hsync_len = mode->hsync_len; | ||
2130 | var->upper_margin = mode->upper_margin; | ||
2131 | var->lower_margin = mode->lower_margin; | ||
2132 | var->vsync_len = mode->vsync_len; | ||
2133 | var->sync = mode->sync; | ||
2134 | } | ||