blob: 56ad185b7b223e70d23481e5eb6783948297132f [file] [log] [blame]
Joseph Chand61e0bf2008-10-15 22:03:23 -07001/*
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 */
Jonathan Corbetec668412010-05-05 14:44:55 -060021
22#include <linux/via-core.h>
Florian Tobias Schandinat32fab7b2011-04-23 22:06:18 +000023#include <asm/olpc.h>
Joseph Chand61e0bf2008-10-15 22:03:23 -070024#include "global.h"
25
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +000026static struct pll_config cle266_pll_config[] = {
27 {19, 4, 0},
28 {26, 5, 0},
29 {28, 5, 0},
30 {31, 5, 0},
31 {33, 5, 0},
32 {55, 5, 0},
33 {102, 5, 0},
34 {53, 6, 0},
35 {92, 6, 0},
36 {98, 6, 0},
37 {112, 6, 0},
38 {41, 7, 0},
39 {60, 7, 0},
40 {99, 7, 0},
41 {100, 7, 0},
42 {83, 8, 0},
43 {86, 8, 0},
44 {108, 8, 0},
45 {87, 9, 0},
46 {118, 9, 0},
47 {95, 12, 0},
48 {115, 12, 0},
49 {108, 13, 0},
50 {83, 17, 0},
51 {67, 20, 0},
52 {86, 20, 0},
53 {98, 20, 0},
54 {121, 24, 0},
55 {99, 29, 0},
56 {33, 3, 1},
57 {15, 4, 1},
58 {23, 4, 1},
59 {37, 5, 1},
60 {83, 5, 1},
61 {85, 5, 1},
62 {94, 5, 1},
63 {103, 5, 1},
64 {109, 5, 1},
65 {113, 5, 1},
66 {121, 5, 1},
67 {82, 6, 1},
68 {31, 7, 1},
69 {55, 7, 1},
70 {84, 7, 1},
71 {83, 8, 1},
72 {76, 9, 1},
73 {127, 9, 1},
74 {33, 4, 2},
75 {75, 4, 2},
76 {119, 4, 2},
77 {121, 4, 2},
78 {91, 5, 2},
79 {118, 5, 2},
80 {83, 6, 2},
81 {109, 6, 2},
82 {90, 7, 2},
83 {93, 2, 3},
84 {53, 3, 3},
85 {73, 4, 3},
86 {89, 4, 3},
87 {105, 4, 3},
88 {117, 4, 3},
89 {101, 5, 3},
90 {121, 5, 3},
91 {127, 5, 3},
92 {99, 7, 3}
93};
94
95static struct pll_config k800_pll_config[] = {
96 {22, 2, 0},
97 {28, 3, 0},
98 {81, 3, 1},
99 {85, 3, 1},
100 {98, 3, 1},
101 {112, 3, 1},
102 {86, 4, 1},
103 {166, 4, 1},
104 {109, 5, 1},
105 {113, 5, 1},
106 {121, 5, 1},
107 {131, 5, 1},
108 {143, 5, 1},
109 {153, 5, 1},
110 {66, 3, 2},
111 {68, 3, 2},
112 {95, 3, 2},
113 {106, 3, 2},
114 {116, 3, 2},
115 {93, 4, 2},
116 {119, 4, 2},
117 {121, 4, 2},
118 {133, 4, 2},
119 {137, 4, 2},
120 {117, 5, 2},
121 {118, 5, 2},
122 {120, 5, 2},
123 {124, 5, 2},
124 {132, 5, 2},
125 {137, 5, 2},
126 {141, 5, 2},
127 {166, 5, 2},
128 {170, 5, 2},
129 {191, 5, 2},
130 {206, 5, 2},
131 {208, 5, 2},
132 {30, 2, 3},
133 {69, 3, 3},
134 {82, 3, 3},
135 {83, 3, 3},
136 {109, 3, 3},
137 {114, 3, 3},
138 {125, 3, 3},
139 {89, 4, 3},
140 {103, 4, 3},
141 {117, 4, 3},
142 {126, 4, 3},
143 {150, 4, 3},
144 {161, 4, 3},
145 {121, 5, 3},
146 {127, 5, 3},
147 {131, 5, 3},
148 {134, 5, 3},
149 {148, 5, 3},
150 {169, 5, 3},
151 {172, 5, 3},
152 {182, 5, 3},
153 {195, 5, 3},
154 {196, 5, 3},
155 {208, 5, 3},
156 {66, 2, 4},
157 {85, 3, 4},
158 {141, 4, 4},
159 {146, 4, 4},
160 {161, 4, 4},
161 {177, 5, 4}
162};
163
164static struct pll_config cx700_pll_config[] = {
165 {98, 3, 1},
166 {86, 4, 1},
167 {109, 5, 1},
168 {110, 5, 1},
169 {113, 5, 1},
170 {121, 5, 1},
171 {131, 5, 1},
172 {135, 5, 1},
173 {142, 5, 1},
174 {143, 5, 1},
175 {153, 5, 1},
176 {187, 5, 1},
177 {208, 5, 1},
178 {68, 2, 2},
179 {95, 3, 2},
180 {116, 3, 2},
181 {93, 4, 2},
182 {119, 4, 2},
183 {133, 4, 2},
184 {137, 4, 2},
185 {151, 4, 2},
186 {166, 4, 2},
187 {110, 5, 2},
188 {112, 5, 2},
189 {117, 5, 2},
190 {118, 5, 2},
191 {120, 5, 2},
192 {132, 5, 2},
193 {137, 5, 2},
194 {141, 5, 2},
195 {151, 5, 2},
196 {166, 5, 2},
197 {175, 5, 2},
198 {191, 5, 2},
199 {206, 5, 2},
200 {174, 7, 2},
201 {82, 3, 3},
202 {109, 3, 3},
203 {117, 4, 3},
204 {150, 4, 3},
205 {161, 4, 3},
206 {112, 5, 3},
207 {115, 5, 3},
208 {121, 5, 3},
209 {127, 5, 3},
210 {129, 5, 3},
211 {131, 5, 3},
212 {134, 5, 3},
213 {138, 5, 3},
214 {148, 5, 3},
215 {157, 5, 3},
216 {169, 5, 3},
217 {172, 5, 3},
218 {190, 5, 3},
219 {195, 5, 3},
220 {196, 5, 3},
221 {208, 5, 3},
222 {141, 5, 4},
223 {150, 5, 4},
224 {166, 5, 4},
225 {176, 5, 4},
226 {177, 5, 4},
227 {183, 5, 4},
228 {202, 5, 4}
229};
230
231static struct pll_config vx855_pll_config[] = {
232 {86, 4, 1},
233 {108, 5, 1},
234 {110, 5, 1},
235 {113, 5, 1},
236 {121, 5, 1},
237 {131, 5, 1},
238 {135, 5, 1},
239 {142, 5, 1},
240 {143, 5, 1},
241 {153, 5, 1},
242 {164, 5, 1},
243 {187, 5, 1},
244 {208, 5, 1},
245 {110, 5, 2},
246 {112, 5, 2},
247 {117, 5, 2},
248 {118, 5, 2},
249 {124, 5, 2},
250 {132, 5, 2},
251 {137, 5, 2},
252 {141, 5, 2},
253 {149, 5, 2},
254 {151, 5, 2},
255 {159, 5, 2},
256 {166, 5, 2},
257 {167, 5, 2},
258 {172, 5, 2},
259 {189, 5, 2},
260 {191, 5, 2},
261 {194, 5, 2},
262 {206, 5, 2},
263 {208, 5, 2},
264 {83, 3, 3},
265 {88, 3, 3},
266 {109, 3, 3},
267 {112, 3, 3},
268 {103, 4, 3},
269 {105, 4, 3},
270 {161, 4, 3},
271 {112, 5, 3},
272 {115, 5, 3},
273 {121, 5, 3},
274 {127, 5, 3},
275 {134, 5, 3},
276 {137, 5, 3},
277 {148, 5, 3},
278 {157, 5, 3},
279 {169, 5, 3},
280 {172, 5, 3},
281 {182, 5, 3},
282 {191, 5, 3},
283 {195, 5, 3},
284 {209, 5, 3},
285 {142, 4, 4},
286 {146, 4, 4},
287 {161, 4, 4},
288 {141, 5, 4},
289 {150, 5, 4},
290 {165, 5, 4},
291 {176, 5, 4}
Joseph Chand61e0bf2008-10-15 22:03:23 -0700292};
293
Florian Tobias Schandinatbf5ea022011-01-05 10:36:05 +0000294/* according to VIA Technologies these values are based on experiment */
295static struct io_reg scaling_parameters[] = {
296 {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
297 {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
298 {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
299 {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
300 {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
301 {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
302 {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
303 {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
304 {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
305 {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
306 {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
307 {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
308 {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
309 {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
310};
311
Joseph Chand61e0bf2008-10-15 22:03:23 -0700312static struct fifo_depth_select display_fifo_depth_reg = {
313 /* IGA1 FIFO Depth_Select */
314 {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
315 /* IGA2 FIFO Depth_Select */
316 {IGA2_FIFO_DEPTH_SELECT_REG_NUM,
317 {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
318};
319
320static struct fifo_threshold_select fifo_threshold_select_reg = {
321 /* IGA1 FIFO Threshold Select */
322 {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
323 /* IGA2 FIFO Threshold Select */
324 {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
325};
326
327static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
328 /* IGA1 FIFO High Threshold Select */
329 {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
330 /* IGA2 FIFO High Threshold Select */
331 {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
332};
333
334static struct display_queue_expire_num display_queue_expire_num_reg = {
335 /* IGA1 Display Queue Expire Num */
336 {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
337 /* IGA2 Display Queue Expire Num */
338 {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
339};
340
341/* Definition Fetch Count Registers*/
342static struct fetch_count fetch_count_reg = {
343 /* IGA1 Fetch Count Register */
344 {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
345 /* IGA2 Fetch Count Register */
346 {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
347};
348
349static struct iga1_crtc_timing iga1_crtc_reg = {
350 /* IGA1 Horizontal Total */
351 {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
352 /* IGA1 Horizontal Addressable Video */
353 {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
354 /* IGA1 Horizontal Blank Start */
355 {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
356 /* IGA1 Horizontal Blank End */
357 {IGA1_HOR_BLANK_END_REG_NUM,
358 {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
359 /* IGA1 Horizontal Sync Start */
360 {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
361 /* IGA1 Horizontal Sync End */
362 {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
363 /* IGA1 Vertical Total */
364 {IGA1_VER_TOTAL_REG_NUM,
365 {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
366 /* IGA1 Vertical Addressable Video */
367 {IGA1_VER_ADDR_REG_NUM,
368 {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
369 /* IGA1 Vertical Blank Start */
370 {IGA1_VER_BLANK_START_REG_NUM,
371 {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
372 /* IGA1 Vertical Blank End */
373 {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
374 /* IGA1 Vertical Sync Start */
375 {IGA1_VER_SYNC_START_REG_NUM,
376 {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
377 /* IGA1 Vertical Sync End */
378 {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
379};
380
381static struct iga2_crtc_timing iga2_crtc_reg = {
382 /* IGA2 Horizontal Total */
383 {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
384 /* IGA2 Horizontal Addressable Video */
385 {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
386 /* IGA2 Horizontal Blank Start */
387 {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
388 /* IGA2 Horizontal Blank End */
389 {IGA2_HOR_BLANK_END_REG_NUM,
390 {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
391 /* IGA2 Horizontal Sync Start */
392 {IGA2_HOR_SYNC_START_REG_NUM,
393 {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
394 /* IGA2 Horizontal Sync End */
395 {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
396 /* IGA2 Vertical Total */
397 {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
398 /* IGA2 Vertical Addressable Video */
399 {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
400 /* IGA2 Vertical Blank Start */
401 {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
402 /* IGA2 Vertical Blank End */
403 {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
404 /* IGA2 Vertical Sync Start */
405 {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
406 /* IGA2 Vertical Sync End */
407 {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
408};
409
410static struct rgbLUT palLUT_table[] = {
411 /* {R,G,B} */
412 /* Index 0x00~0x03 */
413 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
414 0x2A,
415 0x2A},
416 /* Index 0x04~0x07 */
417 {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
418 0x2A,
419 0x2A},
420 /* Index 0x08~0x0B */
421 {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
422 0x3F,
423 0x3F},
424 /* Index 0x0C~0x0F */
425 {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
426 0x3F,
427 0x3F},
428 /* Index 0x10~0x13 */
429 {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
430 0x0B,
431 0x0B},
432 /* Index 0x14~0x17 */
433 {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
434 0x18,
435 0x18},
436 /* Index 0x18~0x1B */
437 {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
438 0x28,
439 0x28},
440 /* Index 0x1C~0x1F */
441 {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
442 0x3F,
443 0x3F},
444 /* Index 0x20~0x23 */
445 {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
446 0x00,
447 0x3F},
448 /* Index 0x24~0x27 */
449 {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
450 0x00,
451 0x10},
452 /* Index 0x28~0x2B */
453 {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
454 0x2F,
455 0x00},
456 /* Index 0x2C~0x2F */
457 {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
458 0x3F,
459 0x00},
460 /* Index 0x30~0x33 */
461 {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
462 0x3F,
463 0x2F},
464 /* Index 0x34~0x37 */
465 {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
466 0x10,
467 0x3F},
468 /* Index 0x38~0x3B */
469 {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
470 0x1F,
471 0x3F},
472 /* Index 0x3C~0x3F */
473 {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
474 0x1F,
475 0x27},
476 /* Index 0x40~0x43 */
477 {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
478 0x3F,
479 0x1F},
480 /* Index 0x44~0x47 */
481 {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
482 0x3F,
483 0x1F},
484 /* Index 0x48~0x4B */
485 {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
486 0x3F,
487 0x37},
488 /* Index 0x4C~0x4F */
489 {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
490 0x27,
491 0x3F},
492 /* Index 0x50~0x53 */
493 {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
494 0x2D,
495 0x3F},
496 /* Index 0x54~0x57 */
497 {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
498 0x2D,
499 0x31},
500 /* Index 0x58~0x5B */
501 {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
502 0x3A,
503 0x2D},
504 /* Index 0x5C~0x5F */
505 {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
506 0x3F,
507 0x2D},
508 /* Index 0x60~0x63 */
509 {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
510 0x3F,
511 0x3A},
512 /* Index 0x64~0x67 */
513 {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
514 0x31,
515 0x3F},
516 /* Index 0x68~0x6B */
517 {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
518 0x00,
519 0x1C},
520 /* Index 0x6C~0x6F */
521 {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
522 0x00,
523 0x07},
524 /* Index 0x70~0x73 */
525 {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
526 0x15,
527 0x00},
528 /* Index 0x74~0x77 */
529 {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
530 0x1C,
531 0x00},
532 /* Index 0x78~0x7B */
533 {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
534 0x1C,
535 0x15},
536 /* Index 0x7C~0x7F */
537 {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
538 0x07,
539 0x1C},
540 /* Index 0x80~0x83 */
541 {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
542 0x0E,
543 0x1C},
544 /* Index 0x84~0x87 */
545 {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
546 0x0E,
547 0x11},
548 /* Index 0x88~0x8B */
549 {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
550 0x18,
551 0x0E},
552 /* Index 0x8C~0x8F */
553 {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
554 0x1C,
555 0x0E},
556 /* Index 0x90~0x93 */
557 {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
558 0x1C,
559 0x18},
560 /* Index 0x94~0x97 */
561 {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
562 0x11,
563 0x1C},
564 /* Index 0x98~0x9B */
565 {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
566 0x14,
567 0x1C},
568 /* Index 0x9C~0x9F */
569 {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
570 0x14,
571 0x16},
572 /* Index 0xA0~0xA3 */
573 {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
574 0x1A,
575 0x14},
576 /* Index 0xA4~0xA7 */
577 {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
578 0x1C,
579 0x14},
580 /* Index 0xA8~0xAB */
581 {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
582 0x1C,
583 0x1A},
584 /* Index 0xAC~0xAF */
585 {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
586 0x16,
587 0x1C},
588 /* Index 0xB0~0xB3 */
589 {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
590 0x00,
591 0x10},
592 /* Index 0xB4~0xB7 */
593 {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
594 0x00,
595 0x04},
596 /* Index 0xB8~0xBB */
597 {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
598 0x0C,
599 0x00},
600 /* Index 0xBC~0xBF */
601 {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
602 0x10,
603 0x00},
604 /* Index 0xC0~0xC3 */
605 {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
606 0x10,
607 0x0C},
608 /* Index 0xC4~0xC7 */
609 {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
610 0x04,
611 0x10},
612 /* Index 0xC8~0xCB */
613 {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
614 0x08,
615 0x10},
616 /* Index 0xCC~0xCF */
617 {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
618 0x08,
619 0x0A},
620 /* Index 0xD0~0xD3 */
621 {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
622 0x0E,
623 0x08},
624 /* Index 0xD4~0xD7 */
625 {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
626 0x10,
627 0x08},
628 /* Index 0xD8~0xDB */
629 {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
630 0x10,
631 0x0E},
632 /* Index 0xDC~0xDF */
633 {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
634 0x0A,
635 0x10},
636 /* Index 0xE0~0xE3 */
637 {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
638 0x0B,
639 0x10},
640 /* Index 0xE4~0xE7 */
641 {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
642 0x0B,
643 0x0C},
644 /* Index 0xE8~0xEB */
645 {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
646 0x0F,
647 0x0B},
648 /* Index 0xEC~0xEF */
649 {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
650 0x10,
651 0x0B},
652 /* Index 0xF0~0xF3 */
653 {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
654 0x10,
655 0x0F},
656 /* Index 0xF4~0xF7 */
657 {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
658 0x0C,
659 0x10},
660 /* Index 0xF8~0xFB */
661 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
662 0x00,
663 0x00},
664 /* Index 0xFC~0xFF */
665 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
666 0x00,
667 0x00}
668};
669
Florian Tobias Schandinat2a918392010-09-05 01:33:28 +0000670static struct via_device_mapping device_mapping[] = {
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000671 {VIA_LDVP0, "LDVP0"},
672 {VIA_LDVP1, "LDVP1"},
673 {VIA_DVP0, "DVP0"},
Florian Tobias Schandinat2a918392010-09-05 01:33:28 +0000674 {VIA_CRT, "CRT"},
675 {VIA_DVP1, "DVP1"},
676 {VIA_LVDS1, "LVDS1"},
677 {VIA_LVDS2, "LVDS2"}
678};
679
Joseph Chand61e0bf2008-10-15 22:03:23 -0700680static void load_fix_bit_crtc_reg(void);
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +0000681static void __devinit init_gfx_chip_info(int chip_type);
682static void __devinit init_tmds_chip_info(void);
683static void __devinit init_lvds_chip_info(void);
Joseph Chand61e0bf2008-10-15 22:03:23 -0700684static void device_screen_off(void);
685static void device_screen_on(void);
686static void set_display_channel(void);
687static void device_off(void);
688static void device_on(void);
689static void enable_second_display_channel(void);
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +0000690static void disable_second_display_channel(void);
Joseph Chand61e0bf2008-10-15 22:03:23 -0700691
Joseph Chand61e0bf2008-10-15 22:03:23 -0700692void viafb_lock_crt(void)
693{
694 viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
695}
696
697void viafb_unlock_crt(void)
698{
699 viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
700 viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
701}
702
Stephen Hemminger23e5abd2011-03-03 10:00:08 -0800703static void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
Joseph Chand61e0bf2008-10-15 22:03:23 -0700704{
705 outb(index, LUT_INDEX_WRITE);
706 outb(r, LUT_DATA);
707 outb(g, LUT_DATA);
708 outb(b, LUT_DATA);
709}
710
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000711static u32 get_dvi_devices(int output_interface)
712{
713 switch (output_interface) {
714 case INTERFACE_DVP0:
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000715 return VIA_DVP0 | VIA_LDVP0;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000716
717 case INTERFACE_DVP1:
718 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000719 return VIA_LDVP1;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000720 else
721 return VIA_DVP1;
722
723 case INTERFACE_DFP_HIGH:
724 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
725 return 0;
726 else
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000727 return VIA_LVDS2 | VIA_DVP0;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000728
729 case INTERFACE_DFP_LOW:
730 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
731 return 0;
732 else
733 return VIA_DVP1 | VIA_LVDS1;
734
735 case INTERFACE_TMDS:
736 return VIA_LVDS1;
737 }
738
739 return 0;
740}
741
742static u32 get_lcd_devices(int output_interface)
743{
744 switch (output_interface) {
745 case INTERFACE_DVP0:
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000746 return VIA_DVP0;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000747
748 case INTERFACE_DVP1:
749 return VIA_DVP1;
750
751 case INTERFACE_DFP_HIGH:
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000752 return VIA_LVDS2 | VIA_DVP0;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000753
754 case INTERFACE_DFP_LOW:
755 return VIA_LVDS1 | VIA_DVP1;
756
757 case INTERFACE_DFP:
758 return VIA_LVDS1 | VIA_LVDS2;
759
760 case INTERFACE_LVDS0:
761 case INTERFACE_LVDS0LVDS1:
762 return VIA_LVDS1;
763
764 case INTERFACE_LVDS1:
765 return VIA_LVDS2;
766 }
767
768 return 0;
769}
770
Joseph Chand61e0bf2008-10-15 22:03:23 -0700771/*Set IGA path for each device*/
772void viafb_set_iga_path(void)
773{
774
775 if (viafb_SAMM_ON == 1) {
776 if (viafb_CRT_ON) {
777 if (viafb_primary_dev == CRT_Device)
778 viaparinfo->crt_setting_info->iga_path = IGA1;
779 else
780 viaparinfo->crt_setting_info->iga_path = IGA2;
781 }
782
783 if (viafb_DVI_ON) {
784 if (viafb_primary_dev == DVI_Device)
785 viaparinfo->tmds_setting_info->iga_path = IGA1;
786 else
787 viaparinfo->tmds_setting_info->iga_path = IGA2;
788 }
789
790 if (viafb_LCD_ON) {
791 if (viafb_primary_dev == LCD_Device) {
792 if (viafb_dual_fb &&
793 (viaparinfo->chip_info->gfx_chip_name ==
794 UNICHROME_CLE266)) {
795 viaparinfo->
796 lvds_setting_info->iga_path = IGA2;
797 viaparinfo->
798 crt_setting_info->iga_path = IGA1;
799 viaparinfo->
800 tmds_setting_info->iga_path = IGA1;
801 } else
802 viaparinfo->
803 lvds_setting_info->iga_path = IGA1;
804 } else {
805 viaparinfo->lvds_setting_info->iga_path = IGA2;
806 }
807 }
808 if (viafb_LCD2_ON) {
809 if (LCD2_Device == viafb_primary_dev)
810 viaparinfo->lvds_setting_info2->iga_path = IGA1;
811 else
812 viaparinfo->lvds_setting_info2->iga_path = IGA2;
813 }
814 } else {
815 viafb_SAMM_ON = 0;
816
817 if (viafb_CRT_ON && viafb_LCD_ON) {
818 viaparinfo->crt_setting_info->iga_path = IGA1;
819 viaparinfo->lvds_setting_info->iga_path = IGA2;
820 } else if (viafb_CRT_ON && viafb_DVI_ON) {
821 viaparinfo->crt_setting_info->iga_path = IGA1;
822 viaparinfo->tmds_setting_info->iga_path = IGA2;
823 } else if (viafb_LCD_ON && viafb_DVI_ON) {
824 viaparinfo->tmds_setting_info->iga_path = IGA1;
825 viaparinfo->lvds_setting_info->iga_path = IGA2;
826 } else if (viafb_LCD_ON && viafb_LCD2_ON) {
827 viaparinfo->lvds_setting_info->iga_path = IGA2;
828 viaparinfo->lvds_setting_info2->iga_path = IGA2;
829 } else if (viafb_CRT_ON) {
830 viaparinfo->crt_setting_info->iga_path = IGA1;
831 } else if (viafb_LCD_ON) {
832 viaparinfo->lvds_setting_info->iga_path = IGA2;
833 } else if (viafb_DVI_ON) {
834 viaparinfo->tmds_setting_info->iga_path = IGA1;
835 }
836 }
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000837
838 viaparinfo->shared->iga1_devices = 0;
839 viaparinfo->shared->iga2_devices = 0;
840 if (viafb_CRT_ON) {
841 if (viaparinfo->crt_setting_info->iga_path == IGA1)
842 viaparinfo->shared->iga1_devices |= VIA_CRT;
843 else
844 viaparinfo->shared->iga2_devices |= VIA_CRT;
845 }
846
847 if (viafb_DVI_ON) {
848 if (viaparinfo->tmds_setting_info->iga_path == IGA1)
849 viaparinfo->shared->iga1_devices |= get_dvi_devices(
850 viaparinfo->chip_info->
851 tmds_chip_info.output_interface);
852 else
853 viaparinfo->shared->iga2_devices |= get_dvi_devices(
854 viaparinfo->chip_info->
855 tmds_chip_info.output_interface);
856 }
857
858 if (viafb_LCD_ON) {
859 if (viaparinfo->lvds_setting_info->iga_path == IGA1)
860 viaparinfo->shared->iga1_devices |= get_lcd_devices(
861 viaparinfo->chip_info->
862 lvds_chip_info.output_interface);
863 else
864 viaparinfo->shared->iga2_devices |= get_lcd_devices(
865 viaparinfo->chip_info->
866 lvds_chip_info.output_interface);
867 }
868
869 if (viafb_LCD2_ON) {
870 if (viaparinfo->lvds_setting_info2->iga_path == IGA1)
871 viaparinfo->shared->iga1_devices |= get_lcd_devices(
872 viaparinfo->chip_info->
873 lvds_chip_info2.output_interface);
874 else
875 viaparinfo->shared->iga2_devices |= get_lcd_devices(
876 viaparinfo->chip_info->
877 lvds_chip_info2.output_interface);
878 }
Florian Tobias Schandinat32fab7b2011-04-23 22:06:18 +0000879
880 /* looks like the OLPC has its display wired to DVP1 and LVDS2 */
881 if (machine_is_olpc())
882 viaparinfo->shared->iga2_devices = VIA_DVP1 | VIA_LVDS2;
Joseph Chand61e0bf2008-10-15 22:03:23 -0700883}
884
Florian Tobias Schandinat415559f2010-03-10 15:21:40 -0800885static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
886{
887 outb(0xFF, 0x3C6); /* bit mask of palette */
888 outb(index, 0x3C8);
889 outb(red, 0x3C9);
890 outb(green, 0x3C9);
891 outb(blue, 0x3C9);
892}
893
894void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
895{
896 viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
897 set_color_register(index, red, green, blue);
898}
899
900void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
901{
902 viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
903 set_color_register(index, red, green, blue);
904}
905
Florian Tobias Schandinata54be172010-07-28 23:06:04 +0000906static void set_source_common(u8 index, u8 offset, u8 iga)
907{
908 u8 value, mask = 1 << offset;
909
910 switch (iga) {
911 case IGA1:
912 value = 0x00;
913 break;
914 case IGA2:
915 value = mask;
916 break;
917 default:
918 printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
919 return;
920 }
921
922 via_write_reg_mask(VIACR, index, value, mask);
923}
924
925static void set_crt_source(u8 iga)
926{
927 u8 value;
928
929 switch (iga) {
930 case IGA1:
931 value = 0x00;
932 break;
933 case IGA2:
934 value = 0x40;
935 break;
936 default:
937 printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
938 return;
939 }
940
941 via_write_reg_mask(VIASR, 0x16, value, 0x40);
942}
943
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000944static inline void set_ldvp0_source(u8 iga)
Florian Tobias Schandinata54be172010-07-28 23:06:04 +0000945{
946 set_source_common(0x6C, 7, iga);
947}
948
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000949static inline void set_ldvp1_source(u8 iga)
Florian Tobias Schandinata54be172010-07-28 23:06:04 +0000950{
951 set_source_common(0x93, 7, iga);
952}
953
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000954static inline void set_dvp0_source(u8 iga)
Florian Tobias Schandinata54be172010-07-28 23:06:04 +0000955{
956 set_source_common(0x96, 4, iga);
957}
958
959static inline void set_dvp1_source(u8 iga)
960{
961 set_source_common(0x9B, 4, iga);
962}
963
964static inline void set_lvds1_source(u8 iga)
965{
966 set_source_common(0x99, 4, iga);
967}
968
969static inline void set_lvds2_source(u8 iga)
970{
971 set_source_common(0x97, 4, iga);
972}
973
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +0000974void via_set_source(u32 devices, u8 iga)
Joseph Chand61e0bf2008-10-15 22:03:23 -0700975{
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000976 if (devices & VIA_LDVP0)
977 set_ldvp0_source(iga);
978 if (devices & VIA_LDVP1)
979 set_ldvp1_source(iga);
980 if (devices & VIA_DVP0)
981 set_dvp0_source(iga);
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +0000982 if (devices & VIA_CRT)
983 set_crt_source(iga);
984 if (devices & VIA_DVP1)
985 set_dvp1_source(iga);
986 if (devices & VIA_LVDS1)
987 set_lvds1_source(iga);
988 if (devices & VIA_LVDS2)
989 set_lvds2_source(iga);
Joseph Chand61e0bf2008-10-15 22:03:23 -0700990}
991
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +0000992static void set_crt_state(u8 state)
993{
994 u8 value;
995
996 switch (state) {
997 case VIA_STATE_ON:
998 value = 0x00;
999 break;
1000 case VIA_STATE_STANDBY:
1001 value = 0x10;
1002 break;
1003 case VIA_STATE_SUSPEND:
1004 value = 0x20;
1005 break;
1006 case VIA_STATE_OFF:
1007 value = 0x30;
1008 break;
1009 default:
1010 return;
1011 }
1012
1013 via_write_reg_mask(VIACR, 0x36, value, 0x30);
1014}
1015
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +00001016static void set_dvp0_state(u8 state)
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00001017{
1018 u8 value;
1019
1020 switch (state) {
1021 case VIA_STATE_ON:
1022 value = 0xC0;
1023 break;
1024 case VIA_STATE_OFF:
1025 value = 0x00;
1026 break;
1027 default:
1028 return;
1029 }
1030
1031 via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
1032}
1033
1034static void set_dvp1_state(u8 state)
1035{
1036 u8 value;
1037
1038 switch (state) {
1039 case VIA_STATE_ON:
1040 value = 0x30;
1041 break;
1042 case VIA_STATE_OFF:
1043 value = 0x00;
1044 break;
1045 default:
1046 return;
1047 }
1048
1049 via_write_reg_mask(VIASR, 0x1E, value, 0x30);
1050}
1051
1052static void set_lvds1_state(u8 state)
1053{
1054 u8 value;
1055
1056 switch (state) {
1057 case VIA_STATE_ON:
1058 value = 0x03;
1059 break;
1060 case VIA_STATE_OFF:
1061 value = 0x00;
1062 break;
1063 default:
1064 return;
1065 }
1066
1067 via_write_reg_mask(VIASR, 0x2A, value, 0x03);
1068}
1069
1070static void set_lvds2_state(u8 state)
1071{
1072 u8 value;
1073
1074 switch (state) {
1075 case VIA_STATE_ON:
1076 value = 0x0C;
1077 break;
1078 case VIA_STATE_OFF:
1079 value = 0x00;
1080 break;
1081 default:
1082 return;
1083 }
1084
1085 via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
1086}
1087
1088void via_set_state(u32 devices, u8 state)
1089{
1090 /*
1091 TODO: Can we enable/disable these devices? How?
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +00001092 if (devices & VIA_LDVP0)
1093 if (devices & VIA_LDVP1)
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00001094 */
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +00001095 if (devices & VIA_DVP0)
1096 set_dvp0_state(state);
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00001097 if (devices & VIA_CRT)
1098 set_crt_state(state);
1099 if (devices & VIA_DVP1)
1100 set_dvp1_state(state);
1101 if (devices & VIA_LVDS1)
1102 set_lvds1_state(state);
1103 if (devices & VIA_LVDS2)
1104 set_lvds2_state(state);
1105}
1106
Florian Tobias Schandinat7f0e1532010-09-18 23:47:28 +00001107void via_set_sync_polarity(u32 devices, u8 polarity)
1108{
1109 if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
1110 printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
1111 polarity);
1112 return;
1113 }
1114
1115 if (devices & VIA_CRT)
1116 via_write_misc_reg_mask(polarity << 6, 0xC0);
1117 if (devices & VIA_DVP1)
1118 via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
1119 if (devices & VIA_LVDS1)
1120 via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
1121 if (devices & VIA_LVDS2)
1122 via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
1123}
1124
Florian Tobias Schandinat2a918392010-09-05 01:33:28 +00001125u32 via_parse_odev(char *input, char **end)
1126{
1127 char *ptr = input;
1128 u32 odev = 0;
1129 bool next = true;
1130 int i, len;
1131
1132 while (next) {
1133 next = false;
1134 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
1135 len = strlen(device_mapping[i].name);
1136 if (!strncmp(ptr, device_mapping[i].name, len)) {
1137 odev |= device_mapping[i].device;
1138 ptr += len;
1139 if (*ptr == ',') {
1140 ptr++;
1141 next = true;
1142 }
1143 }
1144 }
1145 }
1146
1147 *end = ptr;
1148 return odev;
1149}
1150
1151void via_odev_to_seq(struct seq_file *m, u32 odev)
1152{
1153 int i, count = 0;
1154
1155 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
1156 if (odev & device_mapping[i].device) {
1157 if (count > 0)
1158 seq_putc(m, ',');
1159
1160 seq_puts(m, device_mapping[i].name);
1161 count++;
1162 }
1163 }
1164
1165 seq_putc(m, '\n');
1166}
1167
Joseph Chand61e0bf2008-10-15 22:03:23 -07001168static void load_fix_bit_crtc_reg(void)
1169{
1170 /* always set to 1 */
1171 viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
1172 /* line compare should set all bits = 1 (extend modes) */
1173 viafb_write_reg(CR18, VIACR, 0xff);
1174 /* line compare should set all bits = 1 (extend modes) */
1175 viafb_write_reg_mask(CR07, VIACR, 0x10, BIT4);
1176 /* line compare should set all bits = 1 (extend modes) */
1177 viafb_write_reg_mask(CR09, VIACR, 0x40, BIT6);
1178 /* line compare should set all bits = 1 (extend modes) */
1179 viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
1180 /* line compare should set all bits = 1 (extend modes) */
1181 viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
1182 /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
1183 /* extend mode always set to e3h */
1184 viafb_write_reg(CR17, VIACR, 0xe3);
1185 /* extend mode always set to 0h */
1186 viafb_write_reg(CR08, VIACR, 0x00);
1187 /* extend mode always set to 0h */
1188 viafb_write_reg(CR14, VIACR, 0x00);
1189
1190 /* If K8M800, enable Prefetch Mode. */
1191 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
1192 || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
1193 viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
1194 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
1195 && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
1196 viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
1197
1198}
1199
1200void viafb_load_reg(int timing_value, int viafb_load_reg_num,
1201 struct io_register *reg,
1202 int io_type)
1203{
1204 int reg_mask;
1205 int bit_num = 0;
1206 int data;
1207 int i, j;
1208 int shift_next_reg;
1209 int start_index, end_index, cr_index;
1210 u16 get_bit;
1211
1212 for (i = 0; i < viafb_load_reg_num; i++) {
1213 reg_mask = 0;
1214 data = 0;
1215 start_index = reg[i].start_bit;
1216 end_index = reg[i].end_bit;
1217 cr_index = reg[i].io_addr;
1218
1219 shift_next_reg = bit_num;
1220 for (j = start_index; j <= end_index; j++) {
1221 /*if (bit_num==8) timing_value = timing_value >>8; */
1222 reg_mask = reg_mask | (BIT0 << j);
1223 get_bit = (timing_value & (BIT0 << bit_num));
1224 data =
1225 data | ((get_bit >> shift_next_reg) << start_index);
1226 bit_num++;
1227 }
1228 if (io_type == VIACR)
1229 viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
1230 else
1231 viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
1232 }
1233
1234}
1235
1236/* Write Registers */
1237void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
1238{
1239 int i;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001240
1241 /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
1242
Florian Tobias Schandinat384c3042010-04-17 19:44:54 +00001243 for (i = 0; i < ItemNum; i++)
1244 via_write_reg_mask(RegTable[i].port, RegTable[i].index,
1245 RegTable[i].value, RegTable[i].mask);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001246}
1247
Joseph Chand61e0bf2008-10-15 22:03:23 -07001248void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
1249{
1250 int reg_value;
1251 int viafb_load_reg_num;
1252 struct io_register *reg = NULL;
1253
1254 switch (set_iga) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07001255 case IGA1:
1256 reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1257 viafb_load_reg_num = fetch_count_reg.
1258 iga1_fetch_count_reg.reg_num;
1259 reg = fetch_count_reg.iga1_fetch_count_reg.reg;
1260 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001261 break;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001262 case IGA2:
1263 reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1264 viafb_load_reg_num = fetch_count_reg.
1265 iga2_fetch_count_reg.reg_num;
1266 reg = fetch_count_reg.iga2_fetch_count_reg.reg;
1267 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1268 break;
1269 }
1270
1271}
1272
1273void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1274{
1275 int reg_value;
1276 int viafb_load_reg_num;
1277 struct io_register *reg = NULL;
1278 int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
1279 0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
1280 int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
1281 0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
1282
1283 if (set_iga == IGA1) {
1284 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1285 iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
1286 iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
1287 iga1_fifo_high_threshold =
1288 K800_IGA1_FIFO_HIGH_THRESHOLD;
1289 /* If resolution > 1280x1024, expire length = 64, else
1290 expire length = 128 */
1291 if ((hor_active > 1280) && (ver_active > 1024))
1292 iga1_display_queue_expire_num = 16;
1293 else
1294 iga1_display_queue_expire_num =
1295 K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1296
1297 }
1298
1299 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1300 iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
1301 iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
1302 iga1_fifo_high_threshold =
1303 P880_IGA1_FIFO_HIGH_THRESHOLD;
1304 iga1_display_queue_expire_num =
1305 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1306
1307 /* If resolution > 1280x1024, expire length = 64, else
1308 expire length = 128 */
1309 if ((hor_active > 1280) && (ver_active > 1024))
1310 iga1_display_queue_expire_num = 16;
1311 else
1312 iga1_display_queue_expire_num =
1313 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1314 }
1315
1316 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1317 iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
1318 iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
1319 iga1_fifo_high_threshold =
1320 CN700_IGA1_FIFO_HIGH_THRESHOLD;
1321
1322 /* If resolution > 1280x1024, expire length = 64,
1323 else expire length = 128 */
1324 if ((hor_active > 1280) && (ver_active > 1024))
1325 iga1_display_queue_expire_num = 16;
1326 else
1327 iga1_display_queue_expire_num =
1328 CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1329 }
1330
1331 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1332 iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
1333 iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
1334 iga1_fifo_high_threshold =
1335 CX700_IGA1_FIFO_HIGH_THRESHOLD;
1336 iga1_display_queue_expire_num =
1337 CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1338 }
1339
1340 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1341 iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
1342 iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
1343 iga1_fifo_high_threshold =
1344 K8M890_IGA1_FIFO_HIGH_THRESHOLD;
1345 iga1_display_queue_expire_num =
1346 K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1347 }
1348
1349 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1350 iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
1351 iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
1352 iga1_fifo_high_threshold =
1353 P4M890_IGA1_FIFO_HIGH_THRESHOLD;
1354 iga1_display_queue_expire_num =
1355 P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1356 }
1357
1358 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1359 iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
1360 iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
1361 iga1_fifo_high_threshold =
1362 P4M900_IGA1_FIFO_HIGH_THRESHOLD;
1363 iga1_display_queue_expire_num =
1364 P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1365 }
1366
1367 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1368 iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
1369 iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
1370 iga1_fifo_high_threshold =
1371 VX800_IGA1_FIFO_HIGH_THRESHOLD;
1372 iga1_display_queue_expire_num =
1373 VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1374 }
1375
Harald Welte0306ab12009-09-22 16:47:35 -07001376 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1377 iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH;
1378 iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD;
1379 iga1_fifo_high_threshold =
1380 VX855_IGA1_FIFO_HIGH_THRESHOLD;
1381 iga1_display_queue_expire_num =
1382 VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1383 }
1384
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00001385 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1386 iga1_fifo_max_depth = VX900_IGA1_FIFO_MAX_DEPTH;
1387 iga1_fifo_threshold = VX900_IGA1_FIFO_THRESHOLD;
1388 iga1_fifo_high_threshold =
1389 VX900_IGA1_FIFO_HIGH_THRESHOLD;
1390 iga1_display_queue_expire_num =
1391 VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1392 }
1393
Joseph Chand61e0bf2008-10-15 22:03:23 -07001394 /* Set Display FIFO Depath Select */
1395 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
1396 viafb_load_reg_num =
1397 display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
1398 reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
1399 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1400
1401 /* Set Display FIFO Threshold Select */
1402 reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
1403 viafb_load_reg_num =
1404 fifo_threshold_select_reg.
1405 iga1_fifo_threshold_select_reg.reg_num;
1406 reg =
1407 fifo_threshold_select_reg.
1408 iga1_fifo_threshold_select_reg.reg;
1409 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1410
1411 /* Set FIFO High Threshold Select */
1412 reg_value =
1413 IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
1414 viafb_load_reg_num =
1415 fifo_high_threshold_select_reg.
1416 iga1_fifo_high_threshold_select_reg.reg_num;
1417 reg =
1418 fifo_high_threshold_select_reg.
1419 iga1_fifo_high_threshold_select_reg.reg;
1420 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1421
1422 /* Set Display Queue Expire Num */
1423 reg_value =
1424 IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1425 (iga1_display_queue_expire_num);
1426 viafb_load_reg_num =
1427 display_queue_expire_num_reg.
1428 iga1_display_queue_expire_num_reg.reg_num;
1429 reg =
1430 display_queue_expire_num_reg.
1431 iga1_display_queue_expire_num_reg.reg;
1432 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1433
1434 } else {
1435 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1436 iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
1437 iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
1438 iga2_fifo_high_threshold =
1439 K800_IGA2_FIFO_HIGH_THRESHOLD;
1440
1441 /* If resolution > 1280x1024, expire length = 64,
1442 else expire length = 128 */
1443 if ((hor_active > 1280) && (ver_active > 1024))
1444 iga2_display_queue_expire_num = 16;
1445 else
1446 iga2_display_queue_expire_num =
1447 K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1448 }
1449
1450 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1451 iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
1452 iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
1453 iga2_fifo_high_threshold =
1454 P880_IGA2_FIFO_HIGH_THRESHOLD;
1455
1456 /* If resolution > 1280x1024, expire length = 64,
1457 else expire length = 128 */
1458 if ((hor_active > 1280) && (ver_active > 1024))
1459 iga2_display_queue_expire_num = 16;
1460 else
1461 iga2_display_queue_expire_num =
1462 P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1463 }
1464
1465 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1466 iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
1467 iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
1468 iga2_fifo_high_threshold =
1469 CN700_IGA2_FIFO_HIGH_THRESHOLD;
1470
1471 /* If resolution > 1280x1024, expire length = 64,
1472 else expire length = 128 */
1473 if ((hor_active > 1280) && (ver_active > 1024))
1474 iga2_display_queue_expire_num = 16;
1475 else
1476 iga2_display_queue_expire_num =
1477 CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1478 }
1479
1480 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1481 iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
1482 iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
1483 iga2_fifo_high_threshold =
1484 CX700_IGA2_FIFO_HIGH_THRESHOLD;
1485 iga2_display_queue_expire_num =
1486 CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1487 }
1488
1489 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1490 iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
1491 iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
1492 iga2_fifo_high_threshold =
1493 K8M890_IGA2_FIFO_HIGH_THRESHOLD;
1494 iga2_display_queue_expire_num =
1495 K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1496 }
1497
1498 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1499 iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
1500 iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
1501 iga2_fifo_high_threshold =
1502 P4M890_IGA2_FIFO_HIGH_THRESHOLD;
1503 iga2_display_queue_expire_num =
1504 P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1505 }
1506
1507 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1508 iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
1509 iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
1510 iga2_fifo_high_threshold =
1511 P4M900_IGA2_FIFO_HIGH_THRESHOLD;
1512 iga2_display_queue_expire_num =
1513 P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1514 }
1515
1516 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1517 iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
1518 iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
1519 iga2_fifo_high_threshold =
1520 VX800_IGA2_FIFO_HIGH_THRESHOLD;
1521 iga2_display_queue_expire_num =
1522 VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1523 }
1524
Harald Welte0306ab12009-09-22 16:47:35 -07001525 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1526 iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH;
1527 iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD;
1528 iga2_fifo_high_threshold =
1529 VX855_IGA2_FIFO_HIGH_THRESHOLD;
1530 iga2_display_queue_expire_num =
1531 VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1532 }
1533
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00001534 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1535 iga2_fifo_max_depth = VX900_IGA2_FIFO_MAX_DEPTH;
1536 iga2_fifo_threshold = VX900_IGA2_FIFO_THRESHOLD;
1537 iga2_fifo_high_threshold =
1538 VX900_IGA2_FIFO_HIGH_THRESHOLD;
1539 iga2_display_queue_expire_num =
1540 VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1541 }
1542
Joseph Chand61e0bf2008-10-15 22:03:23 -07001543 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1544 /* Set Display FIFO Depath Select */
1545 reg_value =
1546 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
1547 - 1;
1548 /* Patch LCD in IGA2 case */
1549 viafb_load_reg_num =
1550 display_fifo_depth_reg.
1551 iga2_fifo_depth_select_reg.reg_num;
1552 reg =
1553 display_fifo_depth_reg.
1554 iga2_fifo_depth_select_reg.reg;
1555 viafb_load_reg(reg_value,
1556 viafb_load_reg_num, reg, VIACR);
1557 } else {
1558
1559 /* Set Display FIFO Depath Select */
1560 reg_value =
1561 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
1562 viafb_load_reg_num =
1563 display_fifo_depth_reg.
1564 iga2_fifo_depth_select_reg.reg_num;
1565 reg =
1566 display_fifo_depth_reg.
1567 iga2_fifo_depth_select_reg.reg;
1568 viafb_load_reg(reg_value,
1569 viafb_load_reg_num, reg, VIACR);
1570 }
1571
1572 /* Set Display FIFO Threshold Select */
1573 reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
1574 viafb_load_reg_num =
1575 fifo_threshold_select_reg.
1576 iga2_fifo_threshold_select_reg.reg_num;
1577 reg =
1578 fifo_threshold_select_reg.
1579 iga2_fifo_threshold_select_reg.reg;
1580 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1581
1582 /* Set FIFO High Threshold Select */
1583 reg_value =
1584 IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
1585 viafb_load_reg_num =
1586 fifo_high_threshold_select_reg.
1587 iga2_fifo_high_threshold_select_reg.reg_num;
1588 reg =
1589 fifo_high_threshold_select_reg.
1590 iga2_fifo_high_threshold_select_reg.reg;
1591 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1592
1593 /* Set Display Queue Expire Num */
1594 reg_value =
1595 IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1596 (iga2_display_queue_expire_num);
1597 viafb_load_reg_num =
1598 display_queue_expire_num_reg.
1599 iga2_display_queue_expire_num_reg.reg_num;
1600 reg =
1601 display_queue_expire_num_reg.
1602 iga2_display_queue_expire_num_reg.reg;
1603 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1604
1605 }
1606
1607}
1608
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001609static u32 cle266_encode_pll(struct pll_config pll)
1610{
1611 return (pll.multiplier << 8)
1612 | (pll.rshift << 6)
1613 | pll.divisor;
1614}
1615
1616static u32 k800_encode_pll(struct pll_config pll)
1617{
1618 return ((pll.divisor - 2) << 16)
1619 | (pll.rshift << 10)
1620 | (pll.multiplier - 2);
1621}
1622
1623static u32 vx855_encode_pll(struct pll_config pll)
1624{
1625 return (pll.divisor << 16)
1626 | (pll.rshift << 10)
1627 | pll.multiplier;
1628}
1629
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001630static inline u32 get_pll_internal_frequency(u32 ref_freq,
1631 struct pll_config pll)
1632{
1633 return ref_freq / pll.divisor * pll.multiplier;
1634}
1635
1636static inline u32 get_pll_output_frequency(u32 ref_freq, struct pll_config pll)
1637{
1638 return get_pll_internal_frequency(ref_freq, pll)>>pll.rshift;
1639}
1640
1641static struct pll_config get_pll_config(struct pll_config *config, int size,
1642 int clk)
1643{
1644 struct pll_config best = config[0];
1645 const u32 f0 = 14318180; /* X1 frequency */
1646 int i;
1647
1648 for (i = 1; i < size; i++) {
1649 if (abs(get_pll_output_frequency(f0, config[i]) - clk)
1650 < abs(get_pll_output_frequency(f0, best) - clk))
1651 best = config[i];
1652 }
1653
1654 return best;
1655}
1656
Joseph Chand61e0bf2008-10-15 22:03:23 -07001657u32 viafb_get_clk_value(int clk)
1658{
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001659 u32 value = 0;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001660
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001661 switch (viaparinfo->chip_info->gfx_chip_name) {
1662 case UNICHROME_CLE266:
1663 case UNICHROME_K400:
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001664 value = cle266_encode_pll(get_pll_config(cle266_pll_config,
1665 ARRAY_SIZE(cle266_pll_config), clk));
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001666 break;
1667 case UNICHROME_K800:
1668 case UNICHROME_PM800:
1669 case UNICHROME_CN700:
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001670 value = k800_encode_pll(get_pll_config(k800_pll_config,
1671 ARRAY_SIZE(k800_pll_config), clk));
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001672 break;
1673 case UNICHROME_CX700:
1674 case UNICHROME_CN750:
1675 case UNICHROME_K8M890:
1676 case UNICHROME_P4M890:
1677 case UNICHROME_P4M900:
1678 case UNICHROME_VX800:
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001679 value = k800_encode_pll(get_pll_config(cx700_pll_config,
1680 ARRAY_SIZE(cx700_pll_config), clk));
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001681 break;
1682 case UNICHROME_VX855:
1683 case UNICHROME_VX900:
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001684 value = vx855_encode_pll(get_pll_config(vx855_pll_config,
1685 ARRAY_SIZE(vx855_pll_config), clk));
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001686 break;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001687 }
1688
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001689 return value;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001690}
1691
1692/* Set VCLK*/
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001693void viafb_set_vclock(u32 clk, int set_iga)
Joseph Chand61e0bf2008-10-15 22:03:23 -07001694{
Joseph Chand61e0bf2008-10-15 22:03:23 -07001695 /* H.W. Reset : ON */
1696 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1697
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001698 if (set_iga == IGA1) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07001699 /* Change D,N FOR VCLK */
1700 switch (viaparinfo->chip_info->gfx_chip_name) {
1701 case UNICHROME_CLE266:
1702 case UNICHROME_K400:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001703 via_write_reg(VIASR, SR46, (clk & 0x00FF));
1704 via_write_reg(VIASR, SR47, (clk & 0xFF00) >> 8);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001705 break;
1706
1707 case UNICHROME_K800:
1708 case UNICHROME_PM800:
1709 case UNICHROME_CN700:
1710 case UNICHROME_CX700:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001711 case UNICHROME_CN750:
Joseph Chand61e0bf2008-10-15 22:03:23 -07001712 case UNICHROME_K8M890:
1713 case UNICHROME_P4M890:
1714 case UNICHROME_P4M900:
1715 case UNICHROME_VX800:
Harald Welte0306ab12009-09-22 16:47:35 -07001716 case UNICHROME_VX855:
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00001717 case UNICHROME_VX900:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001718 via_write_reg(VIASR, SR44, (clk & 0x0000FF));
1719 via_write_reg(VIASR, SR45, (clk & 0x00FF00) >> 8);
1720 via_write_reg(VIASR, SR46, (clk & 0xFF0000) >> 16);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001721 break;
1722 }
1723 }
1724
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001725 if (set_iga == IGA2) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07001726 /* Change D,N FOR LCK */
1727 switch (viaparinfo->chip_info->gfx_chip_name) {
1728 case UNICHROME_CLE266:
1729 case UNICHROME_K400:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001730 via_write_reg(VIASR, SR44, (clk & 0x00FF));
1731 via_write_reg(VIASR, SR45, (clk & 0xFF00) >> 8);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001732 break;
1733
1734 case UNICHROME_K800:
1735 case UNICHROME_PM800:
1736 case UNICHROME_CN700:
1737 case UNICHROME_CX700:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001738 case UNICHROME_CN750:
Joseph Chand61e0bf2008-10-15 22:03:23 -07001739 case UNICHROME_K8M890:
1740 case UNICHROME_P4M890:
1741 case UNICHROME_P4M900:
1742 case UNICHROME_VX800:
Harald Welte0306ab12009-09-22 16:47:35 -07001743 case UNICHROME_VX855:
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00001744 case UNICHROME_VX900:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001745 via_write_reg(VIASR, SR4A, (clk & 0x0000FF));
1746 via_write_reg(VIASR, SR4B, (clk & 0x00FF00) >> 8);
1747 via_write_reg(VIASR, SR4C, (clk & 0xFF0000) >> 16);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001748 break;
1749 }
1750 }
1751
1752 /* H.W. Reset : OFF */
1753 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1754
1755 /* Reset PLL */
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001756 if (set_iga == IGA1) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07001757 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
1758 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
1759 }
1760
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001761 if (set_iga == IGA2) {
Florian Tobias Schandinate3812ce2010-07-28 00:57:18 +00001762 viafb_write_reg_mask(SR40, VIASR, 0x04, BIT2);
1763 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT2);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001764 }
1765
1766 /* Fire! */
Florian Tobias Schandinat162fc8c2010-04-17 19:44:55 +00001767 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
Joseph Chand61e0bf2008-10-15 22:03:23 -07001768}
1769
1770void viafb_load_crtc_timing(struct display_timing device_timing,
1771 int set_iga)
1772{
1773 int i;
1774 int viafb_load_reg_num = 0;
1775 int reg_value = 0;
1776 struct io_register *reg = NULL;
1777
1778 viafb_unlock_crt();
1779
1780 for (i = 0; i < 12; i++) {
1781 if (set_iga == IGA1) {
1782 switch (i) {
1783 case H_TOTAL_INDEX:
1784 reg_value =
1785 IGA1_HOR_TOTAL_FORMULA(device_timing.
1786 hor_total);
1787 viafb_load_reg_num =
1788 iga1_crtc_reg.hor_total.reg_num;
1789 reg = iga1_crtc_reg.hor_total.reg;
1790 break;
1791 case H_ADDR_INDEX:
1792 reg_value =
1793 IGA1_HOR_ADDR_FORMULA(device_timing.
1794 hor_addr);
1795 viafb_load_reg_num =
1796 iga1_crtc_reg.hor_addr.reg_num;
1797 reg = iga1_crtc_reg.hor_addr.reg;
1798 break;
1799 case H_BLANK_START_INDEX:
1800 reg_value =
1801 IGA1_HOR_BLANK_START_FORMULA
1802 (device_timing.hor_blank_start);
1803 viafb_load_reg_num =
1804 iga1_crtc_reg.hor_blank_start.reg_num;
1805 reg = iga1_crtc_reg.hor_blank_start.reg;
1806 break;
1807 case H_BLANK_END_INDEX:
1808 reg_value =
1809 IGA1_HOR_BLANK_END_FORMULA
1810 (device_timing.hor_blank_start,
1811 device_timing.hor_blank_end);
1812 viafb_load_reg_num =
1813 iga1_crtc_reg.hor_blank_end.reg_num;
1814 reg = iga1_crtc_reg.hor_blank_end.reg;
1815 break;
1816 case H_SYNC_START_INDEX:
1817 reg_value =
1818 IGA1_HOR_SYNC_START_FORMULA
1819 (device_timing.hor_sync_start);
1820 viafb_load_reg_num =
1821 iga1_crtc_reg.hor_sync_start.reg_num;
1822 reg = iga1_crtc_reg.hor_sync_start.reg;
1823 break;
1824 case H_SYNC_END_INDEX:
1825 reg_value =
1826 IGA1_HOR_SYNC_END_FORMULA
1827 (device_timing.hor_sync_start,
1828 device_timing.hor_sync_end);
1829 viafb_load_reg_num =
1830 iga1_crtc_reg.hor_sync_end.reg_num;
1831 reg = iga1_crtc_reg.hor_sync_end.reg;
1832 break;
1833 case V_TOTAL_INDEX:
1834 reg_value =
1835 IGA1_VER_TOTAL_FORMULA(device_timing.
1836 ver_total);
1837 viafb_load_reg_num =
1838 iga1_crtc_reg.ver_total.reg_num;
1839 reg = iga1_crtc_reg.ver_total.reg;
1840 break;
1841 case V_ADDR_INDEX:
1842 reg_value =
1843 IGA1_VER_ADDR_FORMULA(device_timing.
1844 ver_addr);
1845 viafb_load_reg_num =
1846 iga1_crtc_reg.ver_addr.reg_num;
1847 reg = iga1_crtc_reg.ver_addr.reg;
1848 break;
1849 case V_BLANK_START_INDEX:
1850 reg_value =
1851 IGA1_VER_BLANK_START_FORMULA
1852 (device_timing.ver_blank_start);
1853 viafb_load_reg_num =
1854 iga1_crtc_reg.ver_blank_start.reg_num;
1855 reg = iga1_crtc_reg.ver_blank_start.reg;
1856 break;
1857 case V_BLANK_END_INDEX:
1858 reg_value =
1859 IGA1_VER_BLANK_END_FORMULA
1860 (device_timing.ver_blank_start,
1861 device_timing.ver_blank_end);
1862 viafb_load_reg_num =
1863 iga1_crtc_reg.ver_blank_end.reg_num;
1864 reg = iga1_crtc_reg.ver_blank_end.reg;
1865 break;
1866 case V_SYNC_START_INDEX:
1867 reg_value =
1868 IGA1_VER_SYNC_START_FORMULA
1869 (device_timing.ver_sync_start);
1870 viafb_load_reg_num =
1871 iga1_crtc_reg.ver_sync_start.reg_num;
1872 reg = iga1_crtc_reg.ver_sync_start.reg;
1873 break;
1874 case V_SYNC_END_INDEX:
1875 reg_value =
1876 IGA1_VER_SYNC_END_FORMULA
1877 (device_timing.ver_sync_start,
1878 device_timing.ver_sync_end);
1879 viafb_load_reg_num =
1880 iga1_crtc_reg.ver_sync_end.reg_num;
1881 reg = iga1_crtc_reg.ver_sync_end.reg;
1882 break;
1883
1884 }
1885 }
1886
1887 if (set_iga == IGA2) {
1888 switch (i) {
1889 case H_TOTAL_INDEX:
1890 reg_value =
1891 IGA2_HOR_TOTAL_FORMULA(device_timing.
1892 hor_total);
1893 viafb_load_reg_num =
1894 iga2_crtc_reg.hor_total.reg_num;
1895 reg = iga2_crtc_reg.hor_total.reg;
1896 break;
1897 case H_ADDR_INDEX:
1898 reg_value =
1899 IGA2_HOR_ADDR_FORMULA(device_timing.
1900 hor_addr);
1901 viafb_load_reg_num =
1902 iga2_crtc_reg.hor_addr.reg_num;
1903 reg = iga2_crtc_reg.hor_addr.reg;
1904 break;
1905 case H_BLANK_START_INDEX:
1906 reg_value =
1907 IGA2_HOR_BLANK_START_FORMULA
1908 (device_timing.hor_blank_start);
1909 viafb_load_reg_num =
1910 iga2_crtc_reg.hor_blank_start.reg_num;
1911 reg = iga2_crtc_reg.hor_blank_start.reg;
1912 break;
1913 case H_BLANK_END_INDEX:
1914 reg_value =
1915 IGA2_HOR_BLANK_END_FORMULA
1916 (device_timing.hor_blank_start,
1917 device_timing.hor_blank_end);
1918 viafb_load_reg_num =
1919 iga2_crtc_reg.hor_blank_end.reg_num;
1920 reg = iga2_crtc_reg.hor_blank_end.reg;
1921 break;
1922 case H_SYNC_START_INDEX:
1923 reg_value =
1924 IGA2_HOR_SYNC_START_FORMULA
1925 (device_timing.hor_sync_start);
1926 if (UNICHROME_CN700 <=
1927 viaparinfo->chip_info->gfx_chip_name)
1928 viafb_load_reg_num =
1929 iga2_crtc_reg.hor_sync_start.
1930 reg_num;
1931 else
1932 viafb_load_reg_num = 3;
1933 reg = iga2_crtc_reg.hor_sync_start.reg;
1934 break;
1935 case H_SYNC_END_INDEX:
1936 reg_value =
1937 IGA2_HOR_SYNC_END_FORMULA
1938 (device_timing.hor_sync_start,
1939 device_timing.hor_sync_end);
1940 viafb_load_reg_num =
1941 iga2_crtc_reg.hor_sync_end.reg_num;
1942 reg = iga2_crtc_reg.hor_sync_end.reg;
1943 break;
1944 case V_TOTAL_INDEX:
1945 reg_value =
1946 IGA2_VER_TOTAL_FORMULA(device_timing.
1947 ver_total);
1948 viafb_load_reg_num =
1949 iga2_crtc_reg.ver_total.reg_num;
1950 reg = iga2_crtc_reg.ver_total.reg;
1951 break;
1952 case V_ADDR_INDEX:
1953 reg_value =
1954 IGA2_VER_ADDR_FORMULA(device_timing.
1955 ver_addr);
1956 viafb_load_reg_num =
1957 iga2_crtc_reg.ver_addr.reg_num;
1958 reg = iga2_crtc_reg.ver_addr.reg;
1959 break;
1960 case V_BLANK_START_INDEX:
1961 reg_value =
1962 IGA2_VER_BLANK_START_FORMULA
1963 (device_timing.ver_blank_start);
1964 viafb_load_reg_num =
1965 iga2_crtc_reg.ver_blank_start.reg_num;
1966 reg = iga2_crtc_reg.ver_blank_start.reg;
1967 break;
1968 case V_BLANK_END_INDEX:
1969 reg_value =
1970 IGA2_VER_BLANK_END_FORMULA
1971 (device_timing.ver_blank_start,
1972 device_timing.ver_blank_end);
1973 viafb_load_reg_num =
1974 iga2_crtc_reg.ver_blank_end.reg_num;
1975 reg = iga2_crtc_reg.ver_blank_end.reg;
1976 break;
1977 case V_SYNC_START_INDEX:
1978 reg_value =
1979 IGA2_VER_SYNC_START_FORMULA
1980 (device_timing.ver_sync_start);
1981 viafb_load_reg_num =
1982 iga2_crtc_reg.ver_sync_start.reg_num;
1983 reg = iga2_crtc_reg.ver_sync_start.reg;
1984 break;
1985 case V_SYNC_END_INDEX:
1986 reg_value =
1987 IGA2_VER_SYNC_END_FORMULA
1988 (device_timing.ver_sync_start,
1989 device_timing.ver_sync_end);
1990 viafb_load_reg_num =
1991 iga2_crtc_reg.ver_sync_end.reg_num;
1992 reg = iga2_crtc_reg.ver_sync_end.reg;
1993 break;
1994
1995 }
1996 }
1997 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1998 }
1999
2000 viafb_lock_crt();
2001}
2002
Joseph Chand61e0bf2008-10-15 22:03:23 -07002003void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002004 struct VideoModeTable *video_mode, int bpp_byte, int set_iga)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002005{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002006 struct display_timing crt_reg;
2007 int i;
2008 int index = 0;
2009 int h_addr, v_addr;
Florian Tobias Schandinat726abbc2011-03-16 16:31:32 +00002010 u32 pll_D_N, clock, refresh = viafb_refresh;
2011
2012 if (viafb_SAMM_ON && set_iga == IGA2)
2013 refresh = viafb_refresh1;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002014
Joseph Chand61e0bf2008-10-15 22:03:23 -07002015 for (i = 0; i < video_mode->mode_array; i++) {
2016 index = i;
2017
Florian Tobias Schandinat726abbc2011-03-16 16:31:32 +00002018 if (crt_table[i].refresh_rate == refresh)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002019 break;
2020 }
2021
2022 crt_reg = crt_table[index].crtc;
2023
2024 /* Mode 640x480 has border, but LCD/DFP didn't have border. */
2025 /* So we would delete border. */
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002026 if ((viafb_LCD_ON | viafb_DVI_ON)
2027 && video_mode->crtc[0].crtc.hor_addr == 640
2028 && video_mode->crtc[0].crtc.ver_addr == 480
Florian Tobias Schandinat726abbc2011-03-16 16:31:32 +00002029 && refresh == 60) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07002030 /* The border is 8 pixels. */
2031 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
2032
2033 /* Blanking time should add left and right borders. */
2034 crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
2035 }
2036
2037 h_addr = crt_reg.hor_addr;
2038 v_addr = crt_reg.ver_addr;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002039 if (set_iga == IGA1) {
2040 viafb_unlock_crt();
2041 viafb_write_reg(CR09, VIACR, 0x00); /*initial CR09=0 */
2042 viafb_write_reg_mask(CR11, VIACR, 0x00, BIT4 + BIT5 + BIT6);
2043 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
2044 }
2045
2046 switch (set_iga) {
2047 case IGA1:
2048 viafb_load_crtc_timing(crt_reg, IGA1);
2049 break;
2050 case IGA2:
2051 viafb_load_crtc_timing(crt_reg, IGA2);
2052 break;
2053 }
2054
2055 load_fix_bit_crtc_reg();
2056 viafb_lock_crt();
2057 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002058 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
2059
2060 /* load FIFO */
2061 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
2062 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
2063 viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
2064
Florian Tobias Schandinatfd3cc692011-03-11 00:04:01 +00002065 clock = crt_reg.hor_total * crt_reg.ver_total
2066 * crt_table[index].refresh_rate;
2067 pll_D_N = viafb_get_clk_value(clock);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002068 DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
2069 viafb_set_vclock(pll_D_N, set_iga);
2070
2071}
2072
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002073void __devinit viafb_init_chip_info(int chip_type)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002074{
Jonathan Corbet24b4d822010-04-22 13:48:09 -06002075 init_gfx_chip_info(chip_type);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002076 init_tmds_chip_info();
2077 init_lvds_chip_info();
2078
2079 viaparinfo->crt_setting_info->iga_path = IGA1;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002080
2081 /*Set IGA path for each device */
2082 viafb_set_iga_path();
2083
2084 viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002085 viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
2086 viaparinfo->lvds_setting_info2->display_method =
2087 viaparinfo->lvds_setting_info->display_method;
2088 viaparinfo->lvds_setting_info2->lcd_mode =
2089 viaparinfo->lvds_setting_info->lcd_mode;
2090}
2091
Florian Tobias Schandinat726abbc2011-03-16 16:31:32 +00002092void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002093{
2094 if (flag == 0) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07002095 viaparinfo->tmds_setting_info->h_active = hres;
2096 viaparinfo->tmds_setting_info->v_active = vres;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002097
2098 viaparinfo->lvds_setting_info->h_active = hres;
2099 viaparinfo->lvds_setting_info->v_active = vres;
2100 viaparinfo->lvds_setting_info->bpp = bpp;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002101 viaparinfo->lvds_setting_info2->h_active = hres;
2102 viaparinfo->lvds_setting_info2->v_active = vres;
2103 viaparinfo->lvds_setting_info2->bpp = bpp;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002104 } else {
2105
2106 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
2107 viaparinfo->tmds_setting_info->h_active = hres;
2108 viaparinfo->tmds_setting_info->v_active = vres;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002109 }
2110
2111 if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
2112 viaparinfo->lvds_setting_info->h_active = hres;
2113 viaparinfo->lvds_setting_info->v_active = vres;
2114 viaparinfo->lvds_setting_info->bpp = bpp;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002115 }
2116 if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
2117 viaparinfo->lvds_setting_info2->h_active = hres;
2118 viaparinfo->lvds_setting_info2->v_active = vres;
2119 viaparinfo->lvds_setting_info2->bpp = bpp;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002120 }
2121 }
2122}
2123
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002124static void __devinit init_gfx_chip_info(int chip_type)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002125{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002126 u8 tmp;
2127
Jonathan Corbet24b4d822010-04-22 13:48:09 -06002128 viaparinfo->chip_info->gfx_chip_name = chip_type;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002129
2130 /* Check revision of CLE266 Chip */
2131 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
2132 /* CR4F only define in CLE266.CX chip */
2133 tmp = viafb_read_reg(VIACR, CR4F);
2134 viafb_write_reg(CR4F, VIACR, 0x55);
2135 if (viafb_read_reg(VIACR, CR4F) != 0x55)
2136 viaparinfo->chip_info->gfx_chip_revision =
2137 CLE266_REVISION_AX;
2138 else
2139 viaparinfo->chip_info->gfx_chip_revision =
2140 CLE266_REVISION_CX;
2141 /* restore orignal CR4F value */
2142 viafb_write_reg(CR4F, VIACR, tmp);
2143 }
2144
2145 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
2146 tmp = viafb_read_reg(VIASR, SR43);
2147 DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
2148 if (tmp & 0x02) {
2149 viaparinfo->chip_info->gfx_chip_revision =
2150 CX700_REVISION_700M2;
2151 } else if (tmp & 0x40) {
2152 viaparinfo->chip_info->gfx_chip_revision =
2153 CX700_REVISION_700M;
2154 } else {
2155 viaparinfo->chip_info->gfx_chip_revision =
2156 CX700_REVISION_700;
2157 }
2158 }
Harald Welte107ea342009-05-20 01:36:03 +08002159
2160 /* Determine which 2D engine we have */
2161 switch (viaparinfo->chip_info->gfx_chip_name) {
2162 case UNICHROME_VX800:
2163 case UNICHROME_VX855:
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00002164 case UNICHROME_VX900:
Harald Welte107ea342009-05-20 01:36:03 +08002165 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1;
2166 break;
2167 case UNICHROME_K8M890:
2168 case UNICHROME_P4M900:
2169 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5;
2170 break;
2171 default:
2172 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2;
2173 break;
2174 }
Joseph Chand61e0bf2008-10-15 22:03:23 -07002175}
2176
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002177static void __devinit init_tmds_chip_info(void)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002178{
2179 viafb_tmds_trasmitter_identify();
2180
2181 if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
2182 output_interface) {
2183 switch (viaparinfo->chip_info->gfx_chip_name) {
2184 case UNICHROME_CX700:
2185 {
2186 /* we should check support by hardware layout.*/
2187 if ((viafb_display_hardware_layout ==
2188 HW_LAYOUT_DVI_ONLY)
2189 || (viafb_display_hardware_layout ==
2190 HW_LAYOUT_LCD_DVI)) {
2191 viaparinfo->chip_info->tmds_chip_info.
2192 output_interface = INTERFACE_TMDS;
2193 } else {
2194 viaparinfo->chip_info->tmds_chip_info.
2195 output_interface =
2196 INTERFACE_NONE;
2197 }
2198 break;
2199 }
2200 case UNICHROME_K8M890:
2201 case UNICHROME_P4M900:
2202 case UNICHROME_P4M890:
2203 /* TMDS on PCIE, we set DFPLOW as default. */
2204 viaparinfo->chip_info->tmds_chip_info.output_interface =
2205 INTERFACE_DFP_LOW;
2206 break;
2207 default:
2208 {
2209 /* set DVP1 default for DVI */
2210 viaparinfo->chip_info->tmds_chip_info
2211 .output_interface = INTERFACE_DVP1;
2212 }
2213 }
2214 }
2215
2216 DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
2217 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
Florian Tobias Schandinatc5f06f52010-03-10 15:21:30 -08002218 viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info,
2219 &viaparinfo->shared->tmds_setting_info);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002220}
2221
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002222static void __devinit init_lvds_chip_info(void)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002223{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002224 viafb_lvds_trasmitter_identify();
2225 viafb_init_lcd_size();
2226 viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
2227 viaparinfo->lvds_setting_info);
2228 if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
2229 viafb_init_lvds_output_interface(&viaparinfo->chip_info->
2230 lvds_chip_info2, viaparinfo->lvds_setting_info2);
2231 }
2232 /*If CX700,two singel LCD, we need to reassign
2233 LCD interface to different LVDS port */
2234 if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
2235 && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
2236 if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
2237 lvds_chip_name) && (INTEGRATED_LVDS ==
2238 viaparinfo->chip_info->
2239 lvds_chip_info2.lvds_chip_name)) {
2240 viaparinfo->chip_info->lvds_chip_info.output_interface =
2241 INTERFACE_LVDS0;
2242 viaparinfo->chip_info->lvds_chip_info2.
2243 output_interface =
2244 INTERFACE_LVDS1;
2245 }
2246 }
2247
2248 DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
2249 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
2250 DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
2251 viaparinfo->chip_info->lvds_chip_info.output_interface);
2252 DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
2253 viaparinfo->chip_info->lvds_chip_info.output_interface);
2254}
2255
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002256void __devinit viafb_init_dac(int set_iga)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002257{
2258 int i;
2259 u8 tmp;
2260
2261 if (set_iga == IGA1) {
2262 /* access Primary Display's LUT */
2263 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
2264 /* turn off LCK */
2265 viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
2266 for (i = 0; i < 256; i++) {
2267 write_dac_reg(i, palLUT_table[i].red,
2268 palLUT_table[i].green,
2269 palLUT_table[i].blue);
2270 }
2271 /* turn on LCK */
2272 viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
2273 } else {
2274 tmp = viafb_read_reg(VIACR, CR6A);
2275 /* access Secondary Display's LUT */
2276 viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
2277 viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
2278 for (i = 0; i < 256; i++) {
2279 write_dac_reg(i, palLUT_table[i].red,
2280 palLUT_table[i].green,
2281 palLUT_table[i].blue);
2282 }
2283 /* set IGA1 DAC for default */
2284 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
2285 viafb_write_reg(CR6A, VIACR, tmp);
2286 }
2287}
2288
2289static void device_screen_off(void)
2290{
2291 /* turn off CRT screen (IGA1) */
2292 viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
2293}
2294
2295static void device_screen_on(void)
2296{
2297 /* turn on CRT screen (IGA1) */
2298 viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
2299}
2300
2301static void set_display_channel(void)
2302{
2303 /*If viafb_LCD2_ON, on cx700, internal lvds's information
2304 is keeped on lvds_setting_info2 */
2305 if (viafb_LCD2_ON &&
2306 viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
2307 /* For dual channel LCD: */
2308 /* Set to Dual LVDS channel. */
2309 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
2310 } else if (viafb_LCD_ON && viafb_DVI_ON) {
2311 /* For LCD+DFP: */
2312 /* Set to LVDS1 + TMDS channel. */
2313 viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
2314 } else if (viafb_DVI_ON) {
2315 /* Set to single TMDS channel. */
2316 viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
2317 } else if (viafb_LCD_ON) {
2318 if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
2319 /* For dual channel LCD: */
2320 /* Set to Dual LVDS channel. */
2321 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
2322 } else {
2323 /* Set to LVDS0 + LVDS1 channel. */
2324 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
2325 }
2326 }
2327}
2328
Florian Tobias Schandinat2e1abbd2010-09-19 01:20:19 +00002329static u8 get_sync(struct fb_info *info)
2330{
2331 u8 polarity = 0;
2332
2333 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
2334 polarity |= VIA_HSYNC_NEGATIVE;
2335 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
2336 polarity |= VIA_VSYNC_NEGATIVE;
2337 return polarity;
2338}
2339
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002340int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2341 struct VideoModeTable *vmode_tbl1, int video_bpp1)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002342{
2343 int i, j;
2344 int port;
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00002345 u32 devices = viaparinfo->shared->iga1_devices
2346 | viaparinfo->shared->iga2_devices;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002347 u8 value, index, mask;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002348 struct crt_mode_table *crt_timing;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002349 struct crt_mode_table *crt_timing1 = NULL;
2350
Joseph Chand61e0bf2008-10-15 22:03:23 -07002351 device_screen_off();
Joseph Chand61e0bf2008-10-15 22:03:23 -07002352 crt_timing = vmode_tbl->crtc;
2353
2354 if (viafb_SAMM_ON == 1) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07002355 crt_timing1 = vmode_tbl1->crtc;
2356 }
2357
2358 inb(VIAStatus);
2359 outb(0x00, VIAAR);
2360
2361 /* Write Common Setting for Video Mode */
2362 switch (viaparinfo->chip_info->gfx_chip_name) {
2363 case UNICHROME_CLE266:
2364 viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
2365 break;
2366
2367 case UNICHROME_K400:
2368 viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
2369 break;
2370
2371 case UNICHROME_K800:
2372 case UNICHROME_PM800:
2373 viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
2374 break;
2375
2376 case UNICHROME_CN700:
2377 case UNICHROME_K8M890:
2378 case UNICHROME_P4M890:
2379 case UNICHROME_P4M900:
2380 viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
2381 break;
2382
2383 case UNICHROME_CX700:
Joseph Chand61e0bf2008-10-15 22:03:23 -07002384 case UNICHROME_VX800:
Florian Tobias Schandinat0e3ca332009-09-22 16:47:10 -07002385 viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002386 break;
Harald Welte0306ab12009-09-22 16:47:35 -07002387
2388 case UNICHROME_VX855:
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00002389 case UNICHROME_VX900:
Harald Welte0306ab12009-09-22 16:47:35 -07002390 viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
2391 break;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002392 }
2393
Florian Tobias Schandinatbf5ea022011-01-05 10:36:05 +00002394 viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
Joseph Chand61e0bf2008-10-15 22:03:23 -07002395 device_off();
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00002396 via_set_state(devices, VIA_STATE_OFF);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002397
2398 /* Fill VPIT Parameters */
2399 /* Write Misc Register */
Florian Tobias Schandinat162fc8c2010-04-17 19:44:55 +00002400 outb(VPIT.Misc, VIA_MISC_REG_WRITE);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002401
2402 /* Write Sequencer */
Florian Tobias Schandinat384c3042010-04-17 19:44:54 +00002403 for (i = 1; i <= StdSR; i++)
2404 via_write_reg(VIASR, i, VPIT.SR[i - 1]);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002405
Florian Tobias Schandinat415559f2010-03-10 15:21:40 -08002406 viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002407
2408 /* Write CRTC */
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002409 viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002410
2411 /* Write Graphic Controller */
Florian Tobias Schandinat384c3042010-04-17 19:44:54 +00002412 for (i = 0; i < StdGR; i++)
2413 via_write_reg(VIAGR, i, VPIT.GR[i]);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002414
2415 /* Write Attribute Controller */
2416 for (i = 0; i < StdAR; i++) {
2417 inb(VIAStatus);
2418 outb(i, VIAAR);
2419 outb(VPIT.AR[i], VIAAR);
2420 }
2421
2422 inb(VIAStatus);
2423 outb(0x20, VIAAR);
2424
2425 /* Update Patch Register */
2426
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002427 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
2428 || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
2429 && vmode_tbl->crtc[0].crtc.hor_addr == 1024
2430 && vmode_tbl->crtc[0].crtc.ver_addr == 768) {
2431 for (j = 0; j < res_patch_table[0].table_length; j++) {
2432 index = res_patch_table[0].io_reg_table[j].index;
2433 port = res_patch_table[0].io_reg_table[j].port;
2434 value = res_patch_table[0].io_reg_table[j].value;
2435 mask = res_patch_table[0].io_reg_table[j].mask;
2436 viafb_write_reg_mask(index, port, value, mask);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002437 }
2438 }
2439
Florian Tobias Schandinat27494132010-04-17 19:44:52 +00002440 via_set_primary_pitch(viafbinfo->fix.line_length);
2441 via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
Florian Tobias Schandinat2d6e8852009-09-22 16:47:29 -07002442 : viafbinfo->fix.line_length);
Florian Tobias Schandinat27494132010-04-17 19:44:52 +00002443 via_set_primary_color_depth(viaparinfo->depth);
2444 via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
Florian Tobias Schandinatdaacccd2010-03-10 15:21:35 -08002445 : viaparinfo->depth);
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +00002446 via_set_source(viaparinfo->shared->iga1_devices, IGA1);
2447 via_set_source(viaparinfo->shared->iga2_devices, IGA2);
2448 if (viaparinfo->shared->iga2_devices)
2449 enable_second_display_channel();
2450 else
2451 disable_second_display_channel();
2452
Joseph Chand61e0bf2008-10-15 22:03:23 -07002453 /* Update Refresh Rate Setting */
2454
2455 /* Clear On Screen */
2456
2457 /* CRT set mode */
2458 if (viafb_CRT_ON) {
2459 if (viafb_SAMM_ON && (viaparinfo->crt_setting_info->iga_path ==
2460 IGA2)) {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002461 viafb_fill_crtc_timing(crt_timing1, vmode_tbl1,
Joseph Chand61e0bf2008-10-15 22:03:23 -07002462 video_bpp1 / 8,
2463 viaparinfo->crt_setting_info->iga_path);
2464 } else {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002465 viafb_fill_crtc_timing(crt_timing, vmode_tbl,
Joseph Chand61e0bf2008-10-15 22:03:23 -07002466 video_bpp / 8,
2467 viaparinfo->crt_setting_info->iga_path);
2468 }
2469
Joseph Chand61e0bf2008-10-15 22:03:23 -07002470 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
2471 to 8 alignment (1368),there is several pixels (2 pixels)
2472 on right side of screen. */
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002473 if (vmode_tbl->crtc[0].crtc.hor_addr % 8) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07002474 viafb_unlock_crt();
2475 viafb_write_reg(CR02, VIACR,
2476 viafb_read_reg(VIACR, CR02) - 1);
2477 viafb_lock_crt();
2478 }
2479 }
2480
2481 if (viafb_DVI_ON) {
2482 if (viafb_SAMM_ON &&
2483 (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002484 viafb_dvi_set_mode(viafb_get_mode
Joseph Chand61e0bf2008-10-15 22:03:23 -07002485 (viaparinfo->tmds_setting_info->h_active,
2486 viaparinfo->tmds_setting_info->
Florian Tobias Schandinat52159442009-08-06 15:07:34 -07002487 v_active),
Joseph Chand61e0bf2008-10-15 22:03:23 -07002488 video_bpp1, viaparinfo->
2489 tmds_setting_info->iga_path);
2490 } else {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002491 viafb_dvi_set_mode(viafb_get_mode
Joseph Chand61e0bf2008-10-15 22:03:23 -07002492 (viaparinfo->tmds_setting_info->h_active,
2493 viaparinfo->
Florian Tobias Schandinat52159442009-08-06 15:07:34 -07002494 tmds_setting_info->v_active),
Joseph Chand61e0bf2008-10-15 22:03:23 -07002495 video_bpp, viaparinfo->
2496 tmds_setting_info->iga_path);
2497 }
2498 }
2499
2500 if (viafb_LCD_ON) {
2501 if (viafb_SAMM_ON &&
2502 (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
2503 viaparinfo->lvds_setting_info->bpp = video_bpp1;
2504 viafb_lcd_set_mode(crt_timing1, viaparinfo->
2505 lvds_setting_info,
2506 &viaparinfo->chip_info->lvds_chip_info);
2507 } else {
2508 /* IGA1 doesn't have LCD scaling, so set it center. */
2509 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
2510 viaparinfo->lvds_setting_info->display_method =
2511 LCD_CENTERING;
2512 }
2513 viaparinfo->lvds_setting_info->bpp = video_bpp;
2514 viafb_lcd_set_mode(crt_timing, viaparinfo->
2515 lvds_setting_info,
2516 &viaparinfo->chip_info->lvds_chip_info);
2517 }
2518 }
2519 if (viafb_LCD2_ON) {
2520 if (viafb_SAMM_ON &&
2521 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
2522 viaparinfo->lvds_setting_info2->bpp = video_bpp1;
2523 viafb_lcd_set_mode(crt_timing1, viaparinfo->
2524 lvds_setting_info2,
2525 &viaparinfo->chip_info->lvds_chip_info2);
2526 } else {
2527 /* IGA1 doesn't have LCD scaling, so set it center. */
2528 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
2529 viaparinfo->lvds_setting_info2->display_method =
2530 LCD_CENTERING;
2531 }
2532 viaparinfo->lvds_setting_info2->bpp = video_bpp;
2533 viafb_lcd_set_mode(crt_timing, viaparinfo->
2534 lvds_setting_info2,
2535 &viaparinfo->chip_info->lvds_chip_info2);
2536 }
2537 }
2538
2539 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
2540 && (viafb_LCD_ON || viafb_DVI_ON))
2541 set_display_channel();
2542
2543 /* If set mode normally, save resolution information for hot-plug . */
2544 if (!viafb_hotplug) {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002545 viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr;
2546 viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002547 viafb_hotplug_bpp = video_bpp;
2548 viafb_hotplug_refresh = viafb_refresh;
2549
2550 if (viafb_DVI_ON)
2551 viafb_DeviceStatus = DVI_Device;
2552 else
2553 viafb_DeviceStatus = CRT_Device;
2554 }
2555 device_on();
Florian Tobias Schandinat2e1abbd2010-09-19 01:20:19 +00002556 if (!viafb_dual_fb)
2557 via_set_sync_polarity(devices, get_sync(viafbinfo));
2558 else {
2559 via_set_sync_polarity(viaparinfo->shared->iga1_devices,
2560 get_sync(viafbinfo));
2561 via_set_sync_polarity(viaparinfo->shared->iga2_devices,
2562 get_sync(viafbinfo1));
2563 }
2564
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00002565 via_set_state(devices, VIA_STATE_ON);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002566 device_screen_on();
2567 return 1;
2568}
2569
2570int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
2571{
2572 int i;
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002573 struct crt_mode_table *best;
2574 struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002575
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002576 if (!vmode)
2577 return RES_640X480_60HZ_PIXCLOCK;
2578
2579 best = &vmode->crtc[0];
2580 for (i = 1; i < vmode->mode_array; i++) {
2581 if (abs(vmode->crtc[i].refresh_rate - vmode_refresh)
2582 < abs(best->refresh_rate - vmode_refresh))
2583 best = &vmode->crtc[i];
Joseph Chand61e0bf2008-10-15 22:03:23 -07002584 }
Joseph Chand61e0bf2008-10-15 22:03:23 -07002585
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002586 return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total)
2587 * 1000 / best->refresh_rate;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002588}
2589
2590int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2591{
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002592 int i;
2593 struct crt_mode_table *best;
2594 struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
2595
2596 if (!vmode)
2597 return 60;
2598
2599 best = &vmode->crtc[0];
2600 for (i = 1; i < vmode->mode_array; i++) {
2601 if (abs(vmode->crtc[i].refresh_rate - long_refresh)
2602 < abs(best->refresh_rate - long_refresh))
2603 best = &vmode->crtc[i];
Joseph Chand61e0bf2008-10-15 22:03:23 -07002604 }
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002605
Florian Tobias Schandinatb4ce6a22011-04-15 21:35:25 +00002606 if (abs(best->refresh_rate - long_refresh) > 3) {
2607 if (hres == 1200 && vres == 900)
Florian Tobias Schandinatc5a4e6d2011-04-23 22:24:52 +00002608 return 49; /* OLPC DCON only supports 50 Hz */
Florian Tobias Schandinatb4ce6a22011-04-15 21:35:25 +00002609 else
2610 return 60;
2611 }
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002612
2613 return best->refresh_rate;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002614}
2615
2616static void device_off(void)
2617{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002618 viafb_dvi_disable();
2619 viafb_lcd_disable();
2620}
2621
2622static void device_on(void)
2623{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002624 if (viafb_DVI_ON == 1)
2625 viafb_dvi_enable();
2626 if (viafb_LCD_ON == 1)
2627 viafb_lcd_enable();
2628}
2629
Joseph Chand61e0bf2008-10-15 22:03:23 -07002630static void enable_second_display_channel(void)
2631{
2632 /* to enable second display channel. */
2633 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2634 viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
2635 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2636}
2637
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +00002638static void disable_second_display_channel(void)
2639{
2640 /* to disable second display channel. */
2641 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2642 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
2643 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2644}
2645
Joseph Chand61e0bf2008-10-15 22:03:23 -07002646void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2647 *p_gfx_dpa_setting)
2648{
2649 switch (output_interface) {
2650 case INTERFACE_DVP0:
2651 {
2652 /* DVP0 Clock Polarity and Adjust: */
2653 viafb_write_reg_mask(CR96, VIACR,
2654 p_gfx_dpa_setting->DVP0, 0x0F);
2655
2656 /* DVP0 Clock and Data Pads Driving: */
2657 viafb_write_reg_mask(SR1E, VIASR,
2658 p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
2659 viafb_write_reg_mask(SR2A, VIASR,
2660 p_gfx_dpa_setting->DVP0ClockDri_S1,
2661 BIT4);
2662 viafb_write_reg_mask(SR1B, VIASR,
2663 p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
2664 viafb_write_reg_mask(SR2A, VIASR,
2665 p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
2666 break;
2667 }
2668
2669 case INTERFACE_DVP1:
2670 {
2671 /* DVP1 Clock Polarity and Adjust: */
2672 viafb_write_reg_mask(CR9B, VIACR,
2673 p_gfx_dpa_setting->DVP1, 0x0F);
2674
2675 /* DVP1 Clock and Data Pads Driving: */
2676 viafb_write_reg_mask(SR65, VIASR,
2677 p_gfx_dpa_setting->DVP1Driving, 0x0F);
2678 break;
2679 }
2680
2681 case INTERFACE_DFP_HIGH:
2682 {
2683 viafb_write_reg_mask(CR97, VIACR,
2684 p_gfx_dpa_setting->DFPHigh, 0x0F);
2685 break;
2686 }
2687
2688 case INTERFACE_DFP_LOW:
2689 {
2690 viafb_write_reg_mask(CR99, VIACR,
2691 p_gfx_dpa_setting->DFPLow, 0x0F);
2692 break;
2693 }
2694
2695 case INTERFACE_DFP:
2696 {
2697 viafb_write_reg_mask(CR97, VIACR,
2698 p_gfx_dpa_setting->DFPHigh, 0x0F);
2699 viafb_write_reg_mask(CR99, VIACR,
2700 p_gfx_dpa_setting->DFPLow, 0x0F);
2701 break;
2702 }
2703 }
2704}
2705
Joseph Chand61e0bf2008-10-15 22:03:23 -07002706/*According var's xres, yres fill var's other timing information*/
2707void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002708 struct VideoModeTable *vmode_tbl)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002709{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002710 struct crt_mode_table *crt_timing = NULL;
2711 struct display_timing crt_reg;
2712 int i = 0, index = 0;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002713 crt_timing = vmode_tbl->crtc;
2714 for (i = 0; i < vmode_tbl->mode_array; i++) {
2715 index = i;
2716 if (crt_timing[i].refresh_rate == refresh)
2717 break;
2718 }
2719
2720 crt_reg = crt_timing[index].crtc;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002721 var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
2722 var->left_margin =
2723 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
2724 var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
2725 var->hsync_len = crt_reg.hor_sync_end;
2726 var->upper_margin =
2727 crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
2728 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
2729 var->vsync_len = crt_reg.ver_sync_end;
Florian Tobias Schandinat2e1abbd2010-09-19 01:20:19 +00002730 var->sync = 0;
2731 if (crt_timing[index].h_sync_polarity == POSITIVE)
2732 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2733 if (crt_timing[index].v_sync_polarity == POSITIVE)
2734 var->sync |= FB_SYNC_VERT_HIGH_ACT;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002735}