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_tlsv12/sys/src/cmd/aux/vga/clgd542x.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
 * Cirrus Logic True Color VGA Family - CL-GD542X.
10
 * Also works for Alpine VGA Family - CL-GD543X.
11
 * Just the basics. BUGS:
12
 *   the added capabilities of the 543X aren't used.
13
 */
14
 
15
typedef struct {
16
	uchar	id;			/* Id */
17
	ulong	vclk;			/* Maximum dot clock */
18
} Gd542x;
19
 
20
static Gd542x family[] = {
21
	{ 0x88,  75000000, },		/* CL-GD5420 */
22
	{ 0x8C,  80000000, },		/* CL-GD5422 */
23
	{ 0x94,  80000000, },		/* CL-GD5424 */
24
	{ 0x90,  80000000, },		/* CL-GD5426 */
25
	{ 0x98,  80000000, },		/* CL-GD5428 */
26
	{ 0x9C,  86000000, },		/* CL-GD5429 */
27
	{ 0xA0,  86000000, },		/* CL-GD5430 */
28
	{ 0xA8,  86000000, },		/* CL-GD5434 */
29
 
30
	{ 0xAC, 135000000, },		/* CL-GD5436 */
31
	{ 0xB8, 135000000, },		/* CL-GD5446 */
32
	{ 0xBC, 135000000, },		/* CL-GD5480 */
33
 
34
	{ 0x30,  80000000, },		/* CL-GD7543 */
35
 
36
	{ 0x00, },
37
};
38
 
39
static Gd542x*
40
identify(Vga* vga, Ctlr* ctlr)
41
{
42
	Gd542x *gd542x;
43
	uchar id;
44
 
45
	id = vga->crt[0x27] & ~0x03;
46
	for(gd542x = &family[0]; gd542x->id; gd542x++){
47
		if(gd542x->id == id)
48
			return gd542x;
49
	}
50
 
51
	error("%s: unknown chip id - 0x%2.2X\n", ctlr->name, vga->crt[0x27]);
52
	return 0;
53
}
54
 
55
static void
56
snarf(Vga* vga, Ctlr* ctlr)
57
{
58
	int i;
59
	Gd542x *gd542x;
60
 
61
	/*
62
	 * Unlock extended registers.
63
	 */
64
	vgaxo(Seqx, 0x06, 0x12);
65
 
66
	/*
67
	 * Save all the registers, even though we'll only
68
	 * change a handful.
69
	 */
70
	for(i = 0x06; i < 0x20; i++)
71
		vga->sequencer[i] = vgaxi(Seqx, i);
72
 
73
	for(i = 0x09; i < 0x3A; i++)
74
		vga->graphics[i] = vgaxi(Grx, i);
75
 
76
	for(i = 0x19; i < 0x1E; i++)
77
		vga->crt[i] = vgaxi(Crtx, i);
78
 
79
	vga->crt[0x27] = vgaxi(Crtx, 0x27);
80
 
81
	/*
82
	 * Hack for Hidden DAC Register. Do 4 dummy reads
83
	 * of Pixmask first.
84
	 */
85
	for(i = 0; i < 4; i++)
86
		vgai(Pixmask);
87
	vga->crt[0x28] = vgai(Pixmask);
88
 
89
	i = 0;
90
	switch(vga->crt[0x27] & ~0x03){
91
 
92
	case 0x88:				/* CL-GD5420 */
93
	case 0x8C:				/* CL-GD5422 */
94
	case 0x94:				/* CL-GD5424 */
95
	case 0x80:				/* CL-GD5425 */
96
	case 0x90:				/* CL-GD5426 */
97
	case 0x98:				/* CL-GD5427 */
98
	case 0x9C:				/* CL-GD5429 */
99
		/*
100
		 * The BIOS leaves the memory size in Seq0A, bits 4 and 3.
101
		 * See Technical Reference Manual Appendix E1, Section 1.3.2.
102
		 *
103
		 * The storage area for the 64x64 cursors is the last 16Kb of
104
		 * display memory.
105
		 */
106
		i = (vga->sequencer[0x0A]>>3) & 0x03;
107
		break;
108
 
109
	case 0xA0:				/* CL-GD5430 */
110
	case 0xA8:				/* CL-GD5434 */
111
	case 0xAC:				/* CL-GD5436 */
112
	case 0xB8:				/* CL-GD5446 */
113
	case 0x30:				/* CL-GD7543 */
114
		/*
115
		 * Attempt to intuit the memory size from the DRAM control
116
		 * register. Minimum is 512KB.
117
		 * If DRAM bank switching is on then there's double.
118
		 */
119
		i = (vga->sequencer[0x0F]>>3) & 0x03;
120
		if(vga->sequencer[0x0F] & 0x80)
121
			i++;
122
 
123
		/*
124
		 * If it's a PCI card, can do linear.
125
		 * Most of the Cirrus chips can do linear addressing with
126
		 * all the different buses, but it can get messy. It's easy
127
		 * to cut PCI on the CLGD543x chips out of the pack.
128
		 */
129
		if(((vga->sequencer[0x17]>>3) & 0x07) == 0x04)
130
			ctlr->flag |= Hlinear;
131
		break;
132
	case 0xBC:				/* CL-GD5480 */
133
		i = 2;				/* 1024 = 256<<2 */
134
		if((vga->sequencer[0x0F] & 0x18) == 0x18){
135
			i <<= 1;		/* 2048 = 256<<3 */
136
			if(vga->sequencer[0x0F] & 0x80)
137
				i <<= 2;	/* 2048 = 256<<4 */
138
		}
139
		if(vga->sequencer[0x17] & 0x80)
140
			i <<= 1;
141
		ctlr->flag |= Hlinear;
142
		break;
143
 
144
	default:				/* uh, ah dunno */
145
		break;
146
	}
147
 
148
	if(vga->linear && (ctlr->flag & Hlinear)){
149
		vga->vmz = 16*1024*1024;
150
		vga->vma = 16*1024*1024;
151
		ctlr->flag |= Ulinear;
152
	}
153
	else
154
		vga->vmz = (256<<i)*1024;
155
 
156
	gd542x = identify(vga, ctlr);
157
	if(vga->f[1] == 0 || vga->f[1] > gd542x->vclk)
158
		vga->f[1] = gd542x->vclk;
159
	ctlr->flag |= Fsnarf;
160
}
161
 
