1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #include "pci.h"
6 #include "vga.h"
7
8 /*
9 * Laguna Visual Media Accelerators Family CL-GD546x.
10 */
11 typedef struct {
12 Pcidev* pci;
13 uchar* mmio;
14 int mem;
15
16 int format; /* graphics and video format */
17 int threshold; /* display threshold */
18 int tilectrl; /* tiling control */
19 int vsc; /* vendor specific control */
20 int control; /* control */
21 int tilectrl2D3D; /* tiling control 2D3D */
22 } Laguna;
23
24 enum {
25 Format = 0xC0, /* graphics and video format */
26
27 Threshold = 0xEA, /* Display Threshold */
28
29 TileCtrl = 0x2C4,
30
31 Vsc = 0x3FC, /* Vendor Specific Control (32-bits) */
32
33 Control = 0x402, /* 2D Control */
34 TileCtrl2D3D = 0x407, /* (8-bits) */
35 };
36
37 static int
mmio8r(Laguna * laguna,int offset)38 mmio8r(Laguna* laguna, int offset)
39 {
40 return *(laguna->mmio+offset) & 0xFF;
41 }
42
43 static void
mmio8w(Laguna * laguna,int offset,int data)44 mmio8w(Laguna* laguna, int offset, int data)
45 {
46 *(laguna->mmio+offset) = data;
47 }
48
49 static int
mmio16r(Laguna * laguna,int offset)50 mmio16r(Laguna* laguna, int offset)
51 {
52 return *((ushort*)(laguna->mmio+offset)) & 0xFFFF;
53 }
54
55 static void
mmio16w(Laguna * laguna,int offset,int data)56 mmio16w(Laguna* laguna, int offset, int data)
57 {
58 *((ushort*)(laguna->mmio+offset)) = data;
59 }
60
61 static int
mmio32r(Laguna * laguna,int offset)62 mmio32r(Laguna* laguna, int offset)
63 {
64 return *((ulong*)(laguna->mmio+offset));
65 }
66
67 static void
mmio32w(Laguna * laguna,int offset,int data)68 mmio32w(Laguna* laguna, int offset, int data)
69 {
70 *((ulong*)(laguna->mmio+offset)) = data;
71 }
72
73 static void
snarf(Vga * vga,Ctlr * ctlr)74 snarf(Vga* vga, Ctlr* ctlr)
75 {
76 int f, i;
77 uchar *mmio;
78 Pcidev *p;
79 Laguna *laguna;
80
81 /*
82 * Save all the registers, even though we'll only
83 * change a handful.
84 */
85 for(i = 0x06; i < 0x20; i++)
86 vga->sequencer[i] = vgaxi(Seqx, i);
87
88 for(i = 0x09; i < 0x0C; i++)
89 vga->graphics[i] = vgaxi(Grx, i);
90
91 for(i = 0x19; i < 0x20; i++)
92 vga->crt[i] = vgaxi(Crtx, i);
93
94 if(vga->private == nil){
95 vga->private = alloc(sizeof(Laguna));
96 if((p = pcimatch(0, 0x1013, 0)) == nil)
97 error("%s: not found\n", ctlr->name);
98 switch(p->did){
99 case 0xD0: /* CL-GD5462 */
100 vga->f[1] = 170000000;
101 break;
102 case 0xD4: /* CL-GD5464 */
103 case 0xD6: /* CL-GD5465 */
104 vga->f[1] = 230000000;
105 break;
106 default:
107 error("%s: not found\n", ctlr->name);
108 }
109
110 if((f = open("#v/vgactl", OWRITE)) < 0)
111 error("%s: can't open vgactl\n", ctlr->name);
112 if(write(f, "type clgd546x", 13) != 13)
113 error("%s: can't set type\n", ctlr->name);
114 close(f);
115
116 mmio = segattach(0, "clgd546xmmio", 0, p->mem[1].size);
117 if(mmio == (void*)-1)
118 error("%s: can't attach mmio segment\n", ctlr->name);
119 laguna = vga->private;
120 laguna->pci = p;
121 laguna->mmio = mmio;
122 }
123 laguna = vga->private;
124
125 laguna->mem = (vga->sequencer[0x14] & 0x07)+1;
126
127 laguna->format = mmio16r(laguna, Format);
128 laguna->threshold = mmio16r(laguna, Threshold);
129 laguna->tilectrl = mmio16r(laguna, TileCtrl);
130 laguna->vsc = mmio32r(laguna, Vsc);
131 laguna->control = mmio16r(laguna, Control);
132 laguna->tilectrl2D3D = mmio8r(laguna, TileCtrl2D3D);
133
134 vga->vma = vga->vmz = laguna->pci->mem[0].size;
135 ctlr->flag |= Hlinear;
136
137 ctlr->flag |= Fsnarf;
138 }
139
140 static void
init(Vga * vga,Ctlr * ctlr)141 init(Vga* vga, Ctlr* ctlr)
142 {
143 Mode *mode;
144 ushort x;
145 int format, interleave, fetches, nointerleave, notile, pagesize, tiles;
146 Laguna *laguna;
147
148 nointerleave = 1;
149 notile = 1;
150 pagesize = 0;
151
152 mode = vga->mode;
153
154 if(vga->f[0] == 0)
155 vga->f[0] = vga->mode->frequency;
156 if(vga->f[0] > vga->f[1])
157 error("%s: invalid pclk - %lud\n", ctlr->name, vga->f[0]);
158
159 if(mode->z > 8)
160 error("%s: depth %d not supported\n", ctlr->name, mode->z);
161
162 /*
163 * VCLK3
164 */
165 clgd54xxclock(vga, ctlr);
166 vga->misc |= 0x0C;
167 vga->sequencer[0x1E] = vga->n[0];
168 vga->sequencer[0x0E] = (vga->d[0]<<1)|vga->p[0];
169
170 vga->sequencer[0x07] = 0x00;
171 if(mode->z == 8)
172 vga->sequencer[0x07] |= 0x01;
173
174 vga->crt[0x14] = 0;
175 vga->crt[0x17] = 0xC3;
176
177 /*
178 * Overflow bits.
179 */
180 vga->crt[0x1A] = 0x00;
181 x = mode->ehb>>3;
182 if(x & 0x40)
183 vga->crt[0x1A] |= 0x10;
184 if(x & 0x80)
185 vga->crt[0x1A] |= 0x20;
186 if(vga->crt[0x16] & 0x100)
187 vga->crt[0x1A] |= 0x40;
188 if(vga->crt[0x16] & 0x200)
189 vga->crt[0x1A] |= 0x80;
190 vga->crt[0x1B] = 0x22;
191 if(vga->crt[0x13] & 0x100)
192 vga->crt[0x1B] |= 0x10;
193 vga->crt[0x1D] = 0x00;
194 if(vga->crt[0x13] & 0x200)
195 vga->crt[0x1D] |= 0x01;
196 vga->crt[0x1E] = 0x00;
197 if(vga->crt[0x10] & 0x400)
198 vga->crt[0x1E] |= 0x01;
199 if(vga->crt[0x15] & 0x400)
200 vga->crt[0x1E] |= 0x02;
201 if(vga->crt[0x12] & 0x400)
202 vga->crt[0x1E] |= 0x04;
203 if(vga->crt[0x06] & 0x400)
204 vga->crt[0x1E] |= 0x08;
205 if(vga->crt[0x04] & 0x100)
206 vga->crt[0x1E] |= 0x10;
207 if(vga->crt[0x02] & 0x100)
208 vga->crt[0x1E] |= 0x20;
209 if(vga->crt[0x01] & 0x100)
210 vga->crt[0x1E] |= 0x40;
211 if(vga->crt[0x00] & 0x100)
212 vga->crt[0x1E] |= 0x80;
213
214 vga->graphics[0x0B] = 0x00;
215 if(vga->vmz > 1024*1024)
216 vga->graphics[0x0B] |= 0x20;
217
218 if(mode->interlace == 'v'){
219 vga->crt[0x19] = vga->crt[0x00]/2;
220 vga->crt[0x1A] |= 0x01;
221 }
222
223 if(vga->linear && (ctlr->flag & Hlinear))
224 ctlr->flag |= Ulinear;
225
226 laguna = vga->private;
227
228 /*
229 * Ignore wide tiles for now, this simplifies things.
230 */
231 if(mode->x <= 640)
232 tiles = 5;
233 else if(mode->x <= 1024)
234 tiles = 8;
235 else if(mode->x <= 1280)
236 tiles = 10;
237 else if(mode->x <= 1664)
238 tiles = 13;
239 else if(mode->x <= 2048)
240 tiles = 16;
241 else if(mode->x <= 2560)
242 tiles = 20;
243 else if(mode->x <= 3228)
244 tiles = 26;
245 else
246 tiles = 32;
247 fetches = tiles; /* -1? */
248
249 if(nointerleave)
250 interleave = 0;
251 else switch(laguna->mem){
252 default:
253 interleave = 0;
254 break;
255 case 2:
256 interleave = 1;
257 break;
258 case 4:
259 case 8:
260 interleave = 2;
261 break;
262 }
263
264 if(mode->z == 8)
265 format = 0;
266 else if(mode->z == 16)
267 format = (1<<12)|(2<<9);
268 else if(mode->z == 24)
269 format = (2<<12)|(2<<9);
270 else
271 format = (2<<12)|(2<<9);
272
273 //if(ctlr->flag & Ulinear)
274 // laguna->vsc |= 0x10000000;
275 //else
276 laguna->vsc &= ~0x10000000;
277 laguna->format = format;
278 laguna->threshold = (interleave<<14)|(fetches<<8)|0x14;
279 laguna->tilectrl &= 0x3F;
280 laguna->tilectrl |= (interleave<<14)|(tiles<<8);
281 if(!notile)
282 laguna->tilectrl |= 0x80;
283 if(pagesize == 1)
284 laguna->tilectrl |= 0x10;
285 laguna->tilectrl2D3D = (interleave<<6)|tiles;
286 laguna->control = 0;
287 if(notile)
288 laguna->control |= 0x1000;
289 if(pagesize == 1)
290 laguna->control |= 0x0200;
291 }
292
293 static void
load(Vga * vga,Ctlr *)294 load(Vga* vga, Ctlr*)
295 {
296 Laguna *laguna;
297
298 vgaxo(Seqx, 0x0E, vga->sequencer[0x0E]);
299 vgaxo(Seqx, 0x1E, vga->sequencer[0x1E]);
300 vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
301
302 if(vga->mode->interlace == 'v')
303 vgaxo(Crtx, 0x19, vga->crt[0x19]);
304 vgaxo(Crtx, 0x1A, vga->crt[0x1A]);
305 vgaxo(Crtx, 0x1B, vga->crt[0x1B]);
306 vgaxo(Crtx, 0x1D, vga->crt[0x1D]);
307 vgaxo(Crtx, 0x1E, vga->crt[0x1E]);
308
309 vgaxo(Grx, 0x0B, vga->graphics[0x0B]);
310
311 laguna = vga->private;
312 mmio16w(laguna, Format, laguna->format);
313 mmio32w(laguna, Vsc, laguna->vsc);
314 mmio16w(laguna, Threshold, laguna->threshold);
315 mmio16w(laguna, TileCtrl, laguna->tilectrl);
316 mmio8w(laguna, TileCtrl2D3D, laguna->tilectrl2D3D);
317 mmio16w(laguna, Control, laguna->control);
318 }
319
320 static void
dump(Vga * vga,Ctlr * ctlr)321 dump(Vga* vga, Ctlr* ctlr)
322 {
323 int i;
324 char *name;
325 Laguna *laguna;
326
327 name = ctlr->name;
328
329 printitem(name, "Seq06");
330 for(i = 0x06; i < 0x20; i++)
331 printreg(vga->sequencer[i]);
332
333 printitem(name, "Crt19");
334 for(i = 0x19; i < 0x20; i++)
335 printreg(vga->crt[i]);
336
337 printitem(name, "Gr09");
338 for(i = 0x09; i < 0x0C; i++)
339 printreg(vga->graphics[i]);
340
341 laguna = vga->private;
342 Bprint(&stdout, "\n");
343 Bprint(&stdout, "%s mem\t\t%d\n", ctlr->name, laguna->mem*1024*1024);
344 Bprint(&stdout, "%s Format\t\t%uX\n", ctlr->name, laguna->format);
345 Bprint(&stdout, "%s Threshold\t\t\t%uX\n",
346 ctlr->name, laguna->threshold);
347 Bprint(&stdout, "%s TileCtrl\t\t\t%uX\n", ctlr->name, laguna->tilectrl);
348 Bprint(&stdout, "%s Vsc\t\t%uX\n", ctlr->name, laguna->vsc);
349 Bprint(&stdout, "%s Control\t\t%uX\n", ctlr->name, laguna->control);
350 Bprint(&stdout, "%s TileCtrlC2D3D\t\t%uX\n",
351 ctlr->name, laguna->tilectrl2D3D);
352 }
353
354 Ctlr clgd546x = {
355 "clgd546x", /* name */
356 snarf, /* snarf */
357 0, /* options */
358 init, /* init */
359 load, /* load */
360 dump, /* dump */
361 };
362
363 Ctlr clgd546xhwgc = {
364 "clgd546xhwgc", /* name */
365 0, /* snarf */
366 0, /* options */
367 0, /* init */
368 0, /* load */
369 0, /* dump */
370 };
371