blob: e3e597f937a532927f19d1b4b8b635f765ffa691 [file] [log] [blame]
Joseph Chanac6c97e2008-10-15 22:03:25 -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 */
21
22#include "global.h"
23#include "lcdtbl.h"
24
25static struct iga2_shadow_crtc_timing iga2_shadow_crtc_reg = {
26 /* IGA2 Shadow Horizontal Total */
27 {IGA2_SHADOW_HOR_TOTAL_REG_NUM, {{CR6D, 0, 7}, {CR71, 3, 3} } },
28 /* IGA2 Shadow Horizontal Blank End */
29 {IGA2_SHADOW_HOR_BLANK_END_REG_NUM, {{CR6E, 0, 7} } },
30 /* IGA2 Shadow Vertical Total */
31 {IGA2_SHADOW_VER_TOTAL_REG_NUM, {{CR6F, 0, 7}, {CR71, 0, 2} } },
32 /* IGA2 Shadow Vertical Addressable Video */
33 {IGA2_SHADOW_VER_ADDR_REG_NUM, {{CR70, 0, 7}, {CR71, 4, 6} } },
34 /* IGA2 Shadow Vertical Blank Start */
35 {IGA2_SHADOW_VER_BLANK_START_REG_NUM,
36 {{CR72, 0, 7}, {CR74, 4, 6} } },
37 /* IGA2 Shadow Vertical Blank End */
38 {IGA2_SHADOW_VER_BLANK_END_REG_NUM, {{CR73, 0, 7}, {CR74, 0, 2} } },
39 /* IGA2 Shadow Vertical Sync Start */
40 {IGA2_SHADOW_VER_SYNC_START_REG_NUM, {{CR75, 0, 7}, {CR76, 4, 6} } },
41 /* IGA2 Shadow Vertical Sync End */
42 {IGA2_SHADOW_VER_SYNC_END_REG_NUM, {{CR76, 0, 3} } }
43};
44
45static struct _lcd_scaling_factor lcd_scaling_factor = {
46 /* LCD Horizontal Scaling Factor Register */
47 {LCD_HOR_SCALING_FACTOR_REG_NUM,
48 {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
49 /* LCD Vertical Scaling Factor Register */
50 {LCD_VER_SCALING_FACTOR_REG_NUM,
51 {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
52};
53static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
54 /* LCD Horizontal Scaling Factor Register */
55 {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
56 /* LCD Vertical Scaling Factor Register */
57 {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
58};
59
60static int check_lvds_chip(int device_id_subaddr, int device_id);
61static bool lvds_identify_integratedlvds(void);
62static int fp_id_to_vindex(int panel_id);
63static int lvds_register_read(int index);
64static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
65 int panel_vres);
66static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
67 int panel_id);
68static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
69 int panel_id);
70static void load_lcd_patch_regs(int set_hres, int set_vres,
71 int panel_id, int set_iga);
72static void via_pitch_alignment_patch_lcd(
73 struct lvds_setting_information *plvds_setting_info,
74 struct lvds_chip_information
75 *plvds_chip_info);
76static void lcd_patch_skew_dvp0(struct lvds_setting_information
77 *plvds_setting_info,
78 struct lvds_chip_information *plvds_chip_info);
79static void lcd_patch_skew_dvp1(struct lvds_setting_information
80 *plvds_setting_info,
81 struct lvds_chip_information *plvds_chip_info);
82static void lcd_patch_skew(struct lvds_setting_information
83 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
84
85static void integrated_lvds_disable(struct lvds_setting_information
86 *plvds_setting_info,
87 struct lvds_chip_information *plvds_chip_info);
88static void integrated_lvds_enable(struct lvds_setting_information
89 *plvds_setting_info,
90 struct lvds_chip_information *plvds_chip_info);
91static void lcd_powersequence_off(void);
92static void lcd_powersequence_on(void);
93static void fill_lcd_format(void);
94static void check_diport_of_integrated_lvds(
95 struct lvds_chip_information *plvds_chip_info,
96 struct lvds_setting_information
97 *plvds_setting_info);
98static struct display_timing lcd_centering_timging(struct display_timing
99 mode_crt_reg,
100 struct display_timing panel_crt_reg);
101static void load_crtc_shadow_timing(struct display_timing mode_timing,
102 struct display_timing panel_timing);
103static void viafb_load_scaling_factor_for_p4m900(int set_hres,
104 int set_vres, int panel_hres, int panel_vres);
105
106static int check_lvds_chip(int device_id_subaddr, int device_id)
107{
108 if (lvds_register_read(device_id_subaddr) == device_id)
109 return OK;
110 else
111 return FAIL;
112}
113
114void viafb_init_lcd_size(void)
115{
116 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
117 DEBUG_MSG(KERN_INFO
118 "viaparinfo->lvds_setting_info->get_lcd_size_method %d\n",
119 viaparinfo->lvds_setting_info->get_lcd_size_method);
120
121 switch (viaparinfo->lvds_setting_info->get_lcd_size_method) {
122 case GET_LCD_SIZE_BY_SYSTEM_BIOS:
123 break;
124 case GET_LCD_SZIE_BY_HW_STRAPPING:
125 break;
126 case GET_LCD_SIZE_BY_VGA_BIOS:
127 DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
128 viaparinfo->lvds_setting_info->lcd_panel_size =
129 fp_id_to_vindex(viafb_lcd_panel_id);
130 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
131 viaparinfo->lvds_setting_info->lcd_panel_id);
132 DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
133 viaparinfo->lvds_setting_info->lcd_panel_size);
134 break;
135 case GET_LCD_SIZE_BY_USER_SETTING:
136 DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
137 viaparinfo->lvds_setting_info->lcd_panel_size =
138 fp_id_to_vindex(viafb_lcd_panel_id);
139 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
140 viaparinfo->lvds_setting_info->lcd_panel_id);
141 DEBUG_MSG(KERN_INFO "LCD Panel Size = %d\n",
142 viaparinfo->lvds_setting_info->lcd_panel_size);
143 break;
144 default:
145 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
146 viaparinfo->lvds_setting_info->lcd_panel_id =
147 LCD_PANEL_ID1_800X600;
148 viaparinfo->lvds_setting_info->lcd_panel_size =
149 fp_id_to_vindex(LCD_PANEL_ID1_800X600);
150 }
151 viaparinfo->lvds_setting_info2->lcd_panel_id =
152 viaparinfo->lvds_setting_info->lcd_panel_id;
153 viaparinfo->lvds_setting_info2->lcd_panel_size =
154 viaparinfo->lvds_setting_info->lcd_panel_size;
155 viaparinfo->lvds_setting_info2->lcd_panel_hres =
156 viaparinfo->lvds_setting_info->lcd_panel_hres;
157 viaparinfo->lvds_setting_info2->lcd_panel_vres =
158 viaparinfo->lvds_setting_info->lcd_panel_vres;
159 viaparinfo->lvds_setting_info2->device_lcd_dualedge =
160 viaparinfo->lvds_setting_info->device_lcd_dualedge;
161 viaparinfo->lvds_setting_info2->LCDDithering =
162 viaparinfo->lvds_setting_info->LCDDithering;
163}
164
165static bool lvds_identify_integratedlvds(void)
166{
167 if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
168 /* Two dual channel LCD (Internal LVDS + External LVDS): */
169 /* If we have an external LVDS, such as VT1636, we should
170 have its chip ID already. */
171 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
172 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
173 INTEGRATED_LVDS;
174 DEBUG_MSG(KERN_INFO "Support two dual channel LVDS!\
175 (Internal LVDS + External LVDS)\n");
176 } else {
177 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
178 INTEGRATED_LVDS;
179 DEBUG_MSG(KERN_INFO "Not found external LVDS,\
180 so can't support two dual channel LVDS!\n");
181 }
182 } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
183 /* Two single channel LCD (Internal LVDS + Internal LVDS): */
184 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
185 INTEGRATED_LVDS;
186 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
187 INTEGRATED_LVDS;
188 DEBUG_MSG(KERN_INFO "Support two single channel LVDS!\
189 (Internal LVDS + Internal LVDS)\n");
190 } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
191 /* If we have found external LVDS, just use it,
192 otherwise, we will use internal LVDS as default. */
193 if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
194 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
195 INTEGRATED_LVDS;
196 DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
197 }
198 } else {
199 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
200 NON_LVDS_TRANSMITTER;
201 DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
202 return false;
203 }
204
205 return true;
206}
207
208int viafb_lvds_trasmitter_identify(void)
209{
Florian Tobias Schandinatc4df5482009-09-22 16:47:24 -0700210 viaparinfo->shared->i2c_stuff.i2c_port = I2CPORTINDEX;
Joseph Chanac6c97e2008-10-15 22:03:25 -0700211 if (viafb_lvds_identify_vt1636()) {
212 viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX;
213 DEBUG_MSG(KERN_INFO
214 "Found VIA VT1636 LVDS on port i2c 0x31 \n");
215 } else {
Florian Tobias Schandinatc4df5482009-09-22 16:47:24 -0700216 viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX;
Joseph Chanac6c97e2008-10-15 22:03:25 -0700217 if (viafb_lvds_identify_vt1636()) {
218 viaparinfo->chip_info->lvds_chip_info.i2c_port =
219 GPIOPORTINDEX;
220 DEBUG_MSG(KERN_INFO
221 "Found VIA VT1636 LVDS on port gpio 0x2c \n");
222 }
223 }
224
225 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
226 lvds_identify_integratedlvds();
227
228 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
229 return true;
230 /* Check for VT1631: */
231 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
232 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
233 VT1631_LVDS_I2C_ADDR;
234
235 if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID) != FAIL) {
236 DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
237 DEBUG_MSG(KERN_INFO "\n %2d",
238 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
239 DEBUG_MSG(KERN_INFO "\n %2d",
240 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
241 return OK;
242 }
243
244 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
245 NON_LVDS_TRANSMITTER;
246 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
247 VT1631_LVDS_I2C_ADDR;
248 return FAIL;
249}
250
251static int fp_id_to_vindex(int panel_id)
252{
253 DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
254
255 if (panel_id > LCD_PANEL_ID_MAXIMUM)
256 viafb_lcd_panel_id = panel_id =
257 viafb_read_reg(VIACR, CR3F) & 0x0F;
258
259 switch (panel_id) {
260 case 0x0:
261 viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
262 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
263 viaparinfo->lvds_setting_info->lcd_panel_id =
264 LCD_PANEL_ID0_640X480;
265 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
266 viaparinfo->lvds_setting_info->LCDDithering = 1;
267 return VIA_RES_640X480;
268 break;
269 case 0x1:
270 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
271 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
272 viaparinfo->lvds_setting_info->lcd_panel_id =
273 LCD_PANEL_ID1_800X600;
274 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
275 viaparinfo->lvds_setting_info->LCDDithering = 1;
276 return VIA_RES_800X600;
277 break;
278 case 0x2:
279 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
280 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
281 viaparinfo->lvds_setting_info->lcd_panel_id =
282 LCD_PANEL_ID2_1024X768;
283 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
284 viaparinfo->lvds_setting_info->LCDDithering = 1;
285 return VIA_RES_1024X768;
286 break;
287 case 0x3:
288 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
289 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
290 viaparinfo->lvds_setting_info->lcd_panel_id =
291 LCD_PANEL_ID3_1280X768;
292 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
293 viaparinfo->lvds_setting_info->LCDDithering = 1;
294 return VIA_RES_1280X768;
295 break;
296 case 0x4:
297 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
298 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
299 viaparinfo->lvds_setting_info->lcd_panel_id =
300 LCD_PANEL_ID4_1280X1024;
301 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
302 viaparinfo->lvds_setting_info->LCDDithering = 1;
303 return VIA_RES_1280X1024;
304 break;
305 case 0x5:
306 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
307 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
308 viaparinfo->lvds_setting_info->lcd_panel_id =
309 LCD_PANEL_ID5_1400X1050;
310 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
311 viaparinfo->lvds_setting_info->LCDDithering = 1;
312 return VIA_RES_1400X1050;
313 break;
314 case 0x6:
315 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
316 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
317 viaparinfo->lvds_setting_info->lcd_panel_id =
318 LCD_PANEL_ID6_1600X1200;
319 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
320 viaparinfo->lvds_setting_info->LCDDithering = 1;
321 return VIA_RES_1600X1200;
322 break;
323 case 0x8:
324 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
325 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
326 viaparinfo->lvds_setting_info->lcd_panel_id =
327 LCD_PANEL_IDA_800X480;
328 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
329 viaparinfo->lvds_setting_info->LCDDithering = 1;
330 return VIA_RES_800X480;
331 break;
332 case 0x9:
333 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
334 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
335 viaparinfo->lvds_setting_info->lcd_panel_id =
336 LCD_PANEL_ID2_1024X768;
337 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
338 viaparinfo->lvds_setting_info->LCDDithering = 1;
339 return VIA_RES_1024X768;
340 break;
341 case 0xA:
342 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
343 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
344 viaparinfo->lvds_setting_info->lcd_panel_id =
345 LCD_PANEL_ID2_1024X768;
346 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
347 viaparinfo->lvds_setting_info->LCDDithering = 0;
348 return VIA_RES_1024X768;
349 break;
350 case 0xB:
351 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
352 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
353 viaparinfo->lvds_setting_info->lcd_panel_id =
354 LCD_PANEL_ID2_1024X768;
355 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
356 viaparinfo->lvds_setting_info->LCDDithering = 0;
357 return VIA_RES_1024X768;
358 break;
359 case 0xC:
360 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
361 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
362 viaparinfo->lvds_setting_info->lcd_panel_id =
363 LCD_PANEL_ID3_1280X768;
364 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
365 viaparinfo->lvds_setting_info->LCDDithering = 0;
366 return VIA_RES_1280X768;
367 break;
368 case 0xD:
369 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
370 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
371 viaparinfo->lvds_setting_info->lcd_panel_id =
372 LCD_PANEL_ID4_1280X1024;
373 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
374 viaparinfo->lvds_setting_info->LCDDithering = 0;
375 return VIA_RES_1280X1024;
376 break;
377 case 0xE:
378 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
379 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
380 viaparinfo->lvds_setting_info->lcd_panel_id =
381 LCD_PANEL_ID5_1400X1050;
382 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
383 viaparinfo->lvds_setting_info->LCDDithering = 0;
384 return VIA_RES_1400X1050;
385 break;
386 case 0xF:
387 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
388 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
389 viaparinfo->lvds_setting_info->lcd_panel_id =
390 LCD_PANEL_ID6_1600X1200;
391 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
392 viaparinfo->lvds_setting_info->LCDDithering = 0;
393 return VIA_RES_1600X1200;
394 break;
395 case 0x10:
396 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
397 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
398 viaparinfo->lvds_setting_info->lcd_panel_id =
399 LCD_PANEL_ID7_1366X768;
400 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
401 viaparinfo->lvds_setting_info->LCDDithering = 0;
402 return VIA_RES_1368X768;
403 break;
404 case 0x11:
405 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
406 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
407 viaparinfo->lvds_setting_info->lcd_panel_id =
408 LCD_PANEL_ID8_1024X600;
409 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
410 viaparinfo->lvds_setting_info->LCDDithering = 1;
411 return VIA_RES_1024X600;
412 break;
413 case 0x12:
414 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
415 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
416 viaparinfo->lvds_setting_info->lcd_panel_id =
417 LCD_PANEL_ID3_1280X768;
418 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
419 viaparinfo->lvds_setting_info->LCDDithering = 1;
420 return VIA_RES_1280X768;
421 break;
422 case 0x13:
423 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
424 viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
425 viaparinfo->lvds_setting_info->lcd_panel_id =
426 LCD_PANEL_ID9_1280X800;
427 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
428 viaparinfo->lvds_setting_info->LCDDithering = 1;
429 return VIA_RES_1280X800;
430 break;
431 case 0x14:
432 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
433 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
434 viaparinfo->lvds_setting_info->lcd_panel_id =
435 LCD_PANEL_IDB_1360X768;
436 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
437 viaparinfo->lvds_setting_info->LCDDithering = 0;
438 return VIA_RES_1360X768;
439 break;
440 case 0x15:
441 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
442 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
443 viaparinfo->lvds_setting_info->lcd_panel_id =
444 LCD_PANEL_ID3_1280X768;
445 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
446 viaparinfo->lvds_setting_info->LCDDithering = 0;
447 return VIA_RES_1280X768;
448 break;
449 case 0x16:
450 viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
451 viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
452 viaparinfo->lvds_setting_info->lcd_panel_id =
453 LCD_PANEL_IDC_480X640;
454 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
455 viaparinfo->lvds_setting_info->LCDDithering = 1;
456 return VIA_RES_480X640;
457 break;
458 default:
459 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
460 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
461 viaparinfo->lvds_setting_info->lcd_panel_id =
462 LCD_PANEL_ID1_800X600;
463 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
464 viaparinfo->lvds_setting_info->LCDDithering = 1;
465 return VIA_RES_800X600;
466 }
467}
468
469static int lvds_register_read(int index)
470{
471 u8 data;
472
Florian Tobias Schandinatc4df5482009-09-22 16:47:24 -0700473 viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX;
Joseph Chanac6c97e2008-10-15 22:03:25 -0700474 viafb_i2c_readbyte((u8) viaparinfo->chip_info->
475 lvds_chip_info.lvds_chip_slave_addr,
476 (u8) index, &data);
477 return data;
478}
479
480static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
481 int panel_vres)
482{
483 int reg_value = 0;
484 int viafb_load_reg_num;
485 struct io_register *reg = NULL;
486
487 DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
488
489 /* LCD Scaling Enable */
490 viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
491 if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
492 viafb_load_scaling_factor_for_p4m900(set_hres, set_vres,
493 panel_hres, panel_vres);
494 return;
495 }
496
497 /* Check if expansion for horizontal */
498 if (set_hres != panel_hres) {
499 /* Load Horizontal Scaling Factor */
500 switch (viaparinfo->chip_info->gfx_chip_name) {
501 case UNICHROME_CLE266:
502 case UNICHROME_K400:
503 reg_value =
504 CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
505 viafb_load_reg_num =
506 lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
507 reg_num;
508 reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
509 viafb_load_reg(reg_value,
510 viafb_load_reg_num, reg, VIACR);
511 break;
512 case UNICHROME_K800:
513 case UNICHROME_PM800:
514 case UNICHROME_CN700:
515 case UNICHROME_CX700:
516 case UNICHROME_K8M890:
517 case UNICHROME_P4M890:
518 reg_value =
519 K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
520 /* Horizontal scaling enabled */
521 viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
522 viafb_load_reg_num =
523 lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
524 reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
525 viafb_load_reg(reg_value,
526 viafb_load_reg_num, reg, VIACR);
527 break;
528 }
529
530 DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
531 } else {
532 /* Horizontal scaling disabled */
533 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
534 }
535
536 /* Check if expansion for vertical */
537 if (set_vres != panel_vres) {
538 /* Load Vertical Scaling Factor */
539 switch (viaparinfo->chip_info->gfx_chip_name) {
540 case UNICHROME_CLE266:
541 case UNICHROME_K400:
542 reg_value =
543 CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
544 viafb_load_reg_num =
545 lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
546 reg_num;
547 reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
548 viafb_load_reg(reg_value,
549 viafb_load_reg_num, reg, VIACR);
550 break;
551 case UNICHROME_K800:
552 case UNICHROME_PM800:
553 case UNICHROME_CN700:
554 case UNICHROME_CX700:
555 case UNICHROME_K8M890:
556 case UNICHROME_P4M890:
557 reg_value =
558 K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
559 /* Vertical scaling enabled */
560 viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
561 viafb_load_reg_num =
562 lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
563 reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
564 viafb_load_reg(reg_value,
565 viafb_load_reg_num, reg, VIACR);
566 break;
567 }
568
569 DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
570 } else {
571 /* Vertical scaling disabled */
572 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
573 }
574}
575
576static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
577 int panel_id)
578{
579 int vmode_index;
580 int reg_num = 0;
581 struct io_reg *lcd_patch_reg = NULL;
582
Florian Tobias Schandinat52159442009-08-06 15:07:34 -0700583 vmode_index = viafb_get_mode_index(set_hres, set_vres);
Joseph Chanac6c97e2008-10-15 22:03:25 -0700584 switch (panel_id) {
585 /* LCD 800x600 */
586 case LCD_PANEL_ID1_800X600:
587 switch (vmode_index) {
588 case VIA_RES_640X400:
589 case VIA_RES_640X480:
590 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_8X6;
591 lcd_patch_reg = K400_LCD_RES_6X4_8X6;
592 break;
593 case VIA_RES_720X480:
594 case VIA_RES_720X576:
595 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_8X6;
596 lcd_patch_reg = K400_LCD_RES_7X4_8X6;
597 break;
598 }
599 break;
600
601 /* LCD 1024x768 */
602 case LCD_PANEL_ID2_1024X768:
603 switch (vmode_index) {
604 case VIA_RES_640X400:
605 case VIA_RES_640X480:
606 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_10X7;
607 lcd_patch_reg = K400_LCD_RES_6X4_10X7;
608 break;
609 case VIA_RES_720X480:
610 case VIA_RES_720X576:
611 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_10X7;
612 lcd_patch_reg = K400_LCD_RES_7X4_10X7;
613 break;
614 case VIA_RES_800X600:
615 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_10X7;
616 lcd_patch_reg = K400_LCD_RES_8X6_10X7;
617 break;
618 }
619 break;
620
621 /* LCD 1280x1024 */
622 case LCD_PANEL_ID4_1280X1024:
623 switch (vmode_index) {
624 case VIA_RES_640X400:
625 case VIA_RES_640X480:
626 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_12X10;
627 lcd_patch_reg = K400_LCD_RES_6X4_12X10;
628 break;
629 case VIA_RES_720X480:
630 case VIA_RES_720X576:
631 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_12X10;
632 lcd_patch_reg = K400_LCD_RES_7X4_12X10;
633 break;
634 case VIA_RES_800X600:
635 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_12X10;
636 lcd_patch_reg = K400_LCD_RES_8X6_12X10;
637 break;
638 case VIA_RES_1024X768:
639 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_12X10;
640 lcd_patch_reg = K400_LCD_RES_10X7_12X10;
641 break;
642
643 }
644 break;
645
646 /* LCD 1400x1050 */
647 case LCD_PANEL_ID5_1400X1050:
648 switch (vmode_index) {
649 case VIA_RES_640X480:
650 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_14X10;
651 lcd_patch_reg = K400_LCD_RES_6X4_14X10;
652 break;
653 case VIA_RES_800X600:
654 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_14X10;
655 lcd_patch_reg = K400_LCD_RES_8X6_14X10;
656 break;
657 case VIA_RES_1024X768:
658 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_14X10;
659 lcd_patch_reg = K400_LCD_RES_10X7_14X10;
660 break;
661 case VIA_RES_1280X768:
662 case VIA_RES_1280X800:
663 case VIA_RES_1280X960:
664 case VIA_RES_1280X1024:
665 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_14X10;
666 lcd_patch_reg = K400_LCD_RES_12X10_14X10;
667 break;
668 }
669 break;
670
671 /* LCD 1600x1200 */
672 case LCD_PANEL_ID6_1600X1200:
673 switch (vmode_index) {
674 case VIA_RES_640X400:
675 case VIA_RES_640X480:
676 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_16X12;
677 lcd_patch_reg = K400_LCD_RES_6X4_16X12;
678 break;
679 case VIA_RES_720X480:
680 case VIA_RES_720X576:
681 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_16X12;
682 lcd_patch_reg = K400_LCD_RES_7X4_16X12;
683 break;
684 case VIA_RES_800X600:
685 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_16X12;
686 lcd_patch_reg = K400_LCD_RES_8X6_16X12;
687 break;
688 case VIA_RES_1024X768:
689 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_16X12;
690 lcd_patch_reg = K400_LCD_RES_10X7_16X12;
691 break;
692 case VIA_RES_1280X768:
693 case VIA_RES_1280X800:
694 case VIA_RES_1280X960:
695 case VIA_RES_1280X1024:
696 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_16X12;
697 lcd_patch_reg = K400_LCD_RES_12X10_16X12;
698 break;
699 }
700 break;
701
702 /* LCD 1366x768 */
703 case LCD_PANEL_ID7_1366X768:
704 switch (vmode_index) {
705 case VIA_RES_640X480:
706 reg_num = NUM_TOTAL_K400_LCD_RES_6X4_1366X7;
707 lcd_patch_reg = K400_LCD_RES_6X4_1366X7;
708 break;
709 case VIA_RES_720X480:
710 case VIA_RES_720X576:
711 reg_num = NUM_TOTAL_K400_LCD_RES_7X4_1366X7;
712 lcd_patch_reg = K400_LCD_RES_7X4_1366X7;
713 break;
714 case VIA_RES_800X600:
715 reg_num = NUM_TOTAL_K400_LCD_RES_8X6_1366X7;
716 lcd_patch_reg = K400_LCD_RES_8X6_1366X7;
717 break;
718 case VIA_RES_1024X768:
719 reg_num = NUM_TOTAL_K400_LCD_RES_10X7_1366X7;
720 lcd_patch_reg = K400_LCD_RES_10X7_1366X7;
721 break;
722 case VIA_RES_1280X768:
723 case VIA_RES_1280X800:
724 case VIA_RES_1280X960:
725 case VIA_RES_1280X1024:
726 reg_num = NUM_TOTAL_K400_LCD_RES_12X10_1366X7;
727 lcd_patch_reg = K400_LCD_RES_12X10_1366X7;
728 break;
729 }
730 break;
731
732 /* LCD 1360x768 */
733 case LCD_PANEL_IDB_1360X768:
734 break;
735 }
736 if (reg_num != 0) {
737 /* H.W. Reset : ON */
738 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
739
740 viafb_write_regx(lcd_patch_reg, reg_num);
741
742 /* H.W. Reset : OFF */
743 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
744
745 /* Reset PLL */
746 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
747 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
748
749 /* Fire! */
750 outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
751 }
752}
753
754static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
755 int panel_id)
756{
757 int vmode_index;
758 int reg_num = 0;
759 struct io_reg *lcd_patch_reg = NULL;
760
Florian Tobias Schandinat52159442009-08-06 15:07:34 -0700761 vmode_index = viafb_get_mode_index(set_hres, set_vres);
Joseph Chanac6c97e2008-10-15 22:03:25 -0700762
763 switch (panel_id) {
764 case LCD_PANEL_ID5_1400X1050:
765 switch (vmode_index) {
766 case VIA_RES_640X480:
767 reg_num = NUM_TOTAL_P880_LCD_RES_6X4_14X10;
768 lcd_patch_reg = P880_LCD_RES_6X4_14X10;
769 break;
770 case VIA_RES_800X600:
771 reg_num = NUM_TOTAL_P880_LCD_RES_8X6_14X10;
772 lcd_patch_reg = P880_LCD_RES_8X6_14X10;
773 break;
774 }
775 break;
776 case LCD_PANEL_ID6_1600X1200:
777 switch (vmode_index) {
778 case VIA_RES_640X400:
779 case VIA_RES_640X480:
780 reg_num = NUM_TOTAL_P880_LCD_RES_6X4_16X12;
781 lcd_patch_reg = P880_LCD_RES_6X4_16X12;
782 break;
783 case VIA_RES_720X480:
784 case VIA_RES_720X576:
785 reg_num = NUM_TOTAL_P880_LCD_RES_7X4_16X12;
786 lcd_patch_reg = P880_LCD_RES_7X4_16X12;
787 break;
788 case VIA_RES_800X600:
789 reg_num = NUM_TOTAL_P880_LCD_RES_8X6_16X12;
790 lcd_patch_reg = P880_LCD_RES_8X6_16X12;
791 break;
792 case VIA_RES_1024X768:
793 reg_num = NUM_TOTAL_P880_LCD_RES_10X7_16X12;
794 lcd_patch_reg = P880_LCD_RES_10X7_16X12;
795 break;
796 case VIA_RES_1280X768:
797 case VIA_RES_1280X960:
798 case VIA_RES_1280X1024:
799 reg_num = NUM_TOTAL_P880_LCD_RES_12X10_16X12;
800 lcd_patch_reg = P880_LCD_RES_12X10_16X12;
801 break;
802 }
803 break;
804
805 }
806 if (reg_num != 0) {
807 /* H.W. Reset : ON */
808 viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7);
809
810 viafb_write_regx(lcd_patch_reg, reg_num);
811
812 /* H.W. Reset : OFF */
813 viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7);
814
815 /* Reset PLL */
816 viafb_write_reg_mask(SR40, VIASR, 0x02, BIT1);
817 viafb_write_reg_mask(SR40, VIASR, 0x00, BIT1);
818
819 /* Fire! */
820 outb(inb(VIARMisc) | (BIT2 + BIT3), VIAWMisc);
821 }
822}
823
824static void load_lcd_patch_regs(int set_hres, int set_vres,
825 int panel_id, int set_iga)
826{
827 int vmode_index;
828
Florian Tobias Schandinat52159442009-08-06 15:07:34 -0700829 vmode_index = viafb_get_mode_index(set_hres, set_vres);
Joseph Chanac6c97e2008-10-15 22:03:25 -0700830
831 viafb_unlock_crt();
832
833 /* Patch for simultaneous & Expansion */
834 if ((set_iga == IGA1_IGA2) &&
835 (viaparinfo->lvds_setting_info->display_method ==
836 LCD_EXPANDSION)) {
837 switch (viaparinfo->chip_info->gfx_chip_name) {
838 case UNICHROME_CLE266:
839 case UNICHROME_K400:
840 load_lcd_k400_patch_tbl(set_hres, set_vres, panel_id);
841 break;
842 case UNICHROME_K800:
843 break;
844 case UNICHROME_PM800:
845 case UNICHROME_CN700:
846 case UNICHROME_CX700:
847 load_lcd_p880_patch_tbl(set_hres, set_vres, panel_id);
848 }
849 }
850
851 viafb_lock_crt();
852}
853
854static void via_pitch_alignment_patch_lcd(
855 struct lvds_setting_information *plvds_setting_info,
856 struct lvds_chip_information
857 *plvds_chip_info)
858{
859 unsigned char cr13, cr35, cr65, cr66, cr67;
860 unsigned long dwScreenPitch = 0;
861 unsigned long dwPitch;
862
863 dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3);
864 if (dwPitch & 0x1F) {
865 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
866 if (plvds_setting_info->iga_path == IGA2) {
867 if (plvds_setting_info->bpp > 8) {
868 cr66 = (unsigned char)(dwScreenPitch & 0xFF);
869 viafb_write_reg(CR66, VIACR, cr66);
870 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
871 cr67 |=
872 (unsigned
873 char)((dwScreenPitch & 0x300) >> 8);
874 viafb_write_reg(CR67, VIACR, cr67);
875 }
876
877 /* Fetch Count */
878 cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
879 cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
880 viafb_write_reg(CR67, VIACR, cr67);
881 cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
882 cr65 += 2;
883 viafb_write_reg(CR65, VIACR, cr65);
884 } else {
885 if (plvds_setting_info->bpp > 8) {
886 cr13 = (unsigned char)(dwScreenPitch & 0xFF);
887 viafb_write_reg(CR13, VIACR, cr13);
888 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
889 cr35 |=
890 (unsigned
891 char)((dwScreenPitch & 0x700) >> 3);
892 viafb_write_reg(CR35, VIACR, cr35);
893 }
894 }
895 }
896}
897static void lcd_patch_skew_dvp0(struct lvds_setting_information
898 *plvds_setting_info,
899 struct lvds_chip_information *plvds_chip_info)
900{
901 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
902 switch (viaparinfo->chip_info->gfx_chip_name) {
903 case UNICHROME_P4M900:
904 viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
905 plvds_chip_info);
906 break;
907 case UNICHROME_P4M890:
908 viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
909 plvds_chip_info);
910 break;
911 }
912 }
913}
914static void lcd_patch_skew_dvp1(struct lvds_setting_information
915 *plvds_setting_info,
916 struct lvds_chip_information *plvds_chip_info)
917{
918 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
919 switch (viaparinfo->chip_info->gfx_chip_name) {
920 case UNICHROME_CX700:
921 viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
922 plvds_chip_info);
923 break;
924 }
925 }
926}
927static void lcd_patch_skew(struct lvds_setting_information
928 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
929{
930 DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
931 switch (plvds_chip_info->output_interface) {
932 case INTERFACE_DVP0:
933 lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
934 break;
935 case INTERFACE_DVP1:
936 lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
937 break;
938 case INTERFACE_DFP_LOW:
939 if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
940 viafb_write_reg_mask(CR99, VIACR, 0x08,
941 BIT0 + BIT1 + BIT2 + BIT3);
942 }
943 break;
944 }
945}
946
947/* LCD Set Mode */
948void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
949 struct lvds_setting_information *plvds_setting_info,
950 struct lvds_chip_information *plvds_chip_info)
951{
952 int video_index = plvds_setting_info->lcd_panel_size;
953 int set_iga = plvds_setting_info->iga_path;
954 int mode_bpp = plvds_setting_info->bpp;
Joseph Chanac6c97e2008-10-15 22:03:25 -0700955 int set_hres, set_vres;
956 int panel_hres, panel_vres;
957 u32 pll_D_N;
958 int offset;
Joseph Chanac6c97e2008-10-15 22:03:25 -0700959 struct display_timing mode_crt_reg, panel_crt_reg;
960 struct crt_mode_table *panel_crt_table = NULL;
961 struct VideoModeTable *vmode_tbl = NULL;
962
963 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
964 /* Get mode table */
965 mode_crt_reg = mode_crt_table->crtc;
966 /* Get panel table Pointer */
967 vmode_tbl = viafb_get_modetbl_pointer(video_index);
968 panel_crt_table = vmode_tbl->crtc;
969 panel_crt_reg = panel_crt_table->crtc;
970 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
971 set_hres = plvds_setting_info->h_active;
972 set_vres = plvds_setting_info->v_active;
973 panel_hres = plvds_setting_info->lcd_panel_hres;
974 panel_vres = plvds_setting_info->lcd_panel_vres;
975 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
976 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
977 plvds_setting_info->vclk = panel_crt_table->clk;
978 if (set_iga == IGA1) {
979 /* IGA1 doesn't have LCD scaling, so set it as centering. */
980 viafb_load_crtc_timing(lcd_centering_timging
981 (mode_crt_reg, panel_crt_reg), IGA1);
982 } else {
983 /* Expansion */
984 if ((plvds_setting_info->display_method ==
985 LCD_EXPANDSION) & ((set_hres != panel_hres)
986 || (set_vres != panel_vres))) {
987 /* expansion timing IGA2 loaded panel set timing*/
988 viafb_load_crtc_timing(panel_crt_reg, IGA2);
989 DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
990 load_lcd_scaling(set_hres, set_vres, panel_hres,
991 panel_vres);
992 DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
993 } else { /* Centering */
994 /* centering timing IGA2 always loaded panel
995 and mode releative timing */
996 viafb_load_crtc_timing(lcd_centering_timging
997 (mode_crt_reg, panel_crt_reg), IGA2);
998 viafb_write_reg_mask(CR79, VIACR, 0x00,
999 BIT0 + BIT1 + BIT2);
1000 /* LCD scaling disabled */
1001 }
1002 }
1003
1004 if (set_iga == IGA1_IGA2) {
1005 load_crtc_shadow_timing(mode_crt_reg, panel_crt_reg);
1006 /* Fill shadow registers */
1007
1008 switch (plvds_setting_info->lcd_panel_id) {
1009 case LCD_PANEL_ID0_640X480:
1010 offset = 80;
1011 break;
1012 case LCD_PANEL_ID1_800X600:
1013 case LCD_PANEL_IDA_800X480:
1014 offset = 110;
1015 break;
1016 case LCD_PANEL_ID2_1024X768:
1017 offset = 150;
1018 break;
1019 case LCD_PANEL_ID3_1280X768:
1020 case LCD_PANEL_ID4_1280X1024:
1021 case LCD_PANEL_ID5_1400X1050:
1022 case LCD_PANEL_ID9_1280X800:
1023 offset = 190;
1024 break;
1025 case LCD_PANEL_ID6_1600X1200:
1026 offset = 250;
1027 break;
1028 case LCD_PANEL_ID7_1366X768:
1029 case LCD_PANEL_IDB_1360X768:
1030 offset = 212;
1031 break;
1032 default:
1033 offset = 140;
1034 break;
1035 }
1036
1037 /* Offset for simultaneous */
Florian Tobias Schandinat2d6e8852009-09-22 16:47:29 -07001038 viafb_set_secondary_pitch(offset << 3);
Joseph Chanac6c97e2008-10-15 22:03:25 -07001039 DEBUG_MSG(KERN_INFO "viafb_load_reg!!\n");
1040 viafb_load_fetch_count_reg(set_hres, 4, IGA2);
1041 /* Fetch count for simultaneous */
1042 } else { /* SAMM */
Joseph Chanac6c97e2008-10-15 22:03:25 -07001043 /* Fetch count for IGA2 only */
1044 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
1045
1046 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
1047 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
1048 viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
1049
1050 viafb_set_color_depth(mode_bpp / 8, set_iga);
1051 }
1052
1053 fill_lcd_format();
1054
1055 pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
1056 DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
1057 viafb_set_vclock(pll_D_N, set_iga);
1058
1059 viafb_set_output_path(DEVICE_LCD, set_iga,
1060 plvds_chip_info->output_interface);
1061 lcd_patch_skew(plvds_setting_info, plvds_chip_info);
1062
1063 /* If K8M800, enable LCD Prefetch Mode. */
1064 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
1065 || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
1066 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
1067
1068 load_lcd_patch_regs(set_hres, set_vres,
1069 plvds_setting_info->lcd_panel_id, set_iga);
1070
1071 DEBUG_MSG(KERN_INFO "load_lcd_patch_regs!!\n");
1072
1073 /* Patch for non 32bit alignment mode */
1074 via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
1075}
1076
1077static void integrated_lvds_disable(struct lvds_setting_information
1078 *plvds_setting_info,
1079 struct lvds_chip_information *plvds_chip_info)
1080{
1081 bool turn_off_first_powersequence = false;
1082 bool turn_off_second_powersequence = false;
1083 if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
1084 turn_off_first_powersequence = true;
1085 if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
1086 turn_off_first_powersequence = true;
1087 if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
1088 turn_off_second_powersequence = true;
1089 if (turn_off_second_powersequence) {
1090 /* Use second power sequence control: */
1091
1092 /* Turn off power sequence. */
1093 viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
1094
1095 /* Turn off back light. */
1096 viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
1097 }
1098 if (turn_off_first_powersequence) {
1099 /* Use first power sequence control: */
1100
1101 /* Turn off power sequence. */
1102 viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
1103
1104 /* Turn off back light. */
1105 viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
1106 }
1107
1108 /* Turn DFP High/Low Pad off. */
1109 viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
1110
1111 /* Power off LVDS channel. */
1112 switch (plvds_chip_info->output_interface) {
1113 case INTERFACE_LVDS0:
1114 {
1115 viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
1116 break;
1117 }
1118
1119 case INTERFACE_LVDS1:
1120 {
1121 viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
1122 break;
1123 }
1124
1125 case INTERFACE_LVDS0LVDS1:
1126 {
1127 viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
1128 break;
1129 }
1130 }
1131}
1132
1133static void integrated_lvds_enable(struct lvds_setting_information
1134 *plvds_setting_info,
1135 struct lvds_chip_information *plvds_chip_info)
1136{
1137 bool turn_on_first_powersequence = false;
1138 bool turn_on_second_powersequence = false;
1139
1140 DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
1141 plvds_chip_info->output_interface);
1142 if (plvds_setting_info->lcd_mode == LCD_SPWG)
1143 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
1144 else
1145 viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
1146 if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
1147 turn_on_first_powersequence = true;
1148 if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
1149 turn_on_first_powersequence = true;
1150 if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
1151 turn_on_second_powersequence = true;
1152
1153 if (turn_on_second_powersequence) {
1154 /* Use second power sequence control: */
1155
1156 /* Use hardware control power sequence. */
1157 viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
1158
1159 /* Turn on back light. */
1160 viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
1161
1162 /* Turn on hardware power sequence. */
1163 viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
1164 }
1165 if (turn_on_first_powersequence) {
1166 /* Use first power sequence control: */
1167
1168 /* Use hardware control power sequence. */
1169 viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
1170
1171 /* Turn on back light. */
1172 viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
1173
1174 /* Turn on hardware power sequence. */
1175 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
1176 }
1177
1178 /* Turn DFP High/Low pad on. */
1179 viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
1180
1181 /* Power on LVDS channel. */
1182 switch (plvds_chip_info->output_interface) {
1183 case INTERFACE_LVDS0:
1184 {
1185 viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
1186 break;
1187 }
1188
1189 case INTERFACE_LVDS1:
1190 {
1191 viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
1192 break;
1193 }
1194
1195 case INTERFACE_LVDS0LVDS1:
1196 {
1197 viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
1198 break;
1199 }
1200 }
1201}
1202
1203void viafb_lcd_disable(void)
1204{
1205
1206 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
1207 lcd_powersequence_off();
1208 /* DI1 pad off */
1209 viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
1210 } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1211 if (viafb_LCD2_ON
1212 && (INTEGRATED_LVDS ==
1213 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
1214 integrated_lvds_disable(viaparinfo->lvds_setting_info,
1215 &viaparinfo->chip_info->lvds_chip_info2);
1216 if (INTEGRATED_LVDS ==
1217 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
1218 integrated_lvds_disable(viaparinfo->lvds_setting_info,
1219 &viaparinfo->chip_info->lvds_chip_info);
1220 if (VT1636_LVDS == viaparinfo->chip_info->
1221 lvds_chip_info.lvds_chip_name)
1222 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
1223 &viaparinfo->chip_info->lvds_chip_info);
1224 } else if (VT1636_LVDS ==
1225 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1226 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
1227 &viaparinfo->chip_info->lvds_chip_info);
1228 } else {
1229 /* DFP-HL pad off */
1230 viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
1231 /* Backlight off */
1232 viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
1233 /* 24 bit DI data paht off */
1234 viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
1235 /* Simultaneout disabled */
1236 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
1237 }
1238
1239 /* Disable expansion bit */
1240 viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
1241 /* CRT path set to IGA1 */
1242 viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
1243 /* Simultaneout disabled */
1244 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
1245 /* IGA2 path disabled */
1246 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
1247
1248}
1249
1250void viafb_lcd_enable(void)
1251{
1252 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
1253 /* DI1 pad on */
1254 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
1255 lcd_powersequence_on();
1256 } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1257 if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
1258 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
1259 integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
1260 &viaparinfo->chip_info->lvds_chip_info2);
1261 if (INTEGRATED_LVDS ==
1262 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
1263 integrated_lvds_enable(viaparinfo->lvds_setting_info,
1264 &viaparinfo->chip_info->lvds_chip_info);
1265 if (VT1636_LVDS == viaparinfo->chip_info->
1266 lvds_chip_info.lvds_chip_name)
1267 viafb_enable_lvds_vt1636(viaparinfo->
1268 lvds_setting_info, &viaparinfo->chip_info->
1269 lvds_chip_info);
1270 } else if (VT1636_LVDS ==
1271 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1272 viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
1273 &viaparinfo->chip_info->lvds_chip_info);
1274 } else {
1275 /* DFP-HL pad on */
1276 viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
1277 /* Backlight on */
1278 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
1279 /* 24 bit DI data paht on */
1280 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
1281
1282 /* Set data source selection bit by iga path */
1283 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
1284 /* DFP-H set to IGA1 */
1285 viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
1286 /* DFP-L set to IGA1 */
1287 viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
1288 } else {
1289 /* DFP-H set to IGA2 */
1290 viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
1291 /* DFP-L set to IGA2 */
1292 viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
1293 }
1294 /* LCD enabled */
1295 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
1296 }
1297
1298 if ((viaparinfo->lvds_setting_info->iga_path == IGA1)
1299 || (viaparinfo->lvds_setting_info->iga_path == IGA1_IGA2)) {
1300 /* CRT path set to IGA2 */
1301 viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
1302 /* IGA2 path disabled */
1303 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
1304 /* IGA2 path enabled */
1305 } else { /* IGA2 */
1306 viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
1307 }
1308
1309}
1310
1311static void lcd_powersequence_off(void)
1312{
1313 int i, mask, data;
1314
1315 /* Software control power sequence */
1316 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
1317
1318 for (i = 0; i < 3; i++) {
1319 mask = PowerSequenceOff[0][i];
1320 data = PowerSequenceOff[1][i] & mask;
1321 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
1322 udelay(PowerSequenceOff[2][i]);
1323 }
1324
1325 /* Disable LCD */
1326 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
1327}
1328
1329static void lcd_powersequence_on(void)
1330{
1331 int i, mask, data;
1332
1333 /* Software control power sequence */
1334 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
1335
1336 /* Enable LCD */
1337 viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
1338
1339 for (i = 0; i < 3; i++) {
1340 mask = PowerSequenceOn[0][i];
1341 data = PowerSequenceOn[1][i] & mask;
1342 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
1343 udelay(PowerSequenceOn[2][i]);
1344 }
1345
1346 udelay(1);
1347}
1348
1349static void fill_lcd_format(void)
1350{
1351 u8 bdithering = 0, bdual = 0;
1352
1353 if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
1354 bdual = BIT4;
1355 if (viaparinfo->lvds_setting_info->LCDDithering)
1356 bdithering = BIT0;
1357 /* Dual & Dithering */
1358 viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
1359}
1360
1361static void check_diport_of_integrated_lvds(
1362 struct lvds_chip_information *plvds_chip_info,
1363 struct lvds_setting_information
1364 *plvds_setting_info)
1365{
1366 /* Determine LCD DI Port by hardware layout. */
1367 switch (viafb_display_hardware_layout) {
1368 case HW_LAYOUT_LCD_ONLY:
1369 {
1370 if (plvds_setting_info->device_lcd_dualedge) {
1371 plvds_chip_info->output_interface =
1372 INTERFACE_LVDS0LVDS1;
1373 } else {
1374 plvds_chip_info->output_interface =
1375 INTERFACE_LVDS0;
1376 }
1377
1378 break;
1379 }
1380
1381 case HW_LAYOUT_DVI_ONLY:
1382 {
1383 plvds_chip_info->output_interface = INTERFACE_NONE;
1384 break;
1385 }
1386
1387 case HW_LAYOUT_LCD1_LCD2:
1388 case HW_LAYOUT_LCD_EXTERNAL_LCD2:
1389 {
1390 plvds_chip_info->output_interface =
1391 INTERFACE_LVDS0LVDS1;
1392 break;
1393 }
1394
1395 case HW_LAYOUT_LCD_DVI:
1396 {
1397 plvds_chip_info->output_interface = INTERFACE_LVDS1;
1398 break;
1399 }
1400
1401 default:
1402 {
1403 plvds_chip_info->output_interface = INTERFACE_LVDS1;
1404 break;
1405 }
1406 }
1407
1408 DEBUG_MSG(KERN_INFO
1409 "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
1410 viafb_display_hardware_layout,
1411 plvds_chip_info->output_interface);
1412}
1413
1414void viafb_init_lvds_output_interface(struct lvds_chip_information
1415 *plvds_chip_info,
1416 struct lvds_setting_information
1417 *plvds_setting_info)
1418{
1419 if (INTERFACE_NONE != plvds_chip_info->output_interface) {
1420 /*Do nothing, lcd port is specified by module parameter */
1421 return;
1422 }
1423
1424 switch (plvds_chip_info->lvds_chip_name) {
1425
1426 case VT1636_LVDS:
1427 switch (viaparinfo->chip_info->gfx_chip_name) {
1428 case UNICHROME_CX700:
1429 plvds_chip_info->output_interface = INTERFACE_DVP1;
1430 break;
1431 case UNICHROME_CN700:
1432 plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
1433 break;
1434 default:
1435 plvds_chip_info->output_interface = INTERFACE_DVP0;
1436 break;
1437 }
1438 break;
1439
1440 case INTEGRATED_LVDS:
1441 check_diport_of_integrated_lvds(plvds_chip_info,
1442 plvds_setting_info);
1443 break;
1444
1445 default:
1446 switch (viaparinfo->chip_info->gfx_chip_name) {
1447 case UNICHROME_K8M890:
1448 case UNICHROME_P4M900:
1449 case UNICHROME_P4M890:
1450 plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
1451 break;
1452 default:
1453 plvds_chip_info->output_interface = INTERFACE_DFP;
1454 break;
1455 }
1456 break;
1457 }
1458}
1459
1460static struct display_timing lcd_centering_timging(struct display_timing
1461 mode_crt_reg,
1462 struct display_timing panel_crt_reg)
1463{
1464 struct display_timing crt_reg;
1465
1466 crt_reg.hor_total = panel_crt_reg.hor_total;
1467 crt_reg.hor_addr = mode_crt_reg.hor_addr;
1468 crt_reg.hor_blank_start =
1469 (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
1470 crt_reg.hor_addr;
1471 crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
1472 crt_reg.hor_sync_start =
1473 (panel_crt_reg.hor_sync_start -
1474 panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
1475 crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
1476
1477 crt_reg.ver_total = panel_crt_reg.ver_total;
1478 crt_reg.ver_addr = mode_crt_reg.ver_addr;
1479 crt_reg.ver_blank_start =
1480 (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
1481 crt_reg.ver_addr;
1482 crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
1483 crt_reg.ver_sync_start =
1484 (panel_crt_reg.ver_sync_start -
1485 panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
1486 crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
1487
1488 return crt_reg;
1489}
1490
1491static void load_crtc_shadow_timing(struct display_timing mode_timing,
1492 struct display_timing panel_timing)
1493{
1494 struct io_register *reg = NULL;
1495 int i;
1496 int viafb_load_reg_Num = 0;
1497 int reg_value = 0;
1498
1499 if (viaparinfo->lvds_setting_info->display_method == LCD_EXPANDSION) {
1500 /* Expansion */
1501 for (i = 12; i < 20; i++) {
1502 switch (i) {
1503 case H_TOTAL_SHADOW_INDEX:
1504 reg_value =
1505 IGA2_HOR_TOTAL_SHADOW_FORMULA
1506 (panel_timing.hor_total);
1507 viafb_load_reg_Num =
1508 iga2_shadow_crtc_reg.hor_total_shadow.
1509 reg_num;
1510 reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
1511 break;
1512 case H_BLANK_END_SHADOW_INDEX:
1513 reg_value =
1514 IGA2_HOR_BLANK_END_SHADOW_FORMULA
1515 (panel_timing.hor_blank_start,
1516 panel_timing.hor_blank_end);
1517 viafb_load_reg_Num =
1518 iga2_shadow_crtc_reg.
1519 hor_blank_end_shadow.reg_num;
1520 reg =
1521 iga2_shadow_crtc_reg.
1522 hor_blank_end_shadow.reg;
1523 break;
1524 case V_TOTAL_SHADOW_INDEX:
1525 reg_value =
1526 IGA2_VER_TOTAL_SHADOW_FORMULA
1527 (panel_timing.ver_total);
1528 viafb_load_reg_Num =
1529 iga2_shadow_crtc_reg.ver_total_shadow.
1530 reg_num;
1531 reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
1532 break;
1533 case V_ADDR_SHADOW_INDEX:
1534 reg_value =
1535 IGA2_VER_ADDR_SHADOW_FORMULA
1536 (panel_timing.ver_addr);
1537 viafb_load_reg_Num =
1538 iga2_shadow_crtc_reg.ver_addr_shadow.
1539 reg_num;
1540 reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
1541 break;
1542 case V_BLANK_SATRT_SHADOW_INDEX:
1543 reg_value =
1544 IGA2_VER_BLANK_START_SHADOW_FORMULA
1545 (panel_timing.ver_blank_start);
1546 viafb_load_reg_Num =
1547 iga2_shadow_crtc_reg.
1548 ver_blank_start_shadow.reg_num;
1549 reg =
1550 iga2_shadow_crtc_reg.
1551 ver_blank_start_shadow.reg;
1552 break;
1553 case V_BLANK_END_SHADOW_INDEX:
1554 reg_value =
1555 IGA2_VER_BLANK_END_SHADOW_FORMULA
1556 (panel_timing.ver_blank_start,
1557 panel_timing.ver_blank_end);
1558 viafb_load_reg_Num =
1559 iga2_shadow_crtc_reg.
1560 ver_blank_end_shadow.reg_num;
1561 reg =
1562 iga2_shadow_crtc_reg.
1563 ver_blank_end_shadow.reg;
1564 break;
1565 case V_SYNC_SATRT_SHADOW_INDEX:
1566 reg_value =
1567 IGA2_VER_SYNC_START_SHADOW_FORMULA
1568 (panel_timing.ver_sync_start);
1569 viafb_load_reg_Num =
1570 iga2_shadow_crtc_reg.
1571 ver_sync_start_shadow.reg_num;
1572 reg =
1573 iga2_shadow_crtc_reg.
1574 ver_sync_start_shadow.reg;
1575 break;
1576 case V_SYNC_END_SHADOW_INDEX:
1577 reg_value =
1578 IGA2_VER_SYNC_END_SHADOW_FORMULA
1579 (panel_timing.ver_sync_start,
1580 panel_timing.ver_sync_end);
1581 viafb_load_reg_Num =
1582 iga2_shadow_crtc_reg.
1583 ver_sync_end_shadow.reg_num;
1584 reg =
1585 iga2_shadow_crtc_reg.
1586 ver_sync_end_shadow.reg;
1587 break;
1588 }
1589 viafb_load_reg(reg_value,
1590 viafb_load_reg_Num, reg, VIACR);
1591 }
1592 } else { /* Centering */
1593 for (i = 12; i < 20; i++) {
1594 switch (i) {
1595 case H_TOTAL_SHADOW_INDEX:
1596 reg_value =
1597 IGA2_HOR_TOTAL_SHADOW_FORMULA
1598 (panel_timing.hor_total);
1599 viafb_load_reg_Num =
1600 iga2_shadow_crtc_reg.hor_total_shadow.
1601 reg_num;
1602 reg = iga2_shadow_crtc_reg.hor_total_shadow.reg;
1603 break;
1604 case H_BLANK_END_SHADOW_INDEX:
1605 reg_value =
1606 IGA2_HOR_BLANK_END_SHADOW_FORMULA
1607 (panel_timing.hor_blank_start,
1608 panel_timing.hor_blank_end);
1609 viafb_load_reg_Num =
1610 iga2_shadow_crtc_reg.
1611 hor_blank_end_shadow.reg_num;
1612 reg =
1613 iga2_shadow_crtc_reg.
1614 hor_blank_end_shadow.reg;
1615 break;
1616 case V_TOTAL_SHADOW_INDEX:
1617 reg_value =
1618 IGA2_VER_TOTAL_SHADOW_FORMULA
1619 (panel_timing.ver_total);
1620 viafb_load_reg_Num =
1621 iga2_shadow_crtc_reg.ver_total_shadow.
1622 reg_num;
1623 reg = iga2_shadow_crtc_reg.ver_total_shadow.reg;
1624 break;
1625 case V_ADDR_SHADOW_INDEX:
1626 reg_value =
1627 IGA2_VER_ADDR_SHADOW_FORMULA
1628 (mode_timing.ver_addr);
1629 viafb_load_reg_Num =
1630 iga2_shadow_crtc_reg.ver_addr_shadow.
1631 reg_num;
1632 reg = iga2_shadow_crtc_reg.ver_addr_shadow.reg;
1633 break;
1634 case V_BLANK_SATRT_SHADOW_INDEX:
1635 reg_value =
1636 IGA2_VER_BLANK_START_SHADOW_FORMULA
1637 (mode_timing.ver_blank_start);
1638 viafb_load_reg_Num =
1639 iga2_shadow_crtc_reg.
1640 ver_blank_start_shadow.reg_num;
1641 reg =
1642 iga2_shadow_crtc_reg.
1643 ver_blank_start_shadow.reg;
1644 break;
1645 case V_BLANK_END_SHADOW_INDEX:
1646 reg_value =
1647 IGA2_VER_BLANK_END_SHADOW_FORMULA
1648 (panel_timing.ver_blank_start,
1649 panel_timing.ver_blank_end);
1650 viafb_load_reg_Num =
1651 iga2_shadow_crtc_reg.
1652 ver_blank_end_shadow.reg_num;
1653 reg =
1654 iga2_shadow_crtc_reg.
1655 ver_blank_end_shadow.reg;
1656 break;
1657 case V_SYNC_SATRT_SHADOW_INDEX:
1658 reg_value =
1659 IGA2_VER_SYNC_START_SHADOW_FORMULA(
1660 (panel_timing.ver_sync_start -
1661 panel_timing.ver_blank_start) +
1662 (panel_timing.ver_addr -
1663 mode_timing.ver_addr) / 2 +
1664 mode_timing.ver_addr);
1665 viafb_load_reg_Num =
1666 iga2_shadow_crtc_reg.ver_sync_start_shadow.
1667 reg_num;
1668 reg =
1669 iga2_shadow_crtc_reg.ver_sync_start_shadow.
1670 reg;
1671 break;
1672 case V_SYNC_END_SHADOW_INDEX:
1673 reg_value =
1674 IGA2_VER_SYNC_END_SHADOW_FORMULA(
1675 (panel_timing.ver_sync_start -
1676 panel_timing.ver_blank_start) +
1677 (panel_timing.ver_addr -
1678 mode_timing.ver_addr) / 2 +
1679 mode_timing.ver_addr,
1680 panel_timing.ver_sync_end);
1681 viafb_load_reg_Num =
1682 iga2_shadow_crtc_reg.ver_sync_end_shadow.
1683 reg_num;
1684 reg =
1685 iga2_shadow_crtc_reg.ver_sync_end_shadow.
1686 reg;
1687 break;
1688 }
1689 viafb_load_reg(reg_value,
1690 viafb_load_reg_Num, reg, VIACR);
1691 }
1692 }
1693}
1694
1695bool viafb_lcd_get_mobile_state(bool *mobile)
1696{
1697 unsigned char *romptr, *tableptr;
1698 u8 core_base;
1699 unsigned char *biosptr;
1700 /* Rom address */
1701 u32 romaddr = 0x000C0000;
1702 u16 start_pattern = 0;
1703
1704 biosptr = ioremap(romaddr, 0x10000);
1705
1706 memcpy(&start_pattern, biosptr, 2);
1707 /* Compare pattern */
1708 if (start_pattern == 0xAA55) {
1709 /* Get the start of Table */
1710 /* 0x1B means BIOS offset position */
1711 romptr = biosptr + 0x1B;
1712 tableptr = biosptr + *((u16 *) romptr);
1713
1714 /* Get the start of biosver structure */
1715 /* 18 means BIOS version position. */
1716 romptr = tableptr + 18;
1717 romptr = biosptr + *((u16 *) romptr);
1718
1719 /* The offset should be 44, but the
1720 actual image is less three char. */
1721 /* pRom += 44; */
1722 romptr += 41;
1723
1724 core_base = *romptr++;
1725
1726 if (core_base & 0x8)
1727 *mobile = false;
1728 else
1729 *mobile = true;
1730 /* release memory */
1731 iounmap(biosptr);
1732
1733 return true;
1734 } else {
1735 iounmap(biosptr);
1736 return false;
1737 }
1738}
1739
1740static void viafb_load_scaling_factor_for_p4m900(int set_hres,
1741 int set_vres, int panel_hres, int panel_vres)
1742{
1743 int h_scaling_factor;
1744 int v_scaling_factor;
1745 u8 cra2 = 0;
1746 u8 cr77 = 0;
1747 u8 cr78 = 0;
1748 u8 cr79 = 0;
1749 u8 cr9f = 0;
1750 /* Check if expansion for horizontal */
1751 if (set_hres < panel_hres) {
1752 /* Load Horizontal Scaling Factor */
1753
1754 /* For VIA_K8M800 or later chipsets. */
1755 h_scaling_factor =
1756 K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
1757 /* HSCaleFactor[1:0] at CR9F[1:0] */
1758 cr9f = h_scaling_factor & 0x0003;
1759 /* HSCaleFactor[9:2] at CR77[7:0] */
1760 cr77 = (h_scaling_factor & 0x03FC) >> 2;
1761 /* HSCaleFactor[11:10] at CR79[5:4] */
1762 cr79 = (h_scaling_factor & 0x0C00) >> 10;
1763 cr79 <<= 4;
1764
1765 /* Horizontal scaling enabled */
1766 cra2 = 0xC0;
1767
1768 DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n",
1769 h_scaling_factor);
1770 } else {
1771 /* Horizontal scaling disabled */
1772 cra2 = 0x00;
1773 }
1774
1775 /* Check if expansion for vertical */
1776 if (set_vres < panel_vres) {
1777 /* Load Vertical Scaling Factor */
1778
1779 /* For VIA_K8M800 or later chipsets. */
1780 v_scaling_factor =
1781 K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
1782
1783 /* Vertical scaling enabled */
1784 cra2 |= 0x08;
1785 /* VSCaleFactor[0] at CR79[3] */
1786 cr79 |= ((v_scaling_factor & 0x0001) << 3);
1787 /* VSCaleFactor[8:1] at CR78[7:0] */
1788 cr78 |= (v_scaling_factor & 0x01FE) >> 1;
1789 /* VSCaleFactor[10:9] at CR79[7:6] */
1790 cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6;
1791
1792 DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n",
1793 v_scaling_factor);
1794 } else {
1795 /* Vertical scaling disabled */
1796 cra2 |= 0x00;
1797 }
1798
1799 viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7);
1800 viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF);
1801 viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF);
1802 viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8);
1803 viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1);
1804}