cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dvi.c (12617B)


      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
     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_slave_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 later
     78		 */
     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_slave_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_slave_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_slave_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_slave_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 Off
    197		   [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 Off
    218		   [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 secondary
    223		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_slave_addr;
    260	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_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_slave_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_slave_addr;
    284	tmds_chip->tmds_chip_slave_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_slave_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			else
    337				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		else
    401			/*clear CR91[5] to direct on display period
    402			   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		else
    414			/*clear CR91[5] to direct on display period
    415			  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				else
    426					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_slave_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}