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