162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. 462306a36Sopenharmony_ci * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#include <linux/via-core.h> 862306a36Sopenharmony_ci#include <linux/via_i2c.h> 962306a36Sopenharmony_ci#include "global.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic void tmds_register_write(int index, u8 data); 1262306a36Sopenharmony_cistatic int tmds_register_read(int index); 1362306a36Sopenharmony_cistatic int tmds_register_read_bytes(int index, u8 *buff, int buff_len); 1462306a36Sopenharmony_cistatic void dvi_get_panel_size_from_DDCv1( 1562306a36Sopenharmony_ci struct tmds_chip_information *tmds_chip, 1662306a36Sopenharmony_ci struct tmds_setting_information *tmds_setting); 1762306a36Sopenharmony_cistatic int viafb_dvi_query_EDID(void); 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic inline bool check_tmds_chip(int device_id_subaddr, int device_id) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci return tmds_register_read(device_id_subaddr) == device_id; 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_civoid viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, 2562306a36Sopenharmony_ci struct tmds_setting_information *tmds_setting) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci viafb_dvi_sense(); 3062306a36Sopenharmony_ci if (viafb_dvi_query_EDID() == 1) 3162306a36Sopenharmony_ci dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci return; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cibool viafb_tmds_trasmitter_identify(void) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci unsigned char sr2a = 0, sr1e = 0, sr3e = 0; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* Turn on ouputting pad */ 4162306a36Sopenharmony_ci switch (viaparinfo->chip_info->gfx_chip_name) { 4262306a36Sopenharmony_ci case UNICHROME_K8M890: 4362306a36Sopenharmony_ci /*=* DFP Low Pad on *=*/ 4462306a36Sopenharmony_ci sr2a = viafb_read_reg(VIASR, SR2A); 4562306a36Sopenharmony_ci viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); 4662306a36Sopenharmony_ci break; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci case UNICHROME_P4M900: 4962306a36Sopenharmony_ci case UNICHROME_P4M890: 5062306a36Sopenharmony_ci /* DFP Low Pad on */ 5162306a36Sopenharmony_ci sr2a = viafb_read_reg(VIASR, SR2A); 5262306a36Sopenharmony_ci viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); 5362306a36Sopenharmony_ci /* DVP0 Pad on */ 5462306a36Sopenharmony_ci sr1e = viafb_read_reg(VIASR, SR1E); 5562306a36Sopenharmony_ci viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7); 5662306a36Sopenharmony_ci break; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci default: 5962306a36Sopenharmony_ci /* DVP0/DVP1 Pad on */ 6062306a36Sopenharmony_ci sr1e = viafb_read_reg(VIASR, SR1E); 6162306a36Sopenharmony_ci viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 + 6262306a36Sopenharmony_ci BIT5 + BIT6 + BIT7); 6362306a36Sopenharmony_ci /* SR3E[1]Multi-function selection: 6462306a36Sopenharmony_ci 0 = Emulate I2C and DDC bus by GPIO2/3/4. */ 6562306a36Sopenharmony_ci sr3e = viafb_read_reg(VIASR, SR3E); 6662306a36Sopenharmony_ci viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5); 6762306a36Sopenharmony_ci break; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* Check for VT1632: */ 7162306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS; 7262306a36Sopenharmony_ci viaparinfo->chip_info-> 7362306a36Sopenharmony_ci tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; 7462306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31; 7562306a36Sopenharmony_ci if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) { 7662306a36Sopenharmony_ci /* 7762306a36Sopenharmony_ci * Currently only support 12bits,dual edge,add 24bits mode later 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci tmds_register_write(0x08, 0x3b); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); 8262306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n %2d", 8362306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); 8462306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n %2d", 8562306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.i2c_port); 8662306a36Sopenharmony_ci return true; 8762306a36Sopenharmony_ci } else { 8862306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C; 8962306a36Sopenharmony_ci if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) { 9062306a36Sopenharmony_ci tmds_register_write(0x08, 0x3b); 9162306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); 9262306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n %2d", 9362306a36Sopenharmony_ci viaparinfo->chip_info-> 9462306a36Sopenharmony_ci tmds_chip_info.tmds_chip_name); 9562306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n %2d", 9662306a36Sopenharmony_ci viaparinfo->chip_info-> 9762306a36Sopenharmony_ci tmds_chip_info.i2c_port); 9862306a36Sopenharmony_ci return true; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) && 10562306a36Sopenharmony_ci ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) || 10662306a36Sopenharmony_ci (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) { 10762306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n"); 10862306a36Sopenharmony_ci return true; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci switch (viaparinfo->chip_info->gfx_chip_name) { 11262306a36Sopenharmony_ci case UNICHROME_K8M890: 11362306a36Sopenharmony_ci viafb_write_reg(SR2A, VIASR, sr2a); 11462306a36Sopenharmony_ci break; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci case UNICHROME_P4M900: 11762306a36Sopenharmony_ci case UNICHROME_P4M890: 11862306a36Sopenharmony_ci viafb_write_reg(SR2A, VIASR, sr2a); 11962306a36Sopenharmony_ci viafb_write_reg(SR1E, VIASR, sr1e); 12062306a36Sopenharmony_ci break; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci default: 12362306a36Sopenharmony_ci viafb_write_reg(SR1E, VIASR, sr1e); 12462306a36Sopenharmony_ci viafb_write_reg(SR3E, VIASR, sr3e); 12562306a36Sopenharmony_ci break; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci viaparinfo->chip_info-> 12962306a36Sopenharmony_ci tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER; 13062306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info. 13162306a36Sopenharmony_ci tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; 13262306a36Sopenharmony_ci return false; 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic void tmds_register_write(int index, u8 data) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, 13862306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, 13962306a36Sopenharmony_ci index, data); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic int tmds_register_read(int index) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci u8 data; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, 14762306a36Sopenharmony_ci (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, 14862306a36Sopenharmony_ci (u8) index, &data); 14962306a36Sopenharmony_ci return data; 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic int tmds_register_read_bytes(int index, u8 *buff, int buff_len) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port, 15562306a36Sopenharmony_ci (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, 15662306a36Sopenharmony_ci (u8) index, buff, buff_len); 15762306a36Sopenharmony_ci return 0; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/* DVI Set Mode */ 16162306a36Sopenharmony_civoid viafb_dvi_set_mode(const struct fb_var_screeninfo *var, 16262306a36Sopenharmony_ci u16 cxres, u16 cyres, int iga) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci struct fb_var_screeninfo dvi_var = *var; 16562306a36Sopenharmony_ci const struct fb_videomode *rb_mode; 16662306a36Sopenharmony_ci int maxPixelClock; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock; 16962306a36Sopenharmony_ci if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) { 17062306a36Sopenharmony_ci rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60); 17162306a36Sopenharmony_ci if (rb_mode) 17262306a36Sopenharmony_ci viafb_fill_var_timing_info(&dvi_var, rb_mode); 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga); 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/* Sense DVI Connector */ 17962306a36Sopenharmony_ciint viafb_dvi_sense(void) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0, 18262306a36Sopenharmony_ci RegCR93 = 0, RegCR9B = 0, data; 18362306a36Sopenharmony_ci int ret = false; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n"); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 18862306a36Sopenharmony_ci /* DI1 Pad on */ 18962306a36Sopenharmony_ci RegSR1E = viafb_read_reg(VIASR, SR1E); 19062306a36Sopenharmony_ci viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* CR6B[0]VCK Input Selection: 1 = External clock. */ 19362306a36Sopenharmony_ci RegCR6B = viafb_read_reg(VIACR, CR6B); 19462306a36Sopenharmony_ci viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off 19762306a36Sopenharmony_ci [0] Software Control Power Sequence */ 19862306a36Sopenharmony_ci RegCR91 = viafb_read_reg(VIACR, CR91); 19962306a36Sopenharmony_ci viafb_write_reg(CR91, VIACR, 0x1D); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* CR93[7] DI1 Data Source Selection: 1 = DSP2. 20262306a36Sopenharmony_ci CR93[5] DI1 Clock Source: 1 = internal. 20362306a36Sopenharmony_ci CR93[4] DI1 Clock Polarity. 20462306a36Sopenharmony_ci CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */ 20562306a36Sopenharmony_ci RegCR93 = viafb_read_reg(VIACR, CR93); 20662306a36Sopenharmony_ci viafb_write_reg(CR93, VIACR, 0x01); 20762306a36Sopenharmony_ci } else { 20862306a36Sopenharmony_ci /* DVP0/DVP1 Pad on */ 20962306a36Sopenharmony_ci RegSR1E = viafb_read_reg(VIASR, SR1E); 21062306a36Sopenharmony_ci viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* SR3E[1]Multi-function selection: 21362306a36Sopenharmony_ci 0 = Emulate I2C and DDC bus by GPIO2/3/4. */ 21462306a36Sopenharmony_ci RegSR3E = viafb_read_reg(VIASR, SR3E); 21562306a36Sopenharmony_ci viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20)); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off 21862306a36Sopenharmony_ci [0] Software Control Power Sequence */ 21962306a36Sopenharmony_ci RegCR91 = viafb_read_reg(VIACR, CR91); 22062306a36Sopenharmony_ci viafb_write_reg(CR91, VIACR, 0x1D); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary 22362306a36Sopenharmony_ci display.CR9B[2:0] DVP1 Clock Adjust */ 22462306a36Sopenharmony_ci RegCR9B = viafb_read_reg(VIACR, CR9B); 22562306a36Sopenharmony_ci viafb_write_reg(CR9B, VIACR, 0x01); 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci data = (u8) tmds_register_read(0x09); 22962306a36Sopenharmony_ci if (data & 0x04) 23062306a36Sopenharmony_ci ret = true; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci if (ret == false) { 23362306a36Sopenharmony_ci if (viafb_dvi_query_EDID()) 23462306a36Sopenharmony_ci ret = true; 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* Restore status */ 23862306a36Sopenharmony_ci viafb_write_reg(SR1E, VIASR, RegSR1E); 23962306a36Sopenharmony_ci viafb_write_reg(CR91, VIACR, RegCR91); 24062306a36Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 24162306a36Sopenharmony_ci viafb_write_reg(CR6B, VIACR, RegCR6B); 24262306a36Sopenharmony_ci viafb_write_reg(CR93, VIACR, RegCR93); 24362306a36Sopenharmony_ci } else { 24462306a36Sopenharmony_ci viafb_write_reg(SR3E, VIASR, RegSR3E); 24562306a36Sopenharmony_ci viafb_write_reg(CR9B, VIACR, RegCR9B); 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci return ret; 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci/* Query Flat Panel's EDID Table Version Through DVI Connector */ 25262306a36Sopenharmony_cistatic int viafb_dvi_query_EDID(void) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci u8 data0, data1; 25562306a36Sopenharmony_ci int restore; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n"); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; 26062306a36Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci data0 = (u8) tmds_register_read(0x00); 26362306a36Sopenharmony_ci data1 = (u8) tmds_register_read(0x01); 26462306a36Sopenharmony_ci if ((data0 == 0) && (data1 == 0xFF)) { 26562306a36Sopenharmony_ci viaparinfo->chip_info-> 26662306a36Sopenharmony_ci tmds_chip_info.tmds_chip_slave_addr = restore; 26762306a36Sopenharmony_ci return EDID_VERSION_1; /* Found EDID1 Table */ 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci return false; 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci/* Get Panel Size Using EDID1 Table */ 27462306a36Sopenharmony_cistatic void dvi_get_panel_size_from_DDCv1( 27562306a36Sopenharmony_ci struct tmds_chip_information *tmds_chip, 27662306a36Sopenharmony_ci struct tmds_setting_information *tmds_setting) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci int i, restore; 27962306a36Sopenharmony_ci unsigned char EDID_DATA[18]; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci restore = tmds_chip->tmds_chip_slave_addr; 28462306a36Sopenharmony_ci tmds_chip->tmds_chip_slave_addr = 0xA0; 28562306a36Sopenharmony_ci for (i = 0x25; i < 0x6D; i++) { 28662306a36Sopenharmony_ci switch (i) { 28762306a36Sopenharmony_ci case 0x36: 28862306a36Sopenharmony_ci case 0x48: 28962306a36Sopenharmony_ci case 0x5A: 29062306a36Sopenharmony_ci case 0x6C: 29162306a36Sopenharmony_ci tmds_register_read_bytes(i, EDID_DATA, 10); 29262306a36Sopenharmony_ci if (!(EDID_DATA[0] || EDID_DATA[1])) { 29362306a36Sopenharmony_ci /* The first two byte must be zero. */ 29462306a36Sopenharmony_ci if (EDID_DATA[3] == 0xFD) { 29562306a36Sopenharmony_ci /* To get max pixel clock. */ 29662306a36Sopenharmony_ci tmds_setting->max_pixel_clock = 29762306a36Sopenharmony_ci EDID_DATA[9] * 10; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci default: 30362306a36Sopenharmony_ci break; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", 30862306a36Sopenharmony_ci tmds_setting->max_pixel_clock); 30962306a36Sopenharmony_ci tmds_chip->tmds_chip_slave_addr = restore; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci/* If Disable DVI, turn off pad */ 31362306a36Sopenharmony_civoid viafb_dvi_disable(void) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci if (viaparinfo->chip_info-> 31662306a36Sopenharmony_ci tmds_chip_info.output_interface == INTERFACE_TMDS) 31762306a36Sopenharmony_ci /* Turn off TMDS power. */ 31862306a36Sopenharmony_ci viafb_write_reg(CRD2, VIACR, 31962306a36Sopenharmony_ci viafb_read_reg(VIACR, CRD2) | 0x08); 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic void dvi_patch_skew_dvp0(void) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci /* Reset data driving first: */ 32562306a36Sopenharmony_ci viafb_write_reg_mask(SR1B, VIASR, 0, BIT1); 32662306a36Sopenharmony_ci viafb_write_reg_mask(SR2A, VIASR, 0, BIT4); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci switch (viaparinfo->chip_info->gfx_chip_name) { 32962306a36Sopenharmony_ci case UNICHROME_P4M890: 33062306a36Sopenharmony_ci { 33162306a36Sopenharmony_ci if ((viaparinfo->tmds_setting_info->h_active == 1600) && 33262306a36Sopenharmony_ci (viaparinfo->tmds_setting_info->v_active == 33362306a36Sopenharmony_ci 1200)) 33462306a36Sopenharmony_ci viafb_write_reg_mask(CR96, VIACR, 0x03, 33562306a36Sopenharmony_ci BIT0 + BIT1 + BIT2); 33662306a36Sopenharmony_ci else 33762306a36Sopenharmony_ci viafb_write_reg_mask(CR96, VIACR, 0x07, 33862306a36Sopenharmony_ci BIT0 + BIT1 + BIT2); 33962306a36Sopenharmony_ci break; 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci case UNICHROME_P4M900: 34362306a36Sopenharmony_ci { 34462306a36Sopenharmony_ci viafb_write_reg_mask(CR96, VIACR, 0x07, 34562306a36Sopenharmony_ci BIT0 + BIT1 + BIT2 + BIT3); 34662306a36Sopenharmony_ci viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1); 34762306a36Sopenharmony_ci viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4); 34862306a36Sopenharmony_ci break; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci default: 35262306a36Sopenharmony_ci { 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic void dvi_patch_skew_dvp_low(void) 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci switch (viaparinfo->chip_info->gfx_chip_name) { 36162306a36Sopenharmony_ci case UNICHROME_K8M890: 36262306a36Sopenharmony_ci { 36362306a36Sopenharmony_ci viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1); 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci case UNICHROME_P4M900: 36862306a36Sopenharmony_ci { 36962306a36Sopenharmony_ci viafb_write_reg_mask(CR99, VIACR, 0x08, 37062306a36Sopenharmony_ci BIT0 + BIT1 + BIT2 + BIT3); 37162306a36Sopenharmony_ci break; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci case UNICHROME_P4M890: 37562306a36Sopenharmony_ci { 37662306a36Sopenharmony_ci viafb_write_reg_mask(CR99, VIACR, 0x0F, 37762306a36Sopenharmony_ci BIT0 + BIT1 + BIT2 + BIT3); 37862306a36Sopenharmony_ci break; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci default: 38262306a36Sopenharmony_ci { 38362306a36Sopenharmony_ci break; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci/* If Enable DVI, turn off pad */ 38962306a36Sopenharmony_civoid viafb_dvi_enable(void) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci u8 data; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci switch (viaparinfo->chip_info->tmds_chip_info.output_interface) { 39462306a36Sopenharmony_ci case INTERFACE_DVP0: 39562306a36Sopenharmony_ci viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0); 39662306a36Sopenharmony_ci viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5); 39762306a36Sopenharmony_ci dvi_patch_skew_dvp0(); 39862306a36Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 39962306a36Sopenharmony_ci tmds_register_write(0x88, 0x3b); 40062306a36Sopenharmony_ci else 40162306a36Sopenharmony_ci /*clear CR91[5] to direct on display period 40262306a36Sopenharmony_ci in the secondary diplay path */ 40362306a36Sopenharmony_ci via_write_reg_mask(VIACR, 0x91, 0x00, 0x20); 40462306a36Sopenharmony_ci break; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci case INTERFACE_DVP1: 40762306a36Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 40862306a36Sopenharmony_ci viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */ 41162306a36Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 41262306a36Sopenharmony_ci tmds_register_write(0x88, 0x3b); 41362306a36Sopenharmony_ci else 41462306a36Sopenharmony_ci /*clear CR91[5] to direct on display period 41562306a36Sopenharmony_ci in the secondary diplay path */ 41662306a36Sopenharmony_ci via_write_reg_mask(VIACR, 0x91, 0x00, 0x20); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /*fix DVI cannot enable on EPIA-M board */ 41962306a36Sopenharmony_ci if (viafb_platform_epia_dvi == 1) { 42062306a36Sopenharmony_ci viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f); 42162306a36Sopenharmony_ci viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0); 42262306a36Sopenharmony_ci if (viafb_bus_width == 24) { 42362306a36Sopenharmony_ci if (viafb_device_lcd_dualedge == 1) 42462306a36Sopenharmony_ci data = 0x3F; 42562306a36Sopenharmony_ci else 42662306a36Sopenharmony_ci data = 0x37; 42762306a36Sopenharmony_ci viafb_i2c_writebyte(viaparinfo->chip_info-> 42862306a36Sopenharmony_ci tmds_chip_info.i2c_port, 42962306a36Sopenharmony_ci viaparinfo->chip_info-> 43062306a36Sopenharmony_ci tmds_chip_info.tmds_chip_slave_addr, 43162306a36Sopenharmony_ci 0x08, data); 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci case INTERFACE_DFP_HIGH: 43762306a36Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) 43862306a36Sopenharmony_ci via_write_reg_mask(VIACR, CR97, 0x03, 0x03); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci via_write_reg_mask(VIACR, 0x91, 0x00, 0x20); 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci case INTERFACE_DFP_LOW: 44462306a36Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 44562306a36Sopenharmony_ci break; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci dvi_patch_skew_dvp_low(); 44862306a36Sopenharmony_ci via_write_reg_mask(VIACR, 0x91, 0x00, 0x20); 44962306a36Sopenharmony_ci break; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci case INTERFACE_TMDS: 45262306a36Sopenharmony_ci /* Turn on Display period in the panel path. */ 45362306a36Sopenharmony_ci viafb_write_reg_mask(CR91, VIACR, 0, BIT7); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* Turn on TMDS power. */ 45662306a36Sopenharmony_ci viafb_write_reg_mask(CRD2, VIACR, 0, BIT3); 45762306a36Sopenharmony_ci break; 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci if (viaparinfo->tmds_setting_info->iga_path == IGA2) { 46162306a36Sopenharmony_ci /* Disable LCD Scaling */ 46262306a36Sopenharmony_ci viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0); 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci} 465