465 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*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 11static void tmds_register_write(int index, u8 data);12static int tmds_register_read(int index);13static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);14static void dvi_get_panel_size_from_DDCv1(15 struct tmds_chip_information *tmds_chip,16 struct tmds_setting_information *tmds_setting);17static int viafb_dvi_query_EDID(void);18 19static inline bool check_tmds_chip(int device_id_subaddr, int device_id)20{21 return tmds_register_read(device_id_subaddr) == device_id;22}23 24void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,25 struct tmds_setting_information *tmds_setting)26{27 DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");28 29 viafb_dvi_sense();30 if (viafb_dvi_query_EDID() == 1)31 dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);32 33 return;34}35 36bool viafb_tmds_trasmitter_identify(void)37{38 unsigned char sr2a = 0, sr1e = 0, sr3e = 0;39 40 /* Turn on ouputting pad */41 switch (viaparinfo->chip_info->gfx_chip_name) {42 case UNICHROME_K8M890:43 /*=* DFP Low Pad on *=*/44 sr2a = viafb_read_reg(VIASR, SR2A);45 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);46 break;47 48 case UNICHROME_P4M900:49 case UNICHROME_P4M890:50 /* DFP Low Pad on */51 sr2a = viafb_read_reg(VIASR, SR2A);52 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);53 /* DVP0 Pad on */54 sr1e = viafb_read_reg(VIASR, SR1E);55 viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);56 break;57 58 default:59 /* DVP0/DVP1 Pad on */60 sr1e = viafb_read_reg(VIASR, SR1E);61 viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +62 BIT5 + BIT6 + BIT7);63 /* SR3E[1]Multi-function selection:64 0 = Emulate I2C and DDC bus by GPIO2/3/4. */65 sr3e = viafb_read_reg(VIASR, SR3E);66 viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);67 break;68 }69 70 /* Check for VT1632: */71 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;72 viaparinfo->chip_info->73 tmds_chip_info.tmds_chip_target_addr = VT1632_TMDS_I2C_ADDR;74 viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31;75 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {76 /*77 * Currently only support 12bits,dual edge,add 24bits mode later78 */79 tmds_register_write(0x08, 0x3b);80 81 DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");82 DEBUG_MSG(KERN_INFO "\n %2d",83 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);84 DEBUG_MSG(KERN_INFO "\n %2d",85 viaparinfo->chip_info->tmds_chip_info.i2c_port);86 return true;87 } else {88 viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C;89 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {90 tmds_register_write(0x08, 0x3b);91 DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");92 DEBUG_MSG(KERN_INFO "\n %2d",93 viaparinfo->chip_info->94 tmds_chip_info.tmds_chip_name);95 DEBUG_MSG(KERN_INFO "\n %2d",96 viaparinfo->chip_info->97 tmds_chip_info.i2c_port);98 return true;99 }100 }101 102 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;103 104 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&105 ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||106 (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {107 DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");108 return true;109 }110 111 switch (viaparinfo->chip_info->gfx_chip_name) {112 case UNICHROME_K8M890:113 viafb_write_reg(SR2A, VIASR, sr2a);114 break;115 116 case UNICHROME_P4M900:117 case UNICHROME_P4M890:118 viafb_write_reg(SR2A, VIASR, sr2a);119 viafb_write_reg(SR1E, VIASR, sr1e);120 break;121 122 default:123 viafb_write_reg(SR1E, VIASR, sr1e);124 viafb_write_reg(SR3E, VIASR, sr3e);125 break;126 }127 128 viaparinfo->chip_info->129 tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;130 viaparinfo->chip_info->tmds_chip_info.131 tmds_chip_target_addr = VT1632_TMDS_I2C_ADDR;132 return false;133}134 135static void tmds_register_write(int index, u8 data)136{137 viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,138 viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr,139 index, data);140}141 142static int tmds_register_read(int index)143{144 u8 data;145 146 viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,147 (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr,148 (u8) index, &data);149 return data;150}151 152static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)153{154 viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port,155 (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr,156 (u8) index, buff, buff_len);157 return 0;158}159 160/* DVI Set Mode */161void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,162 u16 cxres, u16 cyres, int iga)163{164 struct fb_var_screeninfo dvi_var = *var;165 const struct fb_videomode *rb_mode;166 int maxPixelClock;167 168 maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;169 if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {170 rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);171 if (rb_mode)172 viafb_fill_var_timing_info(&dvi_var, rb_mode);173 }174 175 viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga);176}177 178/* Sense DVI Connector */179int viafb_dvi_sense(void)180{181 u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,182 RegCR93 = 0, RegCR9B = 0, data;183 int ret = false;184 185 DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");186 187 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {188 /* DI1 Pad on */189 RegSR1E = viafb_read_reg(VIASR, SR1E);190 viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);191 192 /* CR6B[0]VCK Input Selection: 1 = External clock. */193 RegCR6B = viafb_read_reg(VIACR, CR6B);194 viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);195 196 /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off197 [0] Software Control Power Sequence */198 RegCR91 = viafb_read_reg(VIACR, CR91);199 viafb_write_reg(CR91, VIACR, 0x1D);200 201 /* CR93[7] DI1 Data Source Selection: 1 = DSP2.202 CR93[5] DI1 Clock Source: 1 = internal.203 CR93[4] DI1 Clock Polarity.204 CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */205 RegCR93 = viafb_read_reg(VIACR, CR93);206 viafb_write_reg(CR93, VIACR, 0x01);207 } else {208 /* DVP0/DVP1 Pad on */209 RegSR1E = viafb_read_reg(VIASR, SR1E);210 viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);211 212 /* SR3E[1]Multi-function selection:213 0 = Emulate I2C and DDC bus by GPIO2/3/4. */214 RegSR3E = viafb_read_reg(VIASR, SR3E);215 viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));216 217 /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off218 [0] Software Control Power Sequence */219 RegCR91 = viafb_read_reg(VIACR, CR91);220 viafb_write_reg(CR91, VIACR, 0x1D);221 222 /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary223 display.CR9B[2:0] DVP1 Clock Adjust */224 RegCR9B = viafb_read_reg(VIACR, CR9B);225 viafb_write_reg(CR9B, VIACR, 0x01);226 }227 228 data = (u8) tmds_register_read(0x09);229 if (data & 0x04)230 ret = true;231 232 if (ret == false) {233 if (viafb_dvi_query_EDID())234 ret = true;235 }236 237 /* Restore status */238 viafb_write_reg(SR1E, VIASR, RegSR1E);239 viafb_write_reg(CR91, VIACR, RegCR91);240 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {241 viafb_write_reg(CR6B, VIACR, RegCR6B);242 viafb_write_reg(CR93, VIACR, RegCR93);243 } else {244 viafb_write_reg(SR3E, VIASR, RegSR3E);245 viafb_write_reg(CR9B, VIACR, RegCR9B);246 }247 248 return ret;249}250 251/* Query Flat Panel's EDID Table Version Through DVI Connector */252static int viafb_dvi_query_EDID(void)253{254 u8 data0, data1;255 int restore;256 257 DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");258 259 restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr;260 viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr = 0xA0;261 262 data0 = (u8) tmds_register_read(0x00);263 data1 = (u8) tmds_register_read(0x01);264 if ((data0 == 0) && (data1 == 0xFF)) {265 viaparinfo->chip_info->266 tmds_chip_info.tmds_chip_target_addr = restore;267 return EDID_VERSION_1; /* Found EDID1 Table */268 }269 270 return false;271}272 273/* Get Panel Size Using EDID1 Table */274static void dvi_get_panel_size_from_DDCv1(275 struct tmds_chip_information *tmds_chip,276 struct tmds_setting_information *tmds_setting)277{278 int i, restore;279 unsigned char EDID_DATA[18];280 281 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");282 283 restore = tmds_chip->tmds_chip_target_addr;284 tmds_chip->tmds_chip_target_addr = 0xA0;285 for (i = 0x25; i < 0x6D; i++) {286 switch (i) {287 case 0x36:288 case 0x48:289 case 0x5A:290 case 0x6C:291 tmds_register_read_bytes(i, EDID_DATA, 10);292 if (!(EDID_DATA[0] || EDID_DATA[1])) {293 /* The first two byte must be zero. */294 if (EDID_DATA[3] == 0xFD) {295 /* To get max pixel clock. */296 tmds_setting->max_pixel_clock =297 EDID_DATA[9] * 10;298 }299 }300 break;301 302 default:303 break;304 }305 }306 307 DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",308 tmds_setting->max_pixel_clock);309 tmds_chip->tmds_chip_target_addr = restore;310}311 312/* If Disable DVI, turn off pad */313void viafb_dvi_disable(void)314{315 if (viaparinfo->chip_info->316 tmds_chip_info.output_interface == INTERFACE_TMDS)317 /* Turn off TMDS power. */318 viafb_write_reg(CRD2, VIACR,319 viafb_read_reg(VIACR, CRD2) | 0x08);320}321 322static void dvi_patch_skew_dvp0(void)323{324 /* Reset data driving first: */325 viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);326 viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);327 328 switch (viaparinfo->chip_info->gfx_chip_name) {329 case UNICHROME_P4M890:330 {331 if ((viaparinfo->tmds_setting_info->h_active == 1600) &&332 (viaparinfo->tmds_setting_info->v_active ==333 1200))334 viafb_write_reg_mask(CR96, VIACR, 0x03,335 BIT0 + BIT1 + BIT2);336 else337 viafb_write_reg_mask(CR96, VIACR, 0x07,338 BIT0 + BIT1 + BIT2);339 break;340 }341 342 case UNICHROME_P4M900:343 {344 viafb_write_reg_mask(CR96, VIACR, 0x07,345 BIT0 + BIT1 + BIT2 + BIT3);346 viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);347 viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);348 break;349 }350 351 default:352 {353 break;354 }355 }356}357 358static void dvi_patch_skew_dvp_low(void)359{360 switch (viaparinfo->chip_info->gfx_chip_name) {361 case UNICHROME_K8M890:362 {363 viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);364 break;365 }366 367 case UNICHROME_P4M900:368 {369 viafb_write_reg_mask(CR99, VIACR, 0x08,370 BIT0 + BIT1 + BIT2 + BIT3);371 break;372 }373 374 case UNICHROME_P4M890:375 {376 viafb_write_reg_mask(CR99, VIACR, 0x0F,377 BIT0 + BIT1 + BIT2 + BIT3);378 break;379 }380 381 default:382 {383 break;384 }385 }386}387 388/* If Enable DVI, turn off pad */389void viafb_dvi_enable(void)390{391 u8 data;392 393 switch (viaparinfo->chip_info->tmds_chip_info.output_interface) {394 case INTERFACE_DVP0:395 viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);396 viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);397 dvi_patch_skew_dvp0();398 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)399 tmds_register_write(0x88, 0x3b);400 else401 /*clear CR91[5] to direct on display period402 in the secondary diplay path */403 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);404 break;405 406 case INTERFACE_DVP1:407 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)408 viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);409 410 /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */411 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)412 tmds_register_write(0x88, 0x3b);413 else414 /*clear CR91[5] to direct on display period415 in the secondary diplay path */416 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);417 418 /*fix DVI cannot enable on EPIA-M board */419 if (viafb_platform_epia_dvi == 1) {420 viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);421 viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);422 if (viafb_bus_width == 24) {423 if (viafb_device_lcd_dualedge == 1)424 data = 0x3F;425 else426 data = 0x37;427 viafb_i2c_writebyte(viaparinfo->chip_info->428 tmds_chip_info.i2c_port,429 viaparinfo->chip_info->430 tmds_chip_info.tmds_chip_target_addr,431 0x08, data);432 }433 }434 break;435 436 case INTERFACE_DFP_HIGH:437 if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)438 via_write_reg_mask(VIACR, CR97, 0x03, 0x03);439 440 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);441 break;442 443 case INTERFACE_DFP_LOW:444 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)445 break;446 447 dvi_patch_skew_dvp_low();448 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);449 break;450 451 case INTERFACE_TMDS:452 /* Turn on Display period in the panel path. */453 viafb_write_reg_mask(CR91, VIACR, 0, BIT7);454 455 /* Turn on TMDS power. */456 viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);457 break;458 }459 460 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {461 /* Disable LCD Scaling */462 viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);463 }464}465