10 * 170/220MHz High Performance Palette DAC.
12 * Assumes hooked up to an S3 Vision96[48].
21 enum { /* index registers */
37 rs2 = vgaxi(Crtx, 0x55);
38 vgaxo(Crtx, 0x55, (rs2 & 0xFC)|0x01);
46 outportb(dacxreg[IndexLo], index & 0xFF);
47 outportb(dacxreg[IndexHi], (index>>8) & 0xFF);
49 return inportb(dacxreg[Data]);
53 rgb524xo(int index, uchar data)
55 outportb(dacxreg[IndexLo], index & 0xFF);
56 outportb(dacxreg[IndexHi], (index>>8) & 0xFF);
58 outportb(dacxreg[Data], data);
64 vgaxo(Crtx, 0x55, rs2);
68 clock(Vga* vga, Ctlr* ctlr)
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;
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);
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);
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);
87 error("%s: pclk %lud out of range\n",
88 ctlr->name, vga->f[0]);
92 init(Vga* vga, Ctlr* ctlr)
98 * Part comes in -170 and -220MHz speed-grades.
101 if(p = strrchr(ctlr->name, '-'))
102 pclk = strtoul(p+1, 0, 0) * 1000000;
105 * If we don't already have a desired pclk,
106 * take it from the mode.
107 * Check it's within range.
110 vga->f[0] = vga->mode->frequency;
112 error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
115 * Determine whether to use clock-doubler or not.
117 if((ctlr->flag & Uclk2) == 0 && vga->mode->z == 8)
118 resyncinit(vga, ctlr, Uclk2, 0);
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.
127 if(vga->mode->z == 8 || (vga->f[0] != VgaFreq0 && vga->f[0] != VgaFreq1)){
129 * Initialise the PLL parameters.
130 * Use internal FS3 fixed-reference divider.
135 else if(vga->f[0] == VgaFreq0)
137 else if(vga->f[0] == VgaFreq1){
146 load(Vga* vga, Ctlr* ctlr)
157 rgb524xo(PLLControl1, 0x00);
158 rgb524xo(Frequency0, 0x24);
159 rgb524xo(Frequency0+1, 0x30);
161 if(val = dbattr(vga->attr, "rgb524refclk")){
162 f = strtol(val, 0, 0);
165 rgb524xo(PLLReference, f/2);
169 * Enable pixel programming and clock divide
172 x = rgb524xi(MiscClock) & ~0x0E;
174 if(ctlr->flag & Uclk2)
176 rgb524xo(MiscClock, x);
178 if(vga->mode->z == 1)
179 rgb524xo(PixelFormat, 0x02);
180 else if(vga->mode->z == 8)
181 rgb524xo(PixelFormat, 0x03);
183 x = rgb524xi(MiscControl1) & ~0x41;
185 rgb524xo(MiscControl1, x);
187 mc2 = rgb524xi(MiscControl2) & ~0x41;
188 vga->crt[0x22] &= ~0x08;
190 rgb524xo(Frequency0+3, vga->d[0]);
191 rgb524xo(PLLControl1, 0x02);
192 rgb524xo(PLLControl2, vga->i[0]);
194 vga->crt[0x22] |= 0x08;
196 rgb524xo(MiscControl2, mc2);
197 vgaxo(Crtx, 0x22, vga->crt[0x22]);
204 dump(Vga*, Ctlr* ctlr)
206 uchar rs2, r, x[256];
208 int df, i, maxf, vcodc, vf;
211 printitem(ctlr->name, "index00");
212 for(i = 0x00; i < 0x0F; i++){
216 printitem(ctlr->name, "index10");
217 for(i = 0x10; i < 0x17; i++){
221 printitem(ctlr->name, "index20");
222 for(i = 0x20; i < 0x30; i++){
226 printitem(ctlr->name, "index30");
227 for(i = 0x30; i < 0x37; i++){
231 printitem(ctlr->name, "index40");
232 for(i = 0x40; i < 0x49; i++){
236 printitem(ctlr->name, "index60");
237 for(i = 0x60; i < 0x63; i++){
241 printitem(ctlr->name, "index70");
242 for(i = 0x70; i < 0x73; i++){
246 printitem(ctlr->name, "index8E");
247 for(i = 0x8E; i < 0x92; i++){
254 * x[0x10] pixel clock frequency selection
255 * 0, 2 for direct programming
256 * x[0x20-0x2F] pixel frequency 0-15
258 printitem(ctlr->name, "refclk");
259 Bprint(&stdout, "%12ud\n", x[PLLReference]*2*1000000);
260 if((i = (x[0x10] & 0x07)) == 0x00 || i == 0x02){
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.
270 for(i = 0; i < maxf; i++){
271 if((r = x[0x20+i]) == 0)
273 sprint(buf, "direct F%X", i);
274 printitem(ctlr->name, buf);
296 Bprint(&stdout, "%12ud\n", vf);