Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_posix/sys/src/cmd/aux/vga/hiqvideo.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
 
5
#include "pci.h"
6
#include "vga.h"
7
 
8
/*
9
 * Chips and Technologies HiQVideo.
10
 * Extensions in the 69000 over the 65550 are not fully taken into account.
11
 * Depths other than 8 are too slow.
12
 */
13
enum {
14
	Frx		= 0x3D0,	/* Flat Panel Extensions Index */
15
	Mrx		= 0x3D2,	/* Multimedia Extensions Index */
16
	Xrx		= 0x3D6,	/* Configuration Extensions Index */
17
};
18
 
19
typedef struct {
20
	Pcidev* pci;
21
 
22
	uchar	fr[256];
23
	uchar	mr[256];
24
	uchar	xr[256];
25
} HiQVideo;
26
 
27
static uchar
28
hiqvideoxi(long port, uchar index)
29
{
30
	uchar data;
31
 
32
	outportb(port, index);
33
	data = inportb(port+1);
34
 
35
	return data;
36
}
37
 
38
static void
39
hiqvideoxo(long port, uchar index, uchar data)
40
{
41
	outportb(port, index);
42
	outportb(port+1, data);
43
}
44
 
45
static void
46
snarf(Vga* vga, Ctlr* ctlr)
47
{
48
	int i;
49
	Pcidev *p;
50
	HiQVideo *hqv;
51
 
52
	if(vga->private == nil){
53
		vga->private = alloc(sizeof(HiQVideo));
54
		hqv = vga->private;
55
		if((p = pcimatch(nil, 0x102C, 0)) == nil)
56
			error("%s: not found\n", ctlr->name);
57
		switch(p->did){
58
		case 0x00C0:		/* 69000 HiQVideo */
59
			vga->f[1] = 135000000;
60
			vga->vmz = 2048*1024;
61
			break;
62
		case 0x00E0:		/* 65550 HiQV32 */
63
		case 0x00E4:		/* 65554 HiQV32 */
64
		case 0x00E5:		/* 65555 HiQV32 */
65
			vga->f[1] = 90000000;
66
			vga->vmz = 2048*1024;
67
			break;
68
		default:
69
			error("%s: DID %4.4uX unsupported\n",
70
				ctlr->name, p->did);
71
		}
72
		hqv->pci = p;
73
	}
74
	hqv = vga->private;
75
 
76
	for(i = 0; i < 0x50; i++)
77
		hqv->fr[i] = hiqvideoxi(Frx, i);
78
	for(i = 0; i < 0x60; i++)
79
		hqv->mr[i] = hiqvideoxi(Mrx, i);
80
	for(i = 0x30; i < 0x80; i++)
81
		vga->crt[i] = vgaxi(Crtx, i);
82
	for(i = 0; i < 0x100; i++)
83
		hqv->xr[i] = hiqvideoxi(Xrx, i);
84
 
85
	switch(hqv->pci->did){
86
	case 0x00C0:			/* 69000 HiQVideo */
87
		vga->f[1] = 135000000;
88
		vga->vmz = 2048*1024;
89
		break;
90
	case 0x00E0:			/* 65550 HiQV32 */
91
	case 0x00E4:			/* 65554 HiQV32 */
92
	case 0x00E5:			/* 65555 HiQV32 */
93
		/*
94
		 * Check VCC to determine max clock.
95
		 * 5V allows a higher rate.
96
		 */
97
		if(hqv->fr[0x0A] & 0x02)
98
			vga->f[1] = 110000000;
99
		else
100
			vga->f[1] = 80000000;
101
		switch((hqv->xr[0x43]>>1) & 0x03){
102
		case 0:
103
			vga->vmz = 1*1024*1024;
104
			break;
105
		case 1:
106
			vga->vmz = 2*1024*1024;
107
			break;
108
		default:
109
			vga->vmz = 16*1024*1024;
110
			break;
111
		}
112
		break;
113
	}
114
 
115
	ctlr->flag |= Fsnarf;
116
}
117
 
118
static void
119
options(Vga*, Ctlr* ctlr)
120
{
121
	ctlr->flag |= Hlinear|Foptions;
122
}
123
 
