0001
0002
0003
0004
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
0014
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
0024 {LCD_HOR_SCALING_FACTOR_REG_NUM,
0025 {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
0026
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
0032 {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
0033
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
0089
0090
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
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
0112
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
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
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
0345 viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
0346
0347
0348 if (set_hres < panel_hres) {
0349
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
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
0388 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
0389 }
0390
0391
0392 if (set_vres < panel_vres) {
0393
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
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
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
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
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
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
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
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
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
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
0604
0605
0606 viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
0607
0608
0609 viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
0610 }
0611 if (turn_off_first_powersequence) {
0612
0613
0614
0615 viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
0616
0617
0618 viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
0619 }
0620
0621
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
0658
0659 viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
0660
0661 viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
0662
0663 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
0664 break;
0665 case INTERFACE_LVDS1:
0666
0667
0668 viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
0669
0670 viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
0671
0672 viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
0673 break;
0674 }
0675
0676
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
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
0725 viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
0726
0727 viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
0728 }
0729
0730
0731 viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
0732
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
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
0791 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
0792
0793 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
0794
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
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
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
0822 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
0823
0824
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
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
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
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
0953 const u32 romaddr = 0x000C0000;
0954 u16 start_pattern;
0955
0956 biosptr = ioremap(romaddr, 0x10000);
0957 start_pattern = readw(biosptr);
0958
0959
0960 if (start_pattern == 0xAA55) {
0961
0962
0963 romptr = biosptr + 0x1B;
0964 tableptr = biosptr + readw(romptr);
0965
0966
0967
0968 romptr = tableptr + 18;
0969 romptr = biosptr + readw(romptr);
0970
0971
0972
0973
0974 romptr += 41;
0975
0976 core_base = readb(romptr);
0977
0978 if (core_base & 0x8)
0979 *mobile = false;
0980 else
0981 *mobile = true;
0982
0983 iounmap(biosptr);
0984
0985 return true;
0986 } else {
0987 iounmap(biosptr);
0988 return false;
0989 }
0990 }