]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/tvp3020.c
abaco: cleanup, handle image/x-icon, don't use backspace as a hotkey, and remove...
[plan9front.git] / sys / src / cmd / aux / vga / tvp3020.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  * Tvp302[056] Viewpoint Video Interface Palette.
10  * Assumes hooked up to an S3 86C928 or S3 Vision964.
11  */
12 enum {
13         Index           = 0x06,         /* Index register */
14         Data            = 0x07,         /* Data register */
15
16         Id              = 0x3F,         /* ID Register */
17         Tvp3020         = 0x20,
18         Tvp3025         = 0x25,
19         Tvp3026         = 0x26,
20 };
21
22 /*
23  * The following two arrays give read (bit 0) and write (bit 1)
24  * permissions on the direct and index registers. Bits 4 and 5
25  * are for the Tvp3025. The Tvp3020 has only 8 direct registers.
26  */
27 static uchar directreg[32] = {
28         0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x33, 0x33,
29         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30         0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
31         0x33, 0x33, 0x11, 0x33, 0x33, 0x33, 0x33, 0x33,
32 };
33
34 static uchar indexreg[64] = {
35         0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00,
36         0x02, 0x02, 0x33, 0x00, 0x00, 0x00, 0x30, 0x30,
37         0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
38         0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x30, 0x00,
39         0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
40         0x33, 0x33, 0x33, 0x33, 0x30, 0x30, 0x30, 0x30,
41         0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
42         0x33, 0x30, 0x33, 0x11, 0x11, 0x11, 0x22, 0x11,
43 };
44
45 /*
46  * Check the index register access is valid.
47  * Return the number of direct registers.
48  */
49 static uchar
50 checkindex(uchar index, uchar access)
51 {
52         uchar crt55;
53         static uchar id;
54
55         if(id == 0){
56                 crt55 = vgaxi(Crtx, 0x55) & 0xFC;
57                 vgaxo(Crtx, 0x55, crt55|((Index>>2) & 0x03));
58                 vgao(dacxreg[Index & 0x03], Id);
59
60                 id = vgai(dacxreg[Data & 0x03]);
61                 vgaxo(Crtx, 0x55, crt55);
62         }
63
64         if(index == 0xFF)
65                 return id;
66
67         access &= 0x03;
68         switch(id){
69
70         case Tvp3020:
71                 break;
72
73         case Tvp3025:
74         case Tvp3026:
75                 access = access<<4;
76                 break;
77
78         default:
79                 Bprint(&stdout, "%s: unknown chip id - 0x%2.2X\n", tvp3020.name, id);
80                 break;
81         }
82
83         if(index > sizeof(indexreg) || (indexreg[index] & access) == 0)
84                 error("%s: bad register index - 0x%2.2X\n", tvp3020.name, index);
85
86         return id;
87 }
88
89 static uchar
90 tvp3020io(uchar reg, uchar data)
91 {
92         uchar crt55;
93
94         crt55 = vgaxi(Crtx, 0x55) & 0xFC;
95         vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
96         vgao(dacxreg[reg & 0x03], data);
97
98         return crt55;
99 }
100
101 uchar
102 tvp3020i(uchar reg)
103 {
104         uchar crt55, r;
105
106         crt55 = vgaxi(Crtx, 0x55) & 0xFC;
107         vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
108         r = vgai(dacxreg[reg & 0x03]);
109         vgaxo(Crtx, 0x55, crt55);
110
111         return r;
112 }
113
114 uchar
115 tvp3020xi(uchar index)
116 {
117         uchar crt55, r;
118
119         checkindex(index, 0x01);
120
121         crt55 = tvp3020io(Index, index);
122         r = vgai(dacxreg[Data & 0x03]);
123         vgaxo(Crtx, 0x55, crt55);
124
125         return r;
126 }
127
128 void
129 tvp3020o(uchar reg, uchar data)
130 {
131         uchar crt55;
132
133         crt55 = tvp3020io(reg, data);
134         vgaxo(Crtx, 0x55, crt55);
135 }
136
137 void
138 tvp3020xo(uchar index, uchar data)
139 {
140         uchar crt55;
141
142         checkindex(index, 0x02);
143
144         crt55 = tvp3020io(Index, index);
145         vgao(dacxreg[Data & 0x03], data);
146         vgaxo(Crtx, 0x55, crt55);
147 }
148
149 static void
150 options(Vga*, Ctlr* ctlr)
151 {
152         ctlr->flag |= Hclk2|Hextsid|Hpvram|Henhanced|Foptions;
153 }
154
155 static void
156 init(Vga* vga, Ctlr* ctlr)
157 {
158         ulong grade;
159         char *p;
160
161         /*
162          * Work out the part speed-grade from name. Name can have,
163          * e.g. '-135' on the end  for 135MHz part.
164          */
165         grade = 110000000;
166         if(p = strrchr(ctlr->name, '-'))
167                 grade = strtoul(p+1, 0, 0) * 1000000;
168
169         /*
170          * If we don't already have a desired pclk,
171          * take it from the mode.
172          * Check it's within range.
173          */
174         if(vga->f[0] == 0)
175                 vga->f[0] = vga->mode->frequency;
176         if(vga->f[0] > grade)
177                 error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
178
179         /*
180          * Determine whether to use clock-doubler or not.
181          */
182         if(vga->f[0] > 85000000){
183                 vga->f[0] /= 2;
184                 resyncinit(vga, ctlr, Uclk2, 0);
185         }
186
187         ctlr->flag |= Finit;
188 }
189
190 static void
191 load(Vga* vga, Ctlr* ctlr)
192 {
193         uchar x;
194
195         /*
196          * Input Clock Selection:
197          *      VGA             CLK0
198          *      enhanced        CLK1
199          * doubled if necessary.
200          */
201         x = 0x00;
202         if(ctlr->flag & Uenhanced)
203                 x |= 0x01;
204         if(ctlr->flag & Uclk2)
205                 x |= 0x10;
206         tvp3020xo(0x1A, x);
207
208         /*
209          * Output Clock Selection:
210          *      VGA             default VGA
211          *      enhanced        RCLK=SCLK=/8, VCLK/4
212          */
213         x = 0x3E;
214         if(ctlr->flag & Uenhanced)
215                 x = 0x53;
216         tvp3020xo(0x1B, x);
217
218         /*
219          * Auxiliary Control:
220          *      default settings - self-clocked, palette graphics, no zoom
221          * Colour Key Control:
222          *      default settings - pointing to palette graphics
223          * Mux Control Register 1:
224          *      pseudo colour
225          */
226         tvp3020xo(0x29, 0x09);
227         tvp3020xo(0x38, 0x10);
228         tvp3020xo(0x18, 0x80);
229
230         /*
231          * Mux Control Register 2:
232          *      VGA             default VGA
233          *      enhanced        8-bpp, 8:1 mux, 64-bit pixel-bus width
234          */
235         x = 0x98;
236         if(ctlr->flag & Uenhanced){
237                 if(vga->mode->z == 8)
238                         x = 0x1C;
239                 else if(vga->mode->z == 1)
240                         x = 0x04;
241         }
242         tvp3020xo(0x19, x);
243
244         /*
245          * General Control:
246          *      output sync polarity
247          * It's important to set this properly and to turn off the
248          * VGA controller H and V syncs. Can't be set in VGA mode.
249          */
250         x = 0x00;
251         if((vga->misc & 0x40) == 0)
252                 x |= 0x01;
253         if((vga->misc & 0x80) == 0)
254                 x |= 0x02;
255         tvp3020xo(0x1D, x);
256         vga->misc |= 0xC0;
257         vgao(MiscW, vga->misc);
258
259         /*
260          * Select the DAC via the General Purpose I/O
261          * Register and Pins.
262          * Guesswork by looking at register dumps.
263          */
264         tvp3020xo(0x2A, 0x1F);
265         if(ctlr->flag & Uenhanced)
266                 x = 0x1D;
267         else
268                 x = 0x1C;
269         tvp3020xo(0x2B, x);
270
271         ctlr->flag |= Fload;
272 }
273
274 static void
275 dump(Vga*, Ctlr* ctlr)
276 {
277         uchar access;
278         int i;
279
280         access = 0x01;
281         if(checkindex(0x00, 0x01) != Tvp3020)
282                 access <<= 4;
283
284         printitem(ctlr->name, "direct");
285         for(i = 0; i < 8; i++){
286                 if(directreg[i] & access)
287                         printreg(tvp3020i(i));
288                 else
289                         printreg(0xFF);
290         }
291
292         printitem(ctlr->name, "index");
293         for(i = 0; i < sizeof(indexreg); i++){
294                 if(indexreg[i] & access)
295                         printreg(tvp3020xi(i));
296                 else
297                         printreg(0xFF);
298         }
299 }
300
301 Ctlr tvp3020 = {
302         "tvp3020",                      /* name */
303         0,                              /* snarf */
304         options,                        /* options */
305         init,                           /* init */
306         load,                           /* load */
307         dump,                           /* dump */
308 };