]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/ics534x.c
abaco: cleanup, handle image/x-icon, don't use backspace as a hotkey, and remove...
[plan9front.git] / sys / src / cmd / aux / vga / ics534x.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  * ICS534x GENDAC.
10  * For now assumed to be hooked to either a Tseng Labs ET4000-W32p
11  * (Hercules Dynamite Power, the Hercules generates RS2 using CLK3)
12  * or an ARK2000pv (Diamond Stealth64 Graphics 2001).
13  */
14 static uchar
15 setrs2(Vga* vga, Ctlr* ctlr)
16 {
17         uchar rs2;
18
19         rs2 = 0;
20         if(strncmp(vga->ctlr->name, "et4000-w32", 10) == 0){
21                 rs2 = vgaxi(Crtx, 0x31);
22                 vgaxo(Crtx, 0x31, 0x40|rs2);
23         }
24         else if(strncmp(vga->ctlr->name, "ark2000pv", 9) == 0){
25                 rs2 = vgaxi(Seqx, 0x1C);
26                 vgaxo(Seqx, 0x1C, 0x80|rs2);
27         }
28         else
29                 error("%s: not configured for %s\n", vga->ctlr->name, ctlr->name);
30
31         return rs2;
32 }
33
34 static void
35 restorers2(Vga* vga, uchar rs2)
36 {
37         if(strncmp(vga->ctlr->name, "et4000-w32", 10) == 0)
38                 vgaxo(Crtx, 0x31, rs2);
39         else if(strncmp(vga->ctlr->name, "ark2000pv", 9) == 0)
40                 vgaxo(Seqx, 0x1C, rs2);
41 }
42
43 static void
44 options(Vga*, Ctlr* ctlr)
45 {
46         ctlr->flag |= Hpclk2x8|Foptions;
47 }
48
49 static void
50 clock(Vga* vga, Ctlr* ctlr)
51 {
52         ulong f, m, n, r;
53         double fmin, fmax, t, tok;
54
55         /*
56          * The PLL frequency is defined by:
57          *                  (M+2)
58          *       Fout = ------------ x Fref
59          *              (N+2) x 2**R
60          * where M, N and R have the following contraints:
61          * 1)        2MHz < Fref < 32MHz
62          * 2)               Fref
63          *         600KHz < ----- <= 8Mhz
64          *                  (N+2)
65          * 3)           (M+2) x Fref
66          *     60MHz <= ------------ <= 270MHz
67          *                  (N+2)
68          * 4) Fout < 135MHz
69          * 5) 1 <= M <= 127, 1 <= N <= 31, 0 <= R <= 3
70          *
71          * First determine R by finding the highest value
72          * for which
73          *            2**R x Fout <= 270Mhz
74          * The datasheet says that if the multiplexed 16-bit
75          * pseudo-colour mode is used then N2 (vga->r) must
76          * be 2.
77          */
78         if(ctlr->flag & Upclk2x8)
79                 vga->r[0] = 2;
80         else{
81                 vga->r[0] = 4;
82                 for(r = 0; r <= 3; r++){
83                         f = vga->f[0]*(1<<r);
84                         if(60000000 < f && f <= 270000000)
85                                 vga->r[0] = r;
86                 }
87                 if(vga->r[0] > 3)
88                         error("%s: pclk %lud out of range\n",
89                                 ctlr->name, vga->f[0]);
90         }
91
92         /*
93          * Now find the closest match for M and N.
94          * Lower values of M and N give better noise rejection.
95          */
96         fmin = vga->f[0]*0.995;
97         fmax = vga->f[0]*1.005;
98         tok = 0.0;
99         for(n = 31; n >= 1; n--){
100                 t = RefFreq/(n+2);
101                 if(600000 >= t || t > 8000000)
102                         continue;
103
104                 t = vga->f[0]*(n+2)*(1<<vga->r[0]);
105                 t /= RefFreq;
106                 m = (t+0.5) - 2;
107                 if(m > 127)
108                         continue;
109
110                 t = (m+2)*RefFreq;
111                 t /= (n+2)*(1<<vga->r[0]);
112
113                 if(fmin <= t && t < fmax){
114                         vga->m[0] = m;
115                         vga->n[0] = n;
116                         tok = t;
117                 }
118         }
119
120         if(tok == 0.0)
121                 error("%s: pclk %lud out of range\n", ctlr->name, vga->f[0]);
122 }
123
124 static void
125 init(Vga* vga, Ctlr* ctlr)
126 {
127         ulong pclk;
128         char *p;
129
130         /*
131          * Part comes in -135, -110 and -80MHz speed-grades.
132          */
133         pclk = 80000000;
134         if(p = strrchr(ctlr->name, '-'))
135                 pclk = strtoul(p+1, 0, 0) * 1000000;
136
137         /*
138          * If we don't already have a desired pclk,
139          * take it from the mode.
140          * Check it's within range.
141          */
142         if(vga->f[0] == 0)
143                 vga->f[0] = vga->mode->frequency;
144         if(vga->f[0] > pclk)
145                 error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
146
147         /*
148          * Determine whether to use 2x8-bit mode or not.
149          * If yes and the clock has already been initialised,
150          * initialise it again.
151          */
152         if(vga->ctlr && (vga->ctlr->flag & Hpclk2x8) && vga->mode->z == 8 && vga->f[0] >= pclk/2){
153                 vga->f[0] /= 2;
154                 resyncinit(vga, ctlr, Upclk2x8, 0);
155         }
156
157         /*
158          * Clock bits. If the desired video clock is
159          * one of the two standard VGA clocks it can just be
160          * set using bits <3:2> of vga->misc, otherwise we
161          * need to programme the DCLK PLL.
162          */
163         vga->misc &= ~0x0C;
164         if(vga->f[0] == VgaFreq0)
165                 vga->i[0] = 0;
166         else if(vga->f[0] == VgaFreq1){
167                 vga->misc |= 0x04;
168                 vga->i[0] = 1;
169         }
170         else{
171                 /*
172                  * Initialise the PLL parameters.
173                  * Use CLK0 f7 internal clock (there are only 3
174                  * clock-select bits).
175                  */
176                 clock(vga, ctlr);
177                 vga->i[0] = 0x07;
178         }
179
180         ctlr->flag |= Finit;
181 }
182
183 static void
184 load(Vga* vga, Ctlr* ctlr)
185 {
186         uchar rs2, mode, pll;
187
188         rs2 = setrs2(vga, ctlr);
189
190         /*
191          * Put the chip into snooze mode,
192          * colour mode 0.
193          */
194         mode = 0x00;
195         outportb(Pixmask, 0x01);
196
197         if(ctlr->flag & Upclk2x8)
198                 mode = 0x10;
199
200         /*
201          * If necessary, set the PLL parameters for CLK0 f7
202          * and make sure the PLL control register selects the
203          * correct clock. Preserve the memory clock setting.
204          */
205         outportb(PaddrR, 0x0E);
206         pll = inportb(Pdata) & 0x10;
207         if(vga->i[0] == 0x07){
208                 outportb(PaddrW, vga->i[0]);
209                 outportb(Pdata, vga->m[0]);
210                 outportb(Pdata, (vga->r[0]<<5)|vga->n[0]);
211                 pll |= 0x27;
212         }
213         outportb(PaddrW, 0x0E);
214         outportb(Pdata, pll);
215         outportb(Pixmask, mode);
216
217         restorers2(vga, rs2);
218         ctlr->flag |= Fload;
219 }
220
221 static void
222 dump(Vga* vga, Ctlr* ctlr)
223 {
224         int i;
225         uchar rs2, m, n;
226         char buf[32];
227         ulong f;
228
229         rs2 = setrs2(vga, ctlr);
230
231         printitem(ctlr->name, "command");
232         printreg(inportb(Pixmask));
233
234         outportb(PaddrR, 0x00);
235         for(i = 0; i < 0x0E; i++){
236                 sprint(buf, "f%X m n", i);
237                 printitem(ctlr->name, buf);
238                 m = inportb(Pdata);
239                 printreg(m);
240                 n = inportb(Pdata);
241                 printreg(n);
242
243                 f = 14318180*(m+2);
244                 f /= (n & 0x1F)+2;
245                 f /= 1<<((n>>5) & 0x03);
246                 Bprint(&stdout, "%12lud", f);
247         }
248         printitem(ctlr->name, "control");
249         printreg(inportb(Pdata));
250
251         restorers2(vga, rs2);
252 }
253
254 Ctlr ics534x = {
255         "ics534x",                      /* name */
256         0,                              /* snarf */
257         options,                        /* options */
258         init,                           /* init */
259         load,                           /* load */
260         dump,                           /* dump */
261 };