brintos

brintos / linux-shallow public Read only

0
0
Text · 12.3 KiB · 27990a7 Raw
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