• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/video/via/
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include <linux/via-core.h>
22#include <linux/via_i2c.h>
23#include "global.h"
24
25static void tmds_register_write(int index, u8 data);
26static int tmds_register_read(int index);
27static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
28static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
29	*tmds_chip, struct tmds_setting_information *tmds_setting);
30static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
31	*tmds_chip, struct tmds_setting_information *tmds_setting);
32static int viafb_dvi_query_EDID(void);
33
34static int check_tmds_chip(int device_id_subaddr, int device_id)
35{
36	if (tmds_register_read(device_id_subaddr) == device_id)
37		return OK;
38	else
39		return FAIL;
40}
41
42void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
43	struct tmds_setting_information *tmds_setting)
44{
45	DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
46
47	viafb_dvi_sense();
48	switch (viafb_dvi_query_EDID()) {
49	case 1:
50		dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);
51		break;
52	case 2:
53		dvi_get_panel_size_from_DDCv2(tmds_chip, tmds_setting);
54		break;
55	default:
56		printk(KERN_WARNING "viafb_init_dvi_size: DVI panel size undetected!\n");
57		break;
58	}
59
60	return;
61}
62
63int viafb_tmds_trasmitter_identify(void)
64{
65	unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
66
67	/* Turn on ouputting pad */
68	switch (viaparinfo->chip_info->gfx_chip_name) {
69	case UNICHROME_K8M890:
70	    /*=* DFP Low Pad on *=*/
71		sr2a = viafb_read_reg(VIASR, SR2A);
72		viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
73		break;
74
75	case UNICHROME_P4M900:
76	case UNICHROME_P4M890:
77		/* DFP Low Pad on */
78		sr2a = viafb_read_reg(VIASR, SR2A);
79		viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
80		/* DVP0 Pad on */
81		sr1e = viafb_read_reg(VIASR, SR1E);
82		viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
83		break;
84
85	default:
86	    /* DVP0/DVP1 Pad on */
87		sr1e = viafb_read_reg(VIASR, SR1E);
88		viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
89			BIT5 + BIT6 + BIT7);
90	    /* SR3E[1]Multi-function selection:
91	    0 = Emulate I2C and DDC bus by GPIO2/3/4. */
92		sr3e = viafb_read_reg(VIASR, SR3E);
93		viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
94		break;
95	}
96
97	/* Check for VT1632: */
98	viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
99	viaparinfo->chip_info->
100		tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
101	viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31;
102	if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) {
103		/*
104		 * Currently only support 12bits,dual edge,add 24bits mode later
105		 */
106		tmds_register_write(0x08, 0x3b);
107
108		DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
109		DEBUG_MSG(KERN_INFO "\n %2d",
110			  viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
111		DEBUG_MSG(KERN_INFO "\n %2d",
112			  viaparinfo->chip_info->tmds_chip_info.i2c_port);
113		return OK;
114	} else {
115		viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C;
116		if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)
117		    != FAIL) {
118			tmds_register_write(0x08, 0x3b);
119			DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
120			DEBUG_MSG(KERN_INFO "\n %2d",
121				  viaparinfo->chip_info->
122				  tmds_chip_info.tmds_chip_name);
123			DEBUG_MSG(KERN_INFO "\n %2d",
124				  viaparinfo->chip_info->
125				  tmds_chip_info.i2c_port);
126			return OK;
127		}
128	}
129
130	viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
131
132	if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
133	    ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
134	     (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
135		DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
136		return OK;
137	}
138
139	switch (viaparinfo->chip_info->gfx_chip_name) {
140	case UNICHROME_K8M890:
141		viafb_write_reg(SR2A, VIASR, sr2a);
142		break;
143
144	case UNICHROME_P4M900:
145	case UNICHROME_P4M890:
146		viafb_write_reg(SR2A, VIASR, sr2a);
147		viafb_write_reg(SR1E, VIASR, sr1e);
148		break;
149
150	default:
151		viafb_write_reg(SR1E, VIASR, sr1e);
152		viafb_write_reg(SR3E, VIASR, sr3e);
153		break;
154	}
155
156	viaparinfo->chip_info->
157		tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
158	viaparinfo->chip_info->tmds_chip_info.
159		tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
160	return FAIL;
161}
162
163static void tmds_register_write(int index, u8 data)
164{
165	viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
166			    viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
167			    index, data);
168}
169
170static int tmds_register_read(int index)
171{
172	u8 data;
173
174	viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
175			   (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
176			   (u8) index, &data);
177	return data;
178}
179
180static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
181{
182	viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port,
183			    (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
184			    (u8) index, buff, buff_len);
185	return 0;
186}
187
188/* DVI Set Mode */
189void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
190	int set_iga)
191{
192	struct VideoModeTable *rb_mode;
193	struct crt_mode_table *pDviTiming;
194	unsigned long desirePixelClock, maxPixelClock;
195	pDviTiming = mode->crtc;
196	desirePixelClock = pDviTiming->clk / 1000000;
197	maxPixelClock = (unsigned long)viaparinfo->
198		tmds_setting_info->max_pixel_clock;
199
200	DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n");
201
202	if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) {
203		rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr,
204			mode->crtc[0].crtc.ver_addr);
205		if (rb_mode) {
206			mode = rb_mode;
207			pDviTiming = rb_mode->crtc;
208		}
209	}
210	viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga);
211	viafb_set_output_path(DEVICE_DVI, set_iga,
212			viaparinfo->chip_info->tmds_chip_info.output_interface);
213}
214
215/* Sense DVI Connector */
216int viafb_dvi_sense(void)
217{
218	u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
219		RegCR93 = 0, RegCR9B = 0, data;
220	int ret = false;
221
222	DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
223
224	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
225		/* DI1 Pad on */
226		RegSR1E = viafb_read_reg(VIASR, SR1E);
227		viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
228
229		/* CR6B[0]VCK Input Selection: 1 = External clock. */
230		RegCR6B = viafb_read_reg(VIACR, CR6B);
231		viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
232
233		/* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
234		   [0] Software Control Power Sequence */
235		RegCR91 = viafb_read_reg(VIACR, CR91);
236		viafb_write_reg(CR91, VIACR, 0x1D);
237
238		/* CR93[7] DI1 Data Source Selection: 1 = DSP2.
239		   CR93[5] DI1 Clock Source: 1 = internal.
240		   CR93[4] DI1 Clock Polarity.
241		   CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
242		RegCR93 = viafb_read_reg(VIACR, CR93);
243		viafb_write_reg(CR93, VIACR, 0x01);
244	} else {
245		/* DVP0/DVP1 Pad on */
246		RegSR1E = viafb_read_reg(VIASR, SR1E);
247		viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
248
249		/* SR3E[1]Multi-function selection:
250		   0 = Emulate I2C and DDC bus by GPIO2/3/4. */
251		RegSR3E = viafb_read_reg(VIASR, SR3E);
252		viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
253
254		/* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
255		   [0] Software Control Power Sequence */
256		RegCR91 = viafb_read_reg(VIACR, CR91);
257		viafb_write_reg(CR91, VIACR, 0x1D);
258
259		/*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
260		display.CR9B[2:0] DVP1 Clock Adjust */
261		RegCR9B = viafb_read_reg(VIACR, CR9B);
262		viafb_write_reg(CR9B, VIACR, 0x01);
263	}
264
265	data = (u8) tmds_register_read(0x09);
266	if (data & 0x04)
267		ret = true;
268
269	if (ret == false) {
270		if (viafb_dvi_query_EDID())
271			ret = true;
272	}
273
274	/* Restore status */
275	viafb_write_reg(SR1E, VIASR, RegSR1E);
276	viafb_write_reg(CR91, VIACR, RegCR91);
277	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
278		viafb_write_reg(CR6B, VIACR, RegCR6B);
279		viafb_write_reg(CR93, VIACR, RegCR93);
280	} else {
281		viafb_write_reg(SR3E, VIASR, RegSR3E);
282		viafb_write_reg(CR9B, VIACR, RegCR9B);
283	}
284
285	return ret;
286}
287
288/* Query Flat Panel's EDID Table Version Through DVI Connector */
289static int viafb_dvi_query_EDID(void)
290{
291	u8 data0, data1;
292	int restore;
293
294	DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
295
296	restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
297	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
298
299	data0 = (u8) tmds_register_read(0x00);
300	data1 = (u8) tmds_register_read(0x01);
301	if ((data0 == 0) && (data1 == 0xFF)) {
302		viaparinfo->chip_info->
303			tmds_chip_info.tmds_chip_slave_addr = restore;
304		return EDID_VERSION_1;	/* Found EDID1 Table */
305	}
306
307	data0 = (u8) tmds_register_read(0x00);
308	viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = restore;
309	if (data0 == 0x20)
310		return EDID_VERSION_2;	/* Found EDID2 Table */
311	else
312		return false;
313}
314
315/* Get Panel Size Using EDID1 Table */
316static void dvi_get_panel_size_from_DDCv1(struct tmds_chip_information
317	*tmds_chip, struct tmds_setting_information *tmds_setting)
318{
319	int i, max_h = 0, tmp, restore;
320	unsigned char rData;
321	unsigned char EDID_DATA[18];
322
323	DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
324
325	restore = tmds_chip->tmds_chip_slave_addr;
326	tmds_chip->tmds_chip_slave_addr = 0xA0;
327
328	rData = tmds_register_read(0x23);
329	if (rData & 0x3C)
330		max_h = 640;
331	if (rData & 0xC0)
332		max_h = 720;
333	if (rData & 0x03)
334		max_h = 800;
335
336	rData = tmds_register_read(0x24);
337	if (rData & 0xC0)
338		max_h = 800;
339	if (rData & 0x1E)
340		max_h = 1024;
341	if (rData & 0x01)
342		max_h = 1280;
343
344	for (i = 0x25; i < 0x6D; i++) {
345		switch (i) {
346		case 0x26:
347		case 0x28:
348		case 0x2A:
349		case 0x2C:
350		case 0x2E:
351		case 0x30:
352		case 0x32:
353		case 0x34:
354			rData = tmds_register_read(i);
355			if (rData == 1)
356				break;
357			/* data = (data + 31) * 8 */
358			tmp = (rData + 31) << 3;
359			if (tmp > max_h)
360				max_h = tmp;
361			break;
362
363		case 0x36:
364		case 0x48:
365		case 0x5A:
366		case 0x6C:
367			tmds_register_read_bytes(i, EDID_DATA, 10);
368			if (!(EDID_DATA[0] || EDID_DATA[1])) {
369				/* The first two byte must be zero. */
370				if (EDID_DATA[3] == 0xFD) {
371					/* To get max pixel clock. */
372					tmds_setting->max_pixel_clock =
373						EDID_DATA[9] * 10;
374				}
375			}
376			break;
377
378		default:
379			break;
380		}
381	}
382
383	tmds_setting->max_hres = max_h;
384	switch (max_h) {
385	case 640:
386		tmds_setting->max_vres = 480;
387		break;
388	case 800:
389		tmds_setting->max_vres = 600;
390		break;
391	case 1024:
392		tmds_setting->max_vres = 768;
393		break;
394	case 1280:
395		tmds_setting->max_vres = 1024;
396		break;
397	case 1400:
398		tmds_setting->max_vres = 1050;
399		break;
400	case 1440:
401		tmds_setting->max_vres = 1050;
402		break;
403	case 1600:
404		tmds_setting->max_vres = 1200;
405		break;
406	case 1920:
407		tmds_setting->max_vres = 1080;
408		break;
409	default:
410		DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d ! "
411					 "set default panel size.\n", max_h);
412		break;
413	}
414
415	DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
416		tmds_setting->max_pixel_clock);
417	tmds_chip->tmds_chip_slave_addr = restore;
418}
419
420/* Get Panel Size Using EDID2 Table */
421static void dvi_get_panel_size_from_DDCv2(struct tmds_chip_information
422	*tmds_chip, struct tmds_setting_information *tmds_setting)
423{
424	int restore;
425	unsigned char R_Buffer[2];
426
427	DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv2 \n");
428
429	restore = tmds_chip->tmds_chip_slave_addr;
430	tmds_chip->tmds_chip_slave_addr = 0xA2;
431
432	/* Horizontal: 0x76, 0x77 */
433	tmds_register_read_bytes(0x76, R_Buffer, 2);
434	tmds_setting->max_hres = R_Buffer[0] + (R_Buffer[1] << 8);
435
436	switch (tmds_setting->max_hres) {
437	case 640:
438		tmds_setting->max_vres = 480;
439		break;
440	case 800:
441		tmds_setting->max_vres = 600;
442		break;
443	case 1024:
444		tmds_setting->max_vres = 768;
445		break;
446	case 1280:
447		tmds_setting->max_vres = 1024;
448		break;
449	case 1400:
450		tmds_setting->max_vres = 1050;
451		break;
452	case 1440:
453		tmds_setting->max_vres = 1050;
454		break;
455	case 1600:
456		tmds_setting->max_vres = 1200;
457		break;
458	default:
459		DEBUG_MSG(KERN_INFO "Unknown panel size max resolution = %d! "
460			"set default panel size.\n", tmds_setting->max_hres);
461		break;
462	}
463
464	tmds_chip->tmds_chip_slave_addr = restore;
465}
466
467/* If Disable DVI, turn off pad */
468void viafb_dvi_disable(void)
469{
470	if (viaparinfo->chip_info->
471		tmds_chip_info.output_interface == INTERFACE_DVP0)
472		viafb_write_reg(SR1E, VIASR,
473		viafb_read_reg(VIASR, SR1E) & (~0xC0));
474
475	if (viaparinfo->chip_info->
476		tmds_chip_info.output_interface == INTERFACE_DVP1)
477		viafb_write_reg(SR1E, VIASR,
478		viafb_read_reg(VIASR, SR1E) & (~0x30));
479
480	if (viaparinfo->chip_info->
481		tmds_chip_info.output_interface == INTERFACE_DFP_HIGH)
482		viafb_write_reg(SR2A, VIASR,
483		viafb_read_reg(VIASR, SR2A) & (~0x0C));
484
485	if (viaparinfo->chip_info->
486		tmds_chip_info.output_interface == INTERFACE_DFP_LOW)
487		viafb_write_reg(SR2A, VIASR,
488		viafb_read_reg(VIASR, SR2A) & (~0x03));
489
490	if (viaparinfo->chip_info->
491		tmds_chip_info.output_interface == INTERFACE_TMDS)
492		/* Turn off TMDS power. */
493		viafb_write_reg(CRD2, VIACR,
494		viafb_read_reg(VIACR, CRD2) | 0x08);
495}
496
497/* If Enable DVI, turn off pad */
498void viafb_dvi_enable(void)
499{
500	u8 data;
501
502	if (viaparinfo->chip_info->
503		tmds_chip_info.output_interface == INTERFACE_DVP0) {
504		viafb_write_reg(SR1E, VIASR,
505			viafb_read_reg(VIASR, SR1E) | 0xC0);
506		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
507			tmds_register_write(0x88, 0x3b);
508		else
509			/*clear CR91[5] to direct on display period
510			   in the secondary diplay path */
511			viafb_write_reg(CR91, VIACR,
512			viafb_read_reg(VIACR, CR91) & 0xDF);
513	}
514
515	if (viaparinfo->chip_info->
516		tmds_chip_info.output_interface == INTERFACE_DVP1) {
517		viafb_write_reg(SR1E, VIASR,
518			viafb_read_reg(VIASR, SR1E) | 0x30);
519
520		/*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
521		if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
522			tmds_register_write(0x88, 0x3b);
523		} else {
524			/*clear CR91[5] to direct on display period
525			  in the secondary diplay path */
526			viafb_write_reg(CR91, VIACR,
527			viafb_read_reg(VIACR, CR91) & 0xDF);
528		}
529
530		/*fix DVI cannot enable on EPIA-M board */
531		if (viafb_platform_epia_dvi == 1) {
532			viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
533			viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
534			if (viafb_bus_width == 24) {
535				if (viafb_device_lcd_dualedge == 1)
536					data = 0x3F;
537				else
538					data = 0x37;
539				viafb_i2c_writebyte(viaparinfo->chip_info->
540						       tmds_chip_info.i2c_port,
541						    viaparinfo->chip_info->
542						       tmds_chip_info.tmds_chip_slave_addr,
543						    0x08, data);
544			}
545		}
546	}
547
548	if (viaparinfo->chip_info->
549		tmds_chip_info.output_interface == INTERFACE_DFP_HIGH) {
550		viafb_write_reg(SR2A, VIASR,
551			viafb_read_reg(VIASR, SR2A) | 0x0C);
552		viafb_write_reg(CR91, VIACR,
553			viafb_read_reg(VIACR, CR91) & 0xDF);
554	}
555
556	if (viaparinfo->chip_info->
557		tmds_chip_info.output_interface == INTERFACE_DFP_LOW) {
558		viafb_write_reg(SR2A, VIASR,
559			viafb_read_reg(VIASR, SR2A) | 0x03);
560		viafb_write_reg(CR91, VIACR,
561			viafb_read_reg(VIACR, CR91) & 0xDF);
562	}
563	if (viaparinfo->chip_info->
564		tmds_chip_info.output_interface == INTERFACE_TMDS) {
565		/* Turn on Display period in the panel path. */
566		viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
567
568		/* Turn on TMDS power. */
569		viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
570	}
571}
572