Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
0004  * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
0005 
0006  */
0007 #include <linux/via-core.h>
0008 #include <linux/via_i2c.h>
0009 #include "global.h"
0010 
0011 #define viafb_compact_res(x, y) (((x)<<16)|(y))
0012 
0013 /* CLE266 Software Power Sequence */
0014 /* {Mask}, {Data}, {Delay} */
0015 static const int PowerSequenceOn[3][3] = {
0016     {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01}
0017 };
0018 static const int PowerSequenceOff[3][3] = {
0019     {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01}
0020 };
0021 
0022 static struct _lcd_scaling_factor lcd_scaling_factor = {
0023     /* LCD Horizontal Scaling Factor Register */
0024     {LCD_HOR_SCALING_FACTOR_REG_NUM,
0025      {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
0026     /* LCD Vertical Scaling Factor Register */
0027     {LCD_VER_SCALING_FACTOR_REG_NUM,
0028      {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
0029 };
0030 static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
0031     /* LCD Horizontal Scaling Factor Register */
0032     {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
0033     /* LCD Vertical Scaling Factor Register */
0034     {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
0035 };
0036 
0037 static bool lvds_identify_integratedlvds(void);
0038 static void fp_id_to_vindex(int panel_id);
0039 static int lvds_register_read(int index);
0040 static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
0041               int panel_vres);
0042 static void lcd_patch_skew_dvp0(struct lvds_setting_information
0043              *plvds_setting_info,
0044              struct lvds_chip_information *plvds_chip_info);
0045 static void lcd_patch_skew_dvp1(struct lvds_setting_information
0046              *plvds_setting_info,
0047              struct lvds_chip_information *plvds_chip_info);
0048 static void lcd_patch_skew(struct lvds_setting_information
0049     *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
0050 
0051 static void integrated_lvds_disable(struct lvds_setting_information
0052                  *plvds_setting_info,
0053                  struct lvds_chip_information *plvds_chip_info);
0054 static void integrated_lvds_enable(struct lvds_setting_information
0055                 *plvds_setting_info,
0056                 struct lvds_chip_information *plvds_chip_info);
0057 static void lcd_powersequence_off(void);
0058 static void lcd_powersequence_on(void);
0059 static void fill_lcd_format(void);
0060 static void check_diport_of_integrated_lvds(
0061     struct lvds_chip_information *plvds_chip_info,
0062                      struct lvds_setting_information
0063                      *plvds_setting_info);
0064 
0065 static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
0066 {
0067     return lvds_register_read(device_id_subaddr) == device_id;
0068 }
0069 
0070 void viafb_init_lcd_size(void)
0071 {
0072     DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
0073 
0074     fp_id_to_vindex(viafb_lcd_panel_id);
0075     viaparinfo->lvds_setting_info2->lcd_panel_hres =
0076         viaparinfo->lvds_setting_info->lcd_panel_hres;
0077     viaparinfo->lvds_setting_info2->lcd_panel_vres =
0078         viaparinfo->lvds_setting_info->lcd_panel_vres;
0079     viaparinfo->lvds_setting_info2->device_lcd_dualedge =
0080         viaparinfo->lvds_setting_info->device_lcd_dualedge;
0081     viaparinfo->lvds_setting_info2->LCDDithering =
0082         viaparinfo->lvds_setting_info->LCDDithering;
0083 }
0084 
0085 static bool lvds_identify_integratedlvds(void)
0086 {
0087     if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
0088         /* Two dual channel LCD (Internal LVDS + External LVDS): */
0089         /* If we have an external LVDS, such as VT1636, we should
0090            have its chip ID already. */
0091         if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
0092             viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
0093                 INTEGRATED_LVDS;
0094             DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "
0095                   "(Internal LVDS + External LVDS)\n");
0096         } else {
0097             viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
0098                 INTEGRATED_LVDS;
0099             DEBUG_MSG(KERN_INFO "Not found external LVDS, "
0100                   "so can't support two dual channel LVDS!\n");
0101         }
0102     } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
0103         /* Two single channel LCD (Internal LVDS + Internal LVDS): */
0104         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
0105         INTEGRATED_LVDS;
0106         viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
0107             INTEGRATED_LVDS;
0108         DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "
0109               "(Internal LVDS + Internal LVDS)\n");
0110     } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
0111         /* If we have found external LVDS, just use it,
0112            otherwise, we will use internal LVDS as default. */
0113         if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
0114             viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
0115                 INTEGRATED_LVDS;
0116             DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
0117         }
0118     } else {
0119         viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
0120             NON_LVDS_TRANSMITTER;
0121         DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
0122         return false;
0123     }
0124 
0125     return true;
0126 }
0127 
0128 bool viafb_lvds_trasmitter_identify(void)
0129 {
0130     if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
0131         viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
0132         DEBUG_MSG(KERN_INFO
0133               "Found VIA VT1636 LVDS on port i2c 0x31\n");
0134     } else {
0135         if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) {
0136             viaparinfo->chip_info->lvds_chip_info.i2c_port =
0137                 VIA_PORT_2C;
0138             DEBUG_MSG(KERN_INFO
0139                   "Found VIA VT1636 LVDS on port gpio 0x2c\n");
0140         }
0141     }
0142 
0143     if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
0144         lvds_identify_integratedlvds();
0145 
0146     if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
0147         return true;
0148     /* Check for VT1631: */
0149     viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
0150     viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
0151         VT1631_LVDS_I2C_ADDR;
0152 
0153     if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) {
0154         DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
0155         DEBUG_MSG(KERN_INFO "\n %2d",
0156               viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
0157         DEBUG_MSG(KERN_INFO "\n %2d",
0158               viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
0159         return true;
0160     }
0161 
0162     viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
0163         NON_LVDS_TRANSMITTER;
0164     viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
0165         VT1631_LVDS_I2C_ADDR;
0166     return false;
0167 }
0168 
0169 static void fp_id_to_vindex(int panel_id)
0170 {
0171     DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
0172 
0173     if (panel_id > LCD_PANEL_ID_MAXIMUM)
0174         viafb_lcd_panel_id = panel_id =
0175         viafb_read_reg(VIACR, CR3F) & 0x0F;
0176 
0177     switch (panel_id) {
0178     case 0x0:
0179         viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
0180         viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
0181         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0182         viaparinfo->lvds_setting_info->LCDDithering = 1;
0183         break;
0184     case 0x1:
0185         viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
0186         viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
0187         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0188         viaparinfo->lvds_setting_info->LCDDithering = 1;
0189         break;
0190     case 0x2:
0191         viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
0192         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0193         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0194         viaparinfo->lvds_setting_info->LCDDithering = 1;
0195         break;
0196     case 0x3:
0197         viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
0198         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0199         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0200         viaparinfo->lvds_setting_info->LCDDithering = 1;
0201         break;
0202     case 0x4:
0203         viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
0204         viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
0205         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0206         viaparinfo->lvds_setting_info->LCDDithering = 1;
0207         break;
0208     case 0x5:
0209         viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
0210         viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
0211         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0212         viaparinfo->lvds_setting_info->LCDDithering = 1;
0213         break;
0214     case 0x6:
0215         viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
0216         viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
0217         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0218         viaparinfo->lvds_setting_info->LCDDithering = 1;
0219         break;
0220     case 0x8:
0221         viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
0222         viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
0223         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0224         viaparinfo->lvds_setting_info->LCDDithering = 1;
0225         break;
0226     case 0x9:
0227         viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
0228         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0229         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0230         viaparinfo->lvds_setting_info->LCDDithering = 1;
0231         break;
0232     case 0xA:
0233         viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
0234         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0235         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0236         viaparinfo->lvds_setting_info->LCDDithering = 0;
0237         break;
0238     case 0xB:
0239         viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
0240         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0241         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0242         viaparinfo->lvds_setting_info->LCDDithering = 0;
0243         break;
0244     case 0xC:
0245         viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
0246         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0247         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0248         viaparinfo->lvds_setting_info->LCDDithering = 0;
0249         break;
0250     case 0xD:
0251         viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
0252         viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
0253         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0254         viaparinfo->lvds_setting_info->LCDDithering = 0;
0255         break;
0256     case 0xE:
0257         viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
0258         viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
0259         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0260         viaparinfo->lvds_setting_info->LCDDithering = 0;
0261         break;
0262     case 0xF:
0263         viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
0264         viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
0265         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0266         viaparinfo->lvds_setting_info->LCDDithering = 0;
0267         break;
0268     case 0x10:
0269         viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
0270         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0271         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0272         viaparinfo->lvds_setting_info->LCDDithering = 0;
0273         break;
0274     case 0x11:
0275         viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
0276         viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
0277         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0278         viaparinfo->lvds_setting_info->LCDDithering = 1;
0279         break;
0280     case 0x12:
0281         viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
0282         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0283         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0284         viaparinfo->lvds_setting_info->LCDDithering = 1;
0285         break;
0286     case 0x13:
0287         viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
0288         viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
0289         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0290         viaparinfo->lvds_setting_info->LCDDithering = 1;
0291         break;
0292     case 0x14:
0293         viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
0294         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0295         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0296         viaparinfo->lvds_setting_info->LCDDithering = 0;
0297         break;
0298     case 0x15:
0299         viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
0300         viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
0301         viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
0302         viaparinfo->lvds_setting_info->LCDDithering = 0;
0303         break;
0304     case 0x16:
0305         viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
0306         viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
0307         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0308         viaparinfo->lvds_setting_info->LCDDithering = 1;
0309         break;
0310     case 0x17:
0311         /* OLPC XO-1.5 panel */
0312         viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
0313         viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
0314         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0315         viaparinfo->lvds_setting_info->LCDDithering = 0;
0316         break;
0317     default:
0318         viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
0319         viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
0320         viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
0321         viaparinfo->lvds_setting_info->LCDDithering = 1;
0322     }
0323 }
0324 
0325 static int lvds_register_read(int index)
0326 {
0327     u8 data;
0328 
0329     viafb_i2c_readbyte(VIA_PORT_2C,
0330             (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
0331             (u8) index, &data);
0332     return data;
0333 }
0334 
0335 static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
0336               int panel_vres)
0337 {
0338     int reg_value = 0;
0339     int viafb_load_reg_num;
0340     struct io_register *reg = NULL;
0341 
0342     DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
0343 
0344     /* LCD Scaling Enable */
0345     viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
0346 
0347     /* Check if expansion for horizontal */
0348     if (set_hres < panel_hres) {
0349         /* Load Horizontal Scaling Factor */
0350         switch (viaparinfo->chip_info->gfx_chip_name) {
0351         case UNICHROME_CLE266:
0352         case UNICHROME_K400:
0353             reg_value =
0354                 CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
0355             viafb_load_reg_num =
0356                 lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
0357                 reg_num;
0358             reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
0359             viafb_load_reg(reg_value,
0360                 viafb_load_reg_num, reg, VIACR);
0361             break;
0362         case UNICHROME_K800:
0363         case UNICHROME_PM800:
0364         case UNICHROME_CN700:
0365         case UNICHROME_CX700:
0366         case UNICHROME_K8M890:
0367         case UNICHROME_P4M890:
0368         case UNICHROME_P4M900:
0369         case UNICHROME_CN750:
0370         case UNICHROME_VX800:
0371         case UNICHROME_VX855:
0372         case UNICHROME_VX900:
0373             reg_value =
0374                 K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
0375             /* Horizontal scaling enabled */
0376             viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
0377             viafb_load_reg_num =
0378                 lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
0379             reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
0380             viafb_load_reg(reg_value,
0381                 viafb_load_reg_num, reg, VIACR);
0382             break;
0383         }
0384 
0385         DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
0386     } else {
0387         /* Horizontal scaling disabled */
0388         viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
0389     }
0390 
0391     /* Check if expansion for vertical */
0392     if (set_vres < panel_vres) {
0393         /* Load Vertical Scaling Factor */
0394         switch (viaparinfo->chip_info->gfx_chip_name) {
0395         case UNICHROME_CLE266:
0396         case UNICHROME_K400:
0397             reg_value =
0398                 CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
0399             viafb_load_reg_num =
0400                 lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
0401                 reg_num;
0402             reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
0403             viafb_load_reg(reg_value,
0404                 viafb_load_reg_num, reg, VIACR);
0405             break;
0406         case UNICHROME_K800:
0407         case UNICHROME_PM800:
0408         case UNICHROME_CN700:
0409         case UNICHROME_CX700:
0410         case UNICHROME_K8M890:
0411         case UNICHROME_P4M890:
0412         case UNICHROME_P4M900:
0413         case UNICHROME_CN750:
0414         case UNICHROME_VX800:
0415         case UNICHROME_VX855:
0416         case UNICHROME_VX900:
0417             reg_value =
0418                 K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
0419             /* Vertical scaling enabled */
0420             viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
0421             viafb_load_reg_num =
0422                 lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
0423             reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
0424             viafb_load_reg(reg_value,
0425                 viafb_load_reg_num, reg, VIACR);
0426             break;
0427         }
0428 
0429         DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
0430     } else {
0431         /* Vertical scaling disabled */
0432         viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
0433     }
0434 }
0435 
0436 static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp)
0437 {
0438     unsigned char cr13, cr35, cr65, cr66, cr67;
0439     unsigned long dwScreenPitch = 0;
0440     unsigned long dwPitch;
0441 
0442     dwPitch = hres * (bpp >> 3);
0443     if (dwPitch & 0x1F) {
0444         dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
0445         if (iga_path == IGA2) {
0446             if (bpp > 8) {
0447                 cr66 = (unsigned char)(dwScreenPitch & 0xFF);
0448                 viafb_write_reg(CR66, VIACR, cr66);
0449                 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
0450                 cr67 |=
0451                     (unsigned
0452                      char)((dwScreenPitch & 0x300) >> 8);
0453                 viafb_write_reg(CR67, VIACR, cr67);
0454             }
0455 
0456             /* Fetch Count */
0457             cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
0458             cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
0459             viafb_write_reg(CR67, VIACR, cr67);
0460             cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
0461             cr65 += 2;
0462             viafb_write_reg(CR65, VIACR, cr65);
0463         } else {
0464             if (bpp > 8) {
0465                 cr13 = (unsigned char)(dwScreenPitch & 0xFF);
0466                 viafb_write_reg(CR13, VIACR, cr13);
0467                 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
0468                 cr35 |=
0469                     (unsigned
0470                      char)((dwScreenPitch & 0x700) >> 3);
0471                 viafb_write_reg(CR35, VIACR, cr35);
0472             }
0473         }
0474     }
0475 }
0476 static void lcd_patch_skew_dvp0(struct lvds_setting_information
0477              *plvds_setting_info,
0478              struct lvds_chip_information *plvds_chip_info)
0479 {
0480     if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
0481         switch (viaparinfo->chip_info->gfx_chip_name) {
0482         case UNICHROME_P4M900:
0483             viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
0484                             plvds_chip_info);
0485             break;
0486         case UNICHROME_P4M890:
0487             viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
0488                             plvds_chip_info);
0489             break;
0490         }
0491     }
0492 }
0493 static void lcd_patch_skew_dvp1(struct lvds_setting_information
0494              *plvds_setting_info,
0495              struct lvds_chip_information *plvds_chip_info)
0496 {
0497     if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
0498         switch (viaparinfo->chip_info->gfx_chip_name) {
0499         case UNICHROME_CX700:
0500             viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
0501                             plvds_chip_info);
0502             break;
0503         }
0504     }
0505 }
0506 static void lcd_patch_skew(struct lvds_setting_information
0507     *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
0508 {
0509     DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
0510     switch (plvds_chip_info->output_interface) {
0511     case INTERFACE_DVP0:
0512         lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
0513         break;
0514     case INTERFACE_DVP1:
0515         lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
0516         break;
0517     case INTERFACE_DFP_LOW:
0518         if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
0519             viafb_write_reg_mask(CR99, VIACR, 0x08,
0520                        BIT0 + BIT1 + BIT2 + BIT3);
0521         }
0522         break;
0523     }
0524 }
0525 
0526 /* LCD Set Mode */
0527 void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
0528     u16 cyres, struct lvds_setting_information *plvds_setting_info,
0529     struct lvds_chip_information *plvds_chip_info)
0530 {
0531     int set_iga = plvds_setting_info->iga_path;
0532     int mode_bpp = var->bits_per_pixel;
0533     int set_hres = cxres ? cxres : var->xres;
0534     int set_vres = cyres ? cyres : var->yres;
0535     int panel_hres = plvds_setting_info->lcd_panel_hres;
0536     int panel_vres = plvds_setting_info->lcd_panel_vres;
0537     u32 clock;
0538     struct via_display_timing timing;
0539     struct fb_var_screeninfo panel_var;
0540     const struct fb_videomode *panel_crt_table;
0541 
0542     DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
0543     /* Get panel table Pointer */
0544     panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
0545     viafb_fill_var_timing_info(&panel_var, panel_crt_table);
0546     DEBUG_MSG(KERN_INFO "below viafb_lcd_set_mode!!\n");
0547     if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
0548         viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
0549     clock = PICOS2KHZ(panel_crt_table->pixclock) * 1000;
0550     plvds_setting_info->vclk = clock;
0551 
0552     if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
0553         && plvds_setting_info->display_method == LCD_EXPANDSION) {
0554         timing = var_to_timing(&panel_var, panel_hres, panel_vres);
0555         load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
0556     } else {
0557         timing = var_to_timing(&panel_var, set_hres, set_vres);
0558         if (set_iga == IGA2)
0559             /* disable scaling */
0560             via_write_reg_mask(VIACR, 0x79, 0x00,
0561                 BIT0 + BIT1 + BIT2);
0562     }
0563 
0564     if (set_iga == IGA1)
0565         via_set_primary_timing(&timing);
0566     else if (set_iga == IGA2)
0567         via_set_secondary_timing(&timing);
0568 
0569     /* Fetch count for IGA2 only */
0570     viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
0571 
0572     if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
0573         && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
0574         viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
0575 
0576     fill_lcd_format();
0577     viafb_set_vclock(clock, set_iga);
0578     lcd_patch_skew(plvds_setting_info, plvds_chip_info);
0579 
0580     /* If K8M800, enable LCD Prefetch Mode. */
0581     if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
0582         || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
0583         viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
0584 
0585     /* Patch for non 32bit alignment mode */
0586     via_pitch_alignment_patch_lcd(plvds_setting_info->iga_path, set_hres,
0587         var->bits_per_pixel);
0588 }
0589 
0590 static void integrated_lvds_disable(struct lvds_setting_information
0591                  *plvds_setting_info,
0592                  struct lvds_chip_information *plvds_chip_info)
0593 {
0594     bool turn_off_first_powersequence = false;
0595     bool turn_off_second_powersequence = false;
0596     if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
0597         turn_off_first_powersequence = true;
0598     if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
0599         turn_off_first_powersequence = true;
0600     if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
0601         turn_off_second_powersequence = true;
0602     if (turn_off_second_powersequence) {
0603         /* Use second power sequence control: */
0604 
0605         /* Turn off power sequence. */
0606         viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
0607 
0608         /* Turn off back light. */
0609         viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
0610     }
0611     if (turn_off_first_powersequence) {
0612         /* Use first power sequence control: */
0613 
0614         /* Turn off power sequence. */
0615         viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
0616 
0617         /* Turn off back light. */
0618         viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
0619     }
0620 
0621     /* Power off LVDS channel. */
0622     switch (plvds_chip_info->output_interface) {
0623     case INTERFACE_LVDS0:
0624         {
0625             viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
0626             break;
0627         }
0628 
0629     case INTERFACE_LVDS1:
0630         {
0631             viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
0632             break;
0633         }
0634 
0635     case INTERFACE_LVDS0LVDS1:
0636         {
0637             viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
0638             break;
0639         }
0640     }
0641 }
0642 
0643 static void integrated_lvds_enable(struct lvds_setting_information
0644                 *plvds_setting_info,
0645                 struct lvds_chip_information *plvds_chip_info)
0646 {
0647     DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
0648           plvds_chip_info->output_interface);
0649     if (plvds_setting_info->lcd_mode == LCD_SPWG)
0650         viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
0651     else
0652         viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
0653 
0654     switch (plvds_chip_info->output_interface) {
0655     case INTERFACE_LVDS0LVDS1:
0656     case INTERFACE_LVDS0:
0657         /* Use first power sequence control: */
0658         /* Use hardware control power sequence. */
0659         viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
0660         /* Turn on back light. */
0661         viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
0662         /* Turn on hardware power sequence. */
0663         viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
0664         break;
0665     case INTERFACE_LVDS1:
0666         /* Use second power sequence control: */
0667         /* Use hardware control power sequence. */
0668         viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
0669         /* Turn on back light. */
0670         viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
0671         /* Turn on hardware power sequence. */
0672         viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
0673         break;
0674     }
0675 
0676     /* Power on LVDS channel. */
0677     switch (plvds_chip_info->output_interface) {
0678     case INTERFACE_LVDS0:
0679         {
0680             viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
0681             break;
0682         }
0683 
0684     case INTERFACE_LVDS1:
0685         {
0686             viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
0687             break;
0688         }
0689 
0690     case INTERFACE_LVDS0LVDS1:
0691         {
0692             viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
0693             break;
0694         }
0695     }
0696 }
0697 
0698 void viafb_lcd_disable(void)
0699 {
0700 
0701     if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
0702         lcd_powersequence_off();
0703         /* DI1 pad off */
0704         viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
0705     } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
0706         if (viafb_LCD2_ON
0707             && (INTEGRATED_LVDS ==
0708             viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
0709             integrated_lvds_disable(viaparinfo->lvds_setting_info,
0710                 &viaparinfo->chip_info->lvds_chip_info2);
0711         if (INTEGRATED_LVDS ==
0712             viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
0713             integrated_lvds_disable(viaparinfo->lvds_setting_info,
0714                 &viaparinfo->chip_info->lvds_chip_info);
0715         if (VT1636_LVDS == viaparinfo->chip_info->
0716             lvds_chip_info.lvds_chip_name)
0717             viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
0718                 &viaparinfo->chip_info->lvds_chip_info);
0719     } else if (VT1636_LVDS ==
0720     viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
0721         viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
0722                     &viaparinfo->chip_info->lvds_chip_info);
0723     } else {
0724         /* Backlight off           */
0725         viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
0726         /* 24 bit DI data paht off */
0727         viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
0728     }
0729 
0730     /* Disable expansion bit   */
0731     viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
0732     /* Simultaneout disabled   */
0733     viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
0734 }
0735 
0736 static void set_lcd_output_path(int set_iga, int output_interface)
0737 {
0738     switch (output_interface) {
0739     case INTERFACE_DFP:
0740         if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
0741             || (UNICHROME_P4M890 ==
0742             viaparinfo->chip_info->gfx_chip_name))
0743             viafb_write_reg_mask(CR97, VIACR, 0x84,
0744                        BIT7 + BIT2 + BIT1 + BIT0);
0745         fallthrough;
0746     case INTERFACE_DVP0:
0747     case INTERFACE_DVP1:
0748     case INTERFACE_DFP_HIGH:
0749     case INTERFACE_DFP_LOW:
0750         if (set_iga == IGA2)
0751             viafb_write_reg(CR91, VIACR, 0x00);
0752         break;
0753     }
0754 }
0755 
0756 void viafb_lcd_enable(void)
0757 {
0758     viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
0759     viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
0760     set_lcd_output_path(viaparinfo->lvds_setting_info->iga_path,
0761         viaparinfo->chip_info->lvds_chip_info.output_interface);
0762     if (viafb_LCD2_ON)
0763         set_lcd_output_path(viaparinfo->lvds_setting_info2->iga_path,
0764             viaparinfo->chip_info->
0765             lvds_chip_info2.output_interface);
0766 
0767     if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
0768         /* DI1 pad on */
0769         viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
0770         lcd_powersequence_on();
0771     } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
0772         if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
0773             viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
0774             integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
0775                 &viaparinfo->chip_info->lvds_chip_info2);
0776         if (INTEGRATED_LVDS ==
0777             viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
0778             integrated_lvds_enable(viaparinfo->lvds_setting_info,
0779                 &viaparinfo->chip_info->lvds_chip_info);
0780         if (VT1636_LVDS == viaparinfo->chip_info->
0781             lvds_chip_info.lvds_chip_name)
0782             viafb_enable_lvds_vt1636(viaparinfo->
0783             lvds_setting_info, &viaparinfo->chip_info->
0784             lvds_chip_info);
0785     } else if (VT1636_LVDS ==
0786     viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
0787         viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
0788                    &viaparinfo->chip_info->lvds_chip_info);
0789     } else {
0790         /* Backlight on            */
0791         viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
0792         /* 24 bit DI data paht on  */
0793         viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
0794         /* LCD enabled             */
0795         viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
0796     }
0797 }
0798 
0799 static void lcd_powersequence_off(void)
0800 {
0801     int i, mask, data;
0802 
0803     /* Software control power sequence */
0804     viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
0805 
0806     for (i = 0; i < 3; i++) {
0807         mask = PowerSequenceOff[0][i];
0808         data = PowerSequenceOff[1][i] & mask;
0809         viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
0810         udelay(PowerSequenceOff[2][i]);
0811     }
0812 
0813     /* Disable LCD */
0814     viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
0815 }
0816 
0817 static void lcd_powersequence_on(void)
0818 {
0819     int i, mask, data;
0820 
0821     /* Software control power sequence */
0822     viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
0823 
0824     /* Enable LCD */
0825     viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
0826 
0827     for (i = 0; i < 3; i++) {
0828         mask = PowerSequenceOn[0][i];
0829         data = PowerSequenceOn[1][i] & mask;
0830         viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
0831         udelay(PowerSequenceOn[2][i]);
0832     }
0833 
0834     udelay(1);
0835 }
0836 
0837 static void fill_lcd_format(void)
0838 {
0839     u8 bdithering = 0, bdual = 0;
0840 
0841     if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
0842         bdual = BIT4;
0843     if (viaparinfo->lvds_setting_info->LCDDithering)
0844         bdithering = BIT0;
0845     /* Dual & Dithering */
0846     viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
0847 }
0848 
0849 static void check_diport_of_integrated_lvds(
0850     struct lvds_chip_information *plvds_chip_info,
0851                      struct lvds_setting_information
0852                      *plvds_setting_info)
0853 {
0854     /* Determine LCD DI Port by hardware layout. */
0855     switch (viafb_display_hardware_layout) {
0856     case HW_LAYOUT_LCD_ONLY:
0857         {
0858             if (plvds_setting_info->device_lcd_dualedge) {
0859                 plvds_chip_info->output_interface =
0860                     INTERFACE_LVDS0LVDS1;
0861             } else {
0862                 plvds_chip_info->output_interface =
0863                     INTERFACE_LVDS0;
0864             }
0865 
0866             break;
0867         }
0868 
0869     case HW_LAYOUT_DVI_ONLY:
0870         {
0871             plvds_chip_info->output_interface = INTERFACE_NONE;
0872             break;
0873         }
0874 
0875     case HW_LAYOUT_LCD1_LCD2:
0876     case HW_LAYOUT_LCD_EXTERNAL_LCD2:
0877         {
0878             plvds_chip_info->output_interface =
0879                 INTERFACE_LVDS0LVDS1;
0880             break;
0881         }
0882 
0883     case HW_LAYOUT_LCD_DVI:
0884         {
0885             plvds_chip_info->output_interface = INTERFACE_LVDS1;
0886             break;
0887         }
0888 
0889     default:
0890         {
0891             plvds_chip_info->output_interface = INTERFACE_LVDS1;
0892             break;
0893         }
0894     }
0895 
0896     DEBUG_MSG(KERN_INFO
0897           "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
0898           viafb_display_hardware_layout,
0899           plvds_chip_info->output_interface);
0900 }
0901 
0902 void viafb_init_lvds_output_interface(struct lvds_chip_information
0903                 *plvds_chip_info,
0904                 struct lvds_setting_information
0905                 *plvds_setting_info)
0906 {
0907     if (INTERFACE_NONE != plvds_chip_info->output_interface) {
0908         /*Do nothing, lcd port is specified by module parameter */
0909         return;
0910     }
0911 
0912     switch (plvds_chip_info->lvds_chip_name) {
0913 
0914     case VT1636_LVDS:
0915         switch (viaparinfo->chip_info->gfx_chip_name) {
0916         case UNICHROME_CX700:
0917             plvds_chip_info->output_interface = INTERFACE_DVP1;
0918             break;
0919         case UNICHROME_CN700:
0920             plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
0921             break;
0922         default:
0923             plvds_chip_info->output_interface = INTERFACE_DVP0;
0924             break;
0925         }
0926         break;
0927 
0928     case INTEGRATED_LVDS:
0929         check_diport_of_integrated_lvds(plvds_chip_info,
0930                         plvds_setting_info);
0931         break;
0932 
0933     default:
0934         switch (viaparinfo->chip_info->gfx_chip_name) {
0935         case UNICHROME_K8M890:
0936         case UNICHROME_P4M900:
0937         case UNICHROME_P4M890:
0938             plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
0939             break;
0940         default:
0941             plvds_chip_info->output_interface = INTERFACE_DFP;
0942             break;
0943         }
0944         break;
0945     }
0946 }
0947 
0948 bool viafb_lcd_get_mobile_state(bool *mobile)
0949 {
0950     unsigned char __iomem *romptr, *tableptr, *biosptr;
0951     u8 core_base;
0952     /* Rom address */
0953     const u32 romaddr = 0x000C0000;
0954     u16 start_pattern;
0955 
0956     biosptr = ioremap(romaddr, 0x10000);
0957     start_pattern = readw(biosptr);
0958 
0959     /* Compare pattern */
0960     if (start_pattern == 0xAA55) {
0961         /* Get the start of Table */
0962         /* 0x1B means BIOS offset position */
0963         romptr = biosptr + 0x1B;
0964         tableptr = biosptr + readw(romptr);
0965 
0966         /* Get the start of biosver structure */
0967         /* 18 means BIOS version position. */
0968         romptr = tableptr + 18;
0969         romptr = biosptr + readw(romptr);
0970 
0971         /* The offset should be 44, but the
0972            actual image is less three char. */
0973         /* pRom += 44; */
0974         romptr += 41;
0975 
0976         core_base = readb(romptr);
0977 
0978         if (core_base & 0x8)
0979             *mobile = false;
0980         else
0981             *mobile = true;
0982         /* release memory */
0983         iounmap(biosptr);
0984 
0985         return true;
0986     } else {
0987         iounmap(biosptr);
0988         return false;
0989     }
0990 }