xref: /plan9/sys/src/cmd/aux/vga/t2r4.c (revision 74f16c8187aab477889167f2422d0597b1b7d0ff)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 
5 #include "pci.h"
6 #include "vga.h"
7 
8 /*
9  * #9 Ticket to Ride IV.
10  */
11 typedef struct {
12 	Pcidev*	pci;
13 	ulong	io;
14 	uchar*	mmio;
15 
16 	ulong	ioreg[13];
17 	ulong	g[25];
18 	ulong	w[25];
19 } T2r4;
20 
21 enum {					/* memory mapped global registers */
22 	IntVcnt		= 0x20/4,	/* vertical interrupt counter */
23 	IntHcnt		= 0x24/4,	/* horizontal interrupt counter */
24 	DbAdr		= 0x28/4,	/* display start address */
25 	DbPtch		= 0x2C/4,	/* display pitch */
26 	CrtHac		= 0x30/4,	/* horizontal active line width */
27 	CrtHbl		= 0x34/4,	/* horizontal blank width */
28 	CrtHfp		= 0x38/4,	/* horizontal front porch */
29 	CrtHs		= 0x3C/4,	/* horizontal sync width */
30 	CrtVac		= 0x40/4,	/* vertical active field width */
31 	CrtVbl		= 0x44/4,	/* vertical blank width */
32 	CrtVfp		= 0x48/4,	/* vertical front porch */
33 	CrtVs		= 0x4C/4,	/* vertical sync width */
34 	CrtLcnt		= 0x50/4,	/* CRT line counter */
35 	CrtZoom		= 0x54/4,	/* display zoom factor */
36 	Crt1con		= 0x58/4,	/* CRT configuration register 1 */
37 	Crt2con		= 0x5C/4,	/* CRT configuration register 2 */
38 	DbAdr2		= 0x60/4,	/* CRT display start address 2 */
39 };
40 
41 enum {					/* memory windows registers */
42 	Mw0Ctrl		= 0x00/4,	/* memory window 0 control */
43 	Mw0Ad		= 0x04/4,	/* memory window 0 address */
44 	Mw0Sz		= 0x08/4,	/* memory window 0 size */
45 	Mw0Org		= 0x10/4,	/* memory window 0 origin */
46 	Mw0Mask		= 0x24/4,	/* Memory window 0 plane mask */
47 	Mw1Ctlr		= 0x28/4,	/* memory window 1 control */
48 	Mw1Ad		= 0x2C/4,	/* memory window 1 address */
49 	Mw1Sz		= 0x30/4,	/* memory window 1 size */
50 	Mw1Org		= 0x38/4,	/* memory window 1 origin */
51 	Mw1Mask		= 0x4C/4,	/* Memory window 1 plane mask */
52 	MwcFcnt		= 0x50/4,	/* memory window cache flush counter */
53 	MwcFlsh		= 0x54/4,	/* manual cache flush */
54 	YuvLi		= 0x58/4,	/* YUV LUT index */
55 	YuvLa		= 0x5C/4,	/* YUV LUT address */
56 	MwCtrl		= 0x60/4,	/* memory window 0 and 1 control */
57 };
58 
59 enum {
60 	IndexLo		= 4,
61 	IndexHi		= 5,
62 	Data		= 6,
63 	IndexCtl	= 7,
64 };
65 
66 static uchar
_rgb524xi(Vga * vga,int index)67 _rgb524xi(Vga* vga, int index)
68 {
69 	ulong *mmio;
70 
71 	mmio = (ulong*)((T2r4*)vga->private)->mmio;
72 	mmio[IndexLo] = index & 0xFF;
73 	mmio[IndexHi] = (index>>8) & 0xFF;
74 
75 	return mmio[Data];
76 }
77 
78 static void
_rgb524xo(Vga * vga,int index,uchar data)79 _rgb524xo(Vga* vga, int index, uchar data)
80 {
81 	ulong *mmio;
82 
83 	mmio = (ulong*)((T2r4*)vga->private)->mmio;
84 	mmio[IndexLo] = index & 0xFF;
85 	mmio[IndexHi] = (index>>8) & 0xFF;
86 
87 	mmio[Data] = data;
88 }
89 
90 static void
snarf(Vga * vga,Ctlr * ctlr)91 snarf(Vga* vga, Ctlr* ctlr)
92 {
93 	ulong *mmio;
94 	int f, i, x;
95 	Pcidev *p;
96 	T2r4 *t2r4;
97 	ulong *rp;
98 
99 	if(vga->private == nil){
100 		vga->private = alloc(sizeof(T2r4));
101 		if((p = pcimatch(0, 0x105D, 0)) == nil)
102 			error("%s: not found\n", ctlr->name);
103 		switch(p->did){
104 		case 0x5348:			/*  */
105 			break;
106 		default:
107 			error("%s: not found\n", ctlr->name);
108 		}
109 
110 		if((f = open("#v/vgactl", OWRITE)) < 0)
111 			error("%s: can't open vgactl\n", ctlr->name);
112 		if(write(f, "type t2r4", 9) != 9)
113 			error("%s: can't set type\n", ctlr->name);
114 		close(f);
115 
116 		mmio = segattach(0, "t2r4mmio", 0, p->mem[4].size);
117 		if(mmio == (void*)-1)
118 			error("%s: can't attach mmio segment\n", ctlr->name);
119 
120 		t2r4 = vga->private;
121 		t2r4->pci = p;
122 		t2r4->io = p->mem[5].bar & ~0x0F;
123 		t2r4->mmio = (uchar*)mmio;
124 	}
125 	t2r4 = vga->private;
126 	for(i = 0; i < nelem(t2r4->ioreg); i++)
127 		t2r4->ioreg[i] = inportl(t2r4->io+(i*4));
128 
129 	x = t2r4->ioreg[7] & 0xFF00001F;		/* config1 */
130 	outportl(t2r4->io+0x1C, x|0x00331F10);
131 
132 	x = t2r4->ioreg[8] & 0xFF0FFFFF;		/* config2 */
133 	outportl(t2r4->io+0x20, x|0x00100000);
134 
135 	x = inportl(t2r4->io+0x30) & 0xFF;		/* vgactl */
136 	outportl(t2r4->io+0x30, x|0x82);
137 
138 	rp = (ulong*)t2r4->mmio;
139 	for(i = 0; i < nelem(t2r4->g); i++)
140 		t2r4->g[i] = *rp++;
141 	rp = (ulong*)(t2r4->mmio+8192);
142 	for(i = 0; i < nelem(t2r4->w); i++)
143 		t2r4->w[i] = *rp++;
144 
145 	vga->vma = vga->vmz = t2r4->pci->mem[0].size;
146 	ctlr->flag |= Hlinear;
147 
148 	/*
149 	 * Currently, the RGB524 has no need of a snarf
150 	 * routine so this will be called before any RGB524 code.
151 	 */
152 	if(vga->ramdac && strncmp(vga->ramdac->name, "rgb524mn", 8) == 0){
153 		rgb524mnxi = _rgb524xi;
154 		rgb524mnxo = _rgb524xo;
155 	}
156 
157 	ctlr->flag |= Fsnarf;
158 }
159 
160 static void
options(Vga * vga,Ctlr * ctlr)161 options(Vga* vga, Ctlr* ctlr)
162 {
163 	USED(vga);
164 	ctlr->flag |= Foptions;
165 }
166 
167 static void
init(Vga * vga,Ctlr * ctlr)168 init(Vga* vga, Ctlr* ctlr)
169 {
170 	char *val;
171 	T2r4 *t2r4;
172 	int crtclocks, zoom;
173 
174 	t2r4 = vga->private;
175 	crtclocks = 64/vga->mode->z;
176 
177 	zoom = 1;
178 	if((val = dbattr(vga->mode->attr, "zoom")) && strtol(val, 0, 0))
179 		zoom = 2;
180 
181 	t2r4->g[DbAdr] = 0;
182 	switch(vga->mode->z){
183 	case 8:
184 		t2r4->g[DbPtch] = vga->mode->x*1;
185 		break;
186 	case 16:
187 		t2r4->g[DbPtch] = vga->mode->x*2;
188 		break;
189 	case 32:
190 		t2r4->g[DbPtch] = vga->mode->x*4;
191 		break;
192 	}
193 	t2r4->g[CrtHac] = vga->mode->x/crtclocks;
194 	t2r4->g[CrtHbl] = (vga->mode->ht-vga->mode->x)/crtclocks;
195 	if(vga->mode->shs == 0)
196 		vga->mode->shs = vga->mode->shb;
197 	t2r4->g[CrtHfp] = (vga->mode->shs-vga->mode->x)/crtclocks;
198 	if(vga->mode->ehs == 0)
199 		vga->mode->ehs = vga->mode->ehb;
200 	t2r4->g[CrtHs] = (vga->mode->ehs-vga->mode->shs)/crtclocks;
201 	t2r4->g[CrtVac] = vga->mode->y * zoom;
202 	t2r4->g[CrtVbl] = (vga->mode->vt-vga->mode->y) * zoom;
203 	t2r4->g[CrtVfp] = (vga->mode->vrs-vga->mode->y) * zoom;
204 	t2r4->g[CrtVs] = (vga->mode->vre-vga->mode->vrs) * zoom;
205 	t2r4->g[CrtZoom] = 0;
206 
207 	/*
208 	 * Turn on the syncs and video.
209 	 * Bts (bit 0x100) is digital RGB output enable. If there's
210 	 * a flat-panel then this is hopefully already set by the BIOS,
211 	 * so don't touch it. (It's possible that bit 0 of SoftSw
212 	 * indicates flat-panel or CRT).
213 	 */
214 	t2r4->g[Crt1con] &= 0x00000100;
215 	t2r4->g[Crt1con] |= 0x70;
216 	t2r4->g[Crt2con] = 0x20000100;
217 
218 	if(zoom == 2)
219 		t2r4->g[CrtZoom] = 1;
220 
221 	t2r4->w[Mw0Ctrl] = 0;
222 	t2r4->w[Mw0Sz] = 0x0D;	/* 32MB */
223 	t2r4->w[Mw0Org] = 0;
224 	t2r4->w[Mw0Mask] = 0xFFFFFFFF;
225 
226 	if(vga->linear && (ctlr->flag & Hlinear))
227 		ctlr->flag |= Ulinear;
228 
229 	ctlr->flag |= Finit;
230 }
231 
232 static void
load(Vga * vga,Ctlr * ctlr)233 load(Vga* vga, Ctlr* ctlr)
234 {
235 	T2r4 *t2r4;
236 	ulong *g, *w;
237 
238 	t2r4 = vga->private;
239 
240 	g = (ulong*)t2r4->mmio;
241 	g[DbAdr] = t2r4->g[DbAdr];
242 	g[DbPtch] = t2r4->g[DbPtch];
243 	g[CrtHac] = t2r4->g[CrtHac];
244 	g[CrtHbl] = t2r4->g[CrtHbl];
245 	g[CrtHfp] = t2r4->g[CrtHfp];
246 	g[CrtHs] = t2r4->g[CrtHs];
247 	g[CrtVac] = t2r4->g[CrtVac];
248 	g[CrtVbl] = t2r4->g[CrtVbl];
249 	g[CrtVfp] = t2r4->g[CrtVfp];
250 	g[CrtVs] = t2r4->g[CrtVs];
251 	g[Crt1con] = t2r4->g[Crt1con];
252 	g[Crt2con] = t2r4->g[Crt2con];
253 	g[CrtZoom] = t2r4->g[CrtZoom];
254 
255 	w = (ulong*)(t2r4->mmio+8192);
256 	w[Mw0Ctrl] = t2r4->w[Mw0Ctrl];
257 	w[Mw0Sz] = t2r4->w[Mw0Sz];
258 	w[Mw0Org] = t2r4->w[Mw0Org];
259 	w[Mw0Mask] = t2r4->w[Mw0Mask];
260 
261 	if(t2r4->g[CrtZoom])
262 		outportl(t2r4->io+0x30, 0xA2);	/* vgactl */
263 	else
264 		outportl(t2r4->io+0x30, 0x82);	/* vgactl */
265 	outportl(t2r4->io+0x24, 0x211BF030);	/* sgram */
266 	sleep(500);
267 	outportl(t2r4->io+0x24, 0xA11BF030);	/* sgram */
268 
269 	ctlr->flag |= Fload;
270 }
271 
272 static void
dump(Vga * vga,Ctlr * ctlr)273 dump(Vga* vga, Ctlr* ctlr)
274 {
275 	int i;
276 	T2r4 *t2r4;
277 
278 	t2r4 = vga->private;
279 	Bprint(&stdout, "\n");
280 	Bprint(&stdout, "%s ioreg\t\t%8.8luX\n", ctlr->name, t2r4->io);
281 	Bprint(&stdout, "%s rbase_g\t%8.8luX\n", ctlr->name, t2r4->ioreg[0]);
282 	Bprint(&stdout, "%s rbase_w\t%8.8luX\n", ctlr->name, t2r4->ioreg[1]);
283 	Bprint(&stdout, "%s rbase_d\t%8.8luX\n", ctlr->name, t2r4->ioreg[2]);
284 	Bprint(&stdout, "%s rbase_i\t%8.8luX\n", ctlr->name, t2r4->ioreg[4]);
285 	Bprint(&stdout, "%s rbase_e\t%8.8luX\n", ctlr->name, t2r4->ioreg[5]);
286 	Bprint(&stdout, "%s id\t\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[6]);
287 	Bprint(&stdout, "%s config1\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[7]);
288 	Bprint(&stdout, "%s config2\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[8]);
289 	Bprint(&stdout, "%s sgram\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[9]);
290 	Bprint(&stdout, "%s softsw\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[10]);
291 	Bprint(&stdout, "%s ddc\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[11]);
292 	Bprint(&stdout, "%s vgactl\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[12]);
293 
294 	Bprint(&stdout, "\n");
295 	for(i = 0; i < nelem(t2r4->g); i++)
296 		Bprint(&stdout, "%s g reg0x%2.2uX\t\t%8.8luX\n",
297 			ctlr->name, i*4, t2r4->g[i]);
298 	Bprint(&stdout, "\n");
299 	for(i = 0; i < nelem(t2r4->w); i++)
300 		Bprint(&stdout, "%s w reg0x%2.2uX\t\t%8.8luX\n",
301 			ctlr->name, i*4, t2r4->w[i]);
302 }
303 
304 Ctlr t2r4 = {
305 	"t2r4",				/* name */
306 	snarf,				/* snarf */
307 	options,			/* options */
308 	init,				/* init */
309 	load,				/* load */
310 	dump,				/* dump */
311 };
312 
313 Ctlr t2r4hwgc = {
314 	"t2r4hwgc",			/* name */
315 	0,				/* snarf */
316 	0,				/* options */
317 	0,				/* init */
318 	0,				/* load */
319 	0,				/* dump */
320 };
321