Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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