18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. 48c2ecf20Sopenharmony_ci * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include <linux/via-core.h> 88c2ecf20Sopenharmony_ci#include <linux/via_i2c.h> 98c2ecf20Sopenharmony_ci#include "global.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistatic void tmds_register_write(int index, u8 data); 128c2ecf20Sopenharmony_cistatic int tmds_register_read(int index); 138c2ecf20Sopenharmony_cistatic int tmds_register_read_bytes(int index, u8 *buff, int buff_len); 148c2ecf20Sopenharmony_cistatic void dvi_get_panel_size_from_DDCv1( 158c2ecf20Sopenharmony_ci struct tmds_chip_information *tmds_chip, 168c2ecf20Sopenharmony_ci struct tmds_setting_information *tmds_setting); 178c2ecf20Sopenharmony_cistatic int viafb_dvi_query_EDID(void); 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic inline bool check_tmds_chip(int device_id_subaddr, int device_id) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci return tmds_register_read(device_id_subaddr) == device_id; 228c2ecf20Sopenharmony_ci} 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_civoid viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, 258c2ecf20Sopenharmony_ci struct tmds_setting_information *tmds_setting) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n"); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci viafb_dvi_sense(); 308c2ecf20Sopenharmony_ci if (viafb_dvi_query_EDID() == 1) 318c2ecf20Sopenharmony_ci dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci return; 348c2ecf20Sopenharmony_ci} 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cibool viafb_tmds_trasmitter_identify(void) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci unsigned char sr2a = 0, sr1e = 0, sr3e = 0; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* Turn on ouputting pad */ 418c2ecf20Sopenharmony_ci switch (viaparinfo->chip_info->gfx_chip_name) { 428c2ecf20Sopenharmony_ci case UNICHROME_K8M890: 438c2ecf20Sopenharmony_ci /*=* DFP Low Pad on *=*/ 448c2ecf20Sopenharmony_ci sr2a = viafb_read_reg(VIASR, SR2A); 458c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); 468c2ecf20Sopenharmony_ci break; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci case UNICHROME_P4M900: 498c2ecf20Sopenharmony_ci case UNICHROME_P4M890: 508c2ecf20Sopenharmony_ci /* DFP Low Pad on */ 518c2ecf20Sopenharmony_ci sr2a = viafb_read_reg(VIASR, SR2A); 528c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1); 538c2ecf20Sopenharmony_ci /* DVP0 Pad on */ 548c2ecf20Sopenharmony_ci sr1e = viafb_read_reg(VIASR, SR1E); 558c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7); 568c2ecf20Sopenharmony_ci break; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci default: 598c2ecf20Sopenharmony_ci /* DVP0/DVP1 Pad on */ 608c2ecf20Sopenharmony_ci sr1e = viafb_read_reg(VIASR, SR1E); 618c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 + 628c2ecf20Sopenharmony_ci BIT5 + BIT6 + BIT7); 638c2ecf20Sopenharmony_ci /* SR3E[1]Multi-function selection: 648c2ecf20Sopenharmony_ci 0 = Emulate I2C and DDC bus by GPIO2/3/4. */ 658c2ecf20Sopenharmony_ci sr3e = viafb_read_reg(VIASR, SR3E); 668c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5); 678c2ecf20Sopenharmony_ci break; 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* Check for VT1632: */ 718c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS; 728c2ecf20Sopenharmony_ci viaparinfo->chip_info-> 738c2ecf20Sopenharmony_ci tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; 748c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31; 758c2ecf20Sopenharmony_ci if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) { 768c2ecf20Sopenharmony_ci /* 778c2ecf20Sopenharmony_ci * Currently only support 12bits,dual edge,add 24bits mode later 788c2ecf20Sopenharmony_ci */ 798c2ecf20Sopenharmony_ci tmds_register_write(0x08, 0x3b); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); 828c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n %2d", 838c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_name); 848c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n %2d", 858c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.i2c_port); 868c2ecf20Sopenharmony_ci return true; 878c2ecf20Sopenharmony_ci } else { 888c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C; 898c2ecf20Sopenharmony_ci if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) { 908c2ecf20Sopenharmony_ci tmds_register_write(0x08, 0x3b); 918c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n"); 928c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n %2d", 938c2ecf20Sopenharmony_ci viaparinfo->chip_info-> 948c2ecf20Sopenharmony_ci tmds_chip_info.tmds_chip_name); 958c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n %2d", 968c2ecf20Sopenharmony_ci viaparinfo->chip_info-> 978c2ecf20Sopenharmony_ci tmds_chip_info.i2c_port); 988c2ecf20Sopenharmony_ci return true; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) && 1058c2ecf20Sopenharmony_ci ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) || 1068c2ecf20Sopenharmony_ci (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) { 1078c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n"); 1088c2ecf20Sopenharmony_ci return true; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci switch (viaparinfo->chip_info->gfx_chip_name) { 1128c2ecf20Sopenharmony_ci case UNICHROME_K8M890: 1138c2ecf20Sopenharmony_ci viafb_write_reg(SR2A, VIASR, sr2a); 1148c2ecf20Sopenharmony_ci break; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci case UNICHROME_P4M900: 1178c2ecf20Sopenharmony_ci case UNICHROME_P4M890: 1188c2ecf20Sopenharmony_ci viafb_write_reg(SR2A, VIASR, sr2a); 1198c2ecf20Sopenharmony_ci viafb_write_reg(SR1E, VIASR, sr1e); 1208c2ecf20Sopenharmony_ci break; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci default: 1238c2ecf20Sopenharmony_ci viafb_write_reg(SR1E, VIASR, sr1e); 1248c2ecf20Sopenharmony_ci viafb_write_reg(SR3E, VIASR, sr3e); 1258c2ecf20Sopenharmony_ci break; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci viaparinfo->chip_info-> 1298c2ecf20Sopenharmony_ci tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER; 1308c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info. 1318c2ecf20Sopenharmony_ci tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; 1328c2ecf20Sopenharmony_ci return false; 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic void tmds_register_write(int index, u8 data) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, 1388c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, 1398c2ecf20Sopenharmony_ci index, data); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic int tmds_register_read(int index) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci u8 data; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, 1478c2ecf20Sopenharmony_ci (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, 1488c2ecf20Sopenharmony_ci (u8) index, &data); 1498c2ecf20Sopenharmony_ci return data; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic int tmds_register_read_bytes(int index, u8 *buff, int buff_len) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port, 1558c2ecf20Sopenharmony_ci (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, 1568c2ecf20Sopenharmony_ci (u8) index, buff, buff_len); 1578c2ecf20Sopenharmony_ci return 0; 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* DVI Set Mode */ 1618c2ecf20Sopenharmony_civoid viafb_dvi_set_mode(const struct fb_var_screeninfo *var, 1628c2ecf20Sopenharmony_ci u16 cxres, u16 cyres, int iga) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci struct fb_var_screeninfo dvi_var = *var; 1658c2ecf20Sopenharmony_ci const struct fb_videomode *rb_mode; 1668c2ecf20Sopenharmony_ci int maxPixelClock; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock; 1698c2ecf20Sopenharmony_ci if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) { 1708c2ecf20Sopenharmony_ci rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60); 1718c2ecf20Sopenharmony_ci if (rb_mode) 1728c2ecf20Sopenharmony_ci viafb_fill_var_timing_info(&dvi_var, rb_mode); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci/* Sense DVI Connector */ 1798c2ecf20Sopenharmony_ciint viafb_dvi_sense(void) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0, 1828c2ecf20Sopenharmony_ci RegCR93 = 0, RegCR9B = 0, data; 1838c2ecf20Sopenharmony_ci int ret = false; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n"); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 1888c2ecf20Sopenharmony_ci /* DI1 Pad on */ 1898c2ecf20Sopenharmony_ci RegSR1E = viafb_read_reg(VIASR, SR1E); 1908c2ecf20Sopenharmony_ci viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* CR6B[0]VCK Input Selection: 1 = External clock. */ 1938c2ecf20Sopenharmony_ci RegCR6B = viafb_read_reg(VIACR, CR6B); 1948c2ecf20Sopenharmony_ci viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off 1978c2ecf20Sopenharmony_ci [0] Software Control Power Sequence */ 1988c2ecf20Sopenharmony_ci RegCR91 = viafb_read_reg(VIACR, CR91); 1998c2ecf20Sopenharmony_ci viafb_write_reg(CR91, VIACR, 0x1D); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* CR93[7] DI1 Data Source Selection: 1 = DSP2. 2028c2ecf20Sopenharmony_ci CR93[5] DI1 Clock Source: 1 = internal. 2038c2ecf20Sopenharmony_ci CR93[4] DI1 Clock Polarity. 2048c2ecf20Sopenharmony_ci CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */ 2058c2ecf20Sopenharmony_ci RegCR93 = viafb_read_reg(VIACR, CR93); 2068c2ecf20Sopenharmony_ci viafb_write_reg(CR93, VIACR, 0x01); 2078c2ecf20Sopenharmony_ci } else { 2088c2ecf20Sopenharmony_ci /* DVP0/DVP1 Pad on */ 2098c2ecf20Sopenharmony_ci RegSR1E = viafb_read_reg(VIASR, SR1E); 2108c2ecf20Sopenharmony_ci viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci /* SR3E[1]Multi-function selection: 2138c2ecf20Sopenharmony_ci 0 = Emulate I2C and DDC bus by GPIO2/3/4. */ 2148c2ecf20Sopenharmony_ci RegSR3E = viafb_read_reg(VIASR, SR3E); 2158c2ecf20Sopenharmony_ci viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20)); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off 2188c2ecf20Sopenharmony_ci [0] Software Control Power Sequence */ 2198c2ecf20Sopenharmony_ci RegCR91 = viafb_read_reg(VIACR, CR91); 2208c2ecf20Sopenharmony_ci viafb_write_reg(CR91, VIACR, 0x1D); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary 2238c2ecf20Sopenharmony_ci display.CR9B[2:0] DVP1 Clock Adjust */ 2248c2ecf20Sopenharmony_ci RegCR9B = viafb_read_reg(VIACR, CR9B); 2258c2ecf20Sopenharmony_ci viafb_write_reg(CR9B, VIACR, 0x01); 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci data = (u8) tmds_register_read(0x09); 2298c2ecf20Sopenharmony_ci if (data & 0x04) 2308c2ecf20Sopenharmony_ci ret = true; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci if (ret == false) { 2338c2ecf20Sopenharmony_ci if (viafb_dvi_query_EDID()) 2348c2ecf20Sopenharmony_ci ret = true; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci /* Restore status */ 2388c2ecf20Sopenharmony_ci viafb_write_reg(SR1E, VIASR, RegSR1E); 2398c2ecf20Sopenharmony_ci viafb_write_reg(CR91, VIACR, RegCR91); 2408c2ecf20Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { 2418c2ecf20Sopenharmony_ci viafb_write_reg(CR6B, VIACR, RegCR6B); 2428c2ecf20Sopenharmony_ci viafb_write_reg(CR93, VIACR, RegCR93); 2438c2ecf20Sopenharmony_ci } else { 2448c2ecf20Sopenharmony_ci viafb_write_reg(SR3E, VIASR, RegSR3E); 2458c2ecf20Sopenharmony_ci viafb_write_reg(CR9B, VIACR, RegCR9B); 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci return ret; 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* Query Flat Panel's EDID Table Version Through DVI Connector */ 2528c2ecf20Sopenharmony_cistatic int viafb_dvi_query_EDID(void) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci u8 data0, data1; 2558c2ecf20Sopenharmony_ci int restore; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n"); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; 2608c2ecf20Sopenharmony_ci viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci data0 = (u8) tmds_register_read(0x00); 2638c2ecf20Sopenharmony_ci data1 = (u8) tmds_register_read(0x01); 2648c2ecf20Sopenharmony_ci if ((data0 == 0) && (data1 == 0xFF)) { 2658c2ecf20Sopenharmony_ci viaparinfo->chip_info-> 2668c2ecf20Sopenharmony_ci tmds_chip_info.tmds_chip_slave_addr = restore; 2678c2ecf20Sopenharmony_ci return EDID_VERSION_1; /* Found EDID1 Table */ 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci return false; 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci/* Get Panel Size Using EDID1 Table */ 2748c2ecf20Sopenharmony_cistatic void dvi_get_panel_size_from_DDCv1( 2758c2ecf20Sopenharmony_ci struct tmds_chip_information *tmds_chip, 2768c2ecf20Sopenharmony_ci struct tmds_setting_information *tmds_setting) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci int i, restore; 2798c2ecf20Sopenharmony_ci unsigned char EDID_DATA[18]; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci restore = tmds_chip->tmds_chip_slave_addr; 2848c2ecf20Sopenharmony_ci tmds_chip->tmds_chip_slave_addr = 0xA0; 2858c2ecf20Sopenharmony_ci for (i = 0x25; i < 0x6D; i++) { 2868c2ecf20Sopenharmony_ci switch (i) { 2878c2ecf20Sopenharmony_ci case 0x36: 2888c2ecf20Sopenharmony_ci case 0x48: 2898c2ecf20Sopenharmony_ci case 0x5A: 2908c2ecf20Sopenharmony_ci case 0x6C: 2918c2ecf20Sopenharmony_ci tmds_register_read_bytes(i, EDID_DATA, 10); 2928c2ecf20Sopenharmony_ci if (!(EDID_DATA[0] || EDID_DATA[1])) { 2938c2ecf20Sopenharmony_ci /* The first two byte must be zero. */ 2948c2ecf20Sopenharmony_ci if (EDID_DATA[3] == 0xFD) { 2958c2ecf20Sopenharmony_ci /* To get max pixel clock. */ 2968c2ecf20Sopenharmony_ci tmds_setting->max_pixel_clock = 2978c2ecf20Sopenharmony_ci EDID_DATA[9] * 10; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci break; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci default: 3038c2ecf20Sopenharmony_ci break; 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", 3088c2ecf20Sopenharmony_ci tmds_setting->max_pixel_clock); 3098c2ecf20Sopenharmony_ci tmds_chip->tmds_chip_slave_addr = restore; 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci/* If Disable DVI, turn off pad */ 3138c2ecf20Sopenharmony_civoid viafb_dvi_disable(void) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci if (viaparinfo->chip_info-> 3168c2ecf20Sopenharmony_ci tmds_chip_info.output_interface == INTERFACE_TMDS) 3178c2ecf20Sopenharmony_ci /* Turn off TMDS power. */ 3188c2ecf20Sopenharmony_ci viafb_write_reg(CRD2, VIACR, 3198c2ecf20Sopenharmony_ci viafb_read_reg(VIACR, CRD2) | 0x08); 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic void dvi_patch_skew_dvp0(void) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci /* Reset data driving first: */ 3258c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR1B, VIASR, 0, BIT1); 3268c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR2A, VIASR, 0, BIT4); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci switch (viaparinfo->chip_info->gfx_chip_name) { 3298c2ecf20Sopenharmony_ci case UNICHROME_P4M890: 3308c2ecf20Sopenharmony_ci { 3318c2ecf20Sopenharmony_ci if ((viaparinfo->tmds_setting_info->h_active == 1600) && 3328c2ecf20Sopenharmony_ci (viaparinfo->tmds_setting_info->v_active == 3338c2ecf20Sopenharmony_ci 1200)) 3348c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR96, VIACR, 0x03, 3358c2ecf20Sopenharmony_ci BIT0 + BIT1 + BIT2); 3368c2ecf20Sopenharmony_ci else 3378c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR96, VIACR, 0x07, 3388c2ecf20Sopenharmony_ci BIT0 + BIT1 + BIT2); 3398c2ecf20Sopenharmony_ci break; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci case UNICHROME_P4M900: 3438c2ecf20Sopenharmony_ci { 3448c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR96, VIACR, 0x07, 3458c2ecf20Sopenharmony_ci BIT0 + BIT1 + BIT2 + BIT3); 3468c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1); 3478c2ecf20Sopenharmony_ci viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4); 3488c2ecf20Sopenharmony_ci break; 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci default: 3528c2ecf20Sopenharmony_ci { 3538c2ecf20Sopenharmony_ci break; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic void dvi_patch_skew_dvp_low(void) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci switch (viaparinfo->chip_info->gfx_chip_name) { 3618c2ecf20Sopenharmony_ci case UNICHROME_K8M890: 3628c2ecf20Sopenharmony_ci { 3638c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1); 3648c2ecf20Sopenharmony_ci break; 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci case UNICHROME_P4M900: 3688c2ecf20Sopenharmony_ci { 3698c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR99, VIACR, 0x08, 3708c2ecf20Sopenharmony_ci BIT0 + BIT1 + BIT2 + BIT3); 3718c2ecf20Sopenharmony_ci break; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci case UNICHROME_P4M890: 3758c2ecf20Sopenharmony_ci { 3768c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR99, VIACR, 0x0F, 3778c2ecf20Sopenharmony_ci BIT0 + BIT1 + BIT2 + BIT3); 3788c2ecf20Sopenharmony_ci break; 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci default: 3828c2ecf20Sopenharmony_ci { 3838c2ecf20Sopenharmony_ci break; 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci/* If Enable DVI, turn off pad */ 3898c2ecf20Sopenharmony_civoid viafb_dvi_enable(void) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci u8 data; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci switch (viaparinfo->chip_info->tmds_chip_info.output_interface) { 3948c2ecf20Sopenharmony_ci case INTERFACE_DVP0: 3958c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0); 3968c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5); 3978c2ecf20Sopenharmony_ci dvi_patch_skew_dvp0(); 3988c2ecf20Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 3998c2ecf20Sopenharmony_ci tmds_register_write(0x88, 0x3b); 4008c2ecf20Sopenharmony_ci else 4018c2ecf20Sopenharmony_ci /*clear CR91[5] to direct on display period 4028c2ecf20Sopenharmony_ci in the secondary diplay path */ 4038c2ecf20Sopenharmony_ci via_write_reg_mask(VIACR, 0x91, 0x00, 0x20); 4048c2ecf20Sopenharmony_ci break; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci case INTERFACE_DVP1: 4078c2ecf20Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 4088c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */ 4118c2ecf20Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 4128c2ecf20Sopenharmony_ci tmds_register_write(0x88, 0x3b); 4138c2ecf20Sopenharmony_ci else 4148c2ecf20Sopenharmony_ci /*clear CR91[5] to direct on display period 4158c2ecf20Sopenharmony_ci in the secondary diplay path */ 4168c2ecf20Sopenharmony_ci via_write_reg_mask(VIACR, 0x91, 0x00, 0x20); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci /*fix DVI cannot enable on EPIA-M board */ 4198c2ecf20Sopenharmony_ci if (viafb_platform_epia_dvi == 1) { 4208c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f); 4218c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0); 4228c2ecf20Sopenharmony_ci if (viafb_bus_width == 24) { 4238c2ecf20Sopenharmony_ci if (viafb_device_lcd_dualedge == 1) 4248c2ecf20Sopenharmony_ci data = 0x3F; 4258c2ecf20Sopenharmony_ci else 4268c2ecf20Sopenharmony_ci data = 0x37; 4278c2ecf20Sopenharmony_ci viafb_i2c_writebyte(viaparinfo->chip_info-> 4288c2ecf20Sopenharmony_ci tmds_chip_info.i2c_port, 4298c2ecf20Sopenharmony_ci viaparinfo->chip_info-> 4308c2ecf20Sopenharmony_ci tmds_chip_info.tmds_chip_slave_addr, 4318c2ecf20Sopenharmony_ci 0x08, data); 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci break; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci case INTERFACE_DFP_HIGH: 4378c2ecf20Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) 4388c2ecf20Sopenharmony_ci via_write_reg_mask(VIACR, CR97, 0x03, 0x03); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci via_write_reg_mask(VIACR, 0x91, 0x00, 0x20); 4418c2ecf20Sopenharmony_ci break; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci case INTERFACE_DFP_LOW: 4448c2ecf20Sopenharmony_ci if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) 4458c2ecf20Sopenharmony_ci break; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci dvi_patch_skew_dvp_low(); 4488c2ecf20Sopenharmony_ci via_write_reg_mask(VIACR, 0x91, 0x00, 0x20); 4498c2ecf20Sopenharmony_ci break; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci case INTERFACE_TMDS: 4528c2ecf20Sopenharmony_ci /* Turn on Display period in the panel path. */ 4538c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR91, VIACR, 0, BIT7); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci /* Turn on TMDS power. */ 4568c2ecf20Sopenharmony_ci viafb_write_reg_mask(CRD2, VIACR, 0, BIT3); 4578c2ecf20Sopenharmony_ci break; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci if (viaparinfo->tmds_setting_info->iga_path == IGA2) { 4618c2ecf20Sopenharmony_ci /* Disable LCD Scaling */ 4628c2ecf20Sopenharmony_ci viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0); 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci} 465