124
static void
125
clock(Vga* vga, Ctlr* ctlr)
126
{
127
	double f, fmin, fvco, m;
128
	ulong n, nmin, nmax, pd, rd;
129
 
130
	/*
131
	 * Constraints:
132
	 *  1.	1MHz <= Fref <= 60MHz
133
	 *  2.	150KHz <= Fref/(RD*N) <= 2MHz
134
	 *  3.	48MHz < Fvco <= 220MHz
135
	 *  4.	3 <= M <= 1023
136
	 *  5.	3 <= N <= 1023
137
	 */
138
	f = vga->f[0];
139
 
140
	/*
141
	 * Although pd = 0 is valid, things seems more stable
142
	 * starting at 1.
143
	 */
144
	for(pd = 1; pd < 6; pd++){
145
		f = vga->f[0]*(1<<pd);
146
		if(f > 48000000 && f <= 220000000)
147
			break;
148
	}
149
	if(pd >= 6)
150
		error("%s: dclk %lud out of range\n", ctlr->name, vga->f[0]);
151
	vga->p[0] = pd;
152
 
153
	/*
154
	 * The reference divisor has only two possible values, 1 and 4.
155
	 */
156
	fmin = f;
157
	for(rd = 1; rd <= 4; rd += 3){
158
		/*
159
		 * Find the range for n (constraint 2).
160
		 */
161
		for(nmin = 3; nmin <= 1023; nmin++){
162
			if(RefFreq/(rd*nmin) <= 2000000)
163
				break;
164
		}
165
		for(nmax = 1023; nmax >= 3; nmax--){
166
			if(RefFreq/(rd*nmax) >= 150000)
167
				break;
168
		}
169
 
170
		/*
171
		 * Now find the closest match for M and N.
172
		 */
173
		for(n = nmin; n < nmax; n++){
174
			for(m = 3; m <= vga->m[1]; m++){
175
				fvco = (RefFreq*4*m)/(rd*n);
176
				if(fvco < 48000000 || fvco > 220000000)
177
					continue;
178
				fvco -= f;
179
				if(fvco < 0)
180
					fvco = -fvco;
181
				if(fvco < fmin){
182
					fmin = fvco;
183
					vga->m[0] = m;
184
					vga->n[0] = n;
185
					vga->p[0] = pd;
186
					vga->r[0] = rd;
187
				}
188
			}
189
		}
190
	}
191
 
192
}
193
 
194
static void
195
init(Vga* vga, Ctlr* ctlr)
196
{
197
	HiQVideo *hqv;
198
 
199
	hqv = vga->private;
200
 
201
	if(vga->f[0] == 0)
202
		vga->f[0] = vga->mode->frequency;
203
	vga->misc &= ~0x0C;
204
	hqv->fr[0x03] &= ~0x0C;
205
 
206
	switch(vga->mode->z){
207
	case 8:
208
	case 16:
209
	case 32:
210
		break;
211
	default:
212
		error("depth %d not supported\n", vga->mode->z);
213
	}
214
 
215
	/*
216
	 * FR[0x01] == 1 for CRT, 2 for LCD.
217
	 * Don't programme the clock if it's an LCD.
218
	 */
219
	if((hqv->fr[0x01] & 0x03) == 0x02){
220
		vga->misc |= 0x08;
221
		hqv->fr[0x03] |= 0x08;
222
	}
223
	else{
224
		/*
225
		 * Clock bits. If the desired video clock is
226
		 * one of the two standard VGA clocks it can just be
227
		 * set using bits <3:2> of vga->misc or Fr03,
228
		 * otherwise the DCLK PLL needs to be programmed.
229
		 */
230
		if(vga->f[0] == VgaFreq0){
231
			/* nothing to do */;
232
		}
233
		else if(vga->f[0] == VgaFreq1){
234
			vga->misc |= 0x04;
235
			hqv->fr[0x03] |= 0x04;
236
		}
237
		else{
238
			if(vga->f[0] > vga->f[1])
239
				error("%s: invalid dclk - %lud\n",
240
					ctlr->name, vga->f[0]);
241
 
242
			if((hqv->fr[0x01] & 0x03) != 0x02){
243
				vga->m[1] = 1023;
244
				clock(vga, ctlr);
245
				hqv->xr[0xC8] = (vga->m[0]-2) & 0xFF;
246
				hqv->xr[0xCA] = ((vga->m[0]-2) & 0x300)>>8;
247
				hqv->xr[0xC9] = (vga->n[0]-2) & 0xFF;
248
				hqv->xr[0xCA] |= ((vga->n[0]-2) & 0x300)>>4;
249
				hqv->xr[0xCB] = (vga->p[0]<<4)|(vga->r[0] == 1);
250
			}
251
			vga->misc |= 0x08;
252
			hqv->fr[0x03] |= 0x08;
253
		}
254
	}
255
 
256
	if(vga->mode->y >= 480)
257
		vga->misc &= ~0xC0;
258
 
259
	/*
260
	 * 10 bits should be enough, but set the extended mode anyway.
261
	 */
262
	hqv->xr[0x09] |= 0x01;
263
	vga->crt[0x30] = ((vga->mode->vt-2)>>8) & 0x0F;
264
	vga->crt[0x31] = ((vga->mode->y-1)>>8) & 0x0F;
265
	vga->crt[0x32] = (vga->mode->vrs>>8) & 0x0F;
266
	vga->crt[0x33] = (vga->mode->vrs>>8) & 0x0F;
267
	vga->crt[0x38] = (((vga->mode->ht>>3)-5)>>8) & 0x01;
268
	vga->crt[0x3C] = (vga->mode->ehb>>3) & 0xC0;
269
	vga->crt[0x41] = (vga->crt[0x13]>>8) & 0x0F;
270
	vga->crt[0x40] = 0x80;
271
 
272
	hqv->xr[0x40] |= 0x03;
273
	hqv->xr[0x80] |= 0x10;
274
	hqv->xr[0x81] &= ~0x0F;
275
	switch(vga->mode->z){
276
	case 8:
277
		hqv->xr[0x81] |= 0x12;
278
		break;
279
	case 16:
280
		hqv->xr[0x81] |= 0x15;
281
		break;
282
	case 32:
283
		hqv->xr[0x81] |= 0x16;
284
		break;
285
	}
286
 
287
	hqv->xr[0x0A] = 0x01;
288
	if(vga->linear && (ctlr->flag & Hlinear))
289
		ctlr->flag |= Ulinear;
290
 
291
	vga->attribute[0x11] = 0;
292
 
293
	ctlr->flag |= Finit;
294
}
295
 
