xref: /plan9/sys/src/cmd/aux/vga/tvp3026.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "pci.h"
6 #include "vga.h"
7 
8 /*
9  * Tvp3026 Viewpoint Video Interface Palette.
10  * Assumes hooked up to an S3 chip of some kind.
11  * Why is register access different from the
12  * Tvp302[05]?
13  */
14 enum {
15 	Index		= 0x00,		/* Index register */
16 	Data		= 0x0A,		/* Data register */
17 
18 	Id		= 0x3F,		/* ID Register */
19 	Tvp3026		= 0x26,
20 };
21 
22 static uchar
tvp3026io(uchar reg,uchar data)23 tvp3026io(uchar reg, uchar data)
24 {
25 	uchar crt55;
26 
27 	crt55 = vgaxi(Crtx, 0x55) & 0xFC;
28 	vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
29 	vgao(dacxreg[reg & 0x03], data);
30 
31 	return crt55;
32 }
33 
34 static uchar
tvp3026i(uchar reg)35 tvp3026i(uchar reg)
36 {
37 	uchar crt55, r;
38 
39 	crt55 = vgaxi(Crtx, 0x55) & 0xFC;
40 	vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
41 	r = vgai(dacxreg[reg & 0x03]);
42 	vgaxo(Crtx, 0x55, crt55);
43 
44 	return r;
45 }
46 
47 uchar
tvp3026xi(uchar index)48 tvp3026xi(uchar index)
49 {
50 	uchar crt55, r;
51 
52 	crt55 = tvp3026io(Index, index);
53 	vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
54 	r = vgai(dacxreg[Data & 0x03]);
55 	vgaxo(Crtx, 0x55, crt55);
56 
57 	return r;
58 }
59 
60 static void
tvp3026o(uchar reg,uchar data)61 tvp3026o(uchar reg, uchar data)
62 {
63 	uchar crt55;
64 
65 	crt55 = tvp3026io(reg, data);
66 	vgaxo(Crtx, 0x55, crt55);
67 }
68 
69 void
tvp3026xo(uchar index,uchar data)70 tvp3026xo(uchar index, uchar data)
71 {
72 	uchar crt55;
73 
74 	crt55 = tvp3026io(Index, index);
75 	vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
76 	vgao(dacxreg[Data & 0x03], data);
77 	vgaxo(Crtx, 0x55, crt55);
78 }
79 
80 static void
options(Vga *,Ctlr * ctlr)81 options(Vga*, Ctlr* ctlr)
82 {
83 	ctlr->flag |= Hclk2|Hextsid|Henhanced|Foptions;
84 }
85 
86 static void
init(Vga * vga,Ctlr * ctlr)87 init(Vga* vga, Ctlr* ctlr)
88 {
89 	ulong grade;
90 	char *p;
91 
92 	/*
93 	 * Work out the part speed-grade from name. Name can have,
94 	 * e.g. '-135' on the end  for 135MHz part.
95 	 */
96 	grade = 110000000;
97 	if(p = strrchr(ctlr->name, '-'))
98 		grade = strtoul(p+1, 0, 0) * 1000000;
99 
100 	/*
101 	 * If we don't already have a desired pclk,
102 	 * take it from the mode.
103 	 * Check it's within range.
104 	 */
105 	if(vga->f[0] == 0)
106 		vga->f[0] = vga->mode->frequency;
107 	if(vga->f[0] > grade)
108 		error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
109 
110 	/*
111 	 * Determine whether to use clock-doubler or not.
112 	 */
113 	if((ctlr->flag & Uclk2) == 0 && vga->mode->z == 8 && vga->f[0] > 85000000)
114 		resyncinit(vga, ctlr, Uclk2, 0);
115 
116 	ctlr->flag |= Finit;
117 }
118 
119 static void
load(Vga * vga,Ctlr * ctlr)120 load(Vga* vga, Ctlr* ctlr)
121 {
122 	uchar x;
123 
124 	/*
125 	 * General Control:
126 	 *	output sync polarity
127 	 * It's important to set this properly and to turn off the
128 	 * VGA controller H and V syncs. Can't be set in VGA mode.
129 	 */
130 	x = 0x00;
131 	if((vga->misc & 0x40) == 0)
132 		x |= 0x01;
133 	if((vga->misc & 0x80) == 0)
134 		x |= 0x02;
135 	tvp3026xo(0x1D, x);
136 	vga->misc |= 0xC0;
137 	vgao(MiscW, vga->misc);
138 
139 	ctlr->flag |= Fload;
140 }
141 
142 static void
dump(Vga *,Ctlr * ctlr)143 dump(Vga*, Ctlr* ctlr)
144 {
145 	int i;
146 	ulong clock[4], f;
147 
148 	printitem(ctlr->name, "direct");
149 	for(i = 0; i < 16; i++)
150 		printreg(tvp3026i(i));
151 
152 	printitem(ctlr->name, "index");
153 	for(i = 0; i < 64; i++)
154 		printreg(tvp3026xi(i));
155 
156 	printitem(ctlr->name, "PCLK");
157 	for(i = 0; i < 3; i++){
158 		tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
159 		printreg(clock[i] = tvp3026xi(0x2D));
160 	}
161 	f = (RefFreq*(65-clock[1]))/(65-(clock[0] & 0x3F));
162 	f >>= clock[2] & 0x03;
163 	Bprint(&stdout, "%23ld", f);
164 
165 	printitem(ctlr->name, "MCLK");
166 	for(i = 0; i < 3; i++){
167 		tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
168 		printreg(clock[i] = tvp3026xi(0x2E));
169 	}
170 	f = (RefFreq*(65-clock[1]))/(65-(clock[0] & 0x3F));
171 	f >>= clock[2] & 0x03;
172 	Bprint(&stdout, "%23ld", f);
173 
174 	printitem(ctlr->name, "LCLK");
175 	for(i = 0; i < 3; i++){
176 		tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
177 		printreg(clock[i] = tvp3026xi(0x2F));
178 	}
179 	Bprint(&stdout, "\n");
180 }
181 
182 Ctlr tvp3026 = {
183 	"tvp3026",			/* name */
184 	0,				/* snarf */
185 	options,			/* options */
186 	init,				/* init */
187 	0,				/* load */
188 	dump,				/* dump */
189 };
190