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