296
static void
297
load(Vga* vga, Ctlr* ctlr)
298
{
299
	HiQVideo *hqv;
300
 
301
	hqv = vga->private;
302
 
303
	hiqvideoxo(Xrx, 0x0E, 0x00);
304
	while((vgai(Status1) & 0x08) == 0x08)
305
		;
306
	while((vgai(Status1) & 0x08) == 0)
307
		;
308
	vgaxo(Seqx, 0x07, 0x00);
309
 
310
	/*
311
	 * Set the clock if necessary.
312
	 */
313
	if((vga->misc & 0x0C) == 0x08 && (hqv->fr[0x01] & 0x03) != 0x02){
314
		vgao(MiscW, vga->misc & ~0x0C);
315
		hiqvideoxo(Frx, 0x03, hqv->fr[0x03] & ~0x0C);
316
 
317
		hiqvideoxo(Xrx, 0xC8, hqv->xr[0xC8]);
318
		hiqvideoxo(Xrx, 0xC9, hqv->xr[0xC9]);
319
		hiqvideoxo(Xrx, 0xCA, hqv->xr[0xCA]);
320
		hiqvideoxo(Xrx, 0xCB, hqv->xr[0xCB]);
321
	}
322
	hiqvideoxo(Frx, 0x03, hqv->fr[0x03]);
323
	vgao(MiscW, vga->misc);
324
 
325
	hiqvideoxo(Xrx, 0x09, hqv->xr[0x09]);
326
	vgaxo(Crtx, 0x30, vga->crt[0x30]);
327
	vgaxo(Crtx, 0x31, vga->crt[0x31]);
328
	vgaxo(Crtx, 0x32, vga->crt[0x32]);
329
	vgaxo(Crtx, 0x33, vga->crt[0x33]);
330
	vgaxo(Crtx, 0x38, vga->crt[0x38]);
331
	vgaxo(Crtx, 0x3C, vga->crt[0x3C]);
332
	vgaxo(Crtx, 0x41, vga->crt[0x41]);
333
	vgaxo(Crtx, 0x40, vga->crt[0x40]);
334
 
335
	hiqvideoxo(Xrx, 0x40, hqv->xr[0x40]);
336
	hiqvideoxo(Xrx, 0x80, hqv->xr[0x80]);
337
	hiqvideoxo(Xrx, 0x81, hqv->xr[0x81]);
338
	if(ctlr->flag & Ulinear){
339
		hqv->xr[0x05] = vga->vmb>>16;
340
		hqv->xr[0x06] = vga->vmb>>24;
341
		hiqvideoxo(Xrx, 0x05, hqv->xr[0x05]);
342
		hiqvideoxo(Xrx, 0x06, hqv->xr[0x06]);
343
		hqv->xr[0x0A] = 0x02;
344
	}
345
	hiqvideoxo(Xrx, 0x0A, hqv->xr[0x0A]);
346
 
347
	ctlr->flag |= Fload;
348
}
349
 
