]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/rgb524mn.c
abaco: cleanup, handle image/x-icon, don't use backspace as a hotkey, and remove...
[plan9front.git] / sys / src / cmd / aux / vga / rgb524mn.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 RGB52x and compatibles.
10  * High Performance Palette DAC.
11  */
12 uchar (*rgb524mnxi)(Vga*, int);
13 void (*rgb524mnxo)(Vga*, int, uchar);
14
15 enum {                                          /* index registers */
16         MiscClock       = 0x02,
17         SyncControl     = 0x03,
18         HSyncControl    = 0x04,
19         PowerMgmnt      = 0x05,
20         PaletteControl  = 0x07,
21         SYSCLKControl   = 0x08,
22         PixelFormat     = 0x0A,
23         Pixel8Control   = 0x0B,
24         Pixel16Control  = 0x0C,
25         Pixel32Control  = 0x0E,
26         PLLControl1     = 0x10,
27         PLLControl2     = 0x11,
28         SYSCLKN         = 0x15,
29         SYSCLKM         = 0x16,
30         M0              = 0x20,
31         N0              = 0x21,
32         MiscControl1    = 0x70,
33         MiscControl2    = 0x71,
34 };
35
36 static void
37 clock(Vga* vga, Ctlr*, ulong fref, ulong maxpclk)
38 {
39         int d, mind;
40         ulong df, f, m, n, vrf;
41
42         mind = vga->f[0]+1;
43         for(df = 0; df < 4; df++){
44                 for(m = 2; m < 64; m++){
45                         for(n = 2; n < 32; n++){
46                                 f = (fref*(m+65))/n;
47                                 switch(df){
48                                 case 0:
49                                         vrf = fref/(n*2);
50                                         if(vrf > maxpclk/4 || vrf < 1000000)
51                                                 continue;
52                                         f /= 8;
53                                         break;
54                                 case 1:
55                                         vrf = fref/(n*2);
56                                         if(vrf > maxpclk/2 || vrf < 1000000)
57                                                 continue;
58                                         f /= 4;
59                                         break;
60                                 case 2:
61                                         vrf = fref/(n*2);
62                                         if(vrf > maxpclk || vrf < 1000000)
63                                                 continue;
64                                         f /= 2;
65                                         break;
66                                 case 3:
67                                         vrf = fref/n;
68                                         if(vrf > maxpclk || vrf < 1000000)
69                                                 continue;
70                                         break;
71                                 }
72                                 if(f > maxpclk)
73                                         continue;
74
75                                 d = vga->f[0] - f;
76                                 if(d < 0)
77                                         d = -d;
78                                 if(d <= mind){
79                                         vga->m[0] = m;
80                                         vga->n[0] = n;
81                                         vga->d[0] = df;
82                                         mind = d;
83                                 }
84                         }
85                 }
86         }
87 }
88
89 static void
90 init(Vga* vga, Ctlr* ctlr)
91 {
92         ulong fref, maxpclk;
93         char *p, *val;
94
95         /*
96          * Part comes in at least a -170MHz speed-grade.
97          */
98         maxpclk = 170000000;
99         if(p = strrchr(ctlr->name, '-'))
100                 maxpclk = strtoul(p+1, 0, 0) * 1000000;
101
102         /*
103          * If we don't already have a desired pclk,
104          * take it from the mode.
105          * Check it's within range.
106          */
107         if(vga->f[0] == 0)
108                 vga->f[0] = vga->mode->frequency;
109         if(vga->f[0] > maxpclk)
110                 error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
111         if(val = dbattr(vga->attr, "rgb524mnrefclk"))
112                 fref = strtol(val, 0, 0);
113         else
114                 fref = RefFreq;
115
116         /*
117          * Initialise the PLL parameters.
118          * Use m/n pair 2.
119          */
120         clock(vga, ctlr, fref, maxpclk);
121         vga->i[0] = 2;
122
123         ctlr->flag |= Finit;
124 }
125
126 static void
127 load(Vga* vga, Ctlr* ctlr)
128 {
129         char *val;
130         int hsyncdelay, x;
131
132         if(rgb524mnxi == nil && rgb524mnxo == nil)
133                 error("%s->load: no access routines\n", ctlr->name);
134                 
135         /*
136          * Set the m/n values for the desired frequency and
137          * set pixel control to use compatibility mode with
138          * internal frequency select using the specified set
139          * of m/n registers.
140          */
141         rgb524mnxo(vga, M0+vga->i[0]*2, vga->d[0]<<6|vga->m[0]);
142         rgb524mnxo(vga, N0+vga->i[0]*2, vga->n[0]);
143         rgb524mnxo(vga, PLLControl2, vga->i[0]);
144         rgb524mnxo(vga, PLLControl1, 0x03);
145
146         /*
147          * Enable pixel programming in MiscClock;
148          * nothing to do in MiscControl1;
149          * set internal PLL clock and !vga in MiscControl2;
150          */
151         x = rgb524mnxi(vga, MiscClock) & ~0x01;
152         x |= 0x01;
153         rgb524mnxo(vga, MiscClock, x);
154
155         x = rgb524mnxi(vga, MiscControl2) & ~0x41;
156         x |= 0x41;
157         rgb524mnxo(vga, MiscControl2, x);
158
159         /*
160          * Syncs.
161          */
162         x = 0;
163         if(vga->mode->hsync == '+')
164                 x |= 0x10;
165         if(vga->mode->vsync == '+')
166                 x |= 0x20;
167         rgb524mnxo(vga, SyncControl, x);
168         if(val = dbattr(vga->mode->attr, "hsyncdelay"))
169                 hsyncdelay = strtol(val, 0, 0);
170         else switch(vga->mode->z){
171         default:
172         case 8:
173                 hsyncdelay = 1;
174                 break;
175         case 15:
176         case 16:
177                 hsyncdelay = 5;
178                 break;
179         case 32:
180                 hsyncdelay = 7;
181                 break;
182         }
183         rgb524mnxo(vga, HSyncControl, hsyncdelay);
184
185 rgb524mnxo(vga, SYSCLKM, 0x50);
186 rgb524mnxo(vga, SYSCLKN, 0x08);
187 sleep(50);
188 //rgb524mnxo(vga, SYSCLKM, 0x6F);
189 //rgb524mnxo(vga, SYSCLKN, 0x0F);
190 //sleep(500);
191
192         /*
193          * Set the palette for the desired format.
194          * ****NEEDS WORK FOR OTHER THAN 8-BITS****
195          */
196         rgb524mnxo(vga, PaletteControl, 0x00);
197         switch(vga->mode->z){
198         case 8:
199                 rgb524mnxo(vga, PixelFormat, 0x03);
200                 rgb524mnxo(vga, Pixel8Control, 0x00);
201                 break;
202         case 15:
203                 rgb524mnxo(vga, PixelFormat, 0x04);
204                 rgb524mnxo(vga, Pixel16Control, 0xC4);
205         case 16:
206                 rgb524mnxo(vga, PixelFormat, 0x04);
207                 rgb524mnxo(vga, Pixel16Control, 0xC6);
208                 break;
209         case 32:
210                 rgb524mnxo(vga, PixelFormat, 0x06);
211                 rgb524mnxo(vga, Pixel32Control, 0x03);
212                 break;
213         }
214 }
215
216 static void
217 dumpclock(Vga*, Ctlr* ctlr, ulong fref, ulong m, ulong n, char* name)
218 {
219         ulong df, f;
220
221         df = (m>>6) & 0x03;
222         m &= 0x3F;
223         n &= 0x1F;
224         if(m == 0 || n == 0)
225                 return;
226         f = (fref*(m+65))/n;
227         switch(df){
228         case 0:
229                 f /= 8;
230                 break;
231         case 1:
232                 f /= 4;
233                 break;
234         case 2:
235                 f /= 2;
236                 break;
237         case 3:
238                 break;
239         }
240         printitem(ctlr->name, name);
241         Bprint(&stdout, "%12lud\n", f);
242 }
243
244 static void
245 dump(Vga* vga, Ctlr* ctlr)
246 {
247         int i;
248         char *val;
249         uchar x[256];
250         ulong fref, fs;
251
252         if(rgb524mnxi == nil && rgb524mnxo == nil)
253                 error("%s->dump: no access routines\n", ctlr->name);
254
255         printitem(ctlr->name, "index00");
256         for(i = 0x00; i < 0x0F; i++){
257                 x[i] = rgb524mnxi(vga, i);
258                 printreg(x[i]);
259         }
260         printitem(ctlr->name, "index10");
261         for(i = 0x10; i < 0x18; i++){
262                 x[i] = rgb524mnxi(vga, i);
263                 printreg(x[i]);
264         }
265         printitem(ctlr->name, "index20");
266         for(i = 0x20; i < 0x30; i++){
267                 x[i] = rgb524mnxi(vga, i);
268                 printreg(x[i]);
269         }
270         printitem(ctlr->name, "index30");
271         for(i = 0x30; i < 0x39; i++){
272                 x[i] = rgb524mnxi(vga, i);
273                 printreg(x[i]);
274         }
275         printitem(ctlr->name, "index40");
276         for(i = 0x40; i < 0x49; i++){
277                 x[i] = rgb524mnxi(vga, i);
278                 printreg(x[i]);
279         }
280         printitem(ctlr->name, "index60");
281         for(i = 0x60; i < 0x63; i++){
282                 x[i] = rgb524mnxi(vga, i);
283                 printreg(x[i]);
284         }
285         printitem(ctlr->name, "index70");
286         for(i = 0x70; i < 0x73; i++){
287                 x[i] = rgb524mnxi(vga, i);
288                 printreg(x[i]);
289         }
290         printitem(ctlr->name, "index8E");
291         for(i = 0x8E; i < 0x92; i++){
292                 x[i] = rgb524mnxi(vga, i);
293                 printreg(x[i]);
294         }
295
296         if(val = dbattr(vga->attr, "rgb524mnrefclk"))
297                 fref = strtol(val, 0, 0);
298         else
299                 fref = RefFreq;
300         if(!(x[SYSCLKControl] & 0x04))
301                 dumpclock(vga, ctlr, fref, x[0x16], x[0x15], "sysclk");
302         fs = x[PLLControl1] & 0x07;
303         if(fs == 0x01 || fs == 0x03){
304                 if(fs == 0x01)
305                         i = ((vga->misc>>2) & 0x03)*2;
306                 else
307                         i = x[PLLControl2] & 0x07;
308                 dumpclock(vga, ctlr, fref, x[M0+i*2], x[N0+i*2], "pllclk");
309         }
310 }
311
312 Ctlr rgb524mn = {
313         "rgb524mn",                     /* name */
314         0,                              /* snarf */
315         0,                              /* options */
316         init,                           /* init */
317         load,                           /* load */
318         dump,                           /* dump */
319 };