xref: /plan9/sys/src/cmd/aux/vga/clgd546x.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  * Laguna Visual Media Accelerators Family CL-GD546x.
10  */
11 typedef struct {
12 	Pcidev*	pci;
13 	uchar*	mmio;
14 	int	mem;
15 
16 	int	format;			/* graphics and video format */
17 	int	threshold;		/* display threshold */
18 	int	tilectrl;		/* tiling control */
19 	int	vsc;			/* vendor specific control */
20 	int	control;		/* control */
21 	int	tilectrl2D3D;		/* tiling control 2D3D */
22 } Laguna;
23 
24 enum {
25 	Format		= 0xC0,		/* graphics and video format */
26 
27 	Threshold	= 0xEA,		/* Display Threshold */
28 
29 	TileCtrl	= 0x2C4,
30 
31 	Vsc		= 0x3FC,	/* Vendor Specific Control (32-bits) */
32 
33 	Control		= 0x402,	/* 2D Control */
34 	TileCtrl2D3D	= 0x407,	/* (8-bits) */
35 };
36 
37 static int
mmio8r(Laguna * laguna,int offset)38 mmio8r(Laguna* laguna, int offset)
39 {
40 	return *(laguna->mmio+offset) & 0xFF;
41 }
42 
43 static void
mmio8w(Laguna * laguna,int offset,int data)44 mmio8w(Laguna* laguna, int offset, int data)
45 {
46 	*(laguna->mmio+offset) = data;
47 }
48 
49 static int
mmio16r(Laguna * laguna,int offset)50 mmio16r(Laguna* laguna, int offset)
51 {
52 	return *((ushort*)(laguna->mmio+offset)) & 0xFFFF;
53 }
54 
55 static void
mmio16w(Laguna * laguna,int offset,int data)56 mmio16w(Laguna* laguna, int offset, int data)
57 {
58 	*((ushort*)(laguna->mmio+offset)) = data;
59 }
60 
61 static int
mmio32r(Laguna * laguna,int offset)62 mmio32r(Laguna* laguna, int offset)
63 {
64 	return *((ulong*)(laguna->mmio+offset));
65 }
66 
67 static void
mmio32w(Laguna * laguna,int offset,int data)68 mmio32w(Laguna* laguna, int offset, int data)
69 {
70 	*((ulong*)(laguna->mmio+offset)) = data;
71 }
72 
73 static void
snarf(Vga * vga,Ctlr * ctlr)74 snarf(Vga* vga, Ctlr* ctlr)
75 {
76 	int f, i;
77 	uchar *mmio;
78 	Pcidev *p;
79 	Laguna *laguna;
80 
81 	/*
82 	 * Save all the registers, even though we'll only
83 	 * change a handful.
84 	 */
85 	for(i = 0x06; i < 0x20; i++)
86 		vga->sequencer[i] = vgaxi(Seqx, i);
87 
88 	for(i = 0x09; i < 0x0C; i++)
89 		vga->graphics[i] = vgaxi(Grx, i);
90 
91 	for(i = 0x19; i < 0x20; i++)
92 		vga->crt[i] = vgaxi(Crtx, i);
93 
94 	if(vga->private == nil){
95 		vga->private = alloc(sizeof(Laguna));
96 		if((p = pcimatch(0, 0x1013, 0)) == nil)
97 			error("%s: not found\n", ctlr->name);
98 		switch(p->did){
99 		case 0xD0:			/* CL-GD5462 */
100 			vga->f[1] = 170000000;
101 			break;
102 		case 0xD4:			/* CL-GD5464 */
103 		case 0xD6:			/* CL-GD5465 */
104 			vga->f[1] = 230000000;
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 clgd546x", 13) != 13)
113 			error("%s: can't set type\n", ctlr->name);
114 		close(f);
115 
116 		mmio = segattach(0, "clgd546xmmio", 0, p->mem[1].size);
117 		if(mmio == (void*)-1)
118 			error("%s: can't attach mmio segment\n", ctlr->name);
119 		laguna = vga->private;
120 		laguna->pci = p;
121 		laguna->mmio = mmio;
122 	}
123 	laguna = vga->private;
124 
125 	laguna->mem = (vga->sequencer[0x14] & 0x07)+1;
126 
127 	laguna->format = mmio16r(laguna, Format);
128 	laguna->threshold = mmio16r(laguna, Threshold);
129 	laguna->tilectrl = mmio16r(laguna, TileCtrl);
130 	laguna->vsc = mmio32r(laguna, Vsc);
131 	laguna->control = mmio16r(laguna, Control);
132 	laguna->tilectrl2D3D = mmio8r(laguna, TileCtrl2D3D);
133 
134 	vga->vma = vga->vmz = laguna->pci->mem[0].size;
135 	ctlr->flag |= Hlinear;
136 
137 	ctlr->flag |= Fsnarf;
138 }
139 
140 static void
init(Vga * vga,Ctlr * ctlr)141 init(Vga* vga, Ctlr* ctlr)
142 {
143 	Mode *mode;
144 	ushort x;
145 	int format, interleave, fetches, nointerleave, notile, pagesize, tiles;
146 	Laguna *laguna;
147 
148 	nointerleave = 1;
149 	notile = 1;
150 	pagesize = 0;
151 
152 	mode = vga->mode;
153 
154 	if(vga->f[0] == 0)
155 		vga->f[0] = vga->mode->frequency;
156 	if(vga->f[0] > vga->f[1])
157 		error("%s: invalid pclk - %lud\n", ctlr->name, vga->f[0]);
158 
159 	if(mode->z > 8)
160 		error("%s: depth %d not supported\n", ctlr->name, mode->z);
161 
162 	/*
163 	 * VCLK3
164 	 */
165 	clgd54xxclock(vga, ctlr);
166 	vga->misc |= 0x0C;
167 	vga->sequencer[0x1E] = vga->n[0];
168 	vga->sequencer[0x0E] = (vga->d[0]<<1)|vga->p[0];
169 
170 	vga->sequencer[0x07] = 0x00;
171 	if(mode->z == 8)
172 		vga->sequencer[0x07] |= 0x01;
173 
174 	vga->crt[0x14] = 0;
175 	vga->crt[0x17] = 0xC3;
176 
177 	/*
178 	 * Overflow bits.
179 	 */
180 	vga->crt[0x1A] = 0x00;
181 	x = mode->ehb>>3;
182 	if(x & 0x40)
183 		vga->crt[0x1A] |= 0x10;
184 	if(x & 0x80)
185 		vga->crt[0x1A] |= 0x20;
186 	if(vga->crt[0x16] & 0x100)
187 		vga->crt[0x1A] |= 0x40;
188 	if(vga->crt[0x16] & 0x200)
189 		vga->crt[0x1A] |= 0x80;
190 	vga->crt[0x1B] = 0x22;
191 	if(vga->crt[0x13] & 0x100)
192 		vga->crt[0x1B] |= 0x10;
193 	vga->crt[0x1D] = 0x00;
194 	if(vga->crt[0x13] & 0x200)
195 		vga->crt[0x1D] |= 0x01;
196 	vga->crt[0x1E] = 0x00;
197 	if(vga->crt[0x10] & 0x400)
198 		vga->crt[0x1E] |= 0x01;
199 	if(vga->crt[0x15] & 0x400)
200 		vga->crt[0x1E] |= 0x02;
201 	if(vga->crt[0x12] & 0x400)
202 		vga->crt[0x1E] |= 0x04;
203 	if(vga->crt[0x06] & 0x400)
204 		vga->crt[0x1E] |= 0x08;
205 	if(vga->crt[0x04] & 0x100)
206 		vga->crt[0x1E] |= 0x10;
207 	if(vga->crt[0x02] & 0x100)
208 		vga->crt[0x1E] |= 0x20;
209 	if(vga->crt[0x01] & 0x100)
210 		vga->crt[0x1E] |= 0x40;
211 	if(vga->crt[0x00] & 0x100)
212 		vga->crt[0x1E] |= 0x80;
213 
214 	vga->graphics[0x0B] = 0x00;
215 	if(vga->vmz > 1024*1024)
216 		vga->graphics[0x0B] |= 0x20;
217 
218 	if(mode->interlace == 'v'){
219 		vga->crt[0x19] = vga->crt[0x00]/2;
220 		vga->crt[0x1A] |= 0x01;
221 	}
222 
223 	if(vga->linear && (ctlr->flag & Hlinear))
224 		ctlr->flag |= Ulinear;
225 
226 	laguna = vga->private;
227 
228 	/*
229 	 * Ignore wide tiles for now, this simplifies things.
230 	 */
231 	if(mode->x <= 640)
232 		tiles = 5;
233 	else if(mode->x <= 1024)
234 		tiles = 8;
235 	else if(mode->x <= 1280)
236 		tiles = 10;
237 	else if(mode->x <= 1664)
238 		tiles = 13;
239 	else if(mode->x <= 2048)
240 		tiles = 16;
241 	else if(mode->x <= 2560)
242 		tiles = 20;
243 	else if(mode->x <= 3228)
244 		tiles = 26;
245 	else
246 		tiles = 32;
247 	fetches = tiles;		/* -1? */
248 
249 	if(nointerleave)
250 		interleave = 0;
251 	else switch(laguna->mem){
252 	default:
253 		interleave = 0;
254 		break;
255 	case 2:
256 		interleave = 1;
257 		break;
258 	case 4:
259 	case 8:
260 		interleave = 2;
261 		break;
262 	}
263 
264 	if(mode->z == 8)
265 		format = 0;
266 	else if(mode->z == 16)
267 		format = (1<<12)|(2<<9);
268 	else if(mode->z == 24)
269 		format = (2<<12)|(2<<9);
270 	else
271 		format = (2<<12)|(2<<9);
272 
273 	//if(ctlr->flag & Ulinear)
274 	//	laguna->vsc |= 0x10000000;
275 	//else
276 		laguna->vsc &= ~0x10000000;
277 	laguna->format = format;
278 	laguna->threshold = (interleave<<14)|(fetches<<8)|0x14;
279 	laguna->tilectrl &= 0x3F;
280 	laguna->tilectrl |= (interleave<<14)|(tiles<<8);
281 	if(!notile)
282 		laguna->tilectrl |= 0x80;
283 	if(pagesize == 1)
284 		laguna->tilectrl |= 0x10;
285 	laguna->tilectrl2D3D = (interleave<<6)|tiles;
286 	laguna->control = 0;
287 	if(notile)
288 		laguna->control |= 0x1000;
289 	if(pagesize == 1)
290 		laguna->control |= 0x0200;
291 }
292 
293 static void
load(Vga * vga,Ctlr *)294 load(Vga* vga, Ctlr*)
295 {
296 	Laguna *laguna;
297 
298 	vgaxo(Seqx, 0x0E, vga->sequencer[0x0E]);
299 	vgaxo(Seqx, 0x1E, vga->sequencer[0x1E]);
300 	vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
301 
302 	if(vga->mode->interlace == 'v')
303 		vgaxo(Crtx, 0x19, vga->crt[0x19]);
304 	vgaxo(Crtx, 0x1A, vga->crt[0x1A]);
305 	vgaxo(Crtx, 0x1B, vga->crt[0x1B]);
306 	vgaxo(Crtx, 0x1D, vga->crt[0x1D]);
307 	vgaxo(Crtx, 0x1E, vga->crt[0x1E]);
308 
309 	vgaxo(Grx, 0x0B, vga->graphics[0x0B]);
310 
311 	laguna = vga->private;
312 	mmio16w(laguna, Format, laguna->format);
313 	mmio32w(laguna, Vsc, laguna->vsc);
314 	mmio16w(laguna, Threshold, laguna->threshold);
315 	mmio16w(laguna, TileCtrl, laguna->tilectrl);
316 	mmio8w(laguna, TileCtrl2D3D, laguna->tilectrl2D3D);
317 	mmio16w(laguna, Control, laguna->control);
318 }
319 
320 static void
dump(Vga * vga,Ctlr * ctlr)321 dump(Vga* vga, Ctlr* ctlr)
322 {
323 	int i;
324 	char *name;
325 	Laguna *laguna;
326 
327 	name = ctlr->name;
328 
329 	printitem(name, "Seq06");
330 	for(i = 0x06; i < 0x20; i++)
331 		printreg(vga->sequencer[i]);
332 
333 	printitem(name, "Crt19");
334 	for(i = 0x19; i < 0x20; i++)
335 		printreg(vga->crt[i]);
336 
337 	printitem(name, "Gr09");
338 	for(i = 0x09; i < 0x0C; i++)
339 		printreg(vga->graphics[i]);
340 
341 	laguna = vga->private;
342 	Bprint(&stdout, "\n");
343 	Bprint(&stdout, "%s mem\t\t%d\n", ctlr->name, laguna->mem*1024*1024);
344 	Bprint(&stdout, "%s Format\t\t%uX\n", ctlr->name, laguna->format);
345 	Bprint(&stdout, "%s Threshold\t\t\t%uX\n",
346 		ctlr->name, laguna->threshold);
347 	Bprint(&stdout, "%s TileCtrl\t\t\t%uX\n", ctlr->name, laguna->tilectrl);
348 	Bprint(&stdout, "%s Vsc\t\t%uX\n", ctlr->name, laguna->vsc);
349 	Bprint(&stdout, "%s Control\t\t%uX\n", ctlr->name, laguna->control);
350 	Bprint(&stdout, "%s TileCtrlC2D3D\t\t%uX\n",
351 		ctlr->name, laguna->tilectrl2D3D);
352 }
353 
354 Ctlr clgd546x = {
355 	"clgd546x",			/* name */
356 	snarf,				/* snarf */
357 	0,				/* options */
358 	init,				/* init */
359 	load,				/* load */
360 	dump,				/* dump */
361 };
362 
363 Ctlr clgd546xhwgc = {
364 	"clgd546xhwgc",			/* name */
365 	0,				/* snarf */
366 	0,				/* options */
367 	0,				/* init */
368 	0,				/* load */
369 	0,				/* dump */
370 };
371