3 * Matrox G200, G400 and G450.
4 * Written by Philippe Anel <xigh@free.fr>
6 * 2006-08-07 : Minor fix to allow the G200 cards to work fine. YDSTORG is now initialized.
7 * : Also support for 16 and 24 bit modes is added.
8 * : by Leonardo Valencia <leoval@anixcorp.com>
12 #include "../port/lib.h"
17 #include "../port/error.h"
44 DWG_SHIFTZERO = 0x4000,
45 DWG_REPLACE = 0x000C0000,
46 DWG_BFCOL = 0x04000000,
74 CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */
75 CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */
77 FILL_OPERAND = 0x800c7804,
81 mgawrite8(VGAscr *scr, int index, uchar val)
83 ((uchar*)scr->mmio)[index] = val;
87 mgaread8(VGAscr *scr, int index)
89 return ((uchar*)scr->mmio)[index];
93 crtcextset(VGAscr *scr, int index, uchar set, uchar clr)
97 mgawrite8(scr, CRTCEXTIDX, index);
98 tmp = mgaread8(scr, CRTCEXTDATA);
99 mgawrite8(scr, CRTCEXTIDX, index);
100 mgawrite8(scr, CRTCEXTDATA, (tmp & ~clr) | set);
106 mga4xxenable(VGAscr* scr)
122 scr->mmio = vmap(pci->mem[1].bar&~0x0F, 16*1024);
126 addvgaseg("mga4xxmmio", pci->mem[1].bar&~0x0F, pci->mem[1].size);
128 /* need to map frame buffer here too, so vga can find memory size */
129 if(pci->did == MGA4xx || pci->did == MGA550)
133 vgalinearaddr(scr, pci->mem[0].bar&~0x0F, size);
137 /* Find out how much memory is here, some multiple of 2 MB */
139 /* First Set MGA Mode ... */
140 crtcext3 = crtcextset(scr, 3, 0x80, 0x00);
144 for(i = 0; i < n; i++){
148 *((uchar*)scr->mmio + CACHEFLUSH) = 0;
151 for(i = 1; i < n; i++)
154 scr->apsize = 2*i*MB; /* sketchy */
155 addvgaseg("mga4xxscreen", scr->paddr, scr->apsize);
156 crtcextset(scr, 3, crtcext3, 0xff);
161 Index = 0x00, /* Index */
162 Data = 0x0A, /* Data */
164 Cxlsb = 0x0C, /* Cursor X LSB */
165 Cxmsb = 0x0D, /* Cursor X MSB */
166 Cylsb = 0x0E, /* Cursor Y LSB */
167 Cymsb = 0x0F, /* Cursor Y MSB */
169 Icuradrl = 0x04, /* Cursor Base Address Low */
170 Icuradrh = 0x05, /* Cursor Base Address High */
171 Icctl = 0x06, /* Indirect Cursor Control */
175 dac4xxdisable(VGAscr *scr)
182 dac4xx = (uchar*)scr->mmio+0x3C00;
184 *(dac4xx+Index) = Icctl;
185 *(dac4xx+Data) = 0x00;
189 dac4xxload(VGAscr *scr, Cursor *curs)
198 dac4xx = (uchar*)scr->mmio+0x3C00;
202 p = (uchar*)scr->storage;
203 for(y = 0; y < 64; y++){
204 *p++ = 0; *p++ = 0; *p++ = 0;
205 *p++ = 0; *p++ = 0; *p++ = 0;
207 *p++ = curs->set[1+y*2];
208 *p++ = curs->set[y*2];
213 *p++ = 0; *p++ = 0; *p++ = 0;
214 *p++ = 0; *p++ = 0; *p++ = 0;
216 *p++ = curs->set[1+y*2]|curs->clr[1+2*y];
217 *p++ = curs->set[y*2]|curs->clr[2*y];
222 scr->offset.x = 64 + curs->offset.x;
223 scr->offset.y = 64 + curs->offset.y;
225 *(dac4xx+Index) = Icctl;
226 *(dac4xx+Data) = 0x03;
230 dac4xxmove(VGAscr *scr, Point p)
238 dac4xx = (uchar*)scr->mmio + 0x3C00;
240 x = p.x + scr->offset.x;
241 y = p.y + scr->offset.y;
243 *(dac4xx+Cxlsb) = x & 0xFF;
244 *(dac4xx+Cxmsb) = (x>>8) & 0x0F;
246 *(dac4xx+Cylsb) = y & 0xFF;
247 *(dac4xx+Cymsb) = (y>>8) & 0x0F;
253 dac4xxenable(VGAscr *scr)
260 dac4xx = (uchar*)scr->mmio+0x3C00;
264 storage = (scr->apsize-4096)&~0x3ff;
266 *(dac4xx+Index) = Icuradrl;
267 *(dac4xx+Data) = 0xff & (storage >> 10);
268 *(dac4xx+Index) = Icuradrh;
269 *(dac4xx+Data) = 0xff & (storage >> 18);
271 scr->storage = (ulong)scr->vaddr + storage;
273 /* Show X11-Like Cursor */
274 *(dac4xx+Index) = Icctl;
275 *(dac4xx+Data) = 0x03;
277 /* Cursor Color 0 : White */
278 *(dac4xx+Index) = 0x08;
279 *(dac4xx+Data) = 0xff;
280 *(dac4xx+Index) = 0x09;
281 *(dac4xx+Data) = 0xff;
282 *(dac4xx+Index) = 0x0a;
283 *(dac4xx+Data) = 0xff;
285 /* Cursor Color 1 : Black */
286 *(dac4xx+Index) = 0x0c;
287 *(dac4xx+Data) = 0x00;
288 *(dac4xx+Index) = 0x0d;
289 *(dac4xx+Data) = 0x00;
290 *(dac4xx+Index) = 0x0e;
291 *(dac4xx+Data) = 0x00;
293 /* Cursor Color 2 : Red */
294 *(dac4xx+Index) = 0x10;
295 *(dac4xx+Data) = 0xff;
296 *(dac4xx+Index) = 0x11;
297 *(dac4xx+Data) = 0x00;
298 *(dac4xx+Index) = 0x12;
299 *(dac4xx+Data) = 0x00;
302 * Load, locate and enable the
303 * 64x64 cursor in X11 mode.
305 dac4xxload(scr, &cursor);
310 mga4xxblank(VGAscr *scr, int blank)
314 uchar seq1, crtcext1;
316 /* blank = 0 -> turn screen on */
317 /* blank = 1 -> turn screen off */
321 mga = (uchar*)scr->mmio;
328 crtcext1 = 0x10; /* Default value ... : standby */
329 cp = getconf("*dpms");
331 if(cistrcmp(cp, "standby") == 0)
333 else if(cistrcmp(cp, "suspend") == 0)
335 else if(cistrcmp(cp, "off") == 0)
341 seq1 |= *(mga + 0x1fc5) & ~0x20;
342 *(mga + 0x1fc5) = seq1;
345 crtcext1 |= *(mga + 0x1fdf) & ~0x30;
346 *(mga + 0x1fdf) = crtcext1;
350 mgawrite32(uchar *mga, ulong reg, ulong val)
352 *((ulong*)(&mga[reg])) = val;
356 mgaread32(uchar *mga, ulong reg)
358 return *((ulong*)(&mga[reg]));
362 mga_fifo(uchar *mga, uchar n)
367 for (t = 0; t < Timeout; t++)
368 if ((mgaread32(mga, FIFOSTATUS) & 0xff) >= n)
371 print("mga4xx: fifo timeout");
375 mga4xxfill(VGAscr *scr, Rectangle r, ulong color)
381 mga = (uchar*)scr->mmio;
384 mgawrite32(mga, DWGCTL, 0);
385 mgawrite32(mga, FCOL, color);
386 mgawrite32(mga, FXLEFT, r.min.x);
387 mgawrite32(mga, FXRIGHT, r.max.x);
388 mgawrite32(mga, YDST, r.min.y);
389 mgawrite32(mga, YLEN, Dy(r));
390 mgawrite32(mga, DWGCTL + GO, FILL_OPERAND);
392 while(mgaread32(mga, STATUS) & 0x00010000)
399 mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr)
404 ulong start, end, sgn;
409 mga = (uchar*)scr->mmio;
411 assert(Dx(sr) == Dx(dr) && Dy(sr) == Dy(dr));
418 pitch = Dx(scr->gscreen->r);
423 if(dp.y > sp.y && dp.y < sp.y + height){
430 start = end = sp.x + (sp.y * pitch);
432 if(dp.x > sp.x && dp.x < sp.x + width){
440 mgawrite32(mga, DWGCTL, 0);
441 mgawrite32(mga, SGN, sgn);
442 mgawrite32(mga, AR5, sgn & SGN_UP ? -pitch : pitch);
443 mgawrite32(mga, AR0, end);
444 mgawrite32(mga, AR3, start);
445 mgawrite32(mga, FXBNDRY, ((dp.x + width) << 16) | dp.x);
446 mgawrite32(mga, YDSTLEN, (dp.y << 16) | height);
447 mgawrite32(mga, DWGCTL + GO, DWG_BITBLT | DWG_SHIFTZERO | DWG_BFCOL | DWG_REPLACE);
449 while(mgaread32(mga, STATUS) & 0x00010000)
456 mga4xxdrawinit(VGAscr *scr)
463 mga = (uchar*)scr->mmio;
465 mgawrite32(mga, SRCORG, 0);
466 mgawrite32(mga, DSTORG, 0);
467 mgawrite32(mga, YDSTORG, 0);
468 mgawrite32(mga, ZORG, 0);
469 mgawrite32(mga, PLNWRT, ~0);
470 mgawrite32(mga, FCOL, 0xffff0000);
471 mgawrite32(mga, CXBNDRY, 0xFFFF0000);
472 mgawrite32(mga, YTOP, 0);
473 mgawrite32(mga, YBOT, 0x01FFFFFF);
474 mgawrite32(mga, PITCH, Dx(scr->gscreen->r) & ((1 << 13) - 1));
475 switch(scr->gscreen->depth){
477 mgawrite32(mga, MACCESS, 0);
480 mgawrite32(mga, MACCESS, 1);
483 mgawrite32(mga, MACCESS, 3);
486 mgawrite32(mga, MACCESS, 2);
489 return; /* depth not supported ! */
491 scr->fill = mga4xxfill;
492 scr->scroll = mga4xxscroll;
493 scr->blank = mga4xxblank;
496 VGAdev vgamga4xxdev = {
498 mga4xxenable, /* enable */
505 VGAcur vgamga4xxcur = {