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} */ 29static const int PowerSequenceOn[3][3] = { 30 {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01} 31}; 32static const int PowerSequenceOff[3][3] = { 33 {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01} 34}; 35 36static 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}; 44static 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 51static bool lvds_identify_integratedlvds(void); 52static void fp_id_to_vindex(int panel_id); 53static int lvds_register_read(int index); 54static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, 55 int panel_vres); 56static void lcd_patch_skew_dvp0(struct lvds_setting_information 57 *plvds_setting_info, 58 struct lvds_chip_information *plvds_chip_info); 59static void lcd_patch_skew_dvp1(struct lvds_setting_information 60 *plvds_setting_info, 61 struct lvds_chip_information *plvds_chip_info); 62static void lcd_patch_skew(struct lvds_setting_information 63 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); 64 65static void integrated_lvds_disable(struct lvds_setting_information 66 *plvds_setting_info, 67 struct lvds_chip_information *plvds_chip_info); 68static void integrated_lvds_enable(struct lvds_setting_information 69 *plvds_setting_info, 70 struct lvds_chip_information *plvds_chip_info); 71static void lcd_powersequence_off(void); 72static void lcd_powersequence_on(void); 73static void fill_lcd_format(void); 74static void check_diport_of_integrated_lvds( 75 struct lvds_chip_information *plvds_chip_info, 76 struct lvds_setting_information 77 *plvds_setting_info); 78 79static 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 84void 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 99static 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 142bool 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 183static 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 339static 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 349static 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 450static 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} 490static 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} 507static 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} 520static 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 */ 541void 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 606static 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 659static 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 714void 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 752static 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 case INTERFACE_DVP0: 762 case INTERFACE_DVP1: 763 case INTERFACE_DFP_HIGH: 764 case INTERFACE_DFP_LOW: 765 if (set_iga == IGA2) 766 viafb_write_reg(CR91, VIACR, 0x00); 767 break; 768 } 769} 770 771void viafb_lcd_enable(void) 772{ 773 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3); 774 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3); 775 set_lcd_output_path(viaparinfo->lvds_setting_info->iga_path, 776 viaparinfo->chip_info->lvds_chip_info.output_interface); 777 if (viafb_LCD2_ON) 778 set_lcd_output_path(viaparinfo->lvds_setting_info2->iga_path, 779 viaparinfo->chip_info-> 780 lvds_chip_info2.output_interface); 781 782 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 783 /* DI1 pad on */ 784 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30); 785 lcd_powersequence_on(); 786 } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) { 787 if (viafb_LCD2_ON && (INTEGRATED_LVDS == 788 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name)) 789 integrated_lvds_enable(viaparinfo->lvds_setting_info2, \ 790 &viaparinfo->chip_info->lvds_chip_info2); 791 if (INTEGRATED_LVDS == 792 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) 793 integrated_lvds_enable(viaparinfo->lvds_setting_info, 794 &viaparinfo->chip_info->lvds_chip_info); 795 if (VT1636_LVDS == viaparinfo->chip_info-> 796 lvds_chip_info.lvds_chip_name) 797 viafb_enable_lvds_vt1636(viaparinfo-> 798 lvds_setting_info, &viaparinfo->chip_info-> 799 lvds_chip_info); 800 } else if (VT1636_LVDS == 801 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) { 802 viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info, 803 &viaparinfo->chip_info->lvds_chip_info); 804 } else { 805 /* Backlight on */ 806 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20); 807 /* 24 bit DI data paht on */ 808 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80); 809 /* LCD enabled */ 810 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48); 811 } 812} 813 814static void lcd_powersequence_off(void) 815{ 816 int i, mask, data; 817 818 /* Software control power sequence */ 819 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11); 820 821 for (i = 0; i < 3; i++) { 822 mask = PowerSequenceOff[0][i]; 823 data = PowerSequenceOff[1][i] & mask; 824 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask); 825 udelay(PowerSequenceOff[2][i]); 826 } 827 828 /* Disable LCD */ 829 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08); 830} 831 832static void lcd_powersequence_on(void) 833{ 834 int i, mask, data; 835 836 /* Software control power sequence */ 837 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11); 838 839 /* Enable LCD */ 840 viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08); 841 842 for (i = 0; i < 3; i++) { 843 mask = PowerSequenceOn[0][i]; 844 data = PowerSequenceOn[1][i] & mask; 845 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask); 846 udelay(PowerSequenceOn[2][i]); 847 } 848 849 udelay(1); 850} 851 852static void fill_lcd_format(void) 853{ 854 u8 bdithering = 0, bdual = 0; 855 856 if (viaparinfo->lvds_setting_info->device_lcd_dualedge) 857 bdual = BIT4; 858 if (viaparinfo->lvds_setting_info->LCDDithering) 859 bdithering = BIT0; 860 /* Dual & Dithering */ 861 viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0); 862} 863 864static void check_diport_of_integrated_lvds( 865 struct lvds_chip_information *plvds_chip_info, 866 struct lvds_setting_information 867 *plvds_setting_info) 868{ 869 /* Determine LCD DI Port by hardware layout. */ 870 switch (viafb_display_hardware_layout) { 871 case HW_LAYOUT_LCD_ONLY: 872 { 873 if (plvds_setting_info->device_lcd_dualedge) { 874 plvds_chip_info->output_interface = 875 INTERFACE_LVDS0LVDS1; 876 } else { 877 plvds_chip_info->output_interface = 878 INTERFACE_LVDS0; 879 } 880 881 break; 882 } 883 884 case HW_LAYOUT_DVI_ONLY: 885 { 886 plvds_chip_info->output_interface = INTERFACE_NONE; 887 break; 888 } 889 890 case HW_LAYOUT_LCD1_LCD2: 891 case HW_LAYOUT_LCD_EXTERNAL_LCD2: 892 { 893 plvds_chip_info->output_interface = 894 INTERFACE_LVDS0LVDS1; 895 break; 896 } 897 898 case HW_LAYOUT_LCD_DVI: 899 { 900 plvds_chip_info->output_interface = INTERFACE_LVDS1; 901 break; 902 } 903 904 default: 905 { 906 plvds_chip_info->output_interface = INTERFACE_LVDS1; 907 break; 908 } 909 } 910 911 DEBUG_MSG(KERN_INFO 912 "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n", 913 viafb_display_hardware_layout, 914 plvds_chip_info->output_interface); 915} 916 917void viafb_init_lvds_output_interface(struct lvds_chip_information 918 *plvds_chip_info, 919 struct lvds_setting_information 920 *plvds_setting_info) 921{ 922 if (INTERFACE_NONE != plvds_chip_info->output_interface) { 923 /*Do nothing, lcd port is specified by module parameter */ 924 return; 925 } 926 927 switch (plvds_chip_info->lvds_chip_name) { 928 929 case VT1636_LVDS: 930 switch (viaparinfo->chip_info->gfx_chip_name) { 931 case UNICHROME_CX700: 932 plvds_chip_info->output_interface = INTERFACE_DVP1; 933 break; 934 case UNICHROME_CN700: 935 plvds_chip_info->output_interface = INTERFACE_DFP_LOW; 936 break; 937 default: 938 plvds_chip_info->output_interface = INTERFACE_DVP0; 939 break; 940 } 941 break; 942 943 case INTEGRATED_LVDS: 944 check_diport_of_integrated_lvds(plvds_chip_info, 945 plvds_setting_info); 946 break; 947 948 default: 949 switch (viaparinfo->chip_info->gfx_chip_name) { 950 case UNICHROME_K8M890: 951 case UNICHROME_P4M900: 952 case UNICHROME_P4M890: 953 plvds_chip_info->output_interface = INTERFACE_DFP_LOW; 954 break; 955 default: 956 plvds_chip_info->output_interface = INTERFACE_DFP; 957 break; 958 } 959 break; 960 } 961} 962 963bool viafb_lcd_get_mobile_state(bool *mobile) 964{ 965 unsigned char __iomem *romptr, *tableptr, *biosptr; 966 u8 core_base; 967 /* Rom address */ 968 const u32 romaddr = 0x000C0000; 969 u16 start_pattern; 970 971 biosptr = ioremap(romaddr, 0x10000); 972 start_pattern = readw(biosptr); 973 974 /* Compare pattern */ 975 if (start_pattern == 0xAA55) { 976 /* Get the start of Table */ 977 /* 0x1B means BIOS offset position */ 978 romptr = biosptr + 0x1B; 979 tableptr = biosptr + readw(romptr); 980 981 /* Get the start of biosver structure */ 982 /* 18 means BIOS version position. */ 983 romptr = tableptr + 18; 984 romptr = biosptr + readw(romptr); 985 986 /* The offset should be 44, but the 987 actual image is less three char. */ 988 /* pRom += 44; */ 989 romptr += 41; 990 991 core_base = readb(romptr); 992 993 if (core_base & 0x8) 994 *mobile = false; 995 else 996 *mobile = true; 997 /* release memory */ 998 iounmap(biosptr); 999 1000 return true; 1001 } else { 1002 iounmap(biosptr); 1003 return false; 1004 } 1005} 1006