Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | 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
 * IBM RGB524.
10
 * 170/220MHz High Performance Palette DAC.
11
 *
12
 * Assumes hooked up to an S3 Vision96[48].
13
 */
14
enum {
15
	IndexLo		= 0x00,
16
	IndexHi		= 0x01,
17
	Data		= 0x02,
18
	IndexCtl	= 0x03,
19
};
20
 
21
enum {						/* index registers */
22
	MiscClock	= 0x02,
23
	PixelFormat	= 0x0A,
24
	PLLControl1	= 0x10,
25
	PLLControl2	= 0x11,
26
	PLLReference	= 0x14,
27
	Frequency0	= 0x20,
28
	MiscControl1	= 0x70,
29
	MiscControl2	= 0x71,
30
};
31
 
32
static uchar
33
setrs2(void)
34
{
35
	uchar rs2;
36
 
37
	rs2 = vgaxi(Crtx, 0x55);
38
	vgaxo(Crtx, 0x55, (rs2 & 0xFC)|0x01);
39
 
40
	return rs2;
41
}
42
 
43
static uchar
44
rgb524xi(int index)
45
{
46
	outportb(dacxreg[IndexLo], index & 0xFF);
47
	outportb(dacxreg[IndexHi], (index>>8) & 0xFF);
48
 
49
	return inportb(dacxreg[Data]);
50
}
51
 
52
static void
53
rgb524xo(int index, uchar data)
54
{
55
	outportb(dacxreg[IndexLo], index & 0xFF);
56
	outportb(dacxreg[IndexHi], (index>>8) & 0xFF);
57
 
58
	outportb(dacxreg[Data], data);
59
}
60
 
61
static void
62
restorers2(uchar rs2)
63
{
64
	vgaxo(Crtx, 0x55, rs2);
65
}
66
 
67
static void
68
clock(Vga* vga, Ctlr* ctlr)
69
{
70
	if(vga->f[0] >= 16250000 && vga->f[0] <= 32000000){
71
		vga->f[0] = (vga->f[0]/250000)*250000;
72
		vga->d[0] = (4*vga->f[0])/1000000 - 65;
73
	}
74
	else if(vga->f[0] >= 32500000 && vga->f[0] <= 64000000){
75
		vga->f[0] = (vga->f[0]/500000)*500000;
76
		vga->d[0] = 0x40|((2*vga->f[0])/1000000 - 65);
77
	}
78
	else if(vga->f[0] >= 65000000 && vga->f[0] <= 128000000){
79
		vga->f[0] = (vga->f[0]/1000000)*1000000;
80
		vga->d[0] = 0x80|(vga->f[0]/1000000 - 65);
81
	}
82
	else if(vga->f[0] >= 130000000 && vga->f[0] <= 220000000){
83
		vga->f[0] = (vga->f[0]/2000000)*2000000;
84
		vga->d[0] = 0xC0|((vga->f[0]/2)/1000000 - 65);
85
	}
86
	else
87
		error("%s: pclk %lud out of range\n",
88
			ctlr->name, vga->f[0]);
89
}
90
 
91
static void
92
init(Vga* vga, Ctlr* ctlr)
93
{
94
	ulong pclk;
95
	char *p;
96
 
97
	/*
98
	 * Part comes in -170 and -220MHz speed-grades.
99
	 */
100
	pclk = 170000000;
101
	if(p = strrchr(ctlr->name, '-'))
102
		pclk = strtoul(p+1, 0, 0) * 1000000;
103
 
104
	/*
105
	 * If we don't already have a desired pclk,
106
	 * take it from the mode.
107
	 * Check it's within range.
108
	 */
109
	if(vga->f[0] == 0)
110
		vga->f[0] = vga->mode->frequency;
111
	if(vga->f[0] > pclk)
112
		error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
113
 
114
	/*
115
	 * Determine whether to use clock-doubler or not.
116
	 */
117
	if((ctlr->flag & Uclk2) == 0 && vga->mode->z == 8)
118
		resyncinit(vga, ctlr, Uclk2, 0);
119
 
120
	/*
121
	 * Clock bits. If the desired video clock is
122
	 * one of the two standard VGA clocks it can just be
123
	 * set using bits <3:2> of vga->misc, otherwise we
124
	 * need to programme the PLL.
125
	 */
126
	vga->misc &= ~0x0C;
127
	if(vga->mode->z == 8 || (vga->f[0] != VgaFreq0 && vga->f[0] != VgaFreq1)){
128
		/*
129
		 * Initialise the PLL parameters.
130
		 * Use internal FS3 fixed-reference divider.
131
		 */
132
		clock(vga, ctlr);
133
		vga->i[0] = 0x03;
134
	}
135
	else if(vga->f[0] == VgaFreq0)
136
		vga->i[0] = 0;
137
	else if(vga->f[0] == VgaFreq1){
138
		vga->misc |= 0x04;
139
		vga->i[0] = 1;
140
	}
141
 
142
	ctlr->flag |= Finit;
143
}
144
 
