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