blob: 5b9c096654be5f1baceab10b8723fe2c08da885d [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>
Joseph Chand61e0bf2008-10-15 22:03:23 -070023#include "global.h"
24
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +000025static struct pll_config cle266_pll_config[] = {
26 {19, 4, 0},
27 {26, 5, 0},
28 {28, 5, 0},
29 {31, 5, 0},
30 {33, 5, 0},
31 {55, 5, 0},
32 {102, 5, 0},
33 {53, 6, 0},
34 {92, 6, 0},
35 {98, 6, 0},
36 {112, 6, 0},
37 {41, 7, 0},
38 {60, 7, 0},
39 {99, 7, 0},
40 {100, 7, 0},
41 {83, 8, 0},
42 {86, 8, 0},
43 {108, 8, 0},
44 {87, 9, 0},
45 {118, 9, 0},
46 {95, 12, 0},
47 {115, 12, 0},
48 {108, 13, 0},
49 {83, 17, 0},
50 {67, 20, 0},
51 {86, 20, 0},
52 {98, 20, 0},
53 {121, 24, 0},
54 {99, 29, 0},
55 {33, 3, 1},
56 {15, 4, 1},
57 {23, 4, 1},
58 {37, 5, 1},
59 {83, 5, 1},
60 {85, 5, 1},
61 {94, 5, 1},
62 {103, 5, 1},
63 {109, 5, 1},
64 {113, 5, 1},
65 {121, 5, 1},
66 {82, 6, 1},
67 {31, 7, 1},
68 {55, 7, 1},
69 {84, 7, 1},
70 {83, 8, 1},
71 {76, 9, 1},
72 {127, 9, 1},
73 {33, 4, 2},
74 {75, 4, 2},
75 {119, 4, 2},
76 {121, 4, 2},
77 {91, 5, 2},
78 {118, 5, 2},
79 {83, 6, 2},
80 {109, 6, 2},
81 {90, 7, 2},
82 {93, 2, 3},
83 {53, 3, 3},
84 {73, 4, 3},
85 {89, 4, 3},
86 {105, 4, 3},
87 {117, 4, 3},
88 {101, 5, 3},
89 {121, 5, 3},
90 {127, 5, 3},
91 {99, 7, 3}
92};
93
94static struct pll_config k800_pll_config[] = {
95 {22, 2, 0},
96 {28, 3, 0},
97 {81, 3, 1},
98 {85, 3, 1},
99 {98, 3, 1},
100 {112, 3, 1},
101 {86, 4, 1},
102 {166, 4, 1},
103 {109, 5, 1},
104 {113, 5, 1},
105 {121, 5, 1},
106 {131, 5, 1},
107 {143, 5, 1},
108 {153, 5, 1},
109 {66, 3, 2},
110 {68, 3, 2},
111 {95, 3, 2},
112 {106, 3, 2},
113 {116, 3, 2},
114 {93, 4, 2},
115 {119, 4, 2},
116 {121, 4, 2},
117 {133, 4, 2},
118 {137, 4, 2},
119 {117, 5, 2},
120 {118, 5, 2},
121 {120, 5, 2},
122 {124, 5, 2},
123 {132, 5, 2},
124 {137, 5, 2},
125 {141, 5, 2},
126 {166, 5, 2},
127 {170, 5, 2},
128 {191, 5, 2},
129 {206, 5, 2},
130 {208, 5, 2},
131 {30, 2, 3},
132 {69, 3, 3},
133 {82, 3, 3},
134 {83, 3, 3},
135 {109, 3, 3},
136 {114, 3, 3},
137 {125, 3, 3},
138 {89, 4, 3},
139 {103, 4, 3},
140 {117, 4, 3},
141 {126, 4, 3},
142 {150, 4, 3},
143 {161, 4, 3},
144 {121, 5, 3},
145 {127, 5, 3},
146 {131, 5, 3},
147 {134, 5, 3},
148 {148, 5, 3},
149 {169, 5, 3},
150 {172, 5, 3},
151 {182, 5, 3},
152 {195, 5, 3},
153 {196, 5, 3},
154 {208, 5, 3},
155 {66, 2, 4},
156 {85, 3, 4},
157 {141, 4, 4},
158 {146, 4, 4},
159 {161, 4, 4},
160 {177, 5, 4}
161};
162
163static struct pll_config cx700_pll_config[] = {
164 {98, 3, 1},
165 {86, 4, 1},
166 {109, 5, 1},
167 {110, 5, 1},
168 {113, 5, 1},
169 {121, 5, 1},
170 {131, 5, 1},
171 {135, 5, 1},
172 {142, 5, 1},
173 {143, 5, 1},
174 {153, 5, 1},
175 {187, 5, 1},
176 {208, 5, 1},
177 {68, 2, 2},
178 {95, 3, 2},
179 {116, 3, 2},
180 {93, 4, 2},
181 {119, 4, 2},
182 {133, 4, 2},
183 {137, 4, 2},
184 {151, 4, 2},
185 {166, 4, 2},
186 {110, 5, 2},
187 {112, 5, 2},
188 {117, 5, 2},
189 {118, 5, 2},
190 {120, 5, 2},
191 {132, 5, 2},
192 {137, 5, 2},
193 {141, 5, 2},
194 {151, 5, 2},
195 {166, 5, 2},
196 {175, 5, 2},
197 {191, 5, 2},
198 {206, 5, 2},
199 {174, 7, 2},
200 {82, 3, 3},
201 {109, 3, 3},
202 {117, 4, 3},
203 {150, 4, 3},
204 {161, 4, 3},
205 {112, 5, 3},
206 {115, 5, 3},
207 {121, 5, 3},
208 {127, 5, 3},
209 {129, 5, 3},
210 {131, 5, 3},
211 {134, 5, 3},
212 {138, 5, 3},
213 {148, 5, 3},
214 {157, 5, 3},
215 {169, 5, 3},
216 {172, 5, 3},
217 {190, 5, 3},
218 {195, 5, 3},
219 {196, 5, 3},
220 {208, 5, 3},
221 {141, 5, 4},
222 {150, 5, 4},
223 {166, 5, 4},
224 {176, 5, 4},
225 {177, 5, 4},
226 {183, 5, 4},
227 {202, 5, 4}
228};
229
230static struct pll_config vx855_pll_config[] = {
231 {86, 4, 1},
232 {108, 5, 1},
233 {110, 5, 1},
234 {113, 5, 1},
235 {121, 5, 1},
236 {131, 5, 1},
237 {135, 5, 1},
238 {142, 5, 1},
239 {143, 5, 1},
240 {153, 5, 1},
241 {164, 5, 1},
242 {187, 5, 1},
243 {208, 5, 1},
244 {110, 5, 2},
245 {112, 5, 2},
246 {117, 5, 2},
247 {118, 5, 2},
248 {124, 5, 2},
249 {132, 5, 2},
250 {137, 5, 2},
251 {141, 5, 2},
252 {149, 5, 2},
253 {151, 5, 2},
254 {159, 5, 2},
255 {166, 5, 2},
256 {167, 5, 2},
257 {172, 5, 2},
258 {189, 5, 2},
259 {191, 5, 2},
260 {194, 5, 2},
261 {206, 5, 2},
262 {208, 5, 2},
263 {83, 3, 3},
264 {88, 3, 3},
265 {109, 3, 3},
266 {112, 3, 3},
267 {103, 4, 3},
268 {105, 4, 3},
269 {161, 4, 3},
270 {112, 5, 3},
271 {115, 5, 3},
272 {121, 5, 3},
273 {127, 5, 3},
274 {134, 5, 3},
275 {137, 5, 3},
276 {148, 5, 3},
277 {157, 5, 3},
278 {169, 5, 3},
279 {172, 5, 3},
280 {182, 5, 3},
281 {191, 5, 3},
282 {195, 5, 3},
283 {209, 5, 3},
284 {142, 4, 4},
285 {146, 4, 4},
286 {161, 4, 4},
287 {141, 5, 4},
288 {150, 5, 4},
289 {165, 5, 4},
290 {176, 5, 4}
Joseph Chand61e0bf2008-10-15 22:03:23 -0700291};
292
Florian Tobias Schandinatbf5ea022011-01-05 10:36:05 +0000293/* according to VIA Technologies these values are based on experiment */
294static struct io_reg scaling_parameters[] = {
295 {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
296 {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
297 {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
298 {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
299 {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
300 {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
301 {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
302 {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
303 {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
304 {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
305 {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
306 {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
307 {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
308 {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
309};
310
Florian Tobias Schandinat95d517c2011-03-26 23:39:07 +0000311static struct io_reg common_vga[] = {
312 {VIACR, CR07, 0x10, 0x10}, /* [0] vertical total (bit 8)
313 [1] vertical display end (bit 8)
314 [2] vertical retrace start (bit 8)
315 [3] start vertical blanking (bit 8)
316 [4] line compare (bit 8)
317 [5] vertical total (bit 9)
318 [6] vertical display end (bit 9)
319 [7] vertical retrace start (bit 9) */
320 {VIACR, CR08, 0xFF, 0x00}, /* [0-4] preset row scan
321 [5-6] byte panning */
322 {VIACR, CR09, 0xDF, 0x40}, /* [0-4] max scan line
323 [5] start vertical blanking (bit 9)
324 [6] line compare (bit 9)
325 [7] scan doubling */
326 {VIACR, CR0A, 0xFF, 0x1E}, /* [0-4] cursor start
327 [5] cursor disable */
328 {VIACR, CR0B, 0xFF, 0x00}, /* [0-4] cursor end
329 [5-6] cursor skew */
330 {VIACR, CR0E, 0xFF, 0x00}, /* [0-7] cursor location (high) */
331 {VIACR, CR0F, 0xFF, 0x00}, /* [0-7] cursor location (low) */
332 {VIACR, CR11, 0xF0, 0x80}, /* [0-3] vertical retrace end
333 [6] memory refresh bandwidth
334 [7] CRTC register protect enable */
335 {VIACR, CR14, 0xFF, 0x00}, /* [0-4] underline location
336 [5] divide memory address clock by 4
337 [6] double word addressing */
338 {VIACR, CR17, 0xFF, 0x63}, /* [0-1] mapping of display address 13-14
339 [2] divide scan line clock by 2
340 [3] divide memory address clock by 2
341 [5] address wrap
342 [6] byte mode select
343 [7] sync enable */
344 {VIACR, CR18, 0xFF, 0xFF}, /* [0-7] line compare */
345};
346
Joseph Chand61e0bf2008-10-15 22:03:23 -0700347static struct fifo_depth_select display_fifo_depth_reg = {
348 /* IGA1 FIFO Depth_Select */
349 {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
350 /* IGA2 FIFO Depth_Select */
351 {IGA2_FIFO_DEPTH_SELECT_REG_NUM,
352 {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
353};
354
355static struct fifo_threshold_select fifo_threshold_select_reg = {
356 /* IGA1 FIFO Threshold Select */
357 {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
358 /* IGA2 FIFO Threshold Select */
359 {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
360};
361
362static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
363 /* IGA1 FIFO High Threshold Select */
364 {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
365 /* IGA2 FIFO High Threshold Select */
366 {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
367};
368
369static struct display_queue_expire_num display_queue_expire_num_reg = {
370 /* IGA1 Display Queue Expire Num */
371 {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
372 /* IGA2 Display Queue Expire Num */
373 {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
374};
375
376/* Definition Fetch Count Registers*/
377static struct fetch_count fetch_count_reg = {
378 /* IGA1 Fetch Count Register */
379 {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
380 /* IGA2 Fetch Count Register */
381 {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
382};
383
384static struct iga1_crtc_timing iga1_crtc_reg = {
385 /* IGA1 Horizontal Total */
386 {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } },
387 /* IGA1 Horizontal Addressable Video */
388 {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } },
389 /* IGA1 Horizontal Blank Start */
390 {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } },
391 /* IGA1 Horizontal Blank End */
392 {IGA1_HOR_BLANK_END_REG_NUM,
393 {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } },
394 /* IGA1 Horizontal Sync Start */
395 {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } },
396 /* IGA1 Horizontal Sync End */
397 {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } },
398 /* IGA1 Vertical Total */
399 {IGA1_VER_TOTAL_REG_NUM,
400 {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } },
401 /* IGA1 Vertical Addressable Video */
402 {IGA1_VER_ADDR_REG_NUM,
403 {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } },
404 /* IGA1 Vertical Blank Start */
405 {IGA1_VER_BLANK_START_REG_NUM,
406 {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } },
407 /* IGA1 Vertical Blank End */
408 {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } },
409 /* IGA1 Vertical Sync Start */
410 {IGA1_VER_SYNC_START_REG_NUM,
411 {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } },
412 /* IGA1 Vertical Sync End */
413 {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } }
414};
415
416static struct iga2_crtc_timing iga2_crtc_reg = {
417 /* IGA2 Horizontal Total */
418 {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } },
419 /* IGA2 Horizontal Addressable Video */
420 {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } },
421 /* IGA2 Horizontal Blank Start */
422 {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } },
423 /* IGA2 Horizontal Blank End */
424 {IGA2_HOR_BLANK_END_REG_NUM,
425 {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } },
426 /* IGA2 Horizontal Sync Start */
427 {IGA2_HOR_SYNC_START_REG_NUM,
428 {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } },
429 /* IGA2 Horizontal Sync End */
430 {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } },
431 /* IGA2 Vertical Total */
432 {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } },
433 /* IGA2 Vertical Addressable Video */
434 {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } },
435 /* IGA2 Vertical Blank Start */
436 {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } },
437 /* IGA2 Vertical Blank End */
438 {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } },
439 /* IGA2 Vertical Sync Start */
440 {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } },
441 /* IGA2 Vertical Sync End */
442 {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } }
443};
444
445static struct rgbLUT palLUT_table[] = {
446 /* {R,G,B} */
447 /* Index 0x00~0x03 */
448 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
449 0x2A,
450 0x2A},
451 /* Index 0x04~0x07 */
452 {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
453 0x2A,
454 0x2A},
455 /* Index 0x08~0x0B */
456 {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
457 0x3F,
458 0x3F},
459 /* Index 0x0C~0x0F */
460 {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
461 0x3F,
462 0x3F},
463 /* Index 0x10~0x13 */
464 {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
465 0x0B,
466 0x0B},
467 /* Index 0x14~0x17 */
468 {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
469 0x18,
470 0x18},
471 /* Index 0x18~0x1B */
472 {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
473 0x28,
474 0x28},
475 /* Index 0x1C~0x1F */
476 {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
477 0x3F,
478 0x3F},
479 /* Index 0x20~0x23 */
480 {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
481 0x00,
482 0x3F},
483 /* Index 0x24~0x27 */
484 {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
485 0x00,
486 0x10},
487 /* Index 0x28~0x2B */
488 {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
489 0x2F,
490 0x00},
491 /* Index 0x2C~0x2F */
492 {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
493 0x3F,
494 0x00},
495 /* Index 0x30~0x33 */
496 {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
497 0x3F,
498 0x2F},
499 /* Index 0x34~0x37 */
500 {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
501 0x10,
502 0x3F},
503 /* Index 0x38~0x3B */
504 {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
505 0x1F,
506 0x3F},
507 /* Index 0x3C~0x3F */
508 {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
509 0x1F,
510 0x27},
511 /* Index 0x40~0x43 */
512 {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
513 0x3F,
514 0x1F},
515 /* Index 0x44~0x47 */
516 {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
517 0x3F,
518 0x1F},
519 /* Index 0x48~0x4B */
520 {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
521 0x3F,
522 0x37},
523 /* Index 0x4C~0x4F */
524 {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
525 0x27,
526 0x3F},
527 /* Index 0x50~0x53 */
528 {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
529 0x2D,
530 0x3F},
531 /* Index 0x54~0x57 */
532 {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
533 0x2D,
534 0x31},
535 /* Index 0x58~0x5B */
536 {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
537 0x3A,
538 0x2D},
539 /* Index 0x5C~0x5F */
540 {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
541 0x3F,
542 0x2D},
543 /* Index 0x60~0x63 */
544 {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
545 0x3F,
546 0x3A},
547 /* Index 0x64~0x67 */
548 {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
549 0x31,
550 0x3F},
551 /* Index 0x68~0x6B */
552 {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
553 0x00,
554 0x1C},
555 /* Index 0x6C~0x6F */
556 {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
557 0x00,
558 0x07},
559 /* Index 0x70~0x73 */
560 {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
561 0x15,
562 0x00},
563 /* Index 0x74~0x77 */
564 {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
565 0x1C,
566 0x00},
567 /* Index 0x78~0x7B */
568 {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
569 0x1C,
570 0x15},
571 /* Index 0x7C~0x7F */
572 {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
573 0x07,
574 0x1C},
575 /* Index 0x80~0x83 */
576 {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
577 0x0E,
578 0x1C},
579 /* Index 0x84~0x87 */
580 {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
581 0x0E,
582 0x11},
583 /* Index 0x88~0x8B */
584 {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
585 0x18,
586 0x0E},
587 /* Index 0x8C~0x8F */
588 {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
589 0x1C,
590 0x0E},
591 /* Index 0x90~0x93 */
592 {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
593 0x1C,
594 0x18},
595 /* Index 0x94~0x97 */
596 {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
597 0x11,
598 0x1C},
599 /* Index 0x98~0x9B */
600 {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
601 0x14,
602 0x1C},
603 /* Index 0x9C~0x9F */
604 {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
605 0x14,
606 0x16},
607 /* Index 0xA0~0xA3 */
608 {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
609 0x1A,
610 0x14},
611 /* Index 0xA4~0xA7 */
612 {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
613 0x1C,
614 0x14},
615 /* Index 0xA8~0xAB */
616 {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
617 0x1C,
618 0x1A},
619 /* Index 0xAC~0xAF */
620 {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
621 0x16,
622 0x1C},
623 /* Index 0xB0~0xB3 */
624 {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
625 0x00,
626 0x10},
627 /* Index 0xB4~0xB7 */
628 {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
629 0x00,
630 0x04},
631 /* Index 0xB8~0xBB */
632 {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
633 0x0C,
634 0x00},
635 /* Index 0xBC~0xBF */
636 {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
637 0x10,
638 0x00},
639 /* Index 0xC0~0xC3 */
640 {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
641 0x10,
642 0x0C},
643 /* Index 0xC4~0xC7 */
644 {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
645 0x04,
646 0x10},
647 /* Index 0xC8~0xCB */
648 {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
649 0x08,
650 0x10},
651 /* Index 0xCC~0xCF */
652 {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
653 0x08,
654 0x0A},
655 /* Index 0xD0~0xD3 */
656 {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
657 0x0E,
658 0x08},
659 /* Index 0xD4~0xD7 */
660 {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
661 0x10,
662 0x08},
663 /* Index 0xD8~0xDB */
664 {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
665 0x10,
666 0x0E},
667 /* Index 0xDC~0xDF */
668 {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
669 0x0A,
670 0x10},
671 /* Index 0xE0~0xE3 */
672 {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
673 0x0B,
674 0x10},
675 /* Index 0xE4~0xE7 */
676 {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
677 0x0B,
678 0x0C},
679 /* Index 0xE8~0xEB */
680 {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
681 0x0F,
682 0x0B},
683 /* Index 0xEC~0xEF */
684 {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
685 0x10,
686 0x0B},
687 /* Index 0xF0~0xF3 */
688 {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
689 0x10,
690 0x0F},
691 /* Index 0xF4~0xF7 */
692 {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
693 0x0C,
694 0x10},
695 /* Index 0xF8~0xFB */
696 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
697 0x00,
698 0x00},
699 /* Index 0xFC~0xFF */
700 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
701 0x00,
702 0x00}
703};
704
Florian Tobias Schandinat2a918392010-09-05 01:33:28 +0000705static struct via_device_mapping device_mapping[] = {
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000706 {VIA_LDVP0, "LDVP0"},
707 {VIA_LDVP1, "LDVP1"},
708 {VIA_DVP0, "DVP0"},
Florian Tobias Schandinat2a918392010-09-05 01:33:28 +0000709 {VIA_CRT, "CRT"},
710 {VIA_DVP1, "DVP1"},
711 {VIA_LVDS1, "LVDS1"},
712 {VIA_LVDS2, "LVDS2"}
713};
714
Joseph Chand61e0bf2008-10-15 22:03:23 -0700715static void load_fix_bit_crtc_reg(void);
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +0000716static void __devinit init_gfx_chip_info(int chip_type);
717static void __devinit init_tmds_chip_info(void);
718static void __devinit init_lvds_chip_info(void);
Joseph Chand61e0bf2008-10-15 22:03:23 -0700719static void device_screen_off(void);
720static void device_screen_on(void);
721static void set_display_channel(void);
722static void device_off(void);
723static void device_on(void);
724static void enable_second_display_channel(void);
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +0000725static void disable_second_display_channel(void);
Joseph Chand61e0bf2008-10-15 22:03:23 -0700726
Joseph Chand61e0bf2008-10-15 22:03:23 -0700727void viafb_lock_crt(void)
728{
729 viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
730}
731
732void viafb_unlock_crt(void)
733{
734 viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
735 viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
736}
737
Stephen Hemminger23e5abd2011-03-03 10:00:08 -0800738static void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
Joseph Chand61e0bf2008-10-15 22:03:23 -0700739{
740 outb(index, LUT_INDEX_WRITE);
741 outb(r, LUT_DATA);
742 outb(g, LUT_DATA);
743 outb(b, LUT_DATA);
744}
745
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000746static u32 get_dvi_devices(int output_interface)
747{
748 switch (output_interface) {
749 case INTERFACE_DVP0:
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000750 return VIA_DVP0 | VIA_LDVP0;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000751
752 case INTERFACE_DVP1:
753 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000754 return VIA_LDVP1;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000755 else
756 return VIA_DVP1;
757
758 case INTERFACE_DFP_HIGH:
759 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
760 return 0;
761 else
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000762 return VIA_LVDS2 | VIA_DVP0;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000763
764 case INTERFACE_DFP_LOW:
765 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
766 return 0;
767 else
768 return VIA_DVP1 | VIA_LVDS1;
769
770 case INTERFACE_TMDS:
771 return VIA_LVDS1;
772 }
773
774 return 0;
775}
776
777static u32 get_lcd_devices(int output_interface)
778{
779 switch (output_interface) {
780 case INTERFACE_DVP0:
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000781 return VIA_DVP0;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000782
783 case INTERFACE_DVP1:
784 return VIA_DVP1;
785
786 case INTERFACE_DFP_HIGH:
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000787 return VIA_LVDS2 | VIA_DVP0;
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000788
789 case INTERFACE_DFP_LOW:
790 return VIA_LVDS1 | VIA_DVP1;
791
792 case INTERFACE_DFP:
793 return VIA_LVDS1 | VIA_LVDS2;
794
795 case INTERFACE_LVDS0:
796 case INTERFACE_LVDS0LVDS1:
797 return VIA_LVDS1;
798
799 case INTERFACE_LVDS1:
800 return VIA_LVDS2;
801 }
802
803 return 0;
804}
805
Joseph Chand61e0bf2008-10-15 22:03:23 -0700806/*Set IGA path for each device*/
807void viafb_set_iga_path(void)
808{
Florian Tobias Schandinat05236562011-03-21 01:46:24 +0000809 int crt_iga_path = 0;
Joseph Chand61e0bf2008-10-15 22:03:23 -0700810
811 if (viafb_SAMM_ON == 1) {
812 if (viafb_CRT_ON) {
813 if (viafb_primary_dev == CRT_Device)
Florian Tobias Schandinat05236562011-03-21 01:46:24 +0000814 crt_iga_path = IGA1;
Joseph Chand61e0bf2008-10-15 22:03:23 -0700815 else
Florian Tobias Schandinat05236562011-03-21 01:46:24 +0000816 crt_iga_path = IGA2;
Joseph Chand61e0bf2008-10-15 22:03:23 -0700817 }
818
819 if (viafb_DVI_ON) {
820 if (viafb_primary_dev == DVI_Device)
821 viaparinfo->tmds_setting_info->iga_path = IGA1;
822 else
823 viaparinfo->tmds_setting_info->iga_path = IGA2;
824 }
825
826 if (viafb_LCD_ON) {
827 if (viafb_primary_dev == LCD_Device) {
828 if (viafb_dual_fb &&
829 (viaparinfo->chip_info->gfx_chip_name ==
830 UNICHROME_CLE266)) {
831 viaparinfo->
832 lvds_setting_info->iga_path = IGA2;
Florian Tobias Schandinat05236562011-03-21 01:46:24 +0000833 crt_iga_path = IGA1;
Joseph Chand61e0bf2008-10-15 22:03:23 -0700834 viaparinfo->
835 tmds_setting_info->iga_path = IGA1;
836 } else
837 viaparinfo->
838 lvds_setting_info->iga_path = IGA1;
839 } else {
840 viaparinfo->lvds_setting_info->iga_path = IGA2;
841 }
842 }
843 if (viafb_LCD2_ON) {
844 if (LCD2_Device == viafb_primary_dev)
845 viaparinfo->lvds_setting_info2->iga_path = IGA1;
846 else
847 viaparinfo->lvds_setting_info2->iga_path = IGA2;
848 }
849 } else {
850 viafb_SAMM_ON = 0;
851
852 if (viafb_CRT_ON && viafb_LCD_ON) {
Florian Tobias Schandinat05236562011-03-21 01:46:24 +0000853 crt_iga_path = IGA1;
Joseph Chand61e0bf2008-10-15 22:03:23 -0700854 viaparinfo->lvds_setting_info->iga_path = IGA2;
855 } else if (viafb_CRT_ON && viafb_DVI_ON) {
Florian Tobias Schandinat05236562011-03-21 01:46:24 +0000856 crt_iga_path = IGA1;
Joseph Chand61e0bf2008-10-15 22:03:23 -0700857 viaparinfo->tmds_setting_info->iga_path = IGA2;
858 } else if (viafb_LCD_ON && viafb_DVI_ON) {
859 viaparinfo->tmds_setting_info->iga_path = IGA1;
860 viaparinfo->lvds_setting_info->iga_path = IGA2;
861 } else if (viafb_LCD_ON && viafb_LCD2_ON) {
862 viaparinfo->lvds_setting_info->iga_path = IGA2;
863 viaparinfo->lvds_setting_info2->iga_path = IGA2;
864 } else if (viafb_CRT_ON) {
Florian Tobias Schandinat05236562011-03-21 01:46:24 +0000865 crt_iga_path = IGA1;
Joseph Chand61e0bf2008-10-15 22:03:23 -0700866 } else if (viafb_LCD_ON) {
867 viaparinfo->lvds_setting_info->iga_path = IGA2;
868 } else if (viafb_DVI_ON) {
869 viaparinfo->tmds_setting_info->iga_path = IGA1;
870 }
871 }
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000872
873 viaparinfo->shared->iga1_devices = 0;
874 viaparinfo->shared->iga2_devices = 0;
875 if (viafb_CRT_ON) {
Florian Tobias Schandinat05236562011-03-21 01:46:24 +0000876 if (crt_iga_path == IGA1)
Florian Tobias Schandinat18d9dc02010-08-10 02:44:44 +0000877 viaparinfo->shared->iga1_devices |= VIA_CRT;
878 else
879 viaparinfo->shared->iga2_devices |= VIA_CRT;
880 }
881
882 if (viafb_DVI_ON) {
883 if (viaparinfo->tmds_setting_info->iga_path == IGA1)
884 viaparinfo->shared->iga1_devices |= get_dvi_devices(
885 viaparinfo->chip_info->
886 tmds_chip_info.output_interface);
887 else
888 viaparinfo->shared->iga2_devices |= get_dvi_devices(
889 viaparinfo->chip_info->
890 tmds_chip_info.output_interface);
891 }
892
893 if (viafb_LCD_ON) {
894 if (viaparinfo->lvds_setting_info->iga_path == IGA1)
895 viaparinfo->shared->iga1_devices |= get_lcd_devices(
896 viaparinfo->chip_info->
897 lvds_chip_info.output_interface);
898 else
899 viaparinfo->shared->iga2_devices |= get_lcd_devices(
900 viaparinfo->chip_info->
901 lvds_chip_info.output_interface);
902 }
903
904 if (viafb_LCD2_ON) {
905 if (viaparinfo->lvds_setting_info2->iga_path == IGA1)
906 viaparinfo->shared->iga1_devices |= get_lcd_devices(
907 viaparinfo->chip_info->
908 lvds_chip_info2.output_interface);
909 else
910 viaparinfo->shared->iga2_devices |= get_lcd_devices(
911 viaparinfo->chip_info->
912 lvds_chip_info2.output_interface);
913 }
Joseph Chand61e0bf2008-10-15 22:03:23 -0700914}
915
Florian Tobias Schandinat415559f2010-03-10 15:21:40 -0800916static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
917{
918 outb(0xFF, 0x3C6); /* bit mask of palette */
919 outb(index, 0x3C8);
920 outb(red, 0x3C9);
921 outb(green, 0x3C9);
922 outb(blue, 0x3C9);
923}
924
925void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
926{
927 viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
928 set_color_register(index, red, green, blue);
929}
930
931void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
932{
933 viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
934 set_color_register(index, red, green, blue);
935}
936
Florian Tobias Schandinata54be172010-07-28 23:06:04 +0000937static void set_source_common(u8 index, u8 offset, u8 iga)
938{
939 u8 value, mask = 1 << offset;
940
941 switch (iga) {
942 case IGA1:
943 value = 0x00;
944 break;
945 case IGA2:
946 value = mask;
947 break;
948 default:
949 printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
950 return;
951 }
952
953 via_write_reg_mask(VIACR, index, value, mask);
954}
955
956static void set_crt_source(u8 iga)
957{
958 u8 value;
959
960 switch (iga) {
961 case IGA1:
962 value = 0x00;
963 break;
964 case IGA2:
965 value = 0x40;
966 break;
967 default:
968 printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
969 return;
970 }
971
972 via_write_reg_mask(VIASR, 0x16, value, 0x40);
973}
974
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000975static inline void set_ldvp0_source(u8 iga)
Florian Tobias Schandinata54be172010-07-28 23:06:04 +0000976{
977 set_source_common(0x6C, 7, iga);
978}
979
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000980static inline void set_ldvp1_source(u8 iga)
Florian Tobias Schandinata54be172010-07-28 23:06:04 +0000981{
982 set_source_common(0x93, 7, iga);
983}
984
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +0000985static inline void set_dvp0_source(u8 iga)
Florian Tobias Schandinata54be172010-07-28 23:06:04 +0000986{
987 set_source_common(0x96, 4, iga);
988}
989
990static inline void set_dvp1_source(u8 iga)
991{
992 set_source_common(0x9B, 4, iga);
993}
994
995static inline void set_lvds1_source(u8 iga)
996{
997 set_source_common(0x99, 4, iga);
998}
999
1000static inline void set_lvds2_source(u8 iga)
1001{
1002 set_source_common(0x97, 4, iga);
1003}
1004
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +00001005void via_set_source(u32 devices, u8 iga)
Joseph Chand61e0bf2008-10-15 22:03:23 -07001006{
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +00001007 if (devices & VIA_LDVP0)
1008 set_ldvp0_source(iga);
1009 if (devices & VIA_LDVP1)
1010 set_ldvp1_source(iga);
1011 if (devices & VIA_DVP0)
1012 set_dvp0_source(iga);
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +00001013 if (devices & VIA_CRT)
1014 set_crt_source(iga);
1015 if (devices & VIA_DVP1)
1016 set_dvp1_source(iga);
1017 if (devices & VIA_LVDS1)
1018 set_lvds1_source(iga);
1019 if (devices & VIA_LVDS2)
1020 set_lvds2_source(iga);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001021}
1022
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00001023static void set_crt_state(u8 state)
1024{
1025 u8 value;
1026
1027 switch (state) {
1028 case VIA_STATE_ON:
1029 value = 0x00;
1030 break;
1031 case VIA_STATE_STANDBY:
1032 value = 0x10;
1033 break;
1034 case VIA_STATE_SUSPEND:
1035 value = 0x20;
1036 break;
1037 case VIA_STATE_OFF:
1038 value = 0x30;
1039 break;
1040 default:
1041 return;
1042 }
1043
1044 via_write_reg_mask(VIACR, 0x36, value, 0x30);
1045}
1046
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +00001047static void set_dvp0_state(u8 state)
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00001048{
1049 u8 value;
1050
1051 switch (state) {
1052 case VIA_STATE_ON:
1053 value = 0xC0;
1054 break;
1055 case VIA_STATE_OFF:
1056 value = 0x00;
1057 break;
1058 default:
1059 return;
1060 }
1061
1062 via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
1063}
1064
1065static void set_dvp1_state(u8 state)
1066{
1067 u8 value;
1068
1069 switch (state) {
1070 case VIA_STATE_ON:
1071 value = 0x30;
1072 break;
1073 case VIA_STATE_OFF:
1074 value = 0x00;
1075 break;
1076 default:
1077 return;
1078 }
1079
1080 via_write_reg_mask(VIASR, 0x1E, value, 0x30);
1081}
1082
1083static void set_lvds1_state(u8 state)
1084{
1085 u8 value;
1086
1087 switch (state) {
1088 case VIA_STATE_ON:
1089 value = 0x03;
1090 break;
1091 case VIA_STATE_OFF:
1092 value = 0x00;
1093 break;
1094 default:
1095 return;
1096 }
1097
1098 via_write_reg_mask(VIASR, 0x2A, value, 0x03);
1099}
1100
1101static void set_lvds2_state(u8 state)
1102{
1103 u8 value;
1104
1105 switch (state) {
1106 case VIA_STATE_ON:
1107 value = 0x0C;
1108 break;
1109 case VIA_STATE_OFF:
1110 value = 0x00;
1111 break;
1112 default:
1113 return;
1114 }
1115
1116 via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
1117}
1118
1119void via_set_state(u32 devices, u8 state)
1120{
1121 /*
1122 TODO: Can we enable/disable these devices? How?
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +00001123 if (devices & VIA_LDVP0)
1124 if (devices & VIA_LDVP1)
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00001125 */
Florian Tobias Schandinata2aa9f92010-09-19 04:40:15 +00001126 if (devices & VIA_DVP0)
1127 set_dvp0_state(state);
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00001128 if (devices & VIA_CRT)
1129 set_crt_state(state);
1130 if (devices & VIA_DVP1)
1131 set_dvp1_state(state);
1132 if (devices & VIA_LVDS1)
1133 set_lvds1_state(state);
1134 if (devices & VIA_LVDS2)
1135 set_lvds2_state(state);
1136}
1137
Florian Tobias Schandinat7f0e1532010-09-18 23:47:28 +00001138void via_set_sync_polarity(u32 devices, u8 polarity)
1139{
1140 if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
1141 printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
1142 polarity);
1143 return;
1144 }
1145
1146 if (devices & VIA_CRT)
1147 via_write_misc_reg_mask(polarity << 6, 0xC0);
1148 if (devices & VIA_DVP1)
1149 via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
1150 if (devices & VIA_LVDS1)
1151 via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
1152 if (devices & VIA_LVDS2)
1153 via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
1154}
1155
Florian Tobias Schandinat2a918392010-09-05 01:33:28 +00001156u32 via_parse_odev(char *input, char **end)
1157{
1158 char *ptr = input;
1159 u32 odev = 0;
1160 bool next = true;
1161 int i, len;
1162
1163 while (next) {
1164 next = false;
1165 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
1166 len = strlen(device_mapping[i].name);
1167 if (!strncmp(ptr, device_mapping[i].name, len)) {
1168 odev |= device_mapping[i].device;
1169 ptr += len;
1170 if (*ptr == ',') {
1171 ptr++;
1172 next = true;
1173 }
1174 }
1175 }
1176 }
1177
1178 *end = ptr;
1179 return odev;
1180}
1181
1182void via_odev_to_seq(struct seq_file *m, u32 odev)
1183{
1184 int i, count = 0;
1185
1186 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
1187 if (odev & device_mapping[i].device) {
1188 if (count > 0)
1189 seq_putc(m, ',');
1190
1191 seq_puts(m, device_mapping[i].name);
1192 count++;
1193 }
1194 }
1195
1196 seq_putc(m, '\n');
1197}
1198
Joseph Chand61e0bf2008-10-15 22:03:23 -07001199static void load_fix_bit_crtc_reg(void)
1200{
Florian Tobias Schandinat0f8132b2011-03-16 13:11:17 +00001201 viafb_unlock_crt();
1202
Joseph Chand61e0bf2008-10-15 22:03:23 -07001203 /* always set to 1 */
1204 viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
1205 /* line compare should set all bits = 1 (extend modes) */
Joseph Chand61e0bf2008-10-15 22:03:23 -07001206 viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
1207 /* line compare should set all bits = 1 (extend modes) */
1208 viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
1209 /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
Florian Tobias Schandinat0f8132b2011-03-16 13:11:17 +00001210
1211 viafb_lock_crt();
Joseph Chand61e0bf2008-10-15 22:03:23 -07001212
1213 /* If K8M800, enable Prefetch Mode. */
1214 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
1215 || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
1216 viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
1217 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
1218 && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
1219 viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
1220
1221}
1222
1223void viafb_load_reg(int timing_value, int viafb_load_reg_num,
1224 struct io_register *reg,
1225 int io_type)
1226{
1227 int reg_mask;
1228 int bit_num = 0;
1229 int data;
1230 int i, j;
1231 int shift_next_reg;
1232 int start_index, end_index, cr_index;
1233 u16 get_bit;
1234
1235 for (i = 0; i < viafb_load_reg_num; i++) {
1236 reg_mask = 0;
1237 data = 0;
1238 start_index = reg[i].start_bit;
1239 end_index = reg[i].end_bit;
1240 cr_index = reg[i].io_addr;
1241
1242 shift_next_reg = bit_num;
1243 for (j = start_index; j <= end_index; j++) {
1244 /*if (bit_num==8) timing_value = timing_value >>8; */
1245 reg_mask = reg_mask | (BIT0 << j);
1246 get_bit = (timing_value & (BIT0 << bit_num));
1247 data =
1248 data | ((get_bit >> shift_next_reg) << start_index);
1249 bit_num++;
1250 }
1251 if (io_type == VIACR)
1252 viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
1253 else
1254 viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
1255 }
1256
1257}
1258
1259/* Write Registers */
1260void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
1261{
1262 int i;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001263
1264 /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
1265
Florian Tobias Schandinat384c3042010-04-17 19:44:54 +00001266 for (i = 0; i < ItemNum; i++)
1267 via_write_reg_mask(RegTable[i].port, RegTable[i].index,
1268 RegTable[i].value, RegTable[i].mask);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001269}
1270
Joseph Chand61e0bf2008-10-15 22:03:23 -07001271void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
1272{
1273 int reg_value;
1274 int viafb_load_reg_num;
1275 struct io_register *reg = NULL;
1276
1277 switch (set_iga) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07001278 case IGA1:
1279 reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1280 viafb_load_reg_num = fetch_count_reg.
1281 iga1_fetch_count_reg.reg_num;
1282 reg = fetch_count_reg.iga1_fetch_count_reg.reg;
1283 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001284 break;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001285 case IGA2:
1286 reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1287 viafb_load_reg_num = fetch_count_reg.
1288 iga2_fetch_count_reg.reg_num;
1289 reg = fetch_count_reg.iga2_fetch_count_reg.reg;
1290 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1291 break;
1292 }
1293
1294}
1295
1296void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1297{
1298 int reg_value;
1299 int viafb_load_reg_num;
1300 struct io_register *reg = NULL;
1301 int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
1302 0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
1303 int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
1304 0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
1305
1306 if (set_iga == IGA1) {
1307 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1308 iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
1309 iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
1310 iga1_fifo_high_threshold =
1311 K800_IGA1_FIFO_HIGH_THRESHOLD;
1312 /* If resolution > 1280x1024, expire length = 64, else
1313 expire length = 128 */
1314 if ((hor_active > 1280) && (ver_active > 1024))
1315 iga1_display_queue_expire_num = 16;
1316 else
1317 iga1_display_queue_expire_num =
1318 K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1319
1320 }
1321
1322 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1323 iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
1324 iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
1325 iga1_fifo_high_threshold =
1326 P880_IGA1_FIFO_HIGH_THRESHOLD;
1327 iga1_display_queue_expire_num =
1328 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1329
1330 /* If resolution > 1280x1024, expire length = 64, else
1331 expire length = 128 */
1332 if ((hor_active > 1280) && (ver_active > 1024))
1333 iga1_display_queue_expire_num = 16;
1334 else
1335 iga1_display_queue_expire_num =
1336 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1337 }
1338
1339 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1340 iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
1341 iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
1342 iga1_fifo_high_threshold =
1343 CN700_IGA1_FIFO_HIGH_THRESHOLD;
1344
1345 /* If resolution > 1280x1024, expire length = 64,
1346 else expire length = 128 */
1347 if ((hor_active > 1280) && (ver_active > 1024))
1348 iga1_display_queue_expire_num = 16;
1349 else
1350 iga1_display_queue_expire_num =
1351 CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1352 }
1353
1354 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1355 iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
1356 iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
1357 iga1_fifo_high_threshold =
1358 CX700_IGA1_FIFO_HIGH_THRESHOLD;
1359 iga1_display_queue_expire_num =
1360 CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1361 }
1362
1363 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1364 iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
1365 iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
1366 iga1_fifo_high_threshold =
1367 K8M890_IGA1_FIFO_HIGH_THRESHOLD;
1368 iga1_display_queue_expire_num =
1369 K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1370 }
1371
1372 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1373 iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
1374 iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
1375 iga1_fifo_high_threshold =
1376 P4M890_IGA1_FIFO_HIGH_THRESHOLD;
1377 iga1_display_queue_expire_num =
1378 P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1379 }
1380
1381 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1382 iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
1383 iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
1384 iga1_fifo_high_threshold =
1385 P4M900_IGA1_FIFO_HIGH_THRESHOLD;
1386 iga1_display_queue_expire_num =
1387 P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1388 }
1389
1390 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1391 iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
1392 iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
1393 iga1_fifo_high_threshold =
1394 VX800_IGA1_FIFO_HIGH_THRESHOLD;
1395 iga1_display_queue_expire_num =
1396 VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1397 }
1398
Harald Welte0306ab12009-09-22 16:47:35 -07001399 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1400 iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH;
1401 iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD;
1402 iga1_fifo_high_threshold =
1403 VX855_IGA1_FIFO_HIGH_THRESHOLD;
1404 iga1_display_queue_expire_num =
1405 VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1406 }
1407
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00001408 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1409 iga1_fifo_max_depth = VX900_IGA1_FIFO_MAX_DEPTH;
1410 iga1_fifo_threshold = VX900_IGA1_FIFO_THRESHOLD;
1411 iga1_fifo_high_threshold =
1412 VX900_IGA1_FIFO_HIGH_THRESHOLD;
1413 iga1_display_queue_expire_num =
1414 VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1415 }
1416
Joseph Chand61e0bf2008-10-15 22:03:23 -07001417 /* Set Display FIFO Depath Select */
1418 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
1419 viafb_load_reg_num =
1420 display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
1421 reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
1422 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1423
1424 /* Set Display FIFO Threshold Select */
1425 reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
1426 viafb_load_reg_num =
1427 fifo_threshold_select_reg.
1428 iga1_fifo_threshold_select_reg.reg_num;
1429 reg =
1430 fifo_threshold_select_reg.
1431 iga1_fifo_threshold_select_reg.reg;
1432 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1433
1434 /* Set FIFO High Threshold Select */
1435 reg_value =
1436 IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
1437 viafb_load_reg_num =
1438 fifo_high_threshold_select_reg.
1439 iga1_fifo_high_threshold_select_reg.reg_num;
1440 reg =
1441 fifo_high_threshold_select_reg.
1442 iga1_fifo_high_threshold_select_reg.reg;
1443 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1444
1445 /* Set Display Queue Expire Num */
1446 reg_value =
1447 IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1448 (iga1_display_queue_expire_num);
1449 viafb_load_reg_num =
1450 display_queue_expire_num_reg.
1451 iga1_display_queue_expire_num_reg.reg_num;
1452 reg =
1453 display_queue_expire_num_reg.
1454 iga1_display_queue_expire_num_reg.reg;
1455 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1456
1457 } else {
1458 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1459 iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
1460 iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
1461 iga2_fifo_high_threshold =
1462 K800_IGA2_FIFO_HIGH_THRESHOLD;
1463
1464 /* If resolution > 1280x1024, expire length = 64,
1465 else expire length = 128 */
1466 if ((hor_active > 1280) && (ver_active > 1024))
1467 iga2_display_queue_expire_num = 16;
1468 else
1469 iga2_display_queue_expire_num =
1470 K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1471 }
1472
1473 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1474 iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
1475 iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
1476 iga2_fifo_high_threshold =
1477 P880_IGA2_FIFO_HIGH_THRESHOLD;
1478
1479 /* If resolution > 1280x1024, expire length = 64,
1480 else expire length = 128 */
1481 if ((hor_active > 1280) && (ver_active > 1024))
1482 iga2_display_queue_expire_num = 16;
1483 else
1484 iga2_display_queue_expire_num =
1485 P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1486 }
1487
1488 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1489 iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
1490 iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
1491 iga2_fifo_high_threshold =
1492 CN700_IGA2_FIFO_HIGH_THRESHOLD;
1493
1494 /* If resolution > 1280x1024, expire length = 64,
1495 else expire length = 128 */
1496 if ((hor_active > 1280) && (ver_active > 1024))
1497 iga2_display_queue_expire_num = 16;
1498 else
1499 iga2_display_queue_expire_num =
1500 CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1501 }
1502
1503 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1504 iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
1505 iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
1506 iga2_fifo_high_threshold =
1507 CX700_IGA2_FIFO_HIGH_THRESHOLD;
1508 iga2_display_queue_expire_num =
1509 CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1510 }
1511
1512 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1513 iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
1514 iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
1515 iga2_fifo_high_threshold =
1516 K8M890_IGA2_FIFO_HIGH_THRESHOLD;
1517 iga2_display_queue_expire_num =
1518 K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1519 }
1520
1521 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1522 iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
1523 iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
1524 iga2_fifo_high_threshold =
1525 P4M890_IGA2_FIFO_HIGH_THRESHOLD;
1526 iga2_display_queue_expire_num =
1527 P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1528 }
1529
1530 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1531 iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
1532 iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
1533 iga2_fifo_high_threshold =
1534 P4M900_IGA2_FIFO_HIGH_THRESHOLD;
1535 iga2_display_queue_expire_num =
1536 P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1537 }
1538
1539 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1540 iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
1541 iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
1542 iga2_fifo_high_threshold =
1543 VX800_IGA2_FIFO_HIGH_THRESHOLD;
1544 iga2_display_queue_expire_num =
1545 VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1546 }
1547
Harald Welte0306ab12009-09-22 16:47:35 -07001548 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1549 iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH;
1550 iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD;
1551 iga2_fifo_high_threshold =
1552 VX855_IGA2_FIFO_HIGH_THRESHOLD;
1553 iga2_display_queue_expire_num =
1554 VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1555 }
1556
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00001557 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1558 iga2_fifo_max_depth = VX900_IGA2_FIFO_MAX_DEPTH;
1559 iga2_fifo_threshold = VX900_IGA2_FIFO_THRESHOLD;
1560 iga2_fifo_high_threshold =
1561 VX900_IGA2_FIFO_HIGH_THRESHOLD;
1562 iga2_display_queue_expire_num =
1563 VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1564 }
1565
Joseph Chand61e0bf2008-10-15 22:03:23 -07001566 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1567 /* Set Display FIFO Depath Select */
1568 reg_value =
1569 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
1570 - 1;
1571 /* Patch LCD in IGA2 case */
1572 viafb_load_reg_num =
1573 display_fifo_depth_reg.
1574 iga2_fifo_depth_select_reg.reg_num;
1575 reg =
1576 display_fifo_depth_reg.
1577 iga2_fifo_depth_select_reg.reg;
1578 viafb_load_reg(reg_value,
1579 viafb_load_reg_num, reg, VIACR);
1580 } else {
1581
1582 /* Set Display FIFO Depath Select */
1583 reg_value =
1584 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
1585 viafb_load_reg_num =
1586 display_fifo_depth_reg.
1587 iga2_fifo_depth_select_reg.reg_num;
1588 reg =
1589 display_fifo_depth_reg.
1590 iga2_fifo_depth_select_reg.reg;
1591 viafb_load_reg(reg_value,
1592 viafb_load_reg_num, reg, VIACR);
1593 }
1594
1595 /* Set Display FIFO Threshold Select */
1596 reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
1597 viafb_load_reg_num =
1598 fifo_threshold_select_reg.
1599 iga2_fifo_threshold_select_reg.reg_num;
1600 reg =
1601 fifo_threshold_select_reg.
1602 iga2_fifo_threshold_select_reg.reg;
1603 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1604
1605 /* Set FIFO High Threshold Select */
1606 reg_value =
1607 IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
1608 viafb_load_reg_num =
1609 fifo_high_threshold_select_reg.
1610 iga2_fifo_high_threshold_select_reg.reg_num;
1611 reg =
1612 fifo_high_threshold_select_reg.
1613 iga2_fifo_high_threshold_select_reg.reg;
1614 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1615
1616 /* Set Display Queue Expire Num */
1617 reg_value =
1618 IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1619 (iga2_display_queue_expire_num);
1620 viafb_load_reg_num =
1621 display_queue_expire_num_reg.
1622 iga2_display_queue_expire_num_reg.reg_num;
1623 reg =
1624 display_queue_expire_num_reg.
1625 iga2_display_queue_expire_num_reg.reg;
1626 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1627
1628 }
1629
1630}
1631
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001632static u32 cle266_encode_pll(struct pll_config pll)
1633{
1634 return (pll.multiplier << 8)
1635 | (pll.rshift << 6)
1636 | pll.divisor;
1637}
1638
1639static u32 k800_encode_pll(struct pll_config pll)
1640{
1641 return ((pll.divisor - 2) << 16)
1642 | (pll.rshift << 10)
1643 | (pll.multiplier - 2);
1644}
1645
1646static u32 vx855_encode_pll(struct pll_config pll)
1647{
1648 return (pll.divisor << 16)
1649 | (pll.rshift << 10)
1650 | pll.multiplier;
1651}
1652
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001653static inline u32 get_pll_internal_frequency(u32 ref_freq,
1654 struct pll_config pll)
1655{
1656 return ref_freq / pll.divisor * pll.multiplier;
1657}
1658
1659static inline u32 get_pll_output_frequency(u32 ref_freq, struct pll_config pll)
1660{
1661 return get_pll_internal_frequency(ref_freq, pll)>>pll.rshift;
1662}
1663
1664static struct pll_config get_pll_config(struct pll_config *config, int size,
1665 int clk)
1666{
1667 struct pll_config best = config[0];
1668 const u32 f0 = 14318180; /* X1 frequency */
1669 int i;
1670
1671 for (i = 1; i < size; i++) {
1672 if (abs(get_pll_output_frequency(f0, config[i]) - clk)
1673 < abs(get_pll_output_frequency(f0, best) - clk))
1674 best = config[i];
1675 }
1676
1677 return best;
1678}
1679
Joseph Chand61e0bf2008-10-15 22:03:23 -07001680u32 viafb_get_clk_value(int clk)
1681{
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001682 u32 value = 0;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001683
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001684 switch (viaparinfo->chip_info->gfx_chip_name) {
1685 case UNICHROME_CLE266:
1686 case UNICHROME_K400:
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001687 value = cle266_encode_pll(get_pll_config(cle266_pll_config,
1688 ARRAY_SIZE(cle266_pll_config), clk));
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001689 break;
1690 case UNICHROME_K800:
1691 case UNICHROME_PM800:
1692 case UNICHROME_CN700:
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001693 value = k800_encode_pll(get_pll_config(k800_pll_config,
1694 ARRAY_SIZE(k800_pll_config), clk));
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001695 break;
1696 case UNICHROME_CX700:
1697 case UNICHROME_CN750:
1698 case UNICHROME_K8M890:
1699 case UNICHROME_P4M890:
1700 case UNICHROME_P4M900:
1701 case UNICHROME_VX800:
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001702 value = k800_encode_pll(get_pll_config(cx700_pll_config,
1703 ARRAY_SIZE(cx700_pll_config), clk));
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001704 break;
1705 case UNICHROME_VX855:
1706 case UNICHROME_VX900:
Florian Tobias Schandinate4fcaef2011-03-12 01:36:38 +00001707 value = vx855_encode_pll(get_pll_config(vx855_pll_config,
1708 ARRAY_SIZE(vx855_pll_config), clk));
Florian Tobias Schandinat97597a32011-03-10 22:39:22 +00001709 break;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001710 }
1711
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001712 return value;
Joseph Chand61e0bf2008-10-15 22:03:23 -07001713}
1714
1715/* Set VCLK*/
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001716void viafb_set_vclock(u32 clk, int set_iga)
Joseph Chand61e0bf2008-10-15 22:03:23 -07001717{
Joseph Chand61e0bf2008-10-15 22:03:23 -07001718 /* H.W. Reset : ON */
1719 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
1720
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001721 if (set_iga == IGA1) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07001722 /* Change D,N FOR VCLK */
1723 switch (viaparinfo->chip_info->gfx_chip_name) {
1724 case UNICHROME_CLE266:
1725 case UNICHROME_K400:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001726 via_write_reg(VIASR, SR46, (clk & 0x00FF));
1727 via_write_reg(VIASR, SR47, (clk & 0xFF00) >> 8);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001728 break;
1729
1730 case UNICHROME_K800:
1731 case UNICHROME_PM800:
1732 case UNICHROME_CN700:
1733 case UNICHROME_CX700:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001734 case UNICHROME_CN750:
Joseph Chand61e0bf2008-10-15 22:03:23 -07001735 case UNICHROME_K8M890:
1736 case UNICHROME_P4M890:
1737 case UNICHROME_P4M900:
1738 case UNICHROME_VX800:
Harald Welte0306ab12009-09-22 16:47:35 -07001739 case UNICHROME_VX855:
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00001740 case UNICHROME_VX900:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001741 via_write_reg(VIASR, SR44, (clk & 0x0000FF));
1742 via_write_reg(VIASR, SR45, (clk & 0x00FF00) >> 8);
1743 via_write_reg(VIASR, SR46, (clk & 0xFF0000) >> 16);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001744 break;
1745 }
1746 }
1747
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001748 if (set_iga == IGA2) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07001749 /* Change D,N FOR LCK */
1750 switch (viaparinfo->chip_info->gfx_chip_name) {
1751 case UNICHROME_CLE266:
1752 case UNICHROME_K400:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001753 via_write_reg(VIASR, SR44, (clk & 0x00FF));
1754 via_write_reg(VIASR, SR45, (clk & 0xFF00) >> 8);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001755 break;
1756
1757 case UNICHROME_K800:
1758 case UNICHROME_PM800:
1759 case UNICHROME_CN700:
1760 case UNICHROME_CX700:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001761 case UNICHROME_CN750:
Joseph Chand61e0bf2008-10-15 22:03:23 -07001762 case UNICHROME_K8M890:
1763 case UNICHROME_P4M890:
1764 case UNICHROME_P4M900:
1765 case UNICHROME_VX800:
Harald Welte0306ab12009-09-22 16:47:35 -07001766 case UNICHROME_VX855:
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00001767 case UNICHROME_VX900:
Florian Tobias Schandinat1f844352010-07-11 00:57:34 +00001768 via_write_reg(VIASR, SR4A, (clk & 0x0000FF));
1769 via_write_reg(VIASR, SR4B, (clk & 0x00FF00) >> 8);
1770 via_write_reg(VIASR, SR4C, (clk & 0xFF0000) >> 16);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001771 break;
1772 }
1773 }
1774
1775 /* H.W. Reset : OFF */
1776 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
1777
1778 /* Reset PLL */
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001779 if (set_iga == IGA1) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07001780 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
1781 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
1782 }
1783
Florian Tobias Schandinat4bbac052010-03-10 15:21:36 -08001784 if (set_iga == IGA2) {
Florian Tobias Schandinate3812ce2010-07-28 00:57:18 +00001785 viafb_write_reg_mask(SR40, VIASR, 0x04, BIT2);
1786 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT2);
Joseph Chand61e0bf2008-10-15 22:03:23 -07001787 }
1788
1789 /* Fire! */
Florian Tobias Schandinat162fc8c2010-04-17 19:44:55 +00001790 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
Joseph Chand61e0bf2008-10-15 22:03:23 -07001791}
1792
1793void viafb_load_crtc_timing(struct display_timing device_timing,
1794 int set_iga)
1795{
1796 int i;
1797 int viafb_load_reg_num = 0;
1798 int reg_value = 0;
1799 struct io_register *reg = NULL;
1800
1801 viafb_unlock_crt();
1802
1803 for (i = 0; i < 12; i++) {
1804 if (set_iga == IGA1) {
1805 switch (i) {
1806 case H_TOTAL_INDEX:
1807 reg_value =
1808 IGA1_HOR_TOTAL_FORMULA(device_timing.
1809 hor_total);
1810 viafb_load_reg_num =
1811 iga1_crtc_reg.hor_total.reg_num;
1812 reg = iga1_crtc_reg.hor_total.reg;
1813 break;
1814 case H_ADDR_INDEX:
1815 reg_value =
1816 IGA1_HOR_ADDR_FORMULA(device_timing.
1817 hor_addr);
1818 viafb_load_reg_num =
1819 iga1_crtc_reg.hor_addr.reg_num;
1820 reg = iga1_crtc_reg.hor_addr.reg;
1821 break;
1822 case H_BLANK_START_INDEX:
1823 reg_value =
1824 IGA1_HOR_BLANK_START_FORMULA
1825 (device_timing.hor_blank_start);
1826 viafb_load_reg_num =
1827 iga1_crtc_reg.hor_blank_start.reg_num;
1828 reg = iga1_crtc_reg.hor_blank_start.reg;
1829 break;
1830 case H_BLANK_END_INDEX:
1831 reg_value =
1832 IGA1_HOR_BLANK_END_FORMULA
1833 (device_timing.hor_blank_start,
1834 device_timing.hor_blank_end);
1835 viafb_load_reg_num =
1836 iga1_crtc_reg.hor_blank_end.reg_num;
1837 reg = iga1_crtc_reg.hor_blank_end.reg;
1838 break;
1839 case H_SYNC_START_INDEX:
1840 reg_value =
1841 IGA1_HOR_SYNC_START_FORMULA
1842 (device_timing.hor_sync_start);
1843 viafb_load_reg_num =
1844 iga1_crtc_reg.hor_sync_start.reg_num;
1845 reg = iga1_crtc_reg.hor_sync_start.reg;
1846 break;
1847 case H_SYNC_END_INDEX:
1848 reg_value =
1849 IGA1_HOR_SYNC_END_FORMULA
1850 (device_timing.hor_sync_start,
1851 device_timing.hor_sync_end);
1852 viafb_load_reg_num =
1853 iga1_crtc_reg.hor_sync_end.reg_num;
1854 reg = iga1_crtc_reg.hor_sync_end.reg;
1855 break;
1856 case V_TOTAL_INDEX:
1857 reg_value =
1858 IGA1_VER_TOTAL_FORMULA(device_timing.
1859 ver_total);
1860 viafb_load_reg_num =
1861 iga1_crtc_reg.ver_total.reg_num;
1862 reg = iga1_crtc_reg.ver_total.reg;
1863 break;
1864 case V_ADDR_INDEX:
1865 reg_value =
1866 IGA1_VER_ADDR_FORMULA(device_timing.
1867 ver_addr);
1868 viafb_load_reg_num =
1869 iga1_crtc_reg.ver_addr.reg_num;
1870 reg = iga1_crtc_reg.ver_addr.reg;
1871 break;
1872 case V_BLANK_START_INDEX:
1873 reg_value =
1874 IGA1_VER_BLANK_START_FORMULA
1875 (device_timing.ver_blank_start);
1876 viafb_load_reg_num =
1877 iga1_crtc_reg.ver_blank_start.reg_num;
1878 reg = iga1_crtc_reg.ver_blank_start.reg;
1879 break;
1880 case V_BLANK_END_INDEX:
1881 reg_value =
1882 IGA1_VER_BLANK_END_FORMULA
1883 (device_timing.ver_blank_start,
1884 device_timing.ver_blank_end);
1885 viafb_load_reg_num =
1886 iga1_crtc_reg.ver_blank_end.reg_num;
1887 reg = iga1_crtc_reg.ver_blank_end.reg;
1888 break;
1889 case V_SYNC_START_INDEX:
1890 reg_value =
1891 IGA1_VER_SYNC_START_FORMULA
1892 (device_timing.ver_sync_start);
1893 viafb_load_reg_num =
1894 iga1_crtc_reg.ver_sync_start.reg_num;
1895 reg = iga1_crtc_reg.ver_sync_start.reg;
1896 break;
1897 case V_SYNC_END_INDEX:
1898 reg_value =
1899 IGA1_VER_SYNC_END_FORMULA
1900 (device_timing.ver_sync_start,
1901 device_timing.ver_sync_end);
1902 viafb_load_reg_num =
1903 iga1_crtc_reg.ver_sync_end.reg_num;
1904 reg = iga1_crtc_reg.ver_sync_end.reg;
1905 break;
1906
1907 }
1908 }
1909
1910 if (set_iga == IGA2) {
1911 switch (i) {
1912 case H_TOTAL_INDEX:
1913 reg_value =
1914 IGA2_HOR_TOTAL_FORMULA(device_timing.
1915 hor_total);
1916 viafb_load_reg_num =
1917 iga2_crtc_reg.hor_total.reg_num;
1918 reg = iga2_crtc_reg.hor_total.reg;
1919 break;
1920 case H_ADDR_INDEX:
1921 reg_value =
1922 IGA2_HOR_ADDR_FORMULA(device_timing.
1923 hor_addr);
1924 viafb_load_reg_num =
1925 iga2_crtc_reg.hor_addr.reg_num;
1926 reg = iga2_crtc_reg.hor_addr.reg;
1927 break;
1928 case H_BLANK_START_INDEX:
1929 reg_value =
1930 IGA2_HOR_BLANK_START_FORMULA
1931 (device_timing.hor_blank_start);
1932 viafb_load_reg_num =
1933 iga2_crtc_reg.hor_blank_start.reg_num;
1934 reg = iga2_crtc_reg.hor_blank_start.reg;
1935 break;
1936 case H_BLANK_END_INDEX:
1937 reg_value =
1938 IGA2_HOR_BLANK_END_FORMULA
1939 (device_timing.hor_blank_start,
1940 device_timing.hor_blank_end);
1941 viafb_load_reg_num =
1942 iga2_crtc_reg.hor_blank_end.reg_num;
1943 reg = iga2_crtc_reg.hor_blank_end.reg;
1944 break;
1945 case H_SYNC_START_INDEX:
1946 reg_value =
1947 IGA2_HOR_SYNC_START_FORMULA
1948 (device_timing.hor_sync_start);
1949 if (UNICHROME_CN700 <=
1950 viaparinfo->chip_info->gfx_chip_name)
1951 viafb_load_reg_num =
1952 iga2_crtc_reg.hor_sync_start.
1953 reg_num;
1954 else
1955 viafb_load_reg_num = 3;
1956 reg = iga2_crtc_reg.hor_sync_start.reg;
1957 break;
1958 case H_SYNC_END_INDEX:
1959 reg_value =
1960 IGA2_HOR_SYNC_END_FORMULA
1961 (device_timing.hor_sync_start,
1962 device_timing.hor_sync_end);
1963 viafb_load_reg_num =
1964 iga2_crtc_reg.hor_sync_end.reg_num;
1965 reg = iga2_crtc_reg.hor_sync_end.reg;
1966 break;
1967 case V_TOTAL_INDEX:
1968 reg_value =
1969 IGA2_VER_TOTAL_FORMULA(device_timing.
1970 ver_total);
1971 viafb_load_reg_num =
1972 iga2_crtc_reg.ver_total.reg_num;
1973 reg = iga2_crtc_reg.ver_total.reg;
1974 break;
1975 case V_ADDR_INDEX:
1976 reg_value =
1977 IGA2_VER_ADDR_FORMULA(device_timing.
1978 ver_addr);
1979 viafb_load_reg_num =
1980 iga2_crtc_reg.ver_addr.reg_num;
1981 reg = iga2_crtc_reg.ver_addr.reg;
1982 break;
1983 case V_BLANK_START_INDEX:
1984 reg_value =
1985 IGA2_VER_BLANK_START_FORMULA
1986 (device_timing.ver_blank_start);
1987 viafb_load_reg_num =
1988 iga2_crtc_reg.ver_blank_start.reg_num;
1989 reg = iga2_crtc_reg.ver_blank_start.reg;
1990 break;
1991 case V_BLANK_END_INDEX:
1992 reg_value =
1993 IGA2_VER_BLANK_END_FORMULA
1994 (device_timing.ver_blank_start,
1995 device_timing.ver_blank_end);
1996 viafb_load_reg_num =
1997 iga2_crtc_reg.ver_blank_end.reg_num;
1998 reg = iga2_crtc_reg.ver_blank_end.reg;
1999 break;
2000 case V_SYNC_START_INDEX:
2001 reg_value =
2002 IGA2_VER_SYNC_START_FORMULA
2003 (device_timing.ver_sync_start);
2004 viafb_load_reg_num =
2005 iga2_crtc_reg.ver_sync_start.reg_num;
2006 reg = iga2_crtc_reg.ver_sync_start.reg;
2007 break;
2008 case V_SYNC_END_INDEX:
2009 reg_value =
2010 IGA2_VER_SYNC_END_FORMULA
2011 (device_timing.ver_sync_start,
2012 device_timing.ver_sync_end);
2013 viafb_load_reg_num =
2014 iga2_crtc_reg.ver_sync_end.reg_num;
2015 reg = iga2_crtc_reg.ver_sync_end.reg;
2016 break;
2017
2018 }
2019 }
2020 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
2021 }
2022
2023 viafb_lock_crt();
2024}
2025
Joseph Chand61e0bf2008-10-15 22:03:23 -07002026void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002027 struct VideoModeTable *video_mode, int bpp_byte, int set_iga)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002028{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002029 struct display_timing crt_reg;
2030 int i;
2031 int index = 0;
2032 int h_addr, v_addr;
Florian Tobias Schandinat726abbc2011-03-16 16:31:32 +00002033 u32 pll_D_N, clock, refresh = viafb_refresh;
2034
2035 if (viafb_SAMM_ON && set_iga == IGA2)
2036 refresh = viafb_refresh1;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002037
Joseph Chand61e0bf2008-10-15 22:03:23 -07002038 for (i = 0; i < video_mode->mode_array; i++) {
2039 index = i;
2040
Florian Tobias Schandinat726abbc2011-03-16 16:31:32 +00002041 if (crt_table[i].refresh_rate == refresh)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002042 break;
2043 }
2044
2045 crt_reg = crt_table[index].crtc;
2046
2047 /* Mode 640x480 has border, but LCD/DFP didn't have border. */
2048 /* So we would delete border. */
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002049 if ((viafb_LCD_ON | viafb_DVI_ON)
2050 && video_mode->crtc[0].crtc.hor_addr == 640
2051 && video_mode->crtc[0].crtc.ver_addr == 480
Florian Tobias Schandinat726abbc2011-03-16 16:31:32 +00002052 && refresh == 60) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07002053 /* The border is 8 pixels. */
2054 crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8;
2055
2056 /* Blanking time should add left and right borders. */
2057 crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16;
2058 }
2059
2060 h_addr = crt_reg.hor_addr;
2061 v_addr = crt_reg.ver_addr;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002062 if (set_iga == IGA1) {
2063 viafb_unlock_crt();
Joseph Chand61e0bf2008-10-15 22:03:23 -07002064 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
2065 }
2066
2067 switch (set_iga) {
2068 case IGA1:
2069 viafb_load_crtc_timing(crt_reg, IGA1);
2070 break;
2071 case IGA2:
2072 viafb_load_crtc_timing(crt_reg, IGA2);
2073 break;
2074 }
2075
Joseph Chand61e0bf2008-10-15 22:03:23 -07002076 viafb_lock_crt();
2077 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002078 viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga);
2079
2080 /* load FIFO */
2081 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
2082 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
2083 viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
2084
Florian Tobias Schandinatfd3cc692011-03-11 00:04:01 +00002085 clock = crt_reg.hor_total * crt_reg.ver_total
2086 * crt_table[index].refresh_rate;
2087 pll_D_N = viafb_get_clk_value(clock);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002088 DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
2089 viafb_set_vclock(pll_D_N, set_iga);
2090
2091}
2092
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002093void __devinit viafb_init_chip_info(int chip_type)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002094{
Jonathan Corbet24b4d822010-04-22 13:48:09 -06002095 init_gfx_chip_info(chip_type);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002096 init_tmds_chip_info();
2097 init_lvds_chip_info();
2098
Joseph Chand61e0bf2008-10-15 22:03:23 -07002099 /*Set IGA path for each device */
2100 viafb_set_iga_path();
2101
2102 viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002103 viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
2104 viaparinfo->lvds_setting_info2->display_method =
2105 viaparinfo->lvds_setting_info->display_method;
2106 viaparinfo->lvds_setting_info2->lcd_mode =
2107 viaparinfo->lvds_setting_info->lcd_mode;
2108}
2109
Florian Tobias Schandinat726abbc2011-03-16 16:31:32 +00002110void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002111{
2112 if (flag == 0) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07002113 viaparinfo->tmds_setting_info->h_active = hres;
2114 viaparinfo->tmds_setting_info->v_active = vres;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002115
2116 viaparinfo->lvds_setting_info->h_active = hres;
2117 viaparinfo->lvds_setting_info->v_active = vres;
2118 viaparinfo->lvds_setting_info->bpp = bpp;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002119 viaparinfo->lvds_setting_info2->h_active = hres;
2120 viaparinfo->lvds_setting_info2->v_active = vres;
2121 viaparinfo->lvds_setting_info2->bpp = bpp;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002122 } else {
2123
2124 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
2125 viaparinfo->tmds_setting_info->h_active = hres;
2126 viaparinfo->tmds_setting_info->v_active = vres;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002127 }
2128
2129 if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
2130 viaparinfo->lvds_setting_info->h_active = hres;
2131 viaparinfo->lvds_setting_info->v_active = vres;
2132 viaparinfo->lvds_setting_info->bpp = bpp;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002133 }
2134 if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
2135 viaparinfo->lvds_setting_info2->h_active = hres;
2136 viaparinfo->lvds_setting_info2->v_active = vres;
2137 viaparinfo->lvds_setting_info2->bpp = bpp;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002138 }
2139 }
2140}
2141
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002142static void __devinit init_gfx_chip_info(int chip_type)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002143{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002144 u8 tmp;
2145
Jonathan Corbet24b4d822010-04-22 13:48:09 -06002146 viaparinfo->chip_info->gfx_chip_name = chip_type;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002147
2148 /* Check revision of CLE266 Chip */
2149 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
2150 /* CR4F only define in CLE266.CX chip */
2151 tmp = viafb_read_reg(VIACR, CR4F);
2152 viafb_write_reg(CR4F, VIACR, 0x55);
2153 if (viafb_read_reg(VIACR, CR4F) != 0x55)
2154 viaparinfo->chip_info->gfx_chip_revision =
2155 CLE266_REVISION_AX;
2156 else
2157 viaparinfo->chip_info->gfx_chip_revision =
2158 CLE266_REVISION_CX;
2159 /* restore orignal CR4F value */
2160 viafb_write_reg(CR4F, VIACR, tmp);
2161 }
2162
2163 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
2164 tmp = viafb_read_reg(VIASR, SR43);
2165 DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
2166 if (tmp & 0x02) {
2167 viaparinfo->chip_info->gfx_chip_revision =
2168 CX700_REVISION_700M2;
2169 } else if (tmp & 0x40) {
2170 viaparinfo->chip_info->gfx_chip_revision =
2171 CX700_REVISION_700M;
2172 } else {
2173 viaparinfo->chip_info->gfx_chip_revision =
2174 CX700_REVISION_700;
2175 }
2176 }
Harald Welte107ea342009-05-20 01:36:03 +08002177
2178 /* Determine which 2D engine we have */
2179 switch (viaparinfo->chip_info->gfx_chip_name) {
2180 case UNICHROME_VX800:
2181 case UNICHROME_VX855:
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00002182 case UNICHROME_VX900:
Harald Welte107ea342009-05-20 01:36:03 +08002183 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1;
2184 break;
2185 case UNICHROME_K8M890:
2186 case UNICHROME_P4M900:
2187 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5;
2188 break;
2189 default:
2190 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2;
2191 break;
2192 }
Joseph Chand61e0bf2008-10-15 22:03:23 -07002193}
2194
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002195static void __devinit init_tmds_chip_info(void)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002196{
2197 viafb_tmds_trasmitter_identify();
2198
2199 if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
2200 output_interface) {
2201 switch (viaparinfo->chip_info->gfx_chip_name) {
2202 case UNICHROME_CX700:
2203 {
2204 /* we should check support by hardware layout.*/
2205 if ((viafb_display_hardware_layout ==
2206 HW_LAYOUT_DVI_ONLY)
2207 || (viafb_display_hardware_layout ==
2208 HW_LAYOUT_LCD_DVI)) {
2209 viaparinfo->chip_info->tmds_chip_info.
2210 output_interface = INTERFACE_TMDS;
2211 } else {
2212 viaparinfo->chip_info->tmds_chip_info.
2213 output_interface =
2214 INTERFACE_NONE;
2215 }
2216 break;
2217 }
2218 case UNICHROME_K8M890:
2219 case UNICHROME_P4M900:
2220 case UNICHROME_P4M890:
2221 /* TMDS on PCIE, we set DFPLOW as default. */
2222 viaparinfo->chip_info->tmds_chip_info.output_interface =
2223 INTERFACE_DFP_LOW;
2224 break;
2225 default:
2226 {
2227 /* set DVP1 default for DVI */
2228 viaparinfo->chip_info->tmds_chip_info
2229 .output_interface = INTERFACE_DVP1;
2230 }
2231 }
2232 }
2233
2234 DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
2235 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
Florian Tobias Schandinatc5f06f52010-03-10 15:21:30 -08002236 viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info,
2237 &viaparinfo->shared->tmds_setting_info);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002238}
2239
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002240static void __devinit init_lvds_chip_info(void)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002241{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002242 viafb_lvds_trasmitter_identify();
2243 viafb_init_lcd_size();
2244 viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
2245 viaparinfo->lvds_setting_info);
2246 if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
2247 viafb_init_lvds_output_interface(&viaparinfo->chip_info->
2248 lvds_chip_info2, viaparinfo->lvds_setting_info2);
2249 }
2250 /*If CX700,two singel LCD, we need to reassign
2251 LCD interface to different LVDS port */
2252 if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
2253 && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
2254 if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
2255 lvds_chip_name) && (INTEGRATED_LVDS ==
2256 viaparinfo->chip_info->
2257 lvds_chip_info2.lvds_chip_name)) {
2258 viaparinfo->chip_info->lvds_chip_info.output_interface =
2259 INTERFACE_LVDS0;
2260 viaparinfo->chip_info->lvds_chip_info2.
2261 output_interface =
2262 INTERFACE_LVDS1;
2263 }
2264 }
2265
2266 DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
2267 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
2268 DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
2269 viaparinfo->chip_info->lvds_chip_info.output_interface);
2270 DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
2271 viaparinfo->chip_info->lvds_chip_info.output_interface);
2272}
2273
Florian Tobias Schandinatf4ab2f7a2010-08-09 01:34:27 +00002274void __devinit viafb_init_dac(int set_iga)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002275{
2276 int i;
2277 u8 tmp;
2278
2279 if (set_iga == IGA1) {
2280 /* access Primary Display's LUT */
2281 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
2282 /* turn off LCK */
2283 viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
2284 for (i = 0; i < 256; i++) {
2285 write_dac_reg(i, palLUT_table[i].red,
2286 palLUT_table[i].green,
2287 palLUT_table[i].blue);
2288 }
2289 /* turn on LCK */
2290 viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
2291 } else {
2292 tmp = viafb_read_reg(VIACR, CR6A);
2293 /* access Secondary Display's LUT */
2294 viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
2295 viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
2296 for (i = 0; i < 256; i++) {
2297 write_dac_reg(i, palLUT_table[i].red,
2298 palLUT_table[i].green,
2299 palLUT_table[i].blue);
2300 }
2301 /* set IGA1 DAC for default */
2302 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
2303 viafb_write_reg(CR6A, VIACR, tmp);
2304 }
2305}
2306
2307static void device_screen_off(void)
2308{
2309 /* turn off CRT screen (IGA1) */
2310 viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
2311}
2312
2313static void device_screen_on(void)
2314{
2315 /* turn on CRT screen (IGA1) */
2316 viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
2317}
2318
2319static void set_display_channel(void)
2320{
2321 /*If viafb_LCD2_ON, on cx700, internal lvds's information
2322 is keeped on lvds_setting_info2 */
2323 if (viafb_LCD2_ON &&
2324 viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
2325 /* For dual channel LCD: */
2326 /* Set to Dual LVDS channel. */
2327 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
2328 } else if (viafb_LCD_ON && viafb_DVI_ON) {
2329 /* For LCD+DFP: */
2330 /* Set to LVDS1 + TMDS channel. */
2331 viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
2332 } else if (viafb_DVI_ON) {
2333 /* Set to single TMDS channel. */
2334 viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
2335 } else if (viafb_LCD_ON) {
2336 if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
2337 /* For dual channel LCD: */
2338 /* Set to Dual LVDS channel. */
2339 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
2340 } else {
2341 /* Set to LVDS0 + LVDS1 channel. */
2342 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
2343 }
2344 }
2345}
2346
Florian Tobias Schandinat2e1abbd2010-09-19 01:20:19 +00002347static u8 get_sync(struct fb_info *info)
2348{
2349 u8 polarity = 0;
2350
2351 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
2352 polarity |= VIA_HSYNC_NEGATIVE;
2353 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
2354 polarity |= VIA_VSYNC_NEGATIVE;
2355 return polarity;
2356}
2357
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002358int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
2359 struct VideoModeTable *vmode_tbl1, int video_bpp1)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002360{
2361 int i, j;
2362 int port;
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00002363 u32 devices = viaparinfo->shared->iga1_devices
2364 | viaparinfo->shared->iga2_devices;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002365 u8 value, index, mask;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002366 struct crt_mode_table *crt_timing;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002367 struct crt_mode_table *crt_timing1 = NULL;
2368
Joseph Chand61e0bf2008-10-15 22:03:23 -07002369 device_screen_off();
Joseph Chand61e0bf2008-10-15 22:03:23 -07002370 crt_timing = vmode_tbl->crtc;
2371
2372 if (viafb_SAMM_ON == 1) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07002373 crt_timing1 = vmode_tbl1->crtc;
2374 }
2375
2376 inb(VIAStatus);
2377 outb(0x00, VIAAR);
2378
2379 /* Write Common Setting for Video Mode */
Florian Tobias Schandinat95d517c2011-03-26 23:39:07 +00002380 viafb_write_regx(common_vga, ARRAY_SIZE(common_vga));
Joseph Chand61e0bf2008-10-15 22:03:23 -07002381 switch (viaparinfo->chip_info->gfx_chip_name) {
2382 case UNICHROME_CLE266:
2383 viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
2384 break;
2385
2386 case UNICHROME_K400:
2387 viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
2388 break;
2389
2390 case UNICHROME_K800:
2391 case UNICHROME_PM800:
2392 viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
2393 break;
2394
2395 case UNICHROME_CN700:
2396 case UNICHROME_K8M890:
2397 case UNICHROME_P4M890:
2398 case UNICHROME_P4M900:
2399 viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
2400 break;
2401
2402 case UNICHROME_CX700:
Joseph Chand61e0bf2008-10-15 22:03:23 -07002403 case UNICHROME_VX800:
Florian Tobias Schandinat0e3ca332009-09-22 16:47:10 -07002404 viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002405 break;
Harald Welte0306ab12009-09-22 16:47:35 -07002406
2407 case UNICHROME_VX855:
Florian Tobias Schandinat51f43322010-10-24 04:02:14 +00002408 case UNICHROME_VX900:
Harald Welte0306ab12009-09-22 16:47:35 -07002409 viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
2410 break;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002411 }
2412
Florian Tobias Schandinatbf5ea022011-01-05 10:36:05 +00002413 viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
Joseph Chand61e0bf2008-10-15 22:03:23 -07002414 device_off();
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00002415 via_set_state(devices, VIA_STATE_OFF);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002416
2417 /* Fill VPIT Parameters */
2418 /* Write Misc Register */
Florian Tobias Schandinat162fc8c2010-04-17 19:44:55 +00002419 outb(VPIT.Misc, VIA_MISC_REG_WRITE);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002420
2421 /* Write Sequencer */
Florian Tobias Schandinat384c3042010-04-17 19:44:54 +00002422 for (i = 1; i <= StdSR; i++)
2423 via_write_reg(VIASR, i, VPIT.SR[i - 1]);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002424
Florian Tobias Schandinat415559f2010-03-10 15:21:40 -08002425 viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002426
Joseph Chand61e0bf2008-10-15 22:03:23 -07002427 /* Write Graphic Controller */
Florian Tobias Schandinat384c3042010-04-17 19:44:54 +00002428 for (i = 0; i < StdGR; i++)
2429 via_write_reg(VIAGR, i, VPIT.GR[i]);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002430
2431 /* Write Attribute Controller */
2432 for (i = 0; i < StdAR; i++) {
2433 inb(VIAStatus);
2434 outb(i, VIAAR);
2435 outb(VPIT.AR[i], VIAAR);
2436 }
2437
2438 inb(VIAStatus);
2439 outb(0x20, VIAAR);
2440
2441 /* Update Patch Register */
2442
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002443 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
2444 || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
2445 && vmode_tbl->crtc[0].crtc.hor_addr == 1024
2446 && vmode_tbl->crtc[0].crtc.ver_addr == 768) {
2447 for (j = 0; j < res_patch_table[0].table_length; j++) {
2448 index = res_patch_table[0].io_reg_table[j].index;
2449 port = res_patch_table[0].io_reg_table[j].port;
2450 value = res_patch_table[0].io_reg_table[j].value;
2451 mask = res_patch_table[0].io_reg_table[j].mask;
2452 viafb_write_reg_mask(index, port, value, mask);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002453 }
2454 }
2455
Florian Tobias Schandinat0f8132b2011-03-16 13:11:17 +00002456 load_fix_bit_crtc_reg();
Florian Tobias Schandinat27494132010-04-17 19:44:52 +00002457 via_set_primary_pitch(viafbinfo->fix.line_length);
2458 via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
Florian Tobias Schandinat2d6e8852009-09-22 16:47:29 -07002459 : viafbinfo->fix.line_length);
Florian Tobias Schandinat27494132010-04-17 19:44:52 +00002460 via_set_primary_color_depth(viaparinfo->depth);
2461 via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
Florian Tobias Schandinatdaacccd2010-03-10 15:21:35 -08002462 : viaparinfo->depth);
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +00002463 via_set_source(viaparinfo->shared->iga1_devices, IGA1);
2464 via_set_source(viaparinfo->shared->iga2_devices, IGA2);
2465 if (viaparinfo->shared->iga2_devices)
2466 enable_second_display_channel();
2467 else
2468 disable_second_display_channel();
2469
Joseph Chand61e0bf2008-10-15 22:03:23 -07002470 /* Update Refresh Rate Setting */
2471
2472 /* Clear On Screen */
2473
2474 /* CRT set mode */
2475 if (viafb_CRT_ON) {
Florian Tobias Schandinat05236562011-03-21 01:46:24 +00002476 if (viafb_SAMM_ON &&
2477 viaparinfo->shared->iga2_devices & VIA_CRT) {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002478 viafb_fill_crtc_timing(crt_timing1, vmode_tbl1,
Florian Tobias Schandinat05236562011-03-21 01:46:24 +00002479 video_bpp1 / 8, IGA2);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002480 } else {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002481 viafb_fill_crtc_timing(crt_timing, vmode_tbl,
Joseph Chand61e0bf2008-10-15 22:03:23 -07002482 video_bpp / 8,
Florian Tobias Schandinat05236562011-03-21 01:46:24 +00002483 (viaparinfo->shared->iga1_devices & VIA_CRT)
2484 ? IGA1 : IGA2);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002485 }
2486
Joseph Chand61e0bf2008-10-15 22:03:23 -07002487 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
2488 to 8 alignment (1368),there is several pixels (2 pixels)
2489 on right side of screen. */
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002490 if (vmode_tbl->crtc[0].crtc.hor_addr % 8) {
Joseph Chand61e0bf2008-10-15 22:03:23 -07002491 viafb_unlock_crt();
2492 viafb_write_reg(CR02, VIACR,
2493 viafb_read_reg(VIACR, CR02) - 1);
2494 viafb_lock_crt();
2495 }
2496 }
2497
2498 if (viafb_DVI_ON) {
2499 if (viafb_SAMM_ON &&
2500 (viaparinfo->tmds_setting_info->iga_path == IGA2)) {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002501 viafb_dvi_set_mode(viafb_get_mode
Joseph Chand61e0bf2008-10-15 22:03:23 -07002502 (viaparinfo->tmds_setting_info->h_active,
2503 viaparinfo->tmds_setting_info->
Florian Tobias Schandinat52159442009-08-06 15:07:34 -07002504 v_active),
Joseph Chand61e0bf2008-10-15 22:03:23 -07002505 video_bpp1, viaparinfo->
2506 tmds_setting_info->iga_path);
2507 } else {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002508 viafb_dvi_set_mode(viafb_get_mode
Joseph Chand61e0bf2008-10-15 22:03:23 -07002509 (viaparinfo->tmds_setting_info->h_active,
2510 viaparinfo->
Florian Tobias Schandinat52159442009-08-06 15:07:34 -07002511 tmds_setting_info->v_active),
Joseph Chand61e0bf2008-10-15 22:03:23 -07002512 video_bpp, viaparinfo->
2513 tmds_setting_info->iga_path);
2514 }
2515 }
2516
2517 if (viafb_LCD_ON) {
2518 if (viafb_SAMM_ON &&
2519 (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
2520 viaparinfo->lvds_setting_info->bpp = video_bpp1;
2521 viafb_lcd_set_mode(crt_timing1, viaparinfo->
2522 lvds_setting_info,
2523 &viaparinfo->chip_info->lvds_chip_info);
2524 } else {
2525 /* IGA1 doesn't have LCD scaling, so set it center. */
2526 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
2527 viaparinfo->lvds_setting_info->display_method =
2528 LCD_CENTERING;
2529 }
2530 viaparinfo->lvds_setting_info->bpp = video_bpp;
2531 viafb_lcd_set_mode(crt_timing, viaparinfo->
2532 lvds_setting_info,
2533 &viaparinfo->chip_info->lvds_chip_info);
2534 }
2535 }
2536 if (viafb_LCD2_ON) {
2537 if (viafb_SAMM_ON &&
2538 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
2539 viaparinfo->lvds_setting_info2->bpp = video_bpp1;
2540 viafb_lcd_set_mode(crt_timing1, viaparinfo->
2541 lvds_setting_info2,
2542 &viaparinfo->chip_info->lvds_chip_info2);
2543 } else {
2544 /* IGA1 doesn't have LCD scaling, so set it center. */
2545 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
2546 viaparinfo->lvds_setting_info2->display_method =
2547 LCD_CENTERING;
2548 }
2549 viaparinfo->lvds_setting_info2->bpp = video_bpp;
2550 viafb_lcd_set_mode(crt_timing, viaparinfo->
2551 lvds_setting_info2,
2552 &viaparinfo->chip_info->lvds_chip_info2);
2553 }
2554 }
2555
2556 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
2557 && (viafb_LCD_ON || viafb_DVI_ON))
2558 set_display_channel();
2559
2560 /* If set mode normally, save resolution information for hot-plug . */
2561 if (!viafb_hotplug) {
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002562 viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr;
2563 viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002564 viafb_hotplug_bpp = video_bpp;
2565 viafb_hotplug_refresh = viafb_refresh;
2566
2567 if (viafb_DVI_ON)
2568 viafb_DeviceStatus = DVI_Device;
2569 else
2570 viafb_DeviceStatus = CRT_Device;
2571 }
2572 device_on();
Florian Tobias Schandinat2e1abbd2010-09-19 01:20:19 +00002573 if (!viafb_dual_fb)
2574 via_set_sync_polarity(devices, get_sync(viafbinfo));
2575 else {
2576 via_set_sync_polarity(viaparinfo->shared->iga1_devices,
2577 get_sync(viafbinfo));
2578 via_set_sync_polarity(viaparinfo->shared->iga2_devices,
2579 get_sync(viafbinfo1));
2580 }
2581
Florian Tobias Schandinat6f9422d2010-09-07 14:28:26 +00002582 via_set_state(devices, VIA_STATE_ON);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002583 device_screen_on();
2584 return 1;
2585}
2586
2587int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
2588{
2589 int i;
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002590 struct crt_mode_table *best;
2591 struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
Joseph Chand61e0bf2008-10-15 22:03:23 -07002592
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002593 if (!vmode)
2594 return RES_640X480_60HZ_PIXCLOCK;
2595
2596 best = &vmode->crtc[0];
2597 for (i = 1; i < vmode->mode_array; i++) {
2598 if (abs(vmode->crtc[i].refresh_rate - vmode_refresh)
2599 < abs(best->refresh_rate - vmode_refresh))
2600 best = &vmode->crtc[i];
Joseph Chand61e0bf2008-10-15 22:03:23 -07002601 }
Joseph Chand61e0bf2008-10-15 22:03:23 -07002602
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002603 return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total)
2604 * 1000 / best->refresh_rate;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002605}
2606
2607int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2608{
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002609 int i;
2610 struct crt_mode_table *best;
2611 struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
2612
2613 if (!vmode)
2614 return 60;
2615
2616 best = &vmode->crtc[0];
2617 for (i = 1; i < vmode->mode_array; i++) {
2618 if (abs(vmode->crtc[i].refresh_rate - long_refresh)
2619 < abs(best->refresh_rate - long_refresh))
2620 best = &vmode->crtc[i];
Joseph Chand61e0bf2008-10-15 22:03:23 -07002621 }
Florian Tobias Schandinatf5b1c4b2011-03-09 22:13:32 +00002622
2623 if (abs(best->refresh_rate - long_refresh) > 3)
2624 return 60;
2625
2626 return best->refresh_rate;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002627}
2628
2629static void device_off(void)
2630{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002631 viafb_dvi_disable();
2632 viafb_lcd_disable();
2633}
2634
2635static void device_on(void)
2636{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002637 if (viafb_DVI_ON == 1)
2638 viafb_dvi_enable();
2639 if (viafb_LCD_ON == 1)
2640 viafb_lcd_enable();
2641}
2642
Joseph Chand61e0bf2008-10-15 22:03:23 -07002643static void enable_second_display_channel(void)
2644{
2645 /* to enable second display channel. */
2646 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2647 viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
2648 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2649}
2650
Florian Tobias Schandinatbc684882010-08-11 00:37:58 +00002651static void disable_second_display_channel(void)
2652{
2653 /* to disable second display channel. */
2654 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2655 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
2656 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2657}
2658
Joseph Chand61e0bf2008-10-15 22:03:23 -07002659void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2660 *p_gfx_dpa_setting)
2661{
2662 switch (output_interface) {
2663 case INTERFACE_DVP0:
2664 {
2665 /* DVP0 Clock Polarity and Adjust: */
2666 viafb_write_reg_mask(CR96, VIACR,
2667 p_gfx_dpa_setting->DVP0, 0x0F);
2668
2669 /* DVP0 Clock and Data Pads Driving: */
2670 viafb_write_reg_mask(SR1E, VIASR,
2671 p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
2672 viafb_write_reg_mask(SR2A, VIASR,
2673 p_gfx_dpa_setting->DVP0ClockDri_S1,
2674 BIT4);
2675 viafb_write_reg_mask(SR1B, VIASR,
2676 p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
2677 viafb_write_reg_mask(SR2A, VIASR,
2678 p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
2679 break;
2680 }
2681
2682 case INTERFACE_DVP1:
2683 {
2684 /* DVP1 Clock Polarity and Adjust: */
2685 viafb_write_reg_mask(CR9B, VIACR,
2686 p_gfx_dpa_setting->DVP1, 0x0F);
2687
2688 /* DVP1 Clock and Data Pads Driving: */
2689 viafb_write_reg_mask(SR65, VIASR,
2690 p_gfx_dpa_setting->DVP1Driving, 0x0F);
2691 break;
2692 }
2693
2694 case INTERFACE_DFP_HIGH:
2695 {
2696 viafb_write_reg_mask(CR97, VIACR,
2697 p_gfx_dpa_setting->DFPHigh, 0x0F);
2698 break;
2699 }
2700
2701 case INTERFACE_DFP_LOW:
2702 {
2703 viafb_write_reg_mask(CR99, VIACR,
2704 p_gfx_dpa_setting->DFPLow, 0x0F);
2705 break;
2706 }
2707
2708 case INTERFACE_DFP:
2709 {
2710 viafb_write_reg_mask(CR97, VIACR,
2711 p_gfx_dpa_setting->DFPHigh, 0x0F);
2712 viafb_write_reg_mask(CR99, VIACR,
2713 p_gfx_dpa_setting->DFPLow, 0x0F);
2714 break;
2715 }
2716 }
2717}
2718
Joseph Chand61e0bf2008-10-15 22:03:23 -07002719/*According var's xres, yres fill var's other timing information*/
2720void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
Florian Tobias Schandinatdd73d682010-03-10 15:21:28 -08002721 struct VideoModeTable *vmode_tbl)
Joseph Chand61e0bf2008-10-15 22:03:23 -07002722{
Joseph Chand61e0bf2008-10-15 22:03:23 -07002723 struct crt_mode_table *crt_timing = NULL;
2724 struct display_timing crt_reg;
2725 int i = 0, index = 0;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002726 crt_timing = vmode_tbl->crtc;
2727 for (i = 0; i < vmode_tbl->mode_array; i++) {
2728 index = i;
2729 if (crt_timing[i].refresh_rate == refresh)
2730 break;
2731 }
2732
2733 crt_reg = crt_timing[index].crtc;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002734 var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh);
2735 var->left_margin =
2736 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end);
2737 var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr;
2738 var->hsync_len = crt_reg.hor_sync_end;
2739 var->upper_margin =
2740 crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
2741 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
2742 var->vsync_len = crt_reg.ver_sync_end;
Florian Tobias Schandinat2e1abbd2010-09-19 01:20:19 +00002743 var->sync = 0;
2744 if (crt_timing[index].h_sync_polarity == POSITIVE)
2745 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2746 if (crt_timing[index].v_sync_polarity == POSITIVE)
2747 var->sync |= FB_SYNC_VERT_HIGH_ACT;
Joseph Chand61e0bf2008-10-15 22:03:23 -07002748}