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