162
void
163
clgd54xxclock(Vga* vga, Ctlr* ctlr)
164
{
165
	int f;
166
	ulong d, dmin, fmin, n, nmin, p;
167
 
168
	trace("%s->init->clgd54xxclock\n", ctlr->name);
169
 
170
	/*
171
	 * Athough the Technical Reference Manual says only a handful
172
	 * of frequencies are tested, it also gives the following formula
173
	 * which can be used to generate any frequency within spec.,
174
	 * including the tested ones.
175
	 *
176
	 * Numerator is 7-bits, denominator 5-bits.
177
	 * Guess from the Technical Reference Manual that
178
	 * The post divisor is 1 for vclk<40MHz.
179
	 *
180
	 * Look for values of n and d and p that give
181
	 * the least error for
182
	 *	vclk = (RefFreq*n)/(d*(1+p));
183
	 *
184
	 * There's nothing like brute force and ignorance.
185
	 */
186
	fmin = vga->f[0];
187
	nmin = 69;
188
	dmin = 24;
189
	if(vga->f[0] >= 40000000)
190
		p = 0;
191
	else
192
		p = 1;
193
	for(n = 1; n < 128; n++){
194
		for(d = 1; d < 32; d++){
195
			f = vga->f[0] - (RefFreq*n)/(d*(1+p));
196
			if(f < 0)
197
				f = -f;
198
			if(f <= fmin){
199
				fmin = f;
200
				nmin = n;
201
				dmin = d;
202
			}
203
		}
204
	}
205
 
206
	vga->f[0] = (RefFreq*nmin)/(dmin*(1+p));
207
	vga->d[0] = dmin;
208
	vga->n[0] = nmin;
209
	vga->p[0] = p;
210
}
211
 
