]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/tvp3026.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / cmd / aux / vga / tvp3026.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  * Tvp3026 Viewpoint Video Interface Palette.
10  * Assumes hooked up to an S3 chip of some kind.
11  * Why is register access different from the
12  * Tvp302[05]?
13  */
14 enum {
15         Index           = 0x00,         /* Index register */
16         Data            = 0x0A,         /* Data register */
17
18         Id              = 0x3F,         /* ID Register */
19         Tvp3026         = 0x26,
20 };
21
22 static uchar
23 tvp3026io(uchar reg, uchar data)
24 {
25         uchar crt55;
26
27         crt55 = vgaxi(Crtx, 0x55) & 0xFC;
28         vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
29         vgao(dacxreg[reg & 0x03], data);
30
31         return crt55;
32 }
33
34 static uchar
35 tvp3026i(uchar reg)
36 {
37         uchar crt55, r;
38
39         crt55 = vgaxi(Crtx, 0x55) & 0xFC;
40         vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
41         r = vgai(dacxreg[reg & 0x03]);
42         vgaxo(Crtx, 0x55, crt55);
43
44         return r;
45 }
46
47 uchar
48 tvp3026xi(uchar index)
49 {
50         uchar crt55, r;
51
52         crt55 = tvp3026io(Index, index);
53         vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
54         r = vgai(dacxreg[Data & 0x03]);
55         vgaxo(Crtx, 0x55, crt55);
56
57         return r;
58 }
59
60 static void
61 tvp3026o(uchar reg, uchar data)
62 {
63         uchar crt55;
64
65         crt55 = tvp3026io(reg, data);
66         vgaxo(Crtx, 0x55, crt55);
67 }
68
69 void
70 tvp3026xo(uchar index, uchar data)
71 {
72         uchar crt55;
73
74         crt55 = tvp3026io(Index, index);
75         vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
76         vgao(dacxreg[Data & 0x03], data);
77         vgaxo(Crtx, 0x55, crt55);
78 }
79
80 static void
81 options(Vga*, Ctlr* ctlr)
82 {
83         ctlr->flag |= Hclk2|Hextsid|Henhanced|Foptions;
84 }
85
86 static void
87 init(Vga* vga, Ctlr* ctlr)
88 {
89         ulong grade;
90         char *p;
91
92         /*
93          * Work out the part speed-grade from name. Name can have,
94          * e.g. '-135' on the end  for 135MHz part.
95          */
96         grade = 110000000;
97         if(p = strrchr(ctlr->name, '-'))
98                 grade = strtoul(p+1, 0, 0) * 1000000;
99
100         /*
101          * If we don't already have a desired pclk,
102          * take it from the mode.
103          * Check it's within range.
104          */
105         if(vga->f[0] == 0)
106                 vga->f[0] = vga->mode->frequency;
107         if(vga->f[0] > grade)
108                 error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
109
110         /*
111          * Determine whether to use clock-doubler or not.
112          */
113         if((ctlr->flag & Uclk2) == 0 && vga->mode->z == 8 && vga->f[0] > 85000000)
114                 resyncinit(vga, ctlr, Uclk2, 0);
115
116         ctlr->flag |= Finit;
117 }
118
119 static void
120 load(Vga* vga, Ctlr* ctlr)
121 {
122         uchar x;
123
124         /*
125          * General Control:
126          *      output sync polarity
127          * It's important to set this properly and to turn off the
128          * VGA controller H and V syncs. Can't be set in VGA mode.
129          */
130         x = 0x00;
131         if((vga->misc & 0x40) == 0)
132                 x |= 0x01;
133         if((vga->misc & 0x80) == 0)
134                 x |= 0x02;
135         tvp3026xo(0x1D, x);
136         vga->misc |= 0xC0;
137         vgao(MiscW, vga->misc);
138
139         ctlr->flag |= Fload;
140 }
141
142 static void
143 dump(Vga*, Ctlr* ctlr)
144 {
145         int i;
146         ulong clock[4], f;
147
148         printitem(ctlr->name, "direct");
149         for(i = 0; i < 16; i++)
150                 printreg(tvp3026i(i));
151
152         printitem(ctlr->name, "index");
153         for(i = 0; i < 64; i++)
154                 printreg(tvp3026xi(i));
155
156         printitem(ctlr->name, "PCLK");
157         for(i = 0; i < 3; i++){
158                 tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
159                 printreg(clock[i] = tvp3026xi(0x2D));
160         }
161         f = (RefFreq*(65-clock[1]))/(65-(clock[0] & 0x3F));
162         f >>= clock[2] & 0x03;
163         Bprint(&stdout, "%23ld", f);
164
165         printitem(ctlr->name, "MCLK");
166         for(i = 0; i < 3; i++){
167                 tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
168                 printreg(clock[i] = tvp3026xi(0x2E));
169         }
170         f = (RefFreq*(65-clock[1]))/(65-(clock[0] & 0x3F));
171         f >>= clock[2] & 0x03;
172         Bprint(&stdout, "%23ld", f);
173
174         printitem(ctlr->name, "LCLK");
175         for(i = 0; i < 3; i++){
176                 tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
177                 printreg(clock[i] = tvp3026xi(0x2F));
178         }
179         Bprint(&stdout, "\n");
180 }
181
182 Ctlr tvp3026 = {
183         "tvp3026",                      /* name */
184         0,                              /* snarf */
185         options,                        /* options */
186         init,                           /* init */
187         0,                              /* load */
188         dump,                           /* dump */
189 };