Merge tag 'soundwire-5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul...
[linux-2.6-microblaze.git] / drivers / video / fbdev / via / lcd.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
4  * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
5
6  */
7 #include <linux/via-core.h>
8 #include <linux/via_i2c.h>
9 #include "global.h"
10
11 #define viafb_compact_res(x, y) (((x)<<16)|(y))
12
13 /* CLE266 Software Power Sequence */
14 /* {Mask}, {Data}, {Delay} */
15 static const int PowerSequenceOn[3][3] = {
16         {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01}
17 };
18 static const int PowerSequenceOff[3][3] = {
19         {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01}
20 };
21
22 static struct _lcd_scaling_factor lcd_scaling_factor = {
23         /* LCD Horizontal Scaling Factor Register */
24         {LCD_HOR_SCALING_FACTOR_REG_NUM,
25          {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
26         /* LCD Vertical Scaling Factor Register */
27         {LCD_VER_SCALING_FACTOR_REG_NUM,
28          {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
29 };
30 static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
31         /* LCD Horizontal Scaling Factor Register */
32         {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
33         /* LCD Vertical Scaling Factor Register */
34         {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
35 };
36
37 static bool lvds_identify_integratedlvds(void);
38 static void fp_id_to_vindex(int panel_id);
39 static int lvds_register_read(int index);
40 static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
41                       int panel_vres);
42 static void lcd_patch_skew_dvp0(struct lvds_setting_information
43                          *plvds_setting_info,
44                          struct lvds_chip_information *plvds_chip_info);
45 static void lcd_patch_skew_dvp1(struct lvds_setting_information
46                          *plvds_setting_info,
47                          struct lvds_chip_information *plvds_chip_info);
48 static void lcd_patch_skew(struct lvds_setting_information
49         *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
50
51 static void integrated_lvds_disable(struct lvds_setting_information
52                              *plvds_setting_info,
53                              struct lvds_chip_information *plvds_chip_info);
54 static void integrated_lvds_enable(struct lvds_setting_information
55                             *plvds_setting_info,
56                             struct lvds_chip_information *plvds_chip_info);
57 static void lcd_powersequence_off(void);
58 static void lcd_powersequence_on(void);
59 static void fill_lcd_format(void);
60 static void check_diport_of_integrated_lvds(
61         struct lvds_chip_information *plvds_chip_info,
62                                      struct lvds_setting_information
63                                      *plvds_setting_info);
64
65 static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
66 {
67         return lvds_register_read(device_id_subaddr) == device_id;
68 }
69
70 void viafb_init_lcd_size(void)
71 {
72         DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
73
74         fp_id_to_vindex(viafb_lcd_panel_id);
75         viaparinfo->lvds_setting_info2->lcd_panel_hres =
76                 viaparinfo->lvds_setting_info->lcd_panel_hres;
77         viaparinfo->lvds_setting_info2->lcd_panel_vres =
78                 viaparinfo->lvds_setting_info->lcd_panel_vres;
79         viaparinfo->lvds_setting_info2->device_lcd_dualedge =
80             viaparinfo->lvds_setting_info->device_lcd_dualedge;
81         viaparinfo->lvds_setting_info2->LCDDithering =
82                 viaparinfo->lvds_setting_info->LCDDithering;
83 }
84
85 static bool lvds_identify_integratedlvds(void)
86 {
87         if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
88                 /* Two dual channel LCD (Internal LVDS + External LVDS): */
89                 /* If we have an external LVDS, such as VT1636, we should
90                    have its chip ID already. */
91                 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
92                         viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
93                             INTEGRATED_LVDS;
94                         DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "
95                                   "(Internal LVDS + External LVDS)\n");
96                 } else {
97                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
98                             INTEGRATED_LVDS;
99                         DEBUG_MSG(KERN_INFO "Not found external LVDS, "
100                                   "so can't support two dual channel LVDS!\n");
101                 }
102         } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
103                 /* Two single channel LCD (Internal LVDS + Internal LVDS): */
104                 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
105                 INTEGRATED_LVDS;
106                 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
107                         INTEGRATED_LVDS;
108                 DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "
109                           "(Internal LVDS + Internal LVDS)\n");
110         } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
111                 /* If we have found external LVDS, just use it,
112                    otherwise, we will use internal LVDS as default. */
113                 if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
114                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
115                             INTEGRATED_LVDS;
116                         DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
117                 }
118         } else {
119                 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
120                         NON_LVDS_TRANSMITTER;
121                 DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
122                 return false;
123         }
124
125         return true;
126 }
127
128 bool viafb_lvds_trasmitter_identify(void)
129 {
130         if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
131                 viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
132                 DEBUG_MSG(KERN_INFO
133                           "Found VIA VT1636 LVDS on port i2c 0x31\n");
134         } else {
135                 if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) {
136                         viaparinfo->chip_info->lvds_chip_info.i2c_port =
137                                 VIA_PORT_2C;
138                         DEBUG_MSG(KERN_INFO
139                                   "Found VIA VT1636 LVDS on port gpio 0x2c\n");
140                 }
141         }
142
143         if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
144                 lvds_identify_integratedlvds();
145
146         if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
147                 return true;
148         /* Check for VT1631: */
149         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
150         viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
151                 VT1631_LVDS_I2C_ADDR;
152
153         if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) {
154                 DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
155                 DEBUG_MSG(KERN_INFO "\n %2d",
156                           viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
157                 DEBUG_MSG(KERN_INFO "\n %2d",
158                           viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
159                 return true;
160         }
161
162         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
163                 NON_LVDS_TRANSMITTER;
164         viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
165                 VT1631_LVDS_I2C_ADDR;
166         return false;
167 }
168
169 static void fp_id_to_vindex(int panel_id)
170 {
171         DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
172
173         if (panel_id > LCD_PANEL_ID_MAXIMUM)
174                 viafb_lcd_panel_id = panel_id =
175                 viafb_read_reg(VIACR, CR3F) & 0x0F;
176
177         switch (panel_id) {
178         case 0x0:
179                 viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
180                 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
181                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
182                 viaparinfo->lvds_setting_info->LCDDithering = 1;
183                 break;
184         case 0x1:
185                 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
186                 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
187                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
188                 viaparinfo->lvds_setting_info->LCDDithering = 1;
189                 break;
190         case 0x2:
191                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
192                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
193                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
194                 viaparinfo->lvds_setting_info->LCDDithering = 1;
195                 break;
196         case 0x3:
197                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
198                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
199                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
200                 viaparinfo->lvds_setting_info->LCDDithering = 1;
201                 break;
202         case 0x4:
203                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
204                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
205                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
206                 viaparinfo->lvds_setting_info->LCDDithering = 1;
207                 break;
208         case 0x5:
209                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
210                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
211                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
212                 viaparinfo->lvds_setting_info->LCDDithering = 1;
213                 break;
214         case 0x6:
215                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
216                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
217                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
218                 viaparinfo->lvds_setting_info->LCDDithering = 1;
219                 break;
220         case 0x8:
221                 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
222                 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
223                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
224                 viaparinfo->lvds_setting_info->LCDDithering = 1;
225                 break;
226         case 0x9:
227                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
228                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
229                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
230                 viaparinfo->lvds_setting_info->LCDDithering = 1;
231                 break;
232         case 0xA:
233                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
234                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
235                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
236                 viaparinfo->lvds_setting_info->LCDDithering = 0;
237                 break;
238         case 0xB:
239                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
240                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
241                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
242                 viaparinfo->lvds_setting_info->LCDDithering = 0;
243                 break;
244         case 0xC:
245                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
246                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
247                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
248                 viaparinfo->lvds_setting_info->LCDDithering = 0;
249                 break;
250         case 0xD:
251                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
252                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
253                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
254                 viaparinfo->lvds_setting_info->LCDDithering = 0;
255                 break;
256         case 0xE:
257                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
258                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
259                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
260                 viaparinfo->lvds_setting_info->LCDDithering = 0;
261                 break;
262         case 0xF:
263                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
264                 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
265                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
266                 viaparinfo->lvds_setting_info->LCDDithering = 0;
267                 break;
268         case 0x10:
269                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
270                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
271                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
272                 viaparinfo->lvds_setting_info->LCDDithering = 0;
273                 break;
274         case 0x11:
275                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
276                 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
277                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
278                 viaparinfo->lvds_setting_info->LCDDithering = 1;
279                 break;
280         case 0x12:
281                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
282                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
283                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
284                 viaparinfo->lvds_setting_info->LCDDithering = 1;
285                 break;
286         case 0x13:
287                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
288                 viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
289                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
290                 viaparinfo->lvds_setting_info->LCDDithering = 1;
291                 break;
292         case 0x14:
293                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
294                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
295                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
296                 viaparinfo->lvds_setting_info->LCDDithering = 0;
297                 break;
298         case 0x15:
299                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
300                 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
301                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
302                 viaparinfo->lvds_setting_info->LCDDithering = 0;
303                 break;
304         case 0x16:
305                 viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
306                 viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
307                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
308                 viaparinfo->lvds_setting_info->LCDDithering = 1;
309                 break;
310         case 0x17:
311                 /* OLPC XO-1.5 panel */
312                 viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
313                 viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
314                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
315                 viaparinfo->lvds_setting_info->LCDDithering = 0;
316                 break;
317         default:
318                 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
319                 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
320                 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
321                 viaparinfo->lvds_setting_info->LCDDithering = 1;
322         }
323 }
324
325 static int lvds_register_read(int index)
326 {
327         u8 data;
328
329         viafb_i2c_readbyte(VIA_PORT_2C,
330                         (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
331                         (u8) index, &data);
332         return data;
333 }
334
335 static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
336                       int panel_vres)
337 {
338         int reg_value = 0;
339         int viafb_load_reg_num;
340         struct io_register *reg = NULL;
341
342         DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
343
344         /* LCD Scaling Enable */
345         viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
346
347         /* Check if expansion for horizontal */
348         if (set_hres < panel_hres) {
349                 /* Load Horizontal Scaling Factor */
350                 switch (viaparinfo->chip_info->gfx_chip_name) {
351                 case UNICHROME_CLE266:
352                 case UNICHROME_K400:
353                         reg_value =
354                             CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
355                         viafb_load_reg_num =
356                             lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
357                             reg_num;
358                         reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
359                         viafb_load_reg(reg_value,
360                                 viafb_load_reg_num, reg, VIACR);
361                         break;
362                 case UNICHROME_K800:
363                 case UNICHROME_PM800:
364                 case UNICHROME_CN700:
365                 case UNICHROME_CX700:
366                 case UNICHROME_K8M890:
367                 case UNICHROME_P4M890:
368                 case UNICHROME_P4M900:
369                 case UNICHROME_CN750:
370                 case UNICHROME_VX800:
371                 case UNICHROME_VX855:
372                 case UNICHROME_VX900:
373                         reg_value =
374                             K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
375                         /* Horizontal scaling enabled */
376                         viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
377                         viafb_load_reg_num =
378                             lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
379                         reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
380                         viafb_load_reg(reg_value,
381                                 viafb_load_reg_num, reg, VIACR);
382                         break;
383                 }
384
385                 DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
386         } else {
387                 /* Horizontal scaling disabled */
388                 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
389         }
390
391         /* Check if expansion for vertical */
392         if (set_vres < panel_vres) {
393                 /* Load Vertical Scaling Factor */
394                 switch (viaparinfo->chip_info->gfx_chip_name) {
395                 case UNICHROME_CLE266:
396                 case UNICHROME_K400:
397                         reg_value =
398                             CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
399                         viafb_load_reg_num =
400                             lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
401                             reg_num;
402                         reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
403                         viafb_load_reg(reg_value,
404                                 viafb_load_reg_num, reg, VIACR);
405                         break;
406                 case UNICHROME_K800:
407                 case UNICHROME_PM800:
408                 case UNICHROME_CN700:
409                 case UNICHROME_CX700:
410                 case UNICHROME_K8M890:
411                 case UNICHROME_P4M890:
412                 case UNICHROME_P4M900:
413                 case UNICHROME_CN750:
414                 case UNICHROME_VX800:
415                 case UNICHROME_VX855:
416                 case UNICHROME_VX900:
417                         reg_value =
418                             K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
419                         /* Vertical scaling enabled */
420                         viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
421                         viafb_load_reg_num =
422                             lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
423                         reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
424                         viafb_load_reg(reg_value,
425                                 viafb_load_reg_num, reg, VIACR);
426                         break;
427                 }
428
429                 DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
430         } else {
431                 /* Vertical scaling disabled */
432                 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
433         }
434 }
435
436 static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp)
437 {
438         unsigned char cr13, cr35, cr65, cr66, cr67;
439         unsigned long dwScreenPitch = 0;
440         unsigned long dwPitch;
441
442         dwPitch = hres * (bpp >> 3);
443         if (dwPitch & 0x1F) {
444                 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
445                 if (iga_path == IGA2) {
446                         if (bpp > 8) {
447                                 cr66 = (unsigned char)(dwScreenPitch & 0xFF);
448                                 viafb_write_reg(CR66, VIACR, cr66);
449                                 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
450                                 cr67 |=
451                                     (unsigned
452                                      char)((dwScreenPitch & 0x300) >> 8);
453                                 viafb_write_reg(CR67, VIACR, cr67);
454                         }
455
456                         /* Fetch Count */
457                         cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
458                         cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
459                         viafb_write_reg(CR67, VIACR, cr67);
460                         cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
461                         cr65 += 2;
462                         viafb_write_reg(CR65, VIACR, cr65);
463                 } else {
464                         if (bpp > 8) {
465                                 cr13 = (unsigned char)(dwScreenPitch & 0xFF);
466                                 viafb_write_reg(CR13, VIACR, cr13);
467                                 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
468                                 cr35 |=
469                                     (unsigned
470                                      char)((dwScreenPitch & 0x700) >> 3);
471                                 viafb_write_reg(CR35, VIACR, cr35);
472                         }
473                 }
474         }
475 }
476 static void lcd_patch_skew_dvp0(struct lvds_setting_information
477                          *plvds_setting_info,
478                          struct lvds_chip_information *plvds_chip_info)
479 {
480         if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
481                 switch (viaparinfo->chip_info->gfx_chip_name) {
482                 case UNICHROME_P4M900:
483                         viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
484                                                     plvds_chip_info);
485                         break;
486                 case UNICHROME_P4M890:
487                         viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
488                                                     plvds_chip_info);
489                         break;
490                 }
491         }
492 }
493 static void lcd_patch_skew_dvp1(struct lvds_setting_information
494                          *plvds_setting_info,
495                          struct lvds_chip_information *plvds_chip_info)
496 {
497         if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
498                 switch (viaparinfo->chip_info->gfx_chip_name) {
499                 case UNICHROME_CX700:
500                         viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
501                                                     plvds_chip_info);
502                         break;
503                 }
504         }
505 }
506 static void lcd_patch_skew(struct lvds_setting_information
507         *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
508 {
509         DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
510         switch (plvds_chip_info->output_interface) {
511         case INTERFACE_DVP0:
512                 lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
513                 break;
514         case INTERFACE_DVP1:
515                 lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
516                 break;
517         case INTERFACE_DFP_LOW:
518                 if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
519                         viafb_write_reg_mask(CR99, VIACR, 0x08,
520                                        BIT0 + BIT1 + BIT2 + BIT3);
521                 }
522                 break;
523         }
524 }
525
526 /* LCD Set Mode */
527 void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
528         u16 cyres, struct lvds_setting_information *plvds_setting_info,
529         struct lvds_chip_information *plvds_chip_info)
530 {
531         int set_iga = plvds_setting_info->iga_path;
532         int mode_bpp = var->bits_per_pixel;
533         int set_hres = cxres ? cxres : var->xres;
534         int set_vres = cyres ? cyres : var->yres;
535         int panel_hres = plvds_setting_info->lcd_panel_hres;
536         int panel_vres = plvds_setting_info->lcd_panel_vres;
537         u32 clock;
538         struct via_display_timing timing;
539         struct fb_var_screeninfo panel_var;
540         const struct fb_videomode *mode_crt_table, *panel_crt_table;
541
542         DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
543         /* Get mode table */
544         mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
545         /* Get panel table Pointer */
546         panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
547         viafb_fill_var_timing_info(&panel_var, panel_crt_table);
548         DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
549         if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
550                 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
551         clock = PICOS2KHZ(panel_crt_table->pixclock) * 1000;
552         plvds_setting_info->vclk = clock;
553
554         if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
555                 && plvds_setting_info->display_method == LCD_EXPANDSION) {
556                 timing = var_to_timing(&panel_var, panel_hres, panel_vres);
557                 load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
558         } else {
559                 timing = var_to_timing(&panel_var, set_hres, set_vres);
560                 if (set_iga == IGA2)
561                         /* disable scaling */
562                         via_write_reg_mask(VIACR, 0x79, 0x00,
563                                 BIT0 + BIT1 + BIT2);
564         }
565
566         if (set_iga == IGA1)
567                 via_set_primary_timing(&timing);
568         else if (set_iga == IGA2)
569                 via_set_secondary_timing(&timing);
570
571         /* Fetch count for IGA2 only */
572         viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
573
574         if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
575                 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
576                 viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
577
578         fill_lcd_format();
579         viafb_set_vclock(clock, set_iga);
580         lcd_patch_skew(plvds_setting_info, plvds_chip_info);
581
582         /* If K8M800, enable LCD Prefetch Mode. */
583         if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
584             || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
585                 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
586
587         /* Patch for non 32bit alignment mode */
588         via_pitch_alignment_patch_lcd(plvds_setting_info->iga_path, set_hres,
589                 var->bits_per_pixel);
590 }
591
592 static void integrated_lvds_disable(struct lvds_setting_information
593                              *plvds_setting_info,
594                              struct lvds_chip_information *plvds_chip_info)
595 {
596         bool turn_off_first_powersequence = false;
597         bool turn_off_second_powersequence = false;
598         if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
599                 turn_off_first_powersequence = true;
600         if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
601                 turn_off_first_powersequence = true;
602         if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
603                 turn_off_second_powersequence = true;
604         if (turn_off_second_powersequence) {
605                 /* Use second power sequence control: */
606
607                 /* Turn off power sequence. */
608                 viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
609
610                 /* Turn off back light. */
611                 viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
612         }
613         if (turn_off_first_powersequence) {
614                 /* Use first power sequence control: */
615
616                 /* Turn off power sequence. */
617                 viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
618
619                 /* Turn off back light. */
620                 viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
621         }
622
623         /* Power off LVDS channel. */
624         switch (plvds_chip_info->output_interface) {
625         case INTERFACE_LVDS0:
626                 {
627                         viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
628                         break;
629                 }
630
631         case INTERFACE_LVDS1:
632                 {
633                         viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
634                         break;
635                 }
636
637         case INTERFACE_LVDS0LVDS1:
638                 {
639                         viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
640                         break;
641                 }
642         }
643 }
644
645 static void integrated_lvds_enable(struct lvds_setting_information
646                             *plvds_setting_info,
647                             struct lvds_chip_information *plvds_chip_info)
648 {
649         DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
650                   plvds_chip_info->output_interface);
651         if (plvds_setting_info->lcd_mode == LCD_SPWG)
652                 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
653         else
654                 viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
655
656         switch (plvds_chip_info->output_interface) {
657         case INTERFACE_LVDS0LVDS1:
658         case INTERFACE_LVDS0:
659                 /* Use first power sequence control: */
660                 /* Use hardware control power sequence. */
661                 viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
662                 /* Turn on back light. */
663                 viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
664                 /* Turn on hardware power sequence. */
665                 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
666                 break;
667         case INTERFACE_LVDS1:
668                 /* Use second power sequence control: */
669                 /* Use hardware control power sequence. */
670                 viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
671                 /* Turn on back light. */
672                 viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
673                 /* Turn on hardware power sequence. */
674                 viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
675                 break;
676         }
677
678         /* Power on LVDS channel. */
679         switch (plvds_chip_info->output_interface) {
680         case INTERFACE_LVDS0:
681                 {
682                         viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
683                         break;
684                 }
685
686         case INTERFACE_LVDS1:
687                 {
688                         viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
689                         break;
690                 }
691
692         case INTERFACE_LVDS0LVDS1:
693                 {
694                         viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
695                         break;
696                 }
697         }
698 }
699
700 void viafb_lcd_disable(void)
701 {
702
703         if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
704                 lcd_powersequence_off();
705                 /* DI1 pad off */
706                 viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
707         } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
708                 if (viafb_LCD2_ON
709                     && (INTEGRATED_LVDS ==
710                         viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
711                         integrated_lvds_disable(viaparinfo->lvds_setting_info,
712                                 &viaparinfo->chip_info->lvds_chip_info2);
713                 if (INTEGRATED_LVDS ==
714                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
715                         integrated_lvds_disable(viaparinfo->lvds_setting_info,
716                                 &viaparinfo->chip_info->lvds_chip_info);
717                 if (VT1636_LVDS == viaparinfo->chip_info->
718                         lvds_chip_info.lvds_chip_name)
719                         viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
720                                 &viaparinfo->chip_info->lvds_chip_info);
721         } else if (VT1636_LVDS ==
722         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
723                 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
724                                     &viaparinfo->chip_info->lvds_chip_info);
725         } else {
726                 /* Backlight off           */
727                 viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
728                 /* 24 bit DI data paht off */
729                 viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
730         }
731
732         /* Disable expansion bit   */
733         viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
734         /* Simultaneout disabled   */
735         viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
736 }
737
738 static void set_lcd_output_path(int set_iga, int output_interface)
739 {
740         switch (output_interface) {
741         case INTERFACE_DFP:
742                 if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
743                     || (UNICHROME_P4M890 ==
744                     viaparinfo->chip_info->gfx_chip_name))
745                         viafb_write_reg_mask(CR97, VIACR, 0x84,
746                                        BIT7 + BIT2 + BIT1 + BIT0);
747                 fallthrough;
748         case INTERFACE_DVP0:
749         case INTERFACE_DVP1:
750         case INTERFACE_DFP_HIGH:
751         case INTERFACE_DFP_LOW:
752                 if (set_iga == IGA2)
753                         viafb_write_reg(CR91, VIACR, 0x00);
754                 break;
755         }
756 }
757
758 void viafb_lcd_enable(void)
759 {
760         viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
761         viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
762         set_lcd_output_path(viaparinfo->lvds_setting_info->iga_path,
763                 viaparinfo->chip_info->lvds_chip_info.output_interface);
764         if (viafb_LCD2_ON)
765                 set_lcd_output_path(viaparinfo->lvds_setting_info2->iga_path,
766                         viaparinfo->chip_info->
767                         lvds_chip_info2.output_interface);
768
769         if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
770                 /* DI1 pad on */
771                 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
772                 lcd_powersequence_on();
773         } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
774                 if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
775                         viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
776                         integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
777                                 &viaparinfo->chip_info->lvds_chip_info2);
778                 if (INTEGRATED_LVDS ==
779                         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
780                         integrated_lvds_enable(viaparinfo->lvds_setting_info,
781                                 &viaparinfo->chip_info->lvds_chip_info);
782                 if (VT1636_LVDS == viaparinfo->chip_info->
783                         lvds_chip_info.lvds_chip_name)
784                         viafb_enable_lvds_vt1636(viaparinfo->
785                         lvds_setting_info, &viaparinfo->chip_info->
786                         lvds_chip_info);
787         } else if (VT1636_LVDS ==
788         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
789                 viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
790                                    &viaparinfo->chip_info->lvds_chip_info);
791         } else {
792                 /* Backlight on            */
793                 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
794                 /* 24 bit DI data paht on  */
795                 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
796                 /* LCD enabled             */
797                 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
798         }
799 }
800
801 static void lcd_powersequence_off(void)
802 {
803         int i, mask, data;
804
805         /* Software control power sequence */
806         viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
807
808         for (i = 0; i < 3; i++) {
809                 mask = PowerSequenceOff[0][i];
810                 data = PowerSequenceOff[1][i] & mask;
811                 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
812                 udelay(PowerSequenceOff[2][i]);
813         }
814
815         /* Disable LCD */
816         viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
817 }
818
819 static void lcd_powersequence_on(void)
820 {
821         int i, mask, data;
822
823         /* Software control power sequence */
824         viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
825
826         /* Enable LCD */
827         viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
828
829         for (i = 0; i < 3; i++) {
830                 mask = PowerSequenceOn[0][i];
831                 data = PowerSequenceOn[1][i] & mask;
832                 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
833                 udelay(PowerSequenceOn[2][i]);
834         }
835
836         udelay(1);
837 }
838
839 static void fill_lcd_format(void)
840 {
841         u8 bdithering = 0, bdual = 0;
842
843         if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
844                 bdual = BIT4;
845         if (viaparinfo->lvds_setting_info->LCDDithering)
846                 bdithering = BIT0;
847         /* Dual & Dithering */
848         viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
849 }
850
851 static void check_diport_of_integrated_lvds(
852         struct lvds_chip_information *plvds_chip_info,
853                                      struct lvds_setting_information
854                                      *plvds_setting_info)
855 {
856         /* Determine LCD DI Port by hardware layout. */
857         switch (viafb_display_hardware_layout) {
858         case HW_LAYOUT_LCD_ONLY:
859                 {
860                         if (plvds_setting_info->device_lcd_dualedge) {
861                                 plvds_chip_info->output_interface =
862                                     INTERFACE_LVDS0LVDS1;
863                         } else {
864                                 plvds_chip_info->output_interface =
865                                     INTERFACE_LVDS0;
866                         }
867
868                         break;
869                 }
870
871         case HW_LAYOUT_DVI_ONLY:
872                 {
873                         plvds_chip_info->output_interface = INTERFACE_NONE;
874                         break;
875                 }
876
877         case HW_LAYOUT_LCD1_LCD2:
878         case HW_LAYOUT_LCD_EXTERNAL_LCD2:
879                 {
880                         plvds_chip_info->output_interface =
881                             INTERFACE_LVDS0LVDS1;
882                         break;
883                 }
884
885         case HW_LAYOUT_LCD_DVI:
886                 {
887                         plvds_chip_info->output_interface = INTERFACE_LVDS1;
888                         break;
889                 }
890
891         default:
892                 {
893                         plvds_chip_info->output_interface = INTERFACE_LVDS1;
894                         break;
895                 }
896         }
897
898         DEBUG_MSG(KERN_INFO
899                   "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
900                   viafb_display_hardware_layout,
901                   plvds_chip_info->output_interface);
902 }
903
904 void viafb_init_lvds_output_interface(struct lvds_chip_information
905                                 *plvds_chip_info,
906                                 struct lvds_setting_information
907                                 *plvds_setting_info)
908 {
909         if (INTERFACE_NONE != plvds_chip_info->output_interface) {
910                 /*Do nothing, lcd port is specified by module parameter */
911                 return;
912         }
913
914         switch (plvds_chip_info->lvds_chip_name) {
915
916         case VT1636_LVDS:
917                 switch (viaparinfo->chip_info->gfx_chip_name) {
918                 case UNICHROME_CX700:
919                         plvds_chip_info->output_interface = INTERFACE_DVP1;
920                         break;
921                 case UNICHROME_CN700:
922                         plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
923                         break;
924                 default:
925                         plvds_chip_info->output_interface = INTERFACE_DVP0;
926                         break;
927                 }
928                 break;
929
930         case INTEGRATED_LVDS:
931                 check_diport_of_integrated_lvds(plvds_chip_info,
932                                                 plvds_setting_info);
933                 break;
934
935         default:
936                 switch (viaparinfo->chip_info->gfx_chip_name) {
937                 case UNICHROME_K8M890:
938                 case UNICHROME_P4M900:
939                 case UNICHROME_P4M890:
940                         plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
941                         break;
942                 default:
943                         plvds_chip_info->output_interface = INTERFACE_DFP;
944                         break;
945                 }
946                 break;
947         }
948 }
949
950 bool viafb_lcd_get_mobile_state(bool *mobile)
951 {
952         unsigned char __iomem *romptr, *tableptr, *biosptr;
953         u8 core_base;
954         /* Rom address */
955         const u32 romaddr = 0x000C0000;
956         u16 start_pattern;
957
958         biosptr = ioremap(romaddr, 0x10000);
959         start_pattern = readw(biosptr);
960
961         /* Compare pattern */
962         if (start_pattern == 0xAA55) {
963                 /* Get the start of Table */
964                 /* 0x1B means BIOS offset position */
965                 romptr = biosptr + 0x1B;
966                 tableptr = biosptr + readw(romptr);
967
968                 /* Get the start of biosver structure */
969                 /* 18 means BIOS version position. */
970                 romptr = tableptr + 18;
971                 romptr = biosptr + readw(romptr);
972
973                 /* The offset should be 44, but the
974                    actual image is less three char. */
975                 /* pRom += 44; */
976                 romptr += 41;
977
978                 core_base = readb(romptr);
979
980                 if (core_base & 0x8)
981                         *mobile = false;
982                 else
983                         *mobile = true;
984                 /* release memory */
985                 iounmap(biosptr);
986
987                 return true;
988         } else {
989                 iounmap(biosptr);
990                 return false;
991         }
992 }