212
void
213
init(Vga* vga, Ctlr* ctlr)
214
{
215
	Mode *mode;
216
	Gd542x *gd542x;
217
	ushort x;
218
 
219
	mode = vga->mode;
220
	gd542x = identify(vga, ctlr);
221
 
222
	if(vga->f[0] == 0)
223
		vga->f[0] = vga->mode->frequency;
224
	if(vga->f[0] > gd542x->vclk)
225
		error("%s: pclk %lud too high (> %lud)\n",
226
			ctlr->name, vga->f[0], gd542x->vclk);
227
 
228
	if(mode->z > 8)
229
		error("%s: depth %d not supported\n", ctlr->name, mode->z);
230
 
231
	/*
232
	 * VCLK3
233
	 */
234
	clgd54xxclock(vga, ctlr);
235
	vga->misc |= 0x0C;
236
	vga->sequencer[0x0E] = vga->n[0];
237
	vga->sequencer[0x1E] = (vga->d[0]<<1)|vga->p[0];
238
 
239
	vga->sequencer[0x07] = 0x00;
240
	if(mode->z == 8)
241
		vga->sequencer[0x07] |= 0x01;
242
 
243
	if(vga->f[0] >= 42000000)
244
		vga->sequencer[0x0F] |= 0x20;
245
	else
246
		vga->sequencer[0x0F] &= ~0x20;
247
 
248
	vga->sequencer[0x16] = (vga->sequencer[0x16] & 0xF0)|0x08;
249
 
250
	/*
251
	 * Overflow bits.
252
	 */
253
	vga->crt[0x1A] = 0x00;
254
	x = mode->ehb>>3;
255
	if(x & 0x40)
256
		vga->crt[0x1A] |= 0x10;
257
	if(x & 0x80)
258
		vga->crt[0x1A] |= 0x20;
259
	if(vga->crt[0x16] & 0x100)
260
		vga->crt[0x1A] |= 0x40;
261
	if(vga->crt[0x16] & 0x200)
262
		vga->crt[0x1A] |= 0x80;
263
	vga->crt[0x1B] = 0x22;
264
	if(vga->crt[0x13] & 0x100)
265
		vga->crt[0x1B] |= 0x10;
266
 
267
	vga->graphics[0x0B] = 0x00;
268
	if(vga->vmz > 1024*1024)
269
		vga->graphics[0x0B] |= 0x20;
270
 
271
	if(mode->interlace == 'v'){
272
		vga->crt[0x19] = vga->crt[0x00]/2;
273
		vga->crt[0x1A] |= 0x01;
274
	}
275
}
276
 
277
static void
278
load(Vga* vga, Ctlr* ctlr)
279
{
280
	vgaxo(Seqx, 0x0E, vga->sequencer[0x0E]);
281
	vgaxo(Seqx, 0x1E, vga->sequencer[0x1E]);
282
	if(ctlr->flag & Ulinear)
283
		vga->sequencer[0x07] |= 0xE0;
284
	vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
285
	vgaxo(Seqx, 0x0F, vga->sequencer[0x0F]);
286
	vgaxo(Seqx, 0x16, vga->sequencer[0x16]);
287
 
288
	if(vga->mode->interlace == 'v')
289
		vgaxo(Crtx, 0x19, vga->crt[0x19]);
290
	vgaxo(Crtx, 0x1A, vga->crt[0x1A]);
291
	vgaxo(Crtx, 0x1B, vga->crt[0x1B]);
292
 
293
	vgaxo(Grx, 0x0B, vga->graphics[0x0B]);
294
}
295
 
296
static void
297
dump(Vga* vga, Ctlr* ctlr)
298
{
299
	int i;
300
	char *name;
301
 
302
	name = ctlr->name;
303
 
304
	printitem(name, "Seq06");
305
	for(i = 0x06; i < 0x20; i++)
306
		printreg(vga->sequencer[i]);
307
 
308
	printitem(name, "Crt19");
309
	for(i = 0x19; i < 0x1E; i++)
310
		printreg(vga->crt[i]);
311
 
312
	printitem(name, "Gr09");
313
	for(i = 0x09; i < 0x3A; i++)
314
		printreg(vga->graphics[i]);
315
 
316
	printitem(name, "Id Hdr");
317
	printreg(vga->crt[0x27]);
318
	printreg(vga->crt[0x28]);
319
}
320
 
321
Ctlr clgd542x = {
322
	"clgd542x",			/* name */
323
	snarf,				/* snarf */
324
	0,				/* options */
325
	init,				/* init */
326
	load,				/* load */
327
	dump,				/* dump */
328
};
329
 
330
Ctlr clgd542xhwgc = {
331
	"clgd542xhwgc",			/* name */
332
	0,				/* snarf */
333
	0,				/* options */
334
	0,				/* init */
335
	0,				/* load */
336
	0,				/* dump */
337
};