]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/rgb524.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / aux / vga / rgb524.c
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 };