]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/vga/geode.c
abaco: cleanup, handle image/x-icon, don't use backspace as a hotkey, and remove...
[plan9front.git] / sys / src / cmd / aux / vga / geode.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 #include "geode_modes.h"
9
10 enum {
11         Nregs = 28,
12         DC_UNLOCK = 0,
13         DC_GENERAL_CFG,
14         DC_DISPLAY_CFG,
15         DC_ARB_CFG,
16         DC_H_ACTIVE_TIMING = 16,
17         DC_H_BLANK_TIMING,
18         DC_H_SYNC_TIMING,
19         DC_V_ACTIVE_TIMING = 20,
20         DC_V_BLANK_TIMING,
21         DC_V_SYNC_TIMING,
22         DC_FB_ACTIVE,
23         DC_LINE_SIZE = 12,
24         DC_GFX_PITCH,
25         
26         DC_UNLOCK_VALUE = 0x4758,
27         
28         /*  DC_GENERAL_CFG */
29         VGAE = 1<<7,                                    /* VGA enable */
30         DFLE = 1,                                               /* display FIFO enable */
31         
32         /* DC_DISPLAY_CFG */
33         TGEN = 1,                                               /* timing enable */
34         GDEN = 1<<3,                                    /* graphics enable */
35         VDEN = 1<<4,                                    /* video enable */
36         TRUP = 1<<6,                                    /* timing register update */
37         PALB = 1<<25,                                   /* palette bypass */
38         DISP_MODE8 = 0,
39         DISP_MODE16 = 1<<8,
40         DISP_MODE24 = 1<<9,
41         DISP_MODE32 = (1<<8) | (1<<9),
42
43         /* low bandwidth */
44         LBW_GENERAL = 0x9500,
45         LBW_DISPLAY = 0x8000,
46         LBW_ARB = 0x150001,
47         /* average bandwidth */
48         ABW_GENERAL = 0xB600,
49         ABW_DISPLAY = 0x9000,
50         ABW_ARB = 0x160001,
51 };
52
53 typedef struct Geode Geode;
54 struct Geode {
55         ulong *mmio;
56         Pcidev *pci;
57         ulong regs[Nregs];
58         uvlong clock;
59 };
60
61 static void
62 snarf(Vga* vga, Ctlr* ctlr)
63 {
64         Geode *geode;
65         int i;
66
67         if(!vga->private) {
68                 geode = alloc(sizeof(Geode));
69                 geode->pci = vga->pci;
70                 if(geode->pci == nil){
71                         geode->pci = pcimatch(0, 0x1022, 0x2081);
72                         if(!geode->pci) error("%s: not found\n", ctlr->name);
73                 }
74                 vgactlpci(geode->pci);
75                 vgactlw("type", "geode");
76                 geode->mmio = segattach(0, "geodemmio", 0, geode->pci->mem[2].size);
77                 if(geode->mmio == (ulong*)-1) error("%s: can't attach mmio segment\n", ctlr->name);
78                 vga->private = geode;
79         }
80         else geode = vga->private;
81         
82         for(i=0;i<Nregs;i++) geode->regs[i] = geode->mmio[i];
83         geode->clock = rdmsr(0x4C000015);
84
85         vga->crt[43] = vgaxi(Crtx, 43);
86         vga->crt[44] = vgaxi(Crtx, 44);
87         vga->crt[47] = vgaxi(Crtx, 47);
88         vga->crt[48] = vgaxi(Crtx, 48);
89         ctlr->flag |= Fsnarf;
90 }
91
92 static void
93 options(Vga* vga, Ctlr* ctlr)
94 {
95         USED(vga);
96         ctlr->flag |= Foptions;
97 }
98
99 static void
100 init(Vga* vga, Ctlr* ctlr)
101 {
102         Geode *geode;
103         Mode *m;
104         int i, bpp;
105         
106         geode = vga->private;
107         m = vga->mode;
108         m->vbs = m->vrs;
109         m->vbe = m->vre;
110         
111         
112         /* there has to be a better solution */
113         if(m->x < 1024) {
114                         geode->regs[DC_GENERAL_CFG] = LBW_GENERAL;
115                         geode->regs[DC_DISPLAY_CFG] = LBW_DISPLAY;
116                         geode->regs[DC_ARB_CFG] = LBW_ARB;
117         } else {
118                         geode->regs[DC_GENERAL_CFG] = ABW_GENERAL;
119                         geode->regs[DC_DISPLAY_CFG] = ABW_DISPLAY;
120                         geode->regs[DC_ARB_CFG] = ABW_ARB;
121         }
122
123         geode->regs[DC_GENERAL_CFG] |= DFLE;
124         geode->regs[DC_DISPLAY_CFG] |= GDEN | VDEN | TGEN | TRUP | PALB;
125         
126         switch(m->z) {
127                 case 8: bpp = 1; break;
128                 case 15: case 16: bpp = 2; geode->regs[DC_DISPLAY_CFG] |= DISP_MODE16; break;
129                 case 24: bpp = 3; geode->regs[DC_DISPLAY_CFG] |= DISP_MODE24; break;
130                 case 32: bpp = 4; geode->regs[DC_DISPLAY_CFG] |= DISP_MODE32; break;
131                 default: error("%s: unknown bpp value\n", ctlr->name); bpp = 0;
132         }
133         
134         geode->regs[DC_H_ACTIVE_TIMING] = (m->x - 1) | ((m->ht - 1) << 16);
135         geode->regs[DC_H_BLANK_TIMING] = (m->shb - 1) | ((m->ehb - 1) << 16);
136         geode->regs[DC_H_SYNC_TIMING] = (m->shs - 1) | ((m->ehs - 1) << 16);
137         geode->regs[DC_V_ACTIVE_TIMING] = (m->y - 1) | ((m->vt - 1) << 16);
138         geode->regs[DC_V_BLANK_TIMING] = (m->vrs - 1) | ((m->vre - 1) << 16);
139         geode->regs[DC_V_SYNC_TIMING] = (m->vbs - 1) | ((m->vbe - 1) << 16);
140         geode->regs[DC_FB_ACTIVE] = (m->x - 1) | ((m->y - 1) << 16);
141         geode->regs[DC_GFX_PITCH] = geode->regs[DC_LINE_SIZE] = (m->x >> 3) * bpp;
142
143         for(i=0;i<NumModes;i++)
144                 if(geode_modes[i][1] == m->frequency)
145                         goto modefound;
146         error("%s: unknown clock value\n", ctlr->name);
147 modefound:
148         geode->clock = ((uvlong)geode_modes[i][0] << 32);
149         
150         ctlr->flag |= Finit;
151 }
152
153 static void
154 load(Vga* vga, Ctlr* ctlr)
155 {
156         Geode *geode;
157         int i;
158         
159         geode = vga->private;
160         wrmsr(0x4C000015, geode->clock);
161         geode->mmio[DC_UNLOCK] = DC_UNLOCK_VALUE;
162         for(i=4;i<Nregs;i++) geode->mmio[i] = geode->regs[i];
163         for(i=1;i<4;i++) geode->mmio[i] = geode->regs[i];
164         ctlr->flag |= Fload;
165 }
166
167 static void
168 printreg32(ulong u) {
169         printreg((u>>24)&0xFF);
170         printreg((u>>16)&0xFF);
171         printreg((u>>8)&0xFF);
172         printreg(u&0xFF);
173 }
174
175 static void
176 dump(Vga* vga, Ctlr* ctlr)
177 {
178         int i;
179         Geode *geode;
180         
181         geode = vga->private;
182         printitem(ctlr->name, "configuration");
183         for(i=0;i<4;i++) printreg32(geode->regs[i]);
184         printitem(ctlr->name, "memory");
185         for(i=4;i<15;i++) printreg32(geode->regs[i]);
186         printitem(ctlr->name, "timing");
187         for(i=16;i<24;i++) printreg32(geode->regs[i]);
188         printitem(ctlr->name, "cursor");
189         for(i=24;i<28;i++) printreg32(geode->regs[i]);
190
191         printitem(ctlr->name, "ext");
192         printreg(vga->crt[43]);
193         printreg(vga->crt[44]);
194         printreg(vga->crt[47]);
195         printreg(vga->crt[48]);
196         
197         printitem(ctlr->name, "clock");
198         printreg32((geode->clock >> 32) & 0xFFFFFFFF);
199         printreg32(geode->clock & 0xFFFFFFFF);
200 }
201
202 Ctlr geode = {
203         "geode",                                /* name */
204         snarf,                          /* snarf */
205         options,                        /* options */
206         init,                           /* init */
207         load,                           /* load */
208         dump,                           /* dump */
209 };
210
211 Ctlr geodehwgc = {
212         "geodehwgc",
213         0,
214         0,
215         0,
216         0,
217         0,
218 };