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