viafb: Move core stuff into via-core.c
[safe/jmp/linux-2.6] / drivers / video / via / lcd.c
1 /*
2  * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public
7  * License as published by the Free Software Foundation;
8  * either version 2, or (at your option) any later version.
9
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12  * the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE.See the GNU General Public License
14  * for more details.
15
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc.,
19  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #include "global.h"
23 #include "lcdtbl.h"
24
25 #define viafb_compact_res(x, y) (((x)<<16)|(y))
26
27 static struct _lcd_scaling_factor lcd_scaling_factor = {
28         /* LCD Horizontal Scaling Factor Register */
29         {LCD_HOR_SCALING_FACTOR_REG_NUM,
30          {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
31         /* LCD Vertical Scaling Factor Register */
32         {LCD_VER_SCALING_FACTOR_REG_NUM,
33          {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
34 };
35 static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
36         /* LCD Horizontal Scaling Factor Register */
37         {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
38         /* LCD Vertical Scaling Factor Register */
39         {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
40 };
41
42 static int check_lvds_chip(int device_id_subaddr, int device_id);
43 static bool lvds_identify_integratedlvds(void);
44 static void fp_id_to_vindex(int panel_id);
45 static int lvds_register_read(int index);
46 static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
47                       int panel_vres);
48 static void via_pitch_alignment_patch_lcd(
49         struct lvds_setting_information *plvds_setting_info,
50                                    struct lvds_chip_information
51                                    *plvds_chip_info);
52 static void lcd_patch_skew_dvp0(struct lvds_setting_information
53                          *plvds_setting_info,
54                          struct lvds_chip_information *plvds_chip_info);
55 static void lcd_patch_skew_dvp1(struct lvds_setting_information
56                          *plvds_setting_info,
57                          struct lvds_chip_information *plvds_chip_info);
58 static void lcd_patch_skew(struct lvds_setting_information
59         *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
60
61 static void integrated_lvds_disable(struct lvds_setting_information
62                              *plvds_setting_info,
63                              struct lvds_chip_information *plvds_chip_info);
64 static void integrated_lvds_enable(struct lvds_setting_information
65                             *plvds_setting_info,
66                             struct lvds_chip_information *plvds_chip_info);
67 static void lcd_powersequence_off(void);
68 static void lcd_powersequence_on(void);
69 static void fill_lcd_format(void);
70 static void check_diport_of_integrated_lvds(
71         struct lvds_chip_information *plvds_chip_info,
72                                      struct lvds_setting_information
73                                      *plvds_setting_info);
74 static struct display_timing lcd_centering_timging(struct display_timing
75                                             mode_crt_reg,
76                                            struct display_timing panel_crt_reg);
77 static void viafb_load_scaling_factor_for_p4m900(int set_hres,
78         int set_vres, int panel_hres, int panel_vres);
79
80 static int check_lvds_chip(int device_id_subaddr, int device_id)
81 {
82         if (lvds_register_read(device_id_subaddr) == device_id)
83                 return OK;
84         else
85                 return FAIL;
86 }
87
88 void viafb_init_lcd_size(void)
89 {
90         DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
91         DEBUG_MSG(KERN_INFO
92                 "viaparinfo->lvds_setting_info->get_lcd_size_method %d\n",
93                 viaparinfo->lvds_setting_info->get_lcd_size_method);
94
95         switch (viaparinfo->lvds_setting_info->get_lcd_size_method) {
96         case GET_LCD_SIZE_BY_SYSTEM_BIOS:
97                 break;
98         case GET_LCD_SZIE_BY_HW_STRAPPING:
99                 break;
100         case GET_LCD_SIZE_BY_VGA_BIOS:
101                 DEBUG_MSG(KERN_INFO "Get LCD Size method by VGA BIOS !!\n");
102                 fp_id_to_vindex(viafb_lcd_panel_id);
103                 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
104                           viaparinfo->lvds_setting_info->lcd_panel_id);
105                 break;
106         case GET_LCD_SIZE_BY_USER_SETTING:
107                 DEBUG_MSG(KERN_INFO "Get LCD Size method by user setting !!\n");
108                 fp_id_to_vindex(viafb_lcd_panel_id);
109                 DEBUG_MSG(KERN_INFO "LCD Panel_ID = %d\n",
110                           viaparinfo->lvds_setting_info->lcd_panel_id);
111                 break;
112         default:
113                 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size fail\n");
114                 viaparinfo->lvds_setting_info->lcd_panel_id =
115                         LCD_PANEL_ID1_800X600;
116                 fp_id_to_vindex(LCD_PANEL_ID1_800X600);
117         }
118         viaparinfo->lvds_setting_info2->lcd_panel_id =
119                 viaparinfo->lvds_setting_info->lcd_panel_id;
120         viaparinfo->lvds_setting_info2->lcd_panel_hres =
121                 viaparinfo->lvds_setting_info->lcd_panel_hres;
122         viaparinfo->lvds_setting_info2->lcd_panel_vres =
123                 viaparinfo->lvds_setting_info->lcd_panel_vres;
124         viaparinfo->lvds_setting_info2->device_lcd_dualedge =
125             viaparinfo->lvds_setting_info->device_lcd_dualedge;
126         viaparinfo->lvds_setting_info2->LCDDithering =
127                 viaparinfo->lvds_setting_info->LCDDithering;
128 }
129
130 static bool lvds_identify_integratedlvds(void)
131 {
132         if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
133                 /* Two dual channel LCD (Internal LVDS + External LVDS): */
134                 /* If we have an external LVDS, such as VT1636, we should
135                    have its chip ID already. */
136                 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
137                         viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
138                             INTEGRATED_LVDS;
139                         DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "
140                                   "(Internal LVDS + External LVDS)\n");
141                 } else {
142                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
143                             INTEGRATED_LVDS;
144                         DEBUG_MSG(KERN_INFO "Not found external LVDS, "
145                                   "so can't support two dual channel LVDS!\n");
146                 }
147         } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
148                 /* Two single channel LCD (Internal LVDS + Internal LVDS): */
149                 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
150                 INTEGRATED_LVDS;
151                 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
152                         INTEGRATED_LVDS;
153                 DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "
154                           "(Internal LVDS + Internal LVDS)\n");
155         } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
156                 /* If we have found external LVDS, just use it,
157                    otherwise, we will use internal LVDS as default. */
158                 if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
159                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
160                             INTEGRATED_LVDS;
161                         DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
162                 }
163         } else {
164                 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
165                         NON_LVDS_TRANSMITTER;
166                 DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
167                 return false;
168         }
169
170         return true;
171 }
172
173 int viafb_lvds_trasmitter_identify(void)
174 {
175         if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
176                 viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
177                 DEBUG_MSG(KERN_INFO
178                           "Found VIA VT1636 LVDS on port i2c 0x31\n");
179         } else {
180                 if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) {
181                         viaparinfo->chip_info->lvds_chip_info.i2c_port =
182                                 VIA_PORT_2C;
183                         DEBUG_MSG(KERN_INFO
184                                   "Found VIA VT1636 LVDS on port gpio 0x2c\n");
185                 }
186         }
187
188         if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
189                 lvds_identify_integratedlvds();
190
191         if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
192                 return true;
193         /* Check for VT1631: */
194         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
195         viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
196                 VT1631_LVDS_I2C_ADDR;
197
198         if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID) != FAIL) {
199                 DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
200                 DEBUG_MSG(KERN_INFO "\n %2d",
201                           viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
202                 DEBUG_MSG(KERN_INFO "\n %2d",
203                           viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
204                 return OK;
205         }
206
207         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
208                 NON_LVDS_TRANSMITTER;
209         viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
210                 VT1631_LVDS_I2C_ADDR;
211         return FAIL;
212 }
213
214 static void fp_id_to_vindex(int panel_id)
215 {
216         DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
217
218         if (panel_id > LCD_PANEL_ID_MAXIMUM)
219                 viafb_lcd_panel_id = panel_id =
220                 viafb_read_reg(VIACR, CR3F) & 0x0F;
221
222         switch (panel_id) {
223         case 0x0:
224                 viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
225                 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
226                 viaparinfo->lvds_setting_info->lcd_panel_id =
227                         LCD_PANEL_ID0_640X480;
228                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
229                 viaparinfo->lvds_setting_info->LCDDithering = 1;
230                 break;
231         case 0x1:
232                 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
233                 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
234                 viaparinfo->lvds_setting_info->lcd_panel_id =
235                         LCD_PANEL_ID1_800X600;
236                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
237                 viaparinfo->lvds_setting_info->LCDDithering = 1;
238                 break;
239         case 0x2:
240                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
241                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
242                 viaparinfo->lvds_setting_info->lcd_panel_id =
243                         LCD_PANEL_ID2_1024X768;
244                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
245                 viaparinfo->lvds_setting_info->LCDDithering = 1;
246                 break;
247         case 0x3:
248                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
249                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
250                 viaparinfo->lvds_setting_info->lcd_panel_id =
251                         LCD_PANEL_ID3_1280X768;
252                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
253                 viaparinfo->lvds_setting_info->LCDDithering = 1;
254                 break;
255         case 0x4:
256                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
257                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
258                 viaparinfo->lvds_setting_info->lcd_panel_id =
259                         LCD_PANEL_ID4_1280X1024;
260                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
261                 viaparinfo->lvds_setting_info->LCDDithering = 1;
262                 break;
263         case 0x5:
264                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
265                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
266                 viaparinfo->lvds_setting_info->lcd_panel_id =
267                         LCD_PANEL_ID5_1400X1050;
268                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
269                 viaparinfo->lvds_setting_info->LCDDithering = 1;
270                 break;
271         case 0x6:
272                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
273                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
274                 viaparinfo->lvds_setting_info->lcd_panel_id =
275                         LCD_PANEL_ID6_1600X1200;
276                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
277                 viaparinfo->lvds_setting_info->LCDDithering = 1;
278                 break;
279         case 0x8:
280                 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
281                 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
282                 viaparinfo->lvds_setting_info->lcd_panel_id =
283                         LCD_PANEL_IDA_800X480;
284                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
285                 viaparinfo->lvds_setting_info->LCDDithering = 1;
286                 break;
287         case 0x9:
288                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
289                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
290                 viaparinfo->lvds_setting_info->lcd_panel_id =
291                         LCD_PANEL_ID2_1024X768;
292                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
293                 viaparinfo->lvds_setting_info->LCDDithering = 1;
294                 break;
295         case 0xA:
296                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
297                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
298                 viaparinfo->lvds_setting_info->lcd_panel_id =
299                         LCD_PANEL_ID2_1024X768;
300                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
301                 viaparinfo->lvds_setting_info->LCDDithering = 0;
302                 break;
303         case 0xB:
304                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
305                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
306                 viaparinfo->lvds_setting_info->lcd_panel_id =
307                         LCD_PANEL_ID2_1024X768;
308                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
309                 viaparinfo->lvds_setting_info->LCDDithering = 0;
310                 break;
311         case 0xC:
312                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
313                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
314                 viaparinfo->lvds_setting_info->lcd_panel_id =
315                         LCD_PANEL_ID3_1280X768;
316                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
317                 viaparinfo->lvds_setting_info->LCDDithering = 0;
318                 break;
319         case 0xD:
320                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
321                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
322                 viaparinfo->lvds_setting_info->lcd_panel_id =
323                         LCD_PANEL_ID4_1280X1024;
324                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
325                 viaparinfo->lvds_setting_info->LCDDithering = 0;
326                 break;
327         case 0xE:
328                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
329                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
330                 viaparinfo->lvds_setting_info->lcd_panel_id =
331                         LCD_PANEL_ID5_1400X1050;
332                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
333                 viaparinfo->lvds_setting_info->LCDDithering = 0;
334                 break;
335         case 0xF:
336                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
337                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
338                 viaparinfo->lvds_setting_info->lcd_panel_id =
339                         LCD_PANEL_ID6_1600X1200;
340                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
341                 viaparinfo->lvds_setting_info->LCDDithering = 0;
342                 break;
343         case 0x10:
344                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
345                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
346                 viaparinfo->lvds_setting_info->lcd_panel_id =
347                         LCD_PANEL_ID7_1366X768;
348                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
349                 viaparinfo->lvds_setting_info->LCDDithering = 0;
350                 break;
351         case 0x11:
352                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
353                 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
354                 viaparinfo->lvds_setting_info->lcd_panel_id =
355                         LCD_PANEL_ID8_1024X600;
356                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
357                 viaparinfo->lvds_setting_info->LCDDithering = 1;
358                 break;
359         case 0x12:
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 = 1;
365                 viaparinfo->lvds_setting_info->LCDDithering = 1;
366                 break;
367         case 0x13:
368                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
369                 viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
370                 viaparinfo->lvds_setting_info->lcd_panel_id =
371                         LCD_PANEL_ID9_1280X800;
372                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
373                 viaparinfo->lvds_setting_info->LCDDithering = 1;
374                 break;
375         case 0x14:
376                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
377                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
378                 viaparinfo->lvds_setting_info->lcd_panel_id =
379                         LCD_PANEL_IDB_1360X768;
380                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
381                 viaparinfo->lvds_setting_info->LCDDithering = 0;
382                 break;
383         case 0x15:
384                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
385                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
386                 viaparinfo->lvds_setting_info->lcd_panel_id =
387                         LCD_PANEL_ID3_1280X768;
388                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
389                 viaparinfo->lvds_setting_info->LCDDithering = 0;
390                 break;
391         case 0x16:
392                 viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
393                 viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
394                 viaparinfo->lvds_setting_info->lcd_panel_id =
395                         LCD_PANEL_IDC_480X640;
396                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
397                 viaparinfo->lvds_setting_info->LCDDithering = 1;
398                 break;
399         case 0x17:
400                 /* OLPC XO-1.5 panel */
401                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
402                 viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
403                 viaparinfo->lvds_setting_info->lcd_panel_id =
404                         LCD_PANEL_IDD_1200X900;
405                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
406                 viaparinfo->lvds_setting_info->LCDDithering = 0;
407                 break;
408         default:
409                 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
410                 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
411                 viaparinfo->lvds_setting_info->lcd_panel_id =
412                         LCD_PANEL_ID1_800X600;
413                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
414                 viaparinfo->lvds_setting_info->LCDDithering = 1;
415         }
416 }
417
418 static int lvds_register_read(int index)
419 {
420         u8 data;
421
422         viafb_i2c_readbyte(VIA_PORT_2C,
423                         (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
424                         (u8) index, &data);
425         return data;
426 }
427
428 static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
429                       int panel_vres)
430 {
431         int reg_value = 0;
432         int viafb_load_reg_num;
433         struct io_register *reg = NULL;
434
435         DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
436
437         /* LCD Scaling Enable */
438         viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
439         if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
440                 viafb_load_scaling_factor_for_p4m900(set_hres, set_vres,
441                                                panel_hres, panel_vres);
442                 return;
443         }
444
445         /* Check if expansion for horizontal */
446         if (set_hres != panel_hres) {
447                 /* Load Horizontal Scaling Factor */
448                 switch (viaparinfo->chip_info->gfx_chip_name) {
449                 case UNICHROME_CLE266:
450                 case UNICHROME_K400:
451                         reg_value =
452                             CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
453                         viafb_load_reg_num =
454                             lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
455                             reg_num;
456                         reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
457                         viafb_load_reg(reg_value,
458                                 viafb_load_reg_num, reg, VIACR);
459                         break;
460                 case UNICHROME_K800:
461                 case UNICHROME_PM800:
462                 case UNICHROME_CN700:
463                 case UNICHROME_CX700:
464                 case UNICHROME_K8M890:
465                 case UNICHROME_P4M890:
466                         reg_value =
467                             K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
468                         /* Horizontal scaling enabled */
469                         viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
470                         viafb_load_reg_num =
471                             lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
472                         reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
473                         viafb_load_reg(reg_value,
474                                 viafb_load_reg_num, reg, VIACR);
475                         break;
476                 }
477
478                 DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
479         } else {
480                 /* Horizontal scaling disabled */
481                 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
482         }
483
484         /* Check if expansion for vertical */
485         if (set_vres != panel_vres) {
486                 /* Load Vertical Scaling Factor */
487                 switch (viaparinfo->chip_info->gfx_chip_name) {
488                 case UNICHROME_CLE266:
489                 case UNICHROME_K400:
490                         reg_value =
491                             CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
492                         viafb_load_reg_num =
493                             lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
494                             reg_num;
495                         reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
496                         viafb_load_reg(reg_value,
497                                 viafb_load_reg_num, reg, VIACR);
498                         break;
499                 case UNICHROME_K800:
500                 case UNICHROME_PM800:
501                 case UNICHROME_CN700:
502                 case UNICHROME_CX700:
503                 case UNICHROME_K8M890:
504                 case UNICHROME_P4M890:
505                         reg_value =
506                             K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
507                         /* Vertical scaling enabled */
508                         viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
509                         viafb_load_reg_num =
510                             lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
511                         reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
512                         viafb_load_reg(reg_value,
513                                 viafb_load_reg_num, reg, VIACR);
514                         break;
515                 }
516
517                 DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
518         } else {
519                 /* Vertical scaling disabled */
520                 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
521         }
522 }
523
524 static void via_pitch_alignment_patch_lcd(
525         struct lvds_setting_information *plvds_setting_info,
526                                    struct lvds_chip_information
527                                    *plvds_chip_info)
528 {
529         unsigned char cr13, cr35, cr65, cr66, cr67;
530         unsigned long dwScreenPitch = 0;
531         unsigned long dwPitch;
532
533         dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3);
534         if (dwPitch & 0x1F) {
535                 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
536                 if (plvds_setting_info->iga_path == IGA2) {
537                         if (plvds_setting_info->bpp > 8) {
538                                 cr66 = (unsigned char)(dwScreenPitch & 0xFF);
539                                 viafb_write_reg(CR66, VIACR, cr66);
540                                 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
541                                 cr67 |=
542                                     (unsigned
543                                      char)((dwScreenPitch & 0x300) >> 8);
544                                 viafb_write_reg(CR67, VIACR, cr67);
545                         }
546
547                         /* Fetch Count */
548                         cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
549                         cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
550                         viafb_write_reg(CR67, VIACR, cr67);
551                         cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
552                         cr65 += 2;
553                         viafb_write_reg(CR65, VIACR, cr65);
554                 } else {
555                         if (plvds_setting_info->bpp > 8) {
556                                 cr13 = (unsigned char)(dwScreenPitch & 0xFF);
557                                 viafb_write_reg(CR13, VIACR, cr13);
558                                 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
559                                 cr35 |=
560                                     (unsigned
561                                      char)((dwScreenPitch & 0x700) >> 3);
562                                 viafb_write_reg(CR35, VIACR, cr35);
563                         }
564                 }
565         }
566 }
567 static void lcd_patch_skew_dvp0(struct lvds_setting_information
568                          *plvds_setting_info,
569                          struct lvds_chip_information *plvds_chip_info)
570 {
571         if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
572                 switch (viaparinfo->chip_info->gfx_chip_name) {
573                 case UNICHROME_P4M900:
574                         viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
575                                                     plvds_chip_info);
576                         break;
577                 case UNICHROME_P4M890:
578                         viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
579                                                     plvds_chip_info);
580                         break;
581                 }
582         }
583 }
584 static void lcd_patch_skew_dvp1(struct lvds_setting_information
585                          *plvds_setting_info,
586                          struct lvds_chip_information *plvds_chip_info)
587 {
588         if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
589                 switch (viaparinfo->chip_info->gfx_chip_name) {
590                 case UNICHROME_CX700:
591                         viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
592                                                     plvds_chip_info);
593                         break;
594                 }
595         }
596 }
597 static void lcd_patch_skew(struct lvds_setting_information
598         *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
599 {
600         DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
601         switch (plvds_chip_info->output_interface) {
602         case INTERFACE_DVP0:
603                 lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
604                 break;
605         case INTERFACE_DVP1:
606                 lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
607                 break;
608         case INTERFACE_DFP_LOW:
609                 if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
610                         viafb_write_reg_mask(CR99, VIACR, 0x08,
611                                        BIT0 + BIT1 + BIT2 + BIT3);
612                 }
613                 break;
614         }
615 }
616
617 /* LCD Set Mode */
618 void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
619                   struct lvds_setting_information *plvds_setting_info,
620                   struct lvds_chip_information *plvds_chip_info)
621 {
622         int set_iga = plvds_setting_info->iga_path;
623         int mode_bpp = plvds_setting_info->bpp;
624         int set_hres = plvds_setting_info->h_active;
625         int set_vres = plvds_setting_info->v_active;
626         int panel_hres = plvds_setting_info->lcd_panel_hres;
627         int panel_vres = plvds_setting_info->lcd_panel_vres;
628         u32 pll_D_N;
629         struct display_timing mode_crt_reg, panel_crt_reg;
630         struct crt_mode_table *panel_crt_table = NULL;
631         struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
632                 panel_vres);
633
634         DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
635         /* Get mode table */
636         mode_crt_reg = mode_crt_table->crtc;
637         /* Get panel table Pointer */
638         panel_crt_table = vmode_tbl->crtc;
639         panel_crt_reg = panel_crt_table->crtc;
640         DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
641         if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
642                 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
643         plvds_setting_info->vclk = panel_crt_table->clk;
644         if (set_iga == IGA1) {
645                 /* IGA1 doesn't have LCD scaling, so set it as centering. */
646                 viafb_load_crtc_timing(lcd_centering_timging
647                                  (mode_crt_reg, panel_crt_reg), IGA1);
648         } else {
649                 /* Expansion */
650                 if ((plvds_setting_info->display_method ==
651                      LCD_EXPANDSION) & ((set_hres != panel_hres)
652                                         || (set_vres != panel_vres))) {
653                         /* expansion timing IGA2 loaded panel set timing*/
654                         viafb_load_crtc_timing(panel_crt_reg, IGA2);
655                         DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n");
656                         load_lcd_scaling(set_hres, set_vres, panel_hres,
657                                          panel_vres);
658                         DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n");
659                 } else {        /* Centering */
660                         /* centering timing IGA2 always loaded panel
661                            and mode releative timing */
662                         viafb_load_crtc_timing(lcd_centering_timging
663                                          (mode_crt_reg, panel_crt_reg), IGA2);
664                         viafb_write_reg_mask(CR79, VIACR, 0x00,
665                                 BIT0 + BIT1 + BIT2);
666                         /* LCD scaling disabled */
667                 }
668         }
669
670         /* Fetch count for IGA2 only */
671         viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
672
673         if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
674                 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
675                 viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
676
677         fill_lcd_format();
678
679         pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
680         DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
681         viafb_set_vclock(pll_D_N, set_iga);
682
683         viafb_set_output_path(DEVICE_LCD, set_iga,
684                 plvds_chip_info->output_interface);
685         lcd_patch_skew(plvds_setting_info, plvds_chip_info);
686
687         /* If K8M800, enable LCD Prefetch Mode. */
688         if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
689             || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
690                 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
691
692         /* Patch for non 32bit alignment mode */
693         via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info);
694 }
695
696 static void integrated_lvds_disable(struct lvds_setting_information
697                              *plvds_setting_info,
698                              struct lvds_chip_information *plvds_chip_info)
699 {
700         bool turn_off_first_powersequence = false;
701         bool turn_off_second_powersequence = false;
702         if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
703                 turn_off_first_powersequence = true;
704         if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
705                 turn_off_first_powersequence = true;
706         if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
707                 turn_off_second_powersequence = true;
708         if (turn_off_second_powersequence) {
709                 /* Use second power sequence control: */
710
711                 /* Turn off power sequence. */
712                 viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
713
714                 /* Turn off back light. */
715                 viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
716         }
717         if (turn_off_first_powersequence) {
718                 /* Use first power sequence control: */
719
720                 /* Turn off power sequence. */
721                 viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
722
723                 /* Turn off back light. */
724                 viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
725         }
726
727         /* Turn DFP High/Low Pad off. */
728         viafb_write_reg_mask(SR2A, VIASR, 0, BIT0 + BIT1 + BIT2 + BIT3);
729
730         /* Power off LVDS channel. */
731         switch (plvds_chip_info->output_interface) {
732         case INTERFACE_LVDS0:
733                 {
734                         viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
735                         break;
736                 }
737
738         case INTERFACE_LVDS1:
739                 {
740                         viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
741                         break;
742                 }
743
744         case INTERFACE_LVDS0LVDS1:
745                 {
746                         viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
747                         break;
748                 }
749         }
750 }
751
752 static void integrated_lvds_enable(struct lvds_setting_information
753                             *plvds_setting_info,
754                             struct lvds_chip_information *plvds_chip_info)
755 {
756         DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
757                   plvds_chip_info->output_interface);
758         if (plvds_setting_info->lcd_mode == LCD_SPWG)
759                 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
760         else
761                 viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
762
763         switch (plvds_chip_info->output_interface) {
764         case INTERFACE_LVDS0LVDS1:
765         case INTERFACE_LVDS0:
766                 /* Use first power sequence control: */
767                 /* Use hardware control power sequence. */
768                 viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
769                 /* Turn on back light. */
770                 viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
771                 /* Turn on hardware power sequence. */
772                 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
773                 break;
774         case INTERFACE_LVDS1:
775                 /* Use second power sequence control: */
776                 /* Use hardware control power sequence. */
777                 viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
778                 /* Turn on back light. */
779                 viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
780                 /* Turn on hardware power sequence. */
781                 viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
782                 break;
783         }
784
785         /* Turn DFP High/Low pad on. */
786         viafb_write_reg_mask(SR2A, VIASR, 0x0F, BIT0 + BIT1 + BIT2 + BIT3);
787
788         /* Power on LVDS channel. */
789         switch (plvds_chip_info->output_interface) {
790         case INTERFACE_LVDS0:
791                 {
792                         viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
793                         break;
794                 }
795
796         case INTERFACE_LVDS1:
797                 {
798                         viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
799                         break;
800                 }
801
802         case INTERFACE_LVDS0LVDS1:
803                 {
804                         viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
805                         break;
806                 }
807         }
808 }
809
810 void viafb_lcd_disable(void)
811 {
812
813         if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
814                 lcd_powersequence_off();
815                 /* DI1 pad off */
816                 viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
817         } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
818                 if (viafb_LCD2_ON
819                     && (INTEGRATED_LVDS ==
820                         viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
821                         integrated_lvds_disable(viaparinfo->lvds_setting_info,
822                                 &viaparinfo->chip_info->lvds_chip_info2);
823                 if (INTEGRATED_LVDS ==
824                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
825                         integrated_lvds_disable(viaparinfo->lvds_setting_info,
826                                 &viaparinfo->chip_info->lvds_chip_info);
827                 if (VT1636_LVDS == viaparinfo->chip_info->
828                         lvds_chip_info.lvds_chip_name)
829                         viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
830                                 &viaparinfo->chip_info->lvds_chip_info);
831         } else if (VT1636_LVDS ==
832         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
833                 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
834                                     &viaparinfo->chip_info->lvds_chip_info);
835         } else {
836                 /* DFP-HL pad off          */
837                 viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0F);
838                 /* Backlight off           */
839                 viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
840                 /* 24 bit DI data paht off */
841                 viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
842                 /* Simultaneout disabled   */
843                 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
844         }
845
846         /* Disable expansion bit   */
847         viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
848         /* CRT path set to IGA1    */
849         viafb_write_reg_mask(SR16, VIASR, 0x00, 0x40);
850         /* Simultaneout disabled   */
851         viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
852         /* IGA2 path disabled      */
853         viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
854
855 }
856
857 void viafb_lcd_enable(void)
858 {
859         if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
860                 /* DI1 pad on */
861                 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
862                 lcd_powersequence_on();
863         } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
864                 if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
865                         viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
866                         integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
867                                 &viaparinfo->chip_info->lvds_chip_info2);
868                 if (INTEGRATED_LVDS ==
869                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
870                         integrated_lvds_enable(viaparinfo->lvds_setting_info,
871                                 &viaparinfo->chip_info->lvds_chip_info);
872                 if (VT1636_LVDS == viaparinfo->chip_info->
873                         lvds_chip_info.lvds_chip_name)
874                         viafb_enable_lvds_vt1636(viaparinfo->
875                         lvds_setting_info, &viaparinfo->chip_info->
876                         lvds_chip_info);
877         } else if (VT1636_LVDS ==
878         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
879                 viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
880                                    &viaparinfo->chip_info->lvds_chip_info);
881         } else {
882                 /* DFP-HL pad on           */
883                 viafb_write_reg_mask(SR2A, VIASR, 0x0F, 0x0F);
884                 /* Backlight on            */
885                 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
886                 /* 24 bit DI data paht on  */
887                 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
888
889                 /* Set data source selection bit by iga path */
890                 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
891                         /* DFP-H set to IGA1       */
892                         viafb_write_reg_mask(CR97, VIACR, 0x00, 0x10);
893                         /* DFP-L set to IGA1       */
894                         viafb_write_reg_mask(CR99, VIACR, 0x00, 0x10);
895                 } else {
896                         /* DFP-H set to IGA2       */
897                         viafb_write_reg_mask(CR97, VIACR, 0x10, 0x10);
898                         /* DFP-L set to IGA2       */
899                         viafb_write_reg_mask(CR99, VIACR, 0x10, 0x10);
900                 }
901                 /* LCD enabled             */
902                 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
903         }
904
905         if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
906                 /* CRT path set to IGA2    */
907                 viafb_write_reg_mask(SR16, VIASR, 0x40, 0x40);
908                 /* IGA2 path disabled      */
909                 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x80);
910                 /* IGA2 path enabled       */
911         } else {                /* IGA2 */
912                 viafb_write_reg_mask(CR6A, VIACR, 0x80, 0x80);
913         }
914
915 }
916
917 static void lcd_powersequence_off(void)
918 {
919         int i, mask, data;
920
921         /* Software control power sequence */
922         viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
923
924         for (i = 0; i < 3; i++) {
925                 mask = PowerSequenceOff[0][i];
926                 data = PowerSequenceOff[1][i] & mask;
927                 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
928                 udelay(PowerSequenceOff[2][i]);
929         }
930
931         /* Disable LCD */
932         viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
933 }
934
935 static void lcd_powersequence_on(void)
936 {
937         int i, mask, data;
938
939         /* Software control power sequence */
940         viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
941
942         /* Enable LCD */
943         viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
944
945         for (i = 0; i < 3; i++) {
946                 mask = PowerSequenceOn[0][i];
947                 data = PowerSequenceOn[1][i] & mask;
948                 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
949                 udelay(PowerSequenceOn[2][i]);
950         }
951
952         udelay(1);
953 }
954
955 static void fill_lcd_format(void)
956 {
957         u8 bdithering = 0, bdual = 0;
958
959         if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
960                 bdual = BIT4;
961         if (viaparinfo->lvds_setting_info->LCDDithering)
962                 bdithering = BIT0;
963         /* Dual & Dithering */
964         viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
965 }
966
967 static void check_diport_of_integrated_lvds(
968         struct lvds_chip_information *plvds_chip_info,
969                                      struct lvds_setting_information
970                                      *plvds_setting_info)
971 {
972         /* Determine LCD DI Port by hardware layout. */
973         switch (viafb_display_hardware_layout) {
974         case HW_LAYOUT_LCD_ONLY:
975                 {
976                         if (plvds_setting_info->device_lcd_dualedge) {
977                                 plvds_chip_info->output_interface =
978                                     INTERFACE_LVDS0LVDS1;
979                         } else {
980                                 plvds_chip_info->output_interface =
981                                     INTERFACE_LVDS0;
982                         }
983
984                         break;
985                 }
986
987         case HW_LAYOUT_DVI_ONLY:
988                 {
989                         plvds_chip_info->output_interface = INTERFACE_NONE;
990                         break;
991                 }
992
993         case HW_LAYOUT_LCD1_LCD2:
994         case HW_LAYOUT_LCD_EXTERNAL_LCD2:
995                 {
996                         plvds_chip_info->output_interface =
997                             INTERFACE_LVDS0LVDS1;
998                         break;
999                 }
1000
1001         case HW_LAYOUT_LCD_DVI:
1002                 {
1003                         plvds_chip_info->output_interface = INTERFACE_LVDS1;
1004                         break;
1005                 }
1006
1007         default:
1008                 {
1009                         plvds_chip_info->output_interface = INTERFACE_LVDS1;
1010                         break;
1011                 }
1012         }
1013
1014         DEBUG_MSG(KERN_INFO
1015                   "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
1016                   viafb_display_hardware_layout,
1017                   plvds_chip_info->output_interface);
1018 }
1019
1020 void viafb_init_lvds_output_interface(struct lvds_chip_information
1021                                 *plvds_chip_info,
1022                                 struct lvds_setting_information
1023                                 *plvds_setting_info)
1024 {
1025         if (INTERFACE_NONE != plvds_chip_info->output_interface) {
1026                 /*Do nothing, lcd port is specified by module parameter */
1027                 return;
1028         }
1029
1030         switch (plvds_chip_info->lvds_chip_name) {
1031
1032         case VT1636_LVDS:
1033                 switch (viaparinfo->chip_info->gfx_chip_name) {
1034                 case UNICHROME_CX700:
1035                         plvds_chip_info->output_interface = INTERFACE_DVP1;
1036                         break;
1037                 case UNICHROME_CN700:
1038                         plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
1039                         break;
1040                 default:
1041                         plvds_chip_info->output_interface = INTERFACE_DVP0;
1042                         break;
1043                 }
1044                 break;
1045
1046         case INTEGRATED_LVDS:
1047                 check_diport_of_integrated_lvds(plvds_chip_info,
1048                                                 plvds_setting_info);
1049                 break;
1050
1051         default:
1052                 switch (viaparinfo->chip_info->gfx_chip_name) {
1053                 case UNICHROME_K8M890:
1054                 case UNICHROME_P4M900:
1055                 case UNICHROME_P4M890:
1056                         plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
1057                         break;
1058                 default:
1059                         plvds_chip_info->output_interface = INTERFACE_DFP;
1060                         break;
1061                 }
1062                 break;
1063         }
1064 }
1065
1066 static struct display_timing lcd_centering_timging(struct display_timing
1067                                             mode_crt_reg,
1068                                             struct display_timing panel_crt_reg)
1069 {
1070         struct display_timing crt_reg;
1071
1072         crt_reg.hor_total = panel_crt_reg.hor_total;
1073         crt_reg.hor_addr = mode_crt_reg.hor_addr;
1074         crt_reg.hor_blank_start =
1075             (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
1076             crt_reg.hor_addr;
1077         crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
1078         crt_reg.hor_sync_start =
1079             (panel_crt_reg.hor_sync_start -
1080              panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
1081         crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
1082
1083         crt_reg.ver_total = panel_crt_reg.ver_total;
1084         crt_reg.ver_addr = mode_crt_reg.ver_addr;
1085         crt_reg.ver_blank_start =
1086             (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
1087             crt_reg.ver_addr;
1088         crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
1089         crt_reg.ver_sync_start =
1090             (panel_crt_reg.ver_sync_start -
1091              panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
1092         crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
1093
1094         return crt_reg;
1095 }
1096
1097 bool viafb_lcd_get_mobile_state(bool *mobile)
1098 {
1099         unsigned char *romptr, *tableptr;
1100         u8 core_base;
1101         unsigned char *biosptr;
1102         /* Rom address */
1103         u32 romaddr = 0x000C0000;
1104         u16 start_pattern = 0;
1105
1106         biosptr = ioremap(romaddr, 0x10000);
1107
1108         memcpy(&start_pattern, biosptr, 2);
1109         /* Compare pattern */
1110         if (start_pattern == 0xAA55) {
1111                 /* Get the start of Table */
1112                 /* 0x1B means BIOS offset position */
1113                 romptr = biosptr + 0x1B;
1114                 tableptr = biosptr + *((u16 *) romptr);
1115
1116                 /* Get the start of biosver structure */
1117                 /* 18 means BIOS version position. */
1118                 romptr = tableptr + 18;
1119                 romptr = biosptr + *((u16 *) romptr);
1120
1121                 /* The offset should be 44, but the
1122                    actual image is less three char. */
1123                 /* pRom += 44; */
1124                 romptr += 41;
1125
1126                 core_base = *romptr++;
1127
1128                 if (core_base & 0x8)
1129                         *mobile = false;
1130                 else
1131                         *mobile = true;
1132                 /* release memory */
1133                 iounmap(biosptr);
1134
1135                 return true;
1136         } else {
1137                 iounmap(biosptr);
1138                 return false;
1139         }
1140 }
1141
1142 static void viafb_load_scaling_factor_for_p4m900(int set_hres,
1143         int set_vres, int panel_hres, int panel_vres)
1144 {
1145         int h_scaling_factor;
1146         int v_scaling_factor;
1147         u8 cra2 = 0;
1148         u8 cr77 = 0;
1149         u8 cr78 = 0;
1150         u8 cr79 = 0;
1151         u8 cr9f = 0;
1152         /* Check if expansion for horizontal */
1153         if (set_hres < panel_hres) {
1154                 /* Load Horizontal Scaling Factor */
1155
1156                 /* For VIA_K8M800 or later chipsets. */
1157                 h_scaling_factor =
1158                     K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
1159                 /* HSCaleFactor[1:0] at CR9F[1:0] */
1160                 cr9f = h_scaling_factor & 0x0003;
1161                 /* HSCaleFactor[9:2] at CR77[7:0] */
1162                 cr77 = (h_scaling_factor & 0x03FC) >> 2;
1163                 /* HSCaleFactor[11:10] at CR79[5:4] */
1164                 cr79 = (h_scaling_factor & 0x0C00) >> 10;
1165                 cr79 <<= 4;
1166
1167                 /* Horizontal scaling enabled */
1168                 cra2 = 0xC0;
1169
1170                 DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d\n",
1171                           h_scaling_factor);
1172         } else {
1173                 /* Horizontal scaling disabled */
1174                 cra2 = 0x00;
1175         }
1176
1177         /* Check if expansion for vertical */
1178         if (set_vres < panel_vres) {
1179                 /* Load Vertical Scaling Factor */
1180
1181                 /* For VIA_K8M800 or later chipsets. */
1182                 v_scaling_factor =
1183                     K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
1184
1185                 /* Vertical scaling enabled */
1186                 cra2 |= 0x08;
1187                 /* VSCaleFactor[0] at CR79[3] */
1188                 cr79 |= ((v_scaling_factor & 0x0001) << 3);
1189                 /* VSCaleFactor[8:1] at CR78[7:0] */
1190                 cr78 |= (v_scaling_factor & 0x01FE) >> 1;
1191                 /* VSCaleFactor[10:9] at CR79[7:6] */
1192                 cr79 |= ((v_scaling_factor & 0x0600) >> 9) << 6;
1193
1194                 DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d\n",
1195                           v_scaling_factor);
1196         } else {
1197                 /* Vertical scaling disabled */
1198                 cra2 |= 0x00;
1199         }
1200
1201         viafb_write_reg_mask(CRA2, VIACR, cra2, BIT3 + BIT6 + BIT7);
1202         viafb_write_reg_mask(CR77, VIACR, cr77, 0xFF);
1203         viafb_write_reg_mask(CR78, VIACR, cr78, 0xFF);
1204         viafb_write_reg_mask(CR79, VIACR, cr79, 0xF8);
1205         viafb_write_reg_mask(CR9F, VIACR, cr9f, BIT0 + BIT1);
1206 }