350
static ulong
351
dumpmclk(uchar data[4])
352
{
353
	double f, m, n;
354
	int pds, rds;
355
 
356
	m = data[0] & 0x7F;
357
	n = data[1] & 0x7F;
358
	pds = 1<<((data[2] & 0x70)>>4);
359
	if(data[2] & 0x01)
360
		rds = 1;
361
	else
362
		rds = 4;
363
	f = (RefFreq*4*(m+2))/(rds*(n+2));
364
	f /= pds;
365
 
366
	return f;
367
}
368
 
369
static ulong
370
dumpvclk(uchar data[4])
371
{
372
	double f, m, n;
373
	int pds, rds;
374
 
375
	m = ((data[2] & 0x03)<<8)|data[0];
376
	n = (((data[2] & 0x30)>>4)<<8)|data[1];
377
	pds = 1<<((data[3] & 0x70)>>4);
378
	if(data[3] & 0x01)
379
		rds = 1;
380
	else
381
		rds = 4;
382
	f = (RefFreq*4*(m+2))/(rds*(n+2));
383
	f /= pds;
384
 
385
	return f;
386
}
387
 
388
static void
389
dump(Vga* vga, Ctlr* ctlr)
390
{
391
	int i;
392
	char *name;
393
	HiQVideo *hqv;
394
 
395
	name = ctlr->name;
396
	hqv = vga->private;
397
 
398
	printitem(name, "Fr00");
399
	for(i = 0; i < 0x50; i++)
400
		printreg(hqv->fr[i]);
401
	printitem(name, "Mr00");
402
	for(i = 0; i < 0x60; i++)
403
		printreg(hqv->mr[i]);
404
	printitem(name, "Crt30");
405
	for(i = 0x30; i < 0x80; i++)
406
		printreg(vga->crt[i]);
407
	printitem(name, "Xr00");
408
	for(i = 0; i < 0x100; i++)
409
		printreg(hqv->xr[i]);
410
 
411
	printitem(ctlr->name, "CLK0");
412
	for(i = 0; i < 4; i++)
413
		printreg(hqv->xr[0xC0+i]);
414
	Bprint(&stdout, "%23ld", dumpvclk(&hqv->xr[0xC0]));
415
	printitem(ctlr->name, "CLK1");
416
	for(i = 0; i < 4; i++)
417
		printreg(hqv->xr[0xC4+i]);
418
	Bprint(&stdout, "%23ld", dumpvclk(&hqv->xr[0xC4]));
419
	printitem(ctlr->name, "CLK2");
420
	for(i = 0; i < 4; i++)
421
		printreg(hqv->xr[0xC8+i]);
422
	Bprint(&stdout, "%23ld", dumpvclk(&hqv->xr[0xC8]));
423
	printitem(ctlr->name, "MCLK");
424
	for(i = 0; i < 4; i++)
425
		printreg(hqv->xr[0xCC+i]);
426
	Bprint(&stdout, "%23ld", dumpmclk(&hqv->xr[0xCC]));
427
 
428
	printitem(ctlr->name, "m n pd rd");
429
	Bprint(&stdout, "%9ld %8ld       - %8ld %8ld\n",
430
		vga->m[0], vga->n[0], vga->p[0], vga->r[0]);
431
}
432
 
433
Ctlr hiqvideo = {
434
	"hiqvideo",			/* name */
435
	snarf,				/* snarf */
436
	options,			/* options */
437
	init,				/* init */
438
	load,				/* load */
439
	dump,				/* dump */
440
};
441
 
442
Ctlr hiqvideohwgc = {
443
	"hiqvideohwgc",			/* name */
444
	0,				/* snarf */
445
	0,				/* options */
446
	0,				/* init */
447
	0,				/* load */
448
	0,				/* dump */
449
};