145
static void
146
load(Vga* vga, Ctlr* ctlr)
147
{
148
	uchar mc2, rs2, x;
149
	char *val;
150
	int f;
151
 
152
	rs2 = setrs2();
153
 
154
	/*
155
	 * Set VgaFreq[01].
156
	 */
157
	rgb524xo(PLLControl1, 0x00);
158
	rgb524xo(Frequency0, 0x24);
159
	rgb524xo(Frequency0+1, 0x30);
160
 
161
	if(val = dbattr(vga->attr, "rgb524refclk")){
162
		f = strtol(val, 0, 0);
163
		if(f > 1000000)
164
			f /= 1000000;
165
		rgb524xo(PLLReference, f/2);
166
	}
167
 
168
	/*
169
	 * Enable pixel programming and clock divide
170
	 * factor.
171
	 */
172
	x = rgb524xi(MiscClock) & ~0x0E;
173
	x |= 0x01;
174
	if(ctlr->flag & Uclk2)
175
		x |= 0x02;
176
	rgb524xo(MiscClock, x);
177
 
178
	if(vga->mode->z == 1)
179
		rgb524xo(PixelFormat, 0x02);
180
	else if(vga->mode->z == 8)
181
		rgb524xo(PixelFormat, 0x03);
182
 
183
	x = rgb524xi(MiscControl1) & ~0x41;
184
	x |= 0x01;
185
	rgb524xo(MiscControl1, x);
186
 
187
	mc2 = rgb524xi(MiscControl2) & ~0x41;
188
	vga->crt[0x22] &= ~0x08;
189
	if(vga->i[0] == 3){
190
		rgb524xo(Frequency0+3, vga->d[0]);
191
		rgb524xo(PLLControl1, 0x02);
192
		rgb524xo(PLLControl2, vga->i[0]);
193
		mc2 |= 0x41;
194
		vga->crt[0x22] |= 0x08;
195
	}
196
	rgb524xo(MiscControl2, mc2);
197
	vgaxo(Crtx, 0x22, vga->crt[0x22]);
198
 
199
	restorers2(rs2);
200
	ctlr->flag |= Fload;
201
}
202
 
203
static void
204
dump(Vga*, Ctlr* ctlr)
205
{
206
	uchar rs2, r, x[256];
207
	char buf[32];
208
	int df, i, maxf, vcodc, vf;
209
 
210
	rs2 = setrs2();
211
	printitem(ctlr->name, "index00");
212
	for(i = 0x00; i < 0x0F; i++){
213
		x[i] = rgb524xi(i);
214
		printreg(x[i]);
215
	}
216
	printitem(ctlr->name, "index10");
217
	for(i = 0x10; i < 0x17; i++){
218
		x[i] = rgb524xi(i);
219
		printreg(x[i]);
220
	}
221
	printitem(ctlr->name, "index20");
222
	for(i = 0x20; i < 0x30; i++){
223
		x[i] = rgb524xi(i);
224
		printreg(x[i]);
225
	}
226
	printitem(ctlr->name, "index30");
227
	for(i = 0x30; i < 0x37; i++){
228
		x[i] = rgb524xi(i);
229
		printreg(x[i]);
230
	}
231
	printitem(ctlr->name, "index40");
232
	for(i = 0x40; i < 0x49; i++){
233
		x[i] = rgb524xi(i);
234
		printreg(x[i]);
235
	}
236
	printitem(ctlr->name, "index60");
237
	for(i = 0x60; i < 0x63; i++){
238
		x[i] = rgb524xi(i);
239
		printreg(x[i]);
240
	}
241
	printitem(ctlr->name, "index70");
242
	for(i = 0x70; i < 0x73; i++){
243
		x[i] = rgb524xi(i);
244
		printreg(x[i]);
245
	}
246
	printitem(ctlr->name, "index8E");
247
	for(i = 0x8E; i < 0x92; i++){
248
		x[i] = rgb524xi(i);
249
		printreg(x[i]);
250
	}
251
	restorers2(rs2);
252
 
253
	/*
254
	 * x[0x10]	pixel clock frequency selection
255
	 *		0, 2 for direct programming
256
	 * x[0x20-0x2F]	pixel frequency 0-15
257
	 */
258
	printitem(ctlr->name, "refclk");
259
	Bprint(&stdout, "%12ud\n", x[PLLReference]*2*1000000);
260
	if((i = (x[0x10] & 0x07)) == 0x00 || i == 0x02){
261
		/*
262
		 * Direct programming, external frequency select.
263
		 * F[0-4] are probably tied directly to the 2 clock-select
264
		 * bits in the VGA Misc register.
265
		 */
266
		if(i == 0)
267
			maxf = 4;
268
		else
269
			maxf = 16;
270
		for(i = 0; i < maxf; i++){
271
			if((r = x[0x20+i]) == 0)
272
				continue;
273
			sprint(buf, "direct F%X", i);
274
			printitem(ctlr->name, buf);
275
			df = (r>>6) & 0x03;
276
			vcodc = r & 0x3F;
277
 
278
			vf = 0;
279
			switch(df){
280
			case 0:
281
				vf = (vcodc+65)/4;
282
				break;
283
 
284
			case 1:
285
				vf = (vcodc+65)/2;
286
				break;
287
 
288
			case 2:
289
				vf = (vcodc+65);
290
				break;
291
 
292
			case 3:
293
				vf = (vcodc+65)*2;
294
				break;
295
			}
296
			Bprint(&stdout, "%12ud\n", vf);
297
		}
298
	}
299
}
300
 
301
Ctlr rgb524 = {
302
	"rgb524",			/* name */
303
	0,				/* snarf */
304
	0,				/* options */
305
	init,				/* init */
306
	load,				/* load */
307
	dump,				/* dump */
308
};