19a747e4fSDavid du Colombier /* Philippe Anel <philippe.anel@noos.fr>
29a747e4fSDavid du Colombier - 2001-08-12 : First release.
39a747e4fSDavid du Colombier - 2001-08-15 : Added G450, with source code "adapted from" from Xfree86 4.1.0
49a747e4fSDavid du Colombier - 2001-08-23 : Added 'palettedepth 8' and a few 'ultradebug' ...
59a747e4fSDavid du Colombier - 2001-08-24 : Removed a possible lock in initialization.
69a747e4fSDavid du Colombier - 2001-08-30 : Hey ! The 32 bits mode is PALETIZED (Gamma Control I presume) !
79a747e4fSDavid du Colombier And it seems plan9 assume the frame buffer is organized in
89a747e4fSDavid du Colombier Big Endian format ! (+ Fix for the palette init. )
99a747e4fSDavid du Colombier - 2001-09-06 : Added Full 2D Accel ! (see drivers in /sys/src/9/pc)
109a747e4fSDavid du Colombier - 2001-10-01 : Rid Fix.
11816336a7SDavid du Colombier - 2006-04-01 : Add MGA550 support.
121066d6deSDavid du Colombier - 2006-08-07 : Add support for 16 and 24bits modes.
131066d6deSDavid du Colombier HW accel now works for the G200 cards too (see kernel).
141066d6deSDavid du Colombier by Leonardo Valencia <leoval@anixcorp.com>
159a747e4fSDavid du Colombier
169a747e4fSDavid du Colombier Greets and Acknowledgements go to :
179a747e4fSDavid du Colombier - Sylvain Chipaux <a.k.a. asle>.
189a747e4fSDavid du Colombier - Nigel Roles.
199a747e4fSDavid du Colombier - Jean Mehat (the man who introduced me into the world of plan9).
209a747e4fSDavid du Colombier - Nicolas Stojanovic.
219a747e4fSDavid du Colombier ... and for those who wrote plan9 of course ... :)
229a747e4fSDavid du Colombier */
239a747e4fSDavid du Colombier
249a747e4fSDavid du Colombier #include <u.h>
259a747e4fSDavid du Colombier #include <libc.h>
269a747e4fSDavid du Colombier #include <bio.h>
279a747e4fSDavid du Colombier
289a747e4fSDavid du Colombier #include "pci.h"
299a747e4fSDavid du Colombier #include "vga.h"
309a747e4fSDavid du Colombier
319a747e4fSDavid du Colombier static int ultradebug = 0;
329a747e4fSDavid du Colombier
339a747e4fSDavid du Colombier /*
349a747e4fSDavid du Colombier * Matrox G4xx 3D graphics accelerators
359a747e4fSDavid du Colombier */
369a747e4fSDavid du Colombier enum {
379a747e4fSDavid du Colombier Kilo = 1024,
389a747e4fSDavid du Colombier Meg = 1024*1024,
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier MATROX = 0x102B, /* pci chip manufacturer */
41816336a7SDavid du Colombier MGA550 = 0x2527, /* pci chip device ids */
42816336a7SDavid du Colombier MGA4XX = 0x0525,
439a747e4fSDavid du Colombier MGA200 = 0x0521,
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier /* Pci configuration space mapping */
469a747e4fSDavid du Colombier PCfgMgaFBAA = 0x10, /* Frame buffer Aperture Address */
479a747e4fSDavid du Colombier PCfgMgaCAA = 0x14, /* Control Aperture Address base */
489a747e4fSDavid du Colombier PCfgMgaIAA = 0x18, /* ILOAD Aperture base Address */
499a747e4fSDavid du Colombier PCfgMgaOption1 = 0x40, /* Option Register 1 */
509a747e4fSDavid du Colombier PCfgMgaOption2 = 0x50, /* Option Register 2 */
519a747e4fSDavid du Colombier PCfgMgaOption3 = 0x54, /* Option Register 3 */
529a747e4fSDavid du Colombier PCfgMgaDevCtrl = 0x04, /* Device Control */
539a747e4fSDavid du Colombier
549a747e4fSDavid du Colombier /* control aperture offsets */
559a747e4fSDavid du Colombier DMAWIN = 0x0000, /* 7KByte Pseudo-DMA Window */
569a747e4fSDavid du Colombier
579a747e4fSDavid du Colombier STATUS0 = 0x1FC2, /* Input Status 0 */
589a747e4fSDavid du Colombier STATUS1 = 0x1FDA, /* Input Status 1 */
599a747e4fSDavid du Colombier
609a747e4fSDavid du Colombier SEQIDX = 0x1FC4, /* Sequencer Index */
619a747e4fSDavid du Colombier SEQDATA = 0x1FC5, /* Sequencer Data */
629a747e4fSDavid du Colombier
639a747e4fSDavid du Colombier MISC_W = 0x1FC2, /* Misc. WO */
649a747e4fSDavid du Colombier MISC_R = 0x1FCC, /* Misc. RO */
659a747e4fSDavid du Colombier
669a747e4fSDavid du Colombier GCTLIDX = 0x1FCE, /* Graphic Controler Index */
679a747e4fSDavid du Colombier GCTLDATA = 0x1FCF, /* Graphic Controler Data */
689a747e4fSDavid du Colombier
699a747e4fSDavid du Colombier CRTCIDX = 0x1FD4, /* CRTC Index */
709a747e4fSDavid du Colombier CRTCDATA = 0x1FD5, /* CRTC Data */
719a747e4fSDavid du Colombier
729a747e4fSDavid du Colombier CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */
739a747e4fSDavid du Colombier CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier RAMDACIDX = 0x3C00, /* RAMDAC registers Index */
769a747e4fSDavid du Colombier RAMDACDATA = 0x3C0A, /* RAMDAC Indexed Data */
779a747e4fSDavid du Colombier RAMDACPALDATA = 0x3C01,
789a747e4fSDavid du Colombier
799a747e4fSDavid du Colombier ATTRIDX = 0x1FC0, /* Attribute Index */
809a747e4fSDavid du Colombier ATTRDATA = 0x1FC1, /* Attribute Data */
819a747e4fSDavid du Colombier
829a747e4fSDavid du Colombier CACHEFLUSH = 0x1FFF,
839a747e4fSDavid du Colombier
849a747e4fSDavid du Colombier C2_CTL = 0X3C10,
859a747e4fSDavid du Colombier MGA_STATUS = 0X1E14,
869a747e4fSDavid du Colombier Z_DEPTH_ORG = 0X1C0C,
879a747e4fSDavid du Colombier
889a747e4fSDavid du Colombier /* ... */
899a747e4fSDavid du Colombier Seq_ClockingMode = 0x01,
909a747e4fSDavid du Colombier Dotmode = (1<<0),
919a747e4fSDavid du Colombier Shftldrt = (1<<2),
929a747e4fSDavid du Colombier Dotclkrt = (1<<3),
939a747e4fSDavid du Colombier Shiftfour = (1<<4),
949a747e4fSDavid du Colombier Scroff = (1<<5),
959a747e4fSDavid du Colombier
969a747e4fSDavid du Colombier CrtcExt_Horizontcount = 0x01,
979a747e4fSDavid du Colombier Htotal = (1<<0),
989a747e4fSDavid du Colombier Hblkstr = (1<<1),
999a747e4fSDavid du Colombier Hsyncstr = (1<<2),
1009a747e4fSDavid du Colombier Hrsten = (1<<3),
1019a747e4fSDavid du Colombier Hsyncoff = (1<<4),
1029a747e4fSDavid du Colombier Vsyncoff = (1<<5),
1039a747e4fSDavid du Colombier Hblkend = (1<<6),
1049a747e4fSDavid du Colombier Vrsten = (1<<7),
1059a747e4fSDavid du Colombier
1069a747e4fSDavid du Colombier CrtcExt_Miscellaneous = 0x03,
1079a747e4fSDavid du Colombier Mgamode = (1<<7),
1089a747e4fSDavid du Colombier
1099a747e4fSDavid du Colombier Dac_Xpixclkctrl = 0x1a,
1109a747e4fSDavid du Colombier Pixclksl = (3<<0),
1119a747e4fSDavid du Colombier Pixclkdis = (1<<2),
1129a747e4fSDavid du Colombier Pixpllpdn = (1<<3),
1139a747e4fSDavid du Colombier
1149a747e4fSDavid du Colombier Dac_Xpixpllstat = 0x4f,
1159a747e4fSDavid du Colombier Pixlock = (1<<6),
1169a747e4fSDavid du Colombier
1179a747e4fSDavid du Colombier Dac_Xpixpllan = 0x45,
1189a747e4fSDavid du Colombier Dac_Xpixpllbn = 0x49,
1199a747e4fSDavid du Colombier Dac_Xpixpllcn = 0x4d,
1209a747e4fSDavid du Colombier
1219a747e4fSDavid du Colombier Dac_Xpixpllam = 0x44,
1229a747e4fSDavid du Colombier Dac_Xpixpllbm = 0x48,
1239a747e4fSDavid du Colombier Dac_Xpixpllcm = 0x4c,
1249a747e4fSDavid du Colombier
1259a747e4fSDavid du Colombier Dac_Xpixpllap = 0x46,
1269a747e4fSDavid du Colombier Dac_Xpixpllbp = 0x4a,
1279a747e4fSDavid du Colombier Dac_Xpixpllcp = 0x4e,
1289a747e4fSDavid du Colombier
1299a747e4fSDavid du Colombier Dac_Xmulctrl = 0x19,
1309a747e4fSDavid du Colombier ColorDepth = (7<<0),
1319a747e4fSDavid du Colombier _8bitsPerPixel = 0,
1329a747e4fSDavid du Colombier _15bitsPerPixel = 1,
1339a747e4fSDavid du Colombier _16bitsPerPixel = 2,
1349a747e4fSDavid du Colombier _24bitsPerPixel = 3,
1359a747e4fSDavid du Colombier _32bitsPerPixelWithOv = 4,
1369a747e4fSDavid du Colombier _32bitsPerPixel = 7,
1379a747e4fSDavid du Colombier
1389a747e4fSDavid du Colombier Dac_Xpanelmode = 0x1f,
1399a747e4fSDavid du Colombier
1409a747e4fSDavid du Colombier Dac_Xmiscctrl = 0x1e,
1419a747e4fSDavid du Colombier Dacpdn = (1<<0),
1429a747e4fSDavid du Colombier Mfcsel = (3<<1),
1439a747e4fSDavid du Colombier Vga8dac = (1<<3),
1449a747e4fSDavid du Colombier Ramcs = (1<<4),
1459a747e4fSDavid du Colombier Vdoutsel = (7<<5),
1469a747e4fSDavid du Colombier
1479a747e4fSDavid du Colombier Dac_Xcurctrl = 0x06,
1489a747e4fSDavid du Colombier CursorDis = 0,
1499a747e4fSDavid du Colombier Cursor3Color = 1,
1509a747e4fSDavid du Colombier CursorXGA = 2,
1519a747e4fSDavid du Colombier CursorX11 = 3,
1529a747e4fSDavid du Colombier Cursor16Color = 4,
1539a747e4fSDavid du Colombier
1549a747e4fSDavid du Colombier Dac_Xzoomctrl = 0x38,
1559a747e4fSDavid du Colombier
1569a747e4fSDavid du Colombier Misc_loaddsel = (1<<0),
1579a747e4fSDavid du Colombier Misc_rammapen = (1<<1),
1589a747e4fSDavid du Colombier Misc_clksel = (3<<2),
1599a747e4fSDavid du Colombier Misc_videodis = (1<<4),
1609a747e4fSDavid du Colombier Misc_hpgoddev = (1<<5),
1619a747e4fSDavid du Colombier Misc_hsyncpol = (1<<6),
1629a747e4fSDavid du Colombier Misc_vsyncpol = (1<<7),
1639a747e4fSDavid du Colombier
1649a747e4fSDavid du Colombier MNP_TABLE_SIZE = 64,
1659a747e4fSDavid du Colombier
1669a747e4fSDavid du Colombier TRUE = (1 == 1),
1679a747e4fSDavid du Colombier FALSE = (1 == 0),
1689a747e4fSDavid du Colombier };
1699a747e4fSDavid du Colombier
1709a747e4fSDavid du Colombier typedef struct {
1719a747e4fSDavid du Colombier Pcidev* pci;
1729a747e4fSDavid du Colombier int devid;
1739a747e4fSDavid du Colombier int revid;
1749a747e4fSDavid du Colombier
17574f16c81SDavid du Colombier uchar* mmio;
17674f16c81SDavid du Colombier uchar* mmfb;
1779a747e4fSDavid du Colombier int fbsize;
1789a747e4fSDavid du Colombier ulong iload;
1799a747e4fSDavid du Colombier
1809a747e4fSDavid du Colombier uchar syspll_m;
1819a747e4fSDavid du Colombier uchar syspll_n;
1829a747e4fSDavid du Colombier uchar syspll_p;
1839a747e4fSDavid du Colombier uchar syspll_s;
1849a747e4fSDavid du Colombier
1859a747e4fSDavid du Colombier uchar pixpll_m;
1869a747e4fSDavid du Colombier uchar pixpll_n;
1879a747e4fSDavid du Colombier uchar pixpll_p;
1889a747e4fSDavid du Colombier uchar pixpll_s;
1899a747e4fSDavid du Colombier
1909a747e4fSDavid du Colombier ulong option1;
1919a747e4fSDavid du Colombier ulong option2;
1929a747e4fSDavid du Colombier ulong option3;
1939a747e4fSDavid du Colombier
1949a747e4fSDavid du Colombier ulong Fneeded;
1959a747e4fSDavid du Colombier
1969a747e4fSDavid du Colombier /* From plan9.ini ... later */
1979a747e4fSDavid du Colombier uchar sdram;
1989a747e4fSDavid du Colombier uchar colorkey;
1999a747e4fSDavid du Colombier uchar maskkey;
2009a747e4fSDavid du Colombier ulong maxpclk;
2019a747e4fSDavid du Colombier
2029a747e4fSDavid du Colombier uchar graphics[9];
2039a747e4fSDavid du Colombier uchar attribute[0x14];
2049a747e4fSDavid du Colombier uchar sequencer[5];
2059a747e4fSDavid du Colombier uchar crtc[0x19];
2069a747e4fSDavid du Colombier uchar crtcext[9];
2079a747e4fSDavid du Colombier
2089a747e4fSDavid du Colombier ulong htotal;
2099a747e4fSDavid du Colombier ulong hdispend;
2109a747e4fSDavid du Colombier ulong hblkstr;
2119a747e4fSDavid du Colombier ulong hblkend;
2129a747e4fSDavid du Colombier ulong hsyncstr;
2139a747e4fSDavid du Colombier ulong hsyncend;
2149a747e4fSDavid du Colombier ulong vtotal;
2159a747e4fSDavid du Colombier ulong vdispend;
2169a747e4fSDavid du Colombier ulong vblkstr;
2179a747e4fSDavid du Colombier ulong vblkend;
2189a747e4fSDavid du Colombier ulong vsyncstr;
2199a747e4fSDavid du Colombier ulong vsyncend;
2209a747e4fSDavid du Colombier ulong linecomp;
2219a747e4fSDavid du Colombier ulong hsyncsel;
2229a747e4fSDavid du Colombier ulong startadd;
2239a747e4fSDavid du Colombier ulong offset;
2249a747e4fSDavid du Colombier ulong maxscan;
2259a747e4fSDavid du Colombier ulong curloc;
2269a747e4fSDavid du Colombier ulong prowscan;
2279a747e4fSDavid du Colombier ulong currowstr;
2289a747e4fSDavid du Colombier ulong currowend;
2299a747e4fSDavid du Colombier ulong curoff;
2309a747e4fSDavid du Colombier ulong undrow;
2319a747e4fSDavid du Colombier ulong curskew;
2329a747e4fSDavid du Colombier ulong conv2t4;
2339a747e4fSDavid du Colombier ulong interlace;
2349a747e4fSDavid du Colombier ulong hsyncdel;
2359a747e4fSDavid du Colombier ulong hdispskew;
2369a747e4fSDavid du Colombier ulong bytepan;
2379a747e4fSDavid du Colombier ulong dotclkrt;
2389a747e4fSDavid du Colombier ulong dword;
2399a747e4fSDavid du Colombier ulong wbmode;
2409a747e4fSDavid du Colombier ulong addwrap;
2419a747e4fSDavid du Colombier ulong selrowscan;
2429a747e4fSDavid du Colombier ulong cms;
2439a747e4fSDavid du Colombier ulong csynccen;
2449a747e4fSDavid du Colombier ulong hrsten;
2459a747e4fSDavid du Colombier ulong vrsten;
2469a747e4fSDavid du Colombier ulong vinten;
2479a747e4fSDavid du Colombier ulong vintclr;
2489a747e4fSDavid du Colombier ulong hsyncoff;
2499a747e4fSDavid du Colombier ulong vsyncoff;
2509a747e4fSDavid du Colombier ulong crtcrstN;
2519a747e4fSDavid du Colombier ulong mgamode;
2529a747e4fSDavid du Colombier ulong scale;
2539a747e4fSDavid du Colombier ulong hiprilvl;
2549a747e4fSDavid du Colombier ulong maxhipri;
2559a747e4fSDavid du Colombier ulong c2hiprilvl;
2569a747e4fSDavid du Colombier ulong c2maxhipri;
2579a747e4fSDavid du Colombier ulong misc;
2589a747e4fSDavid du Colombier ulong crtcprotect;
2599a747e4fSDavid du Colombier ulong winsize;
2609a747e4fSDavid du Colombier ulong winfreq;
2619a747e4fSDavid du Colombier
2629a747e4fSDavid du Colombier ulong mgaapsize;
2639a747e4fSDavid du Colombier } Mga;
2649a747e4fSDavid du Colombier
2659a747e4fSDavid du Colombier static void
mgawrite32(Mga * mga,int index,ulong val)2669a747e4fSDavid du Colombier mgawrite32(Mga* mga, int index, ulong val)
2679a747e4fSDavid du Colombier {
2689a747e4fSDavid du Colombier ((ulong*)mga->mmio)[index] = val;
2699a747e4fSDavid du Colombier }
2709a747e4fSDavid du Colombier
2719a747e4fSDavid du Colombier static ulong
mgaread32(Mga * mga,int index)2729a747e4fSDavid du Colombier mgaread32(Mga* mga, int index)
2739a747e4fSDavid du Colombier {
2749a747e4fSDavid du Colombier return ((ulong*)mga->mmio)[index];
2759a747e4fSDavid du Colombier }
2769a747e4fSDavid du Colombier
2779a747e4fSDavid du Colombier static void
mgawrite8(Mga * mga,int index,uchar val)2789a747e4fSDavid du Colombier mgawrite8(Mga* mga, int index, uchar val)
2799a747e4fSDavid du Colombier {
28074f16c81SDavid du Colombier mga->mmio[index] = val;
2819a747e4fSDavid du Colombier }
2829a747e4fSDavid du Colombier
2839a747e4fSDavid du Colombier static uchar
mgaread8(Mga * mga,int index)2849a747e4fSDavid du Colombier mgaread8(Mga* mga, int index)
2859a747e4fSDavid du Colombier {
28674f16c81SDavid du Colombier return mga->mmio[index];
2879a747e4fSDavid du Colombier }
2889a747e4fSDavid du Colombier
2899a747e4fSDavid du Colombier static uchar
seqget(Mga * mga,int index)2909a747e4fSDavid du Colombier seqget(Mga* mga, int index)
2919a747e4fSDavid du Colombier {
2929a747e4fSDavid du Colombier mgawrite8(mga, SEQIDX, index);
2939a747e4fSDavid du Colombier return mgaread8(mga, SEQDATA);
2949a747e4fSDavid du Colombier }
2959a747e4fSDavid du Colombier
2969a747e4fSDavid du Colombier static uchar
seqset(Mga * mga,int index,uchar set,uchar clr)2979a747e4fSDavid du Colombier seqset(Mga* mga, int index, uchar set, uchar clr)
2989a747e4fSDavid du Colombier {
2999a747e4fSDavid du Colombier uchar tmp;
3009a747e4fSDavid du Colombier
3019a747e4fSDavid du Colombier mgawrite8(mga, SEQIDX, index);
3029a747e4fSDavid du Colombier tmp = mgaread8(mga, SEQDATA);
3039a747e4fSDavid du Colombier mgawrite8(mga, SEQIDX, index);
3049a747e4fSDavid du Colombier mgawrite8(mga, SEQDATA, (tmp & ~clr) | set);
3059a747e4fSDavid du Colombier return tmp;
3069a747e4fSDavid du Colombier }
3079a747e4fSDavid du Colombier
3089a747e4fSDavid du Colombier static uchar
crtcget(Mga * mga,int index)3099a747e4fSDavid du Colombier crtcget(Mga* mga, int index)
3109a747e4fSDavid du Colombier {
3119a747e4fSDavid du Colombier mgawrite8(mga, CRTCIDX, index);
3129a747e4fSDavid du Colombier return mgaread8(mga, CRTCDATA);
3139a747e4fSDavid du Colombier }
3149a747e4fSDavid du Colombier
3159a747e4fSDavid du Colombier static uchar
crtcset(Mga * mga,int index,uchar set,uchar clr)3169a747e4fSDavid du Colombier crtcset(Mga* mga, int index, uchar set, uchar clr)
3179a747e4fSDavid du Colombier {
3189a747e4fSDavid du Colombier uchar tmp;
3199a747e4fSDavid du Colombier
3209a747e4fSDavid du Colombier mgawrite8(mga, CRTCIDX, index);
3219a747e4fSDavid du Colombier tmp = mgaread8(mga, CRTCDATA);
3229a747e4fSDavid du Colombier mgawrite8(mga, CRTCIDX, index);
3239a747e4fSDavid du Colombier mgawrite8(mga, CRTCDATA, (tmp & ~clr) | set);
3249a747e4fSDavid du Colombier return tmp;
3259a747e4fSDavid du Colombier }
3269a747e4fSDavid du Colombier
3279a747e4fSDavid du Colombier static uchar
crtcextget(Mga * mga,int index)3289a747e4fSDavid du Colombier crtcextget(Mga* mga, int index)
3299a747e4fSDavid du Colombier {
3309a747e4fSDavid du Colombier mgawrite8(mga, CRTCEXTIDX, index);
3319a747e4fSDavid du Colombier return mgaread8(mga, CRTCEXTDATA);
3329a747e4fSDavid du Colombier }
3339a747e4fSDavid du Colombier
3349a747e4fSDavid du Colombier static uchar
crtcextset(Mga * mga,int index,uchar set,uchar clr)3359a747e4fSDavid du Colombier crtcextset(Mga* mga, int index, uchar set, uchar clr)
3369a747e4fSDavid du Colombier {
3379a747e4fSDavid du Colombier uchar tmp;
3389a747e4fSDavid du Colombier
3399a747e4fSDavid du Colombier mgawrite8(mga, CRTCEXTIDX, index);
3409a747e4fSDavid du Colombier tmp = mgaread8(mga, CRTCEXTDATA);
3419a747e4fSDavid du Colombier mgawrite8(mga, CRTCEXTIDX, index);
3429a747e4fSDavid du Colombier mgawrite8(mga, CRTCEXTDATA, (tmp & ~clr) | set);
3439a747e4fSDavid du Colombier return tmp;
3449a747e4fSDavid du Colombier }
3459a747e4fSDavid du Colombier
3469a747e4fSDavid du Colombier static uchar
dacget(Mga * mga,int index)3479a747e4fSDavid du Colombier dacget(Mga* mga, int index)
3489a747e4fSDavid du Colombier {
3499a747e4fSDavid du Colombier mgawrite8(mga, RAMDACIDX, index);
3509a747e4fSDavid du Colombier return mgaread8(mga, RAMDACDATA);
3519a747e4fSDavid du Colombier }
3529a747e4fSDavid du Colombier
3539a747e4fSDavid du Colombier static uchar
dacset(Mga * mga,int index,uchar set,uchar clr)3549a747e4fSDavid du Colombier dacset(Mga* mga, int index, uchar set, uchar clr)
3559a747e4fSDavid du Colombier {
3569a747e4fSDavid du Colombier uchar tmp;
3579a747e4fSDavid du Colombier
3589a747e4fSDavid du Colombier mgawrite8(mga, RAMDACIDX, index);
3599a747e4fSDavid du Colombier tmp = mgaread8(mga, RAMDACDATA);
3609a747e4fSDavid du Colombier mgawrite8(mga, RAMDACIDX, index);
3619a747e4fSDavid du Colombier mgawrite8(mga, RAMDACDATA, (tmp & ~clr) | set);
3629a747e4fSDavid du Colombier return tmp;
3639a747e4fSDavid du Colombier }
3649a747e4fSDavid du Colombier
3659a747e4fSDavid du Colombier static uchar
gctlget(Mga * mga,int index)3669a747e4fSDavid du Colombier gctlget(Mga* mga, int index)
3679a747e4fSDavid du Colombier {
3689a747e4fSDavid du Colombier mgawrite8(mga, GCTLIDX, index);
3699a747e4fSDavid du Colombier return mgaread8(mga, GCTLDATA);
3709a747e4fSDavid du Colombier }
3719a747e4fSDavid du Colombier
3729a747e4fSDavid du Colombier static uchar
gctlset(Mga * mga,int index,uchar set,uchar clr)3739a747e4fSDavid du Colombier gctlset(Mga* mga, int index, uchar set, uchar clr)
3749a747e4fSDavid du Colombier {
3759a747e4fSDavid du Colombier uchar tmp;
3769a747e4fSDavid du Colombier
3779a747e4fSDavid du Colombier mgawrite8(mga, GCTLIDX, index);
3789a747e4fSDavid du Colombier tmp = mgaread8(mga, GCTLDATA);
3799a747e4fSDavid du Colombier mgawrite8(mga, GCTLIDX, index);
3809a747e4fSDavid du Colombier mgawrite8(mga, GCTLDATA, (tmp & ~clr) | set);
3819a747e4fSDavid du Colombier return tmp;
3829a747e4fSDavid du Colombier }
3839a747e4fSDavid du Colombier
3849a747e4fSDavid du Colombier static uchar
attrget(Mga * mga,int index)3859a747e4fSDavid du Colombier attrget(Mga* mga, int index)
3869a747e4fSDavid du Colombier {
3879a747e4fSDavid du Colombier mgawrite8(mga, ATTRIDX, index);
3889a747e4fSDavid du Colombier return mgaread8(mga, ATTRDATA);
3899a747e4fSDavid du Colombier }
3909a747e4fSDavid du Colombier
3919a747e4fSDavid du Colombier static uchar
attrset(Mga * mga,int index,uchar set,uchar clr)3929a747e4fSDavid du Colombier attrset(Mga* mga, int index, uchar set, uchar clr)
3939a747e4fSDavid du Colombier {
3949a747e4fSDavid du Colombier uchar tmp;
3959a747e4fSDavid du Colombier
3969a747e4fSDavid du Colombier mgawrite8(mga, ATTRIDX, index);
3979a747e4fSDavid du Colombier tmp = mgaread8(mga, ATTRDATA);
3989a747e4fSDavid du Colombier mgawrite8(mga, ATTRIDX, index);
3999a747e4fSDavid du Colombier mgawrite8(mga, ATTRDATA, (tmp & ~clr) | set);
4009a747e4fSDavid du Colombier return tmp;
4019a747e4fSDavid du Colombier }
4029a747e4fSDavid du Colombier
4039a747e4fSDavid du Colombier static uchar
miscget(Mga * mga)4049a747e4fSDavid du Colombier miscget(Mga* mga)
4059a747e4fSDavid du Colombier {
4069a747e4fSDavid du Colombier return mgaread8(mga, MISC_R);
4079a747e4fSDavid du Colombier }
4089a747e4fSDavid du Colombier
4099a747e4fSDavid du Colombier static uchar
miscset(Mga * mga,uchar set,uchar clr)4109a747e4fSDavid du Colombier miscset(Mga* mga, uchar set, uchar clr)
4119a747e4fSDavid du Colombier {
4129a747e4fSDavid du Colombier uchar tmp;
4139a747e4fSDavid du Colombier
4149a747e4fSDavid du Colombier tmp = mgaread8(mga, MISC_R);
4159a747e4fSDavid du Colombier mgawrite8(mga, MISC_W, (tmp & ~clr) | set);
4169a747e4fSDavid du Colombier return tmp;
4179a747e4fSDavid du Colombier }
4189a747e4fSDavid du Colombier
4199a747e4fSDavid du Colombier /* ************************************************************ */
4209a747e4fSDavid du Colombier
4219a747e4fSDavid du Colombier static void
dump_all_regs(Mga * mga)4229a747e4fSDavid du Colombier dump_all_regs(Mga* mga)
4239a747e4fSDavid du Colombier {
4249a747e4fSDavid du Colombier int i;
4259a747e4fSDavid du Colombier
4269a747e4fSDavid du Colombier for (i = 0; i < 25; i++)
4279a747e4fSDavid du Colombier trace("crtc[%d] = 0x%x\n", i, crtcget(mga, i));
4289a747e4fSDavid du Colombier for (i = 0; i < 9; i++)
4299a747e4fSDavid du Colombier trace("crtcext[%d] = 0x%x\n", i, crtcextget(mga, i));
4309a747e4fSDavid du Colombier for (i = 0; i < 5; i++)
4319a747e4fSDavid du Colombier trace("seq[%d] = 0x%x\n", i, seqget(mga, i));
4329a747e4fSDavid du Colombier for (i = 0; i < 9; i++)
4339a747e4fSDavid du Colombier trace("gctl[%d] = 0x%x\n", i, gctlget(mga, i));
4349a747e4fSDavid du Colombier trace("misc = 0x%x\n", mgaread8(mga, MISC_R));
4359a747e4fSDavid du Colombier for (i = 0; i < 0x87; i++)
4369a747e4fSDavid du Colombier trace("dac[%d] = 0x%x\n", i, dacget(mga, i));
4379a747e4fSDavid du Colombier }
4389a747e4fSDavid du Colombier
4399a747e4fSDavid du Colombier /* ************************************************************ */
4409a747e4fSDavid du Colombier
4419a747e4fSDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)4429a747e4fSDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
4439a747e4fSDavid du Colombier {
4449a747e4fSDavid du Colombier dump_all_regs(vga->private);
4459a747e4fSDavid du Colombier ctlr->flag |= Fdump;
4469a747e4fSDavid du Colombier }
4479a747e4fSDavid du Colombier
4489a747e4fSDavid du Colombier static void
setpalettedepth(int depth)4499a747e4fSDavid du Colombier setpalettedepth(int depth)
4509a747e4fSDavid du Colombier {
4519a747e4fSDavid du Colombier int fd;
4529a747e4fSDavid du Colombier char *cmd = strdup("palettedepth X");
4539a747e4fSDavid du Colombier
4549a747e4fSDavid du Colombier if ((depth != 8) && (depth != 6) && (depth != 16))
4559a747e4fSDavid du Colombier error("mga: invalid palette depth %d\n", depth);
4569a747e4fSDavid du Colombier
4579a747e4fSDavid du Colombier fd = open("#v/vgactl", OWRITE);
4589a747e4fSDavid du Colombier if(fd < 0)
4599a747e4fSDavid du Colombier error("mga: can't open vgactl\n");
4609a747e4fSDavid du Colombier
4619a747e4fSDavid du Colombier cmd[13] = '0' + depth;
4629a747e4fSDavid du Colombier if(write(fd, cmd, 14) != 14)
4639a747e4fSDavid du Colombier error("mga: can't set palette depth to %d\n", depth);
4649a747e4fSDavid du Colombier
4659a747e4fSDavid du Colombier close(fd);
4669a747e4fSDavid du Colombier }
4679a747e4fSDavid du Colombier
4689a747e4fSDavid du Colombier static void
mapmga4xx(Vga * vga,Ctlr * ctlr)4699a747e4fSDavid du Colombier mapmga4xx(Vga* vga, Ctlr* ctlr)
4709a747e4fSDavid du Colombier {
4719a747e4fSDavid du Colombier int f;
47274f16c81SDavid du Colombier uchar* m;
4739a747e4fSDavid du Colombier Mga * mga;
4749a747e4fSDavid du Colombier
4759a747e4fSDavid du Colombier if(vga->private == nil)
4769a747e4fSDavid du Colombier error("%s: g4xxio: no *mga4xx\n", ctlr->name);
4779a747e4fSDavid du Colombier mga = vga->private;
4789a747e4fSDavid du Colombier
4799a747e4fSDavid du Colombier f = open("#v/vgactl", OWRITE);
4809a747e4fSDavid du Colombier if(f < 0)
4819a747e4fSDavid du Colombier error("%s: can't open vgactl\n", ctlr->name);
4829a747e4fSDavid du Colombier
4839a747e4fSDavid du Colombier if(write(f, "type mga4xx", 11) != 11)
4849a747e4fSDavid du Colombier error("%s: can't set mga type\n", ctlr->name);
4859a747e4fSDavid du Colombier
4869a747e4fSDavid du Colombier m = segattach(0, "mga4xxmmio", 0, 16*Kilo);
48774f16c81SDavid du Colombier if(m == (void*)-1)
4889a747e4fSDavid du Colombier error("%s: can't attach mga4xxmmio segment\n", ctlr->name);
4899a747e4fSDavid du Colombier mga->mmio = m;
49074f16c81SDavid du Colombier trace("%s: mmio at %#p\n", ctlr->name, mga->mmio);
4919a747e4fSDavid du Colombier
4929a747e4fSDavid du Colombier m = segattach(0, "mga4xxscreen", 0, 32*Meg);
49374f16c81SDavid du Colombier if(m == (void*)-1) {
4949a747e4fSDavid du Colombier mga->mgaapsize = 8*Meg;
4959a747e4fSDavid du Colombier m = segattach(0, "mga4xxscreen", 0, 8*Meg);
49674f16c81SDavid du Colombier if(m == (void*)-1)
4979a747e4fSDavid du Colombier error("%s: can't attach mga4xxscreen segment\n", ctlr->name);
4989a747e4fSDavid du Colombier } else {
4999a747e4fSDavid du Colombier mga->mgaapsize = 32*Meg;
5009a747e4fSDavid du Colombier }
5019a747e4fSDavid du Colombier mga->mmfb = m;
50274f16c81SDavid du Colombier trace("%s: frame buffer at %#p\n", ctlr->name, mga->mmfb);
5039a747e4fSDavid du Colombier
5049a747e4fSDavid du Colombier close(f);
5059a747e4fSDavid du Colombier }
5069a747e4fSDavid du Colombier
5079a747e4fSDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)5089a747e4fSDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
5099a747e4fSDavid du Colombier {
5109a747e4fSDavid du Colombier int i, k, n;
5119a747e4fSDavid du Colombier uchar * p;
5129a747e4fSDavid du Colombier uchar x[16];
5139a747e4fSDavid du Colombier Pcidev * pci;
5149a747e4fSDavid du Colombier Mga * mga;
5159a747e4fSDavid du Colombier uchar crtcext3;
5169a747e4fSDavid du Colombier uchar rid;
5179a747e4fSDavid du Colombier
5189a747e4fSDavid du Colombier trace("%s->snarf\n", ctlr->name);
5199a747e4fSDavid du Colombier if(vga->private == nil) {
5209a747e4fSDavid du Colombier pci = pcimatch(nil, MATROX, MGA4XX);
521816336a7SDavid du Colombier if(pci == nil)
522816336a7SDavid du Colombier pci = pcimatch(nil, MATROX, MGA550);
523816336a7SDavid du Colombier if(pci == nil)
5249a747e4fSDavid du Colombier pci = pcimatch(nil, MATROX, MGA200);
525816336a7SDavid du Colombier if(pci == nil)
526816336a7SDavid du Colombier error("%s: cannot find matrox adapter\n", ctlr->name);
5279a747e4fSDavid du Colombier
5289a747e4fSDavid du Colombier rid = pcicfgr8(pci, PciRID); // PciRID = 0x08
5299a747e4fSDavid du Colombier
530816336a7SDavid du Colombier trace("%s: G%d%d0 rev %d\n", ctlr->name,
531816336a7SDavid du Colombier 2*(pci->did==MGA200)
532816336a7SDavid du Colombier +4*(pci->did==MGA4XX)
533816336a7SDavid du Colombier +5*(pci->did==MGA550),
534816336a7SDavid du Colombier rid&0x80 ? 5 : 0,
535816336a7SDavid du Colombier rid&~0x80);
5369a747e4fSDavid du Colombier i = pcicfgr32(pci, PCfgMgaDevCtrl);
5379a747e4fSDavid du Colombier if ((i & 2) != 2)
5389a747e4fSDavid du Colombier error("%s: Memory Space not enabled ... Aborting ...\n", ctlr->name);
5399a747e4fSDavid du Colombier
5409a747e4fSDavid du Colombier vga->private = alloc(sizeof(Mga));
5419a747e4fSDavid du Colombier mga = (Mga*)vga->private;
5429a747e4fSDavid du Colombier mga->devid = pci->did;
5439a747e4fSDavid du Colombier mga->revid = rid;
5449a747e4fSDavid du Colombier mga->pci = pci;
5459a747e4fSDavid du Colombier
5469a747e4fSDavid du Colombier mapmga4xx(vga, ctlr);
5479a747e4fSDavid du Colombier }
5489a747e4fSDavid du Colombier else {
5499a747e4fSDavid du Colombier mga = (Mga*)vga->private;
5509a747e4fSDavid du Colombier }
5519a747e4fSDavid du Colombier
5529a747e4fSDavid du Colombier /* Find out how much memory is here, some multiple of 2Meg */
5539a747e4fSDavid du Colombier
5549a747e4fSDavid du Colombier /* First Set MGA Mode ... */
5559a747e4fSDavid du Colombier crtcext3 = crtcextset(mga, 3, 0x80, 0x00);
5569a747e4fSDavid du Colombier
55774f16c81SDavid du Colombier p = mga->mmfb;
5589a747e4fSDavid du Colombier n = (mga->mgaapsize / Meg) / 2;
5599a747e4fSDavid du Colombier for (i = 0; i < n; i++) {
5609a747e4fSDavid du Colombier k = (2*i+1)*Meg;
5619a747e4fSDavid du Colombier p[k] = 0;
5629a747e4fSDavid du Colombier p[k] = i+1;
56374f16c81SDavid du Colombier *(mga->mmio + CACHEFLUSH) = 0;
5649a747e4fSDavid du Colombier x[i] = p[k];
5659a747e4fSDavid du Colombier trace("x[%d]=%d\n", i, x[i]);
5669a747e4fSDavid du Colombier }
5679a747e4fSDavid du Colombier for(i = 1; i < n; i++)
5689a747e4fSDavid du Colombier if(x[i] != i+1)
5699a747e4fSDavid du Colombier break;
5709a747e4fSDavid du Colombier vga->vmz = mga->fbsize = 2*i*Meg;
5719a747e4fSDavid du Colombier trace("probe found %d megabytes\n", 2*i);
5729a747e4fSDavid du Colombier
5739a747e4fSDavid du Colombier crtcextset(mga, 3, crtcext3, 0xff);
5749a747e4fSDavid du Colombier
5759a747e4fSDavid du Colombier ctlr->flag |= Fsnarf;
5769a747e4fSDavid du Colombier }
5779a747e4fSDavid du Colombier
5789a747e4fSDavid du Colombier static void
options(Vga * vga,Ctlr * ctlr)5799a747e4fSDavid du Colombier options(Vga* vga, Ctlr* ctlr)
5809a747e4fSDavid du Colombier {
5819a747e4fSDavid du Colombier if(vga->virtx & 127)
5829a747e4fSDavid du Colombier vga->virtx = (vga->virtx+127)&~127;
5839a747e4fSDavid du Colombier ctlr->flag |= Foptions;
5849a747e4fSDavid du Colombier }
5859a747e4fSDavid du Colombier
5869a747e4fSDavid du Colombier /* ************************************************************ */
5879a747e4fSDavid du Colombier
5889a747e4fSDavid du Colombier static void
G450ApplyPFactor(Mga *,uchar ucP,ulong * pulFIn)5899a747e4fSDavid du Colombier G450ApplyPFactor(Mga*, uchar ucP, ulong *pulFIn)
5909a747e4fSDavid du Colombier {
5919a747e4fSDavid du Colombier if(!(ucP & 0x40))
5929a747e4fSDavid du Colombier {
5939a747e4fSDavid du Colombier *pulFIn = *pulFIn / (2L << (ucP & 3));
5949a747e4fSDavid du Colombier }
5959a747e4fSDavid du Colombier }
5969a747e4fSDavid du Colombier
5979a747e4fSDavid du Colombier
5989a747e4fSDavid du Colombier static void
G450RemovePFactor(Mga *,uchar ucP,ulong * pulFIn)5999a747e4fSDavid du Colombier G450RemovePFactor(Mga*, uchar ucP, ulong *pulFIn)
6009a747e4fSDavid du Colombier {
6019a747e4fSDavid du Colombier if(!(ucP & 0x40))
6029a747e4fSDavid du Colombier {
6039a747e4fSDavid du Colombier *pulFIn = *pulFIn * (2L << (ucP & 3));
6049a747e4fSDavid du Colombier }
6059a747e4fSDavid du Colombier }
6069a747e4fSDavid du Colombier
6079a747e4fSDavid du Colombier static void
G450CalculVCO(Mga *,ulong ulMNP,ulong * pulF)6089a747e4fSDavid du Colombier G450CalculVCO(Mga*, ulong ulMNP, ulong *pulF)
6099a747e4fSDavid du Colombier {
6109a747e4fSDavid du Colombier uchar ucM, ucN;
6119a747e4fSDavid du Colombier
6129a747e4fSDavid du Colombier ucM = (uchar)((ulMNP >> 16) & 0xff);
6139a747e4fSDavid du Colombier ucN = (uchar)((ulMNP >> 8) & 0xff);
6149a747e4fSDavid du Colombier
6159a747e4fSDavid du Colombier *pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1);
6169a747e4fSDavid du Colombier trace("G450CalculVCO: ulMNP %lx, pulF %ld\n", ulMNP, *pulF);
6179a747e4fSDavid du Colombier }
6189a747e4fSDavid du Colombier
6199a747e4fSDavid du Colombier
6209a747e4fSDavid du Colombier static void
G450CalculDeltaFreq(Mga *,ulong ulF1,ulong ulF2,ulong * pulDelta)6219a747e4fSDavid du Colombier G450CalculDeltaFreq(Mga*, ulong ulF1, ulong ulF2, ulong *pulDelta)
6229a747e4fSDavid du Colombier {
6239a747e4fSDavid du Colombier if(ulF2 < ulF1)
6249a747e4fSDavid du Colombier {
6259a747e4fSDavid du Colombier *pulDelta = ((ulF1 - ulF2) * 1000) / ulF1;
6269a747e4fSDavid du Colombier }
6279a747e4fSDavid du Colombier else
6289a747e4fSDavid du Colombier {
6299a747e4fSDavid du Colombier *pulDelta = ((ulF2 - ulF1) * 1000) / ulF1;
6309a747e4fSDavid du Colombier }
6319a747e4fSDavid du Colombier trace("G450CalculDeltaFreq: ulF1 %ld, ulF2 %ld, pulDelta %ld\n", ulF1, ulF2, *pulDelta);
6329a747e4fSDavid du Colombier }
6339a747e4fSDavid du Colombier
6349a747e4fSDavid du Colombier static void
G450FindNextPLLParam(Mga * mga,ulong ulFout,ulong * pulPLLMNP)6359a747e4fSDavid du Colombier G450FindNextPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
6369a747e4fSDavid du Colombier {
6379a747e4fSDavid du Colombier uchar ucM, ucN, ucP, ucS;
6389a747e4fSDavid du Colombier ulong ulVCO, ulVCOMin;
6399a747e4fSDavid du Colombier
6409a747e4fSDavid du Colombier ucM = (uchar)((*pulPLLMNP >> 16) & 0xff);
6419a747e4fSDavid du Colombier /* ucN = (uchar)((*pulPLLMNP >> 8) & 0xff); */
6429a747e4fSDavid du Colombier ucP = (uchar)(*pulPLLMNP & 0x43);
6439a747e4fSDavid du Colombier
6449a747e4fSDavid du Colombier ulVCOMin = 256000;
6459a747e4fSDavid du Colombier
6469a747e4fSDavid du Colombier if(ulVCOMin >= (255L * 8000))
6479a747e4fSDavid du Colombier {
6489a747e4fSDavid du Colombier ulVCOMin = 230000;
6499a747e4fSDavid du Colombier }
6509a747e4fSDavid du Colombier
6519a747e4fSDavid du Colombier if((ucM == 9) && (ucP & 0x40))
6529a747e4fSDavid du Colombier {
6539a747e4fSDavid du Colombier *pulPLLMNP = 0xffffffff;
6549a747e4fSDavid du Colombier } else if (ucM == 9)
6559a747e4fSDavid du Colombier {
6569a747e4fSDavid du Colombier if(ucP)
6579a747e4fSDavid du Colombier {
6589a747e4fSDavid du Colombier ucP--;
6599a747e4fSDavid du Colombier }
6609a747e4fSDavid du Colombier else
6619a747e4fSDavid du Colombier {
6629a747e4fSDavid du Colombier ucP = 0x40;
6639a747e4fSDavid du Colombier }
6649a747e4fSDavid du Colombier ucM = 0;
6659a747e4fSDavid du Colombier }
6669a747e4fSDavid du Colombier else
6679a747e4fSDavid du Colombier {
6689a747e4fSDavid du Colombier ucM++;
6699a747e4fSDavid du Colombier }
6709a747e4fSDavid du Colombier
6719a747e4fSDavid du Colombier ulVCO = ulFout;
6729a747e4fSDavid du Colombier
6739a747e4fSDavid du Colombier G450RemovePFactor(mga, ucP, &ulVCO);
6749a747e4fSDavid du Colombier
6759a747e4fSDavid du Colombier if(ulVCO < ulVCOMin)
6769a747e4fSDavid du Colombier {
6779a747e4fSDavid du Colombier *pulPLLMNP = 0xffffffff;
6789a747e4fSDavid du Colombier }
6799a747e4fSDavid du Colombier
6809a747e4fSDavid du Colombier if(*pulPLLMNP != 0xffffffff)
6819a747e4fSDavid du Colombier {
6829a747e4fSDavid du Colombier ucN = (uchar)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2);
6839a747e4fSDavid du Colombier
6849a747e4fSDavid du Colombier ucS = 5;
6859a747e4fSDavid du Colombier if(ulVCO < 1300000) ucS = 4;
6869a747e4fSDavid du Colombier if(ulVCO < 1100000) ucS = 3;
6879a747e4fSDavid du Colombier if(ulVCO < 900000) ucS = 2;
6889a747e4fSDavid du Colombier if(ulVCO < 700000) ucS = 1;
6899a747e4fSDavid du Colombier if(ulVCO < 550000) ucS = 0;
6909a747e4fSDavid du Colombier
6919a747e4fSDavid du Colombier ucP |= (uchar)(ucS << 3);
6929a747e4fSDavid du Colombier
6939a747e4fSDavid du Colombier *pulPLLMNP &= 0xff000000;
6949a747e4fSDavid du Colombier *pulPLLMNP |= (ulong)ucM << 16;
6959a747e4fSDavid du Colombier *pulPLLMNP |= (ulong)ucN << 8;
6969a747e4fSDavid du Colombier *pulPLLMNP |= (ulong)ucP;
6979a747e4fSDavid du Colombier }
6989a747e4fSDavid du Colombier }
6999a747e4fSDavid du Colombier
7009a747e4fSDavid du Colombier static void
G450FindFirstPLLParam(Mga * mga,ulong ulFout,ulong * pulPLLMNP)7019a747e4fSDavid du Colombier G450FindFirstPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
7029a747e4fSDavid du Colombier {
7039a747e4fSDavid du Colombier uchar ucP;
7049a747e4fSDavid du Colombier ulong ulVCO;
7059a747e4fSDavid du Colombier ulong ulVCOMax;
7069a747e4fSDavid du Colombier
7079a747e4fSDavid du Colombier /* Default value */
7089a747e4fSDavid du Colombier ulVCOMax = 1300000;
7099a747e4fSDavid du Colombier
7109a747e4fSDavid du Colombier if(ulFout > (ulVCOMax/2))
7119a747e4fSDavid du Colombier {
7129a747e4fSDavid du Colombier ucP = 0x40;
7139a747e4fSDavid du Colombier ulVCO = ulFout;
7149a747e4fSDavid du Colombier }
7159a747e4fSDavid du Colombier else
7169a747e4fSDavid du Colombier {
7179a747e4fSDavid du Colombier ucP = 3;
7189a747e4fSDavid du Colombier ulVCO = ulFout;
7199a747e4fSDavid du Colombier G450RemovePFactor(mga, ucP, &ulVCO);
7209a747e4fSDavid du Colombier while(ucP && (ulVCO > ulVCOMax))
7219a747e4fSDavid du Colombier {
7229a747e4fSDavid du Colombier ucP--;
7239a747e4fSDavid du Colombier ulVCO = ulFout;
7249a747e4fSDavid du Colombier G450RemovePFactor(mga, ucP, &ulVCO);
7259a747e4fSDavid du Colombier }
7269a747e4fSDavid du Colombier }
7279a747e4fSDavid du Colombier
7289a747e4fSDavid du Colombier if(ulVCO > ulVCOMax)
7299a747e4fSDavid du Colombier {
7309a747e4fSDavid du Colombier *pulPLLMNP = 0xffffffff;
7319a747e4fSDavid du Colombier }
7329a747e4fSDavid du Colombier else
7339a747e4fSDavid du Colombier {
7349a747e4fSDavid du Colombier /* Pixel clock: 1 */
7359a747e4fSDavid du Colombier *pulPLLMNP = (1 << 24) + 0xff0000 + ucP;
7369a747e4fSDavid du Colombier G450FindNextPLLParam(mga, ulFout, pulPLLMNP);
7379a747e4fSDavid du Colombier }
7389a747e4fSDavid du Colombier }
7399a747e4fSDavid du Colombier
7409a747e4fSDavid du Colombier
7419a747e4fSDavid du Colombier static void
G450WriteMNP(Mga * mga,ulong ulMNP)7429a747e4fSDavid du Colombier G450WriteMNP(Mga* mga, ulong ulMNP)
7439a747e4fSDavid du Colombier {
7449a747e4fSDavid du Colombier if (0) trace("G450WriteMNP : 0x%lx\n", ulMNP);
7459a747e4fSDavid du Colombier dacset(mga, Dac_Xpixpllcm, (uchar)(ulMNP >> 16), 0xff);
7469a747e4fSDavid du Colombier dacset(mga, Dac_Xpixpllcn, (uchar)(ulMNP >> 8), 0xff);
7479a747e4fSDavid du Colombier dacset(mga, Dac_Xpixpllcp, (uchar)ulMNP, 0xff);
7489a747e4fSDavid du Colombier }
7499a747e4fSDavid du Colombier
7509a747e4fSDavid du Colombier
7519a747e4fSDavid du Colombier static void
G450CompareMNP(Mga * mga,ulong ulFout,ulong ulMNP1,ulong ulMNP2,long * pulResult)7529a747e4fSDavid du Colombier G450CompareMNP(Mga* mga, ulong ulFout, ulong ulMNP1,
7539a747e4fSDavid du Colombier ulong ulMNP2, long *pulResult)
7549a747e4fSDavid du Colombier {
7559a747e4fSDavid du Colombier ulong ulFreq, ulDelta1, ulDelta2;
7569a747e4fSDavid du Colombier
7579a747e4fSDavid du Colombier G450CalculVCO(mga, ulMNP1, &ulFreq);
7589a747e4fSDavid du Colombier G450ApplyPFactor(mga, (uchar) ulMNP1, &ulFreq);
7599a747e4fSDavid du Colombier G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta1);
7609a747e4fSDavid du Colombier
7619a747e4fSDavid du Colombier G450CalculVCO(mga, ulMNP2, &ulFreq);
7629a747e4fSDavid du Colombier G450ApplyPFactor(mga, (uchar) ulMNP2, &ulFreq);
7639a747e4fSDavid du Colombier G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta2);
7649a747e4fSDavid du Colombier
7659a747e4fSDavid du Colombier if(ulDelta1 < ulDelta2)
7669a747e4fSDavid du Colombier {
7679a747e4fSDavid du Colombier *pulResult = -1;
7689a747e4fSDavid du Colombier }
7699a747e4fSDavid du Colombier else if(ulDelta1 > ulDelta2)
7709a747e4fSDavid du Colombier {
7719a747e4fSDavid du Colombier *pulResult = 1;
7729a747e4fSDavid du Colombier }
7739a747e4fSDavid du Colombier else
7749a747e4fSDavid du Colombier {
7759a747e4fSDavid du Colombier *pulResult = 0;
7769a747e4fSDavid du Colombier }
7779a747e4fSDavid du Colombier
7789a747e4fSDavid du Colombier if((ulDelta1 <= 5) && (ulDelta2 <= 5))
7799a747e4fSDavid du Colombier {
7809a747e4fSDavid du Colombier if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000))
7819a747e4fSDavid du Colombier {
7829a747e4fSDavid du Colombier *pulResult = -1;
7839a747e4fSDavid du Colombier }
7849a747e4fSDavid du Colombier else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000))
7859a747e4fSDavid du Colombier {
7869a747e4fSDavid du Colombier *pulResult = 1;
7879a747e4fSDavid du Colombier }
7889a747e4fSDavid du Colombier }
7899a747e4fSDavid du Colombier }
7909a747e4fSDavid du Colombier
7919a747e4fSDavid du Colombier
7929a747e4fSDavid du Colombier static void
G450IsPllLocked(Mga * mga,int * lpbLocked)7939a747e4fSDavid du Colombier G450IsPllLocked(Mga* mga, int *lpbLocked)
7949a747e4fSDavid du Colombier {
7959a747e4fSDavid du Colombier ulong ulFallBackCounter, ulLockCount, ulCount;
7969a747e4fSDavid du Colombier uchar ucPLLStatus;
7979a747e4fSDavid du Colombier
7989a747e4fSDavid du Colombier /* Pixel PLL */
7999a747e4fSDavid du Colombier mgawrite8(mga, 0x3c00, 0x4f);
8009a747e4fSDavid du Colombier ulFallBackCounter = 0;
8019a747e4fSDavid du Colombier
8029a747e4fSDavid du Colombier do
8039a747e4fSDavid du Colombier {
8049a747e4fSDavid du Colombier ucPLLStatus = mgaread8(mga, 0x3c0a);
8059a747e4fSDavid du Colombier if (0) trace("ucPLLStatus[1] : 0x%x\n", ucPLLStatus);
8069a747e4fSDavid du Colombier ulFallBackCounter++;
8079a747e4fSDavid du Colombier } while(!(ucPLLStatus & 0x40) && (ulFallBackCounter < 1000));
8089a747e4fSDavid du Colombier
8099a747e4fSDavid du Colombier ulLockCount = 0;
8109a747e4fSDavid du Colombier if(ulFallBackCounter < 1000)
8119a747e4fSDavid du Colombier {
8129a747e4fSDavid du Colombier for(ulCount = 0; ulCount < 100; ulCount++)
8139a747e4fSDavid du Colombier {
8149a747e4fSDavid du Colombier ucPLLStatus = mgaread8(mga, 0x3c0a);
8159a747e4fSDavid du Colombier if (0) trace("ucPLLStatus[2] : 0x%x\n", ucPLLStatus);
8169a747e4fSDavid du Colombier if(ucPLLStatus & 0x40)
8179a747e4fSDavid du Colombier {
8189a747e4fSDavid du Colombier ulLockCount++;
8199a747e4fSDavid du Colombier }
8209a747e4fSDavid du Colombier }
8219a747e4fSDavid du Colombier }
8229a747e4fSDavid du Colombier
8239a747e4fSDavid du Colombier *lpbLocked = ulLockCount >= 90;
8249a747e4fSDavid du Colombier }
8259a747e4fSDavid du Colombier
8269a747e4fSDavid du Colombier static void
G450SetPLLFreq(Mga * mga,long f_out)8279a747e4fSDavid du Colombier G450SetPLLFreq(Mga* mga, long f_out)
8289a747e4fSDavid du Colombier {
8299a747e4fSDavid du Colombier int bFoundValidPLL;
8309a747e4fSDavid du Colombier int bLocked;
8319a747e4fSDavid du Colombier ulong ulMaxIndex;
8329a747e4fSDavid du Colombier ulong ulMNP;
8339a747e4fSDavid du Colombier ulong ulMNPTable[MNP_TABLE_SIZE];
8349a747e4fSDavid du Colombier ulong ulIndex;
8359a747e4fSDavid du Colombier ulong ulTryMNP;
8369a747e4fSDavid du Colombier long lCompareResult;
8379a747e4fSDavid du Colombier
8389a747e4fSDavid du Colombier trace("f_out : %ld\n", f_out);
8399a747e4fSDavid du Colombier
8409a747e4fSDavid du Colombier G450FindFirstPLLParam(mga, f_out, &ulMNP);
8419a747e4fSDavid du Colombier ulMNPTable[0] = ulMNP;
8429a747e4fSDavid du Colombier G450FindNextPLLParam(mga, f_out, &ulMNP);
8439a747e4fSDavid du Colombier ulMaxIndex = 1;
8449a747e4fSDavid du Colombier while(ulMNP != 0xffffffff)
8459a747e4fSDavid du Colombier {
8469a747e4fSDavid du Colombier int ulIndex;
8479a747e4fSDavid du Colombier int bSkipValue;
8489a747e4fSDavid du Colombier
8499a747e4fSDavid du Colombier bSkipValue = FALSE;
8509a747e4fSDavid du Colombier if(ulMaxIndex == MNP_TABLE_SIZE)
8519a747e4fSDavid du Colombier {
8529a747e4fSDavid du Colombier G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1],
8539a747e4fSDavid du Colombier &lCompareResult);
8549a747e4fSDavid du Colombier
8559a747e4fSDavid du Colombier if(lCompareResult > 0)
8569a747e4fSDavid du Colombier {
8579a747e4fSDavid du Colombier bSkipValue = TRUE;
8589a747e4fSDavid du Colombier }
8599a747e4fSDavid du Colombier else
8609a747e4fSDavid du Colombier {
8619a747e4fSDavid du Colombier ulMaxIndex--;
8629a747e4fSDavid du Colombier }
8639a747e4fSDavid du Colombier }
8649a747e4fSDavid du Colombier
8659a747e4fSDavid du Colombier if(!bSkipValue)
8669a747e4fSDavid du Colombier {
8679a747e4fSDavid du Colombier for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--)
8689a747e4fSDavid du Colombier {
8699a747e4fSDavid du Colombier G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[ulIndex - 1],
8709a747e4fSDavid du Colombier &lCompareResult);
8719a747e4fSDavid du Colombier
8729a747e4fSDavid du Colombier if(lCompareResult < 0)
8739a747e4fSDavid du Colombier {
8749a747e4fSDavid du Colombier ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1];
8759a747e4fSDavid du Colombier }
8769a747e4fSDavid du Colombier else
8779a747e4fSDavid du Colombier {
8789a747e4fSDavid du Colombier break;
8799a747e4fSDavid du Colombier }
8809a747e4fSDavid du Colombier }
8819a747e4fSDavid du Colombier ulMNPTable[ulIndex] = ulMNP;
8829a747e4fSDavid du Colombier ulMaxIndex++;
8839a747e4fSDavid du Colombier }
8849a747e4fSDavid du Colombier
8859a747e4fSDavid du Colombier G450FindNextPLLParam(mga, f_out, &ulMNP);
8869a747e4fSDavid du Colombier }
8879a747e4fSDavid du Colombier
8889a747e4fSDavid du Colombier bFoundValidPLL = FALSE;
8899a747e4fSDavid du Colombier ulMNP = 0;
8909a747e4fSDavid du Colombier
8919a747e4fSDavid du Colombier for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++)
8929a747e4fSDavid du Colombier {
8939a747e4fSDavid du Colombier ulTryMNP = ulMNPTable[ulIndex];
8949a747e4fSDavid du Colombier
8959a747e4fSDavid du Colombier {
8969a747e4fSDavid du Colombier bLocked = TRUE;
8979a747e4fSDavid du Colombier if((ulMNPTable[ulIndex] & 0xff00) < 0x300 ||
8989a747e4fSDavid du Colombier (ulMNPTable[ulIndex] & 0xff00) > 0x7a00)
8999a747e4fSDavid du Colombier {
9009a747e4fSDavid du Colombier bLocked = FALSE;
9019a747e4fSDavid du Colombier }
9029a747e4fSDavid du Colombier
9039a747e4fSDavid du Colombier if(bLocked)
9049a747e4fSDavid du Colombier {
9059a747e4fSDavid du Colombier G450WriteMNP(mga, ulTryMNP - 0x300);
9069a747e4fSDavid du Colombier G450IsPllLocked(mga, &bLocked);
9079a747e4fSDavid du Colombier }
9089a747e4fSDavid du Colombier
9099a747e4fSDavid du Colombier if(bLocked)
9109a747e4fSDavid du Colombier {
9119a747e4fSDavid du Colombier G450WriteMNP(mga, ulTryMNP + 0x300);
9129a747e4fSDavid du Colombier G450IsPllLocked(mga, &bLocked);
9139a747e4fSDavid du Colombier }
9149a747e4fSDavid du Colombier
9159a747e4fSDavid du Colombier if(bLocked)
9169a747e4fSDavid du Colombier {
9179a747e4fSDavid du Colombier G450WriteMNP(mga, ulTryMNP - 0x200);
9189a747e4fSDavid du Colombier G450IsPllLocked(mga, &bLocked);
9199a747e4fSDavid du Colombier }
9209a747e4fSDavid du Colombier
9219a747e4fSDavid du Colombier if(bLocked)
9229a747e4fSDavid du Colombier {
9239a747e4fSDavid du Colombier G450WriteMNP(mga, ulTryMNP + 0x200);
9249a747e4fSDavid du Colombier G450IsPllLocked(mga, &bLocked);
9259a747e4fSDavid du Colombier }
9269a747e4fSDavid du Colombier
9279a747e4fSDavid du Colombier if(bLocked)
9289a747e4fSDavid du Colombier {
9299a747e4fSDavid du Colombier G450WriteMNP(mga, ulTryMNP - 0x100);
9309a747e4fSDavid du Colombier G450IsPllLocked(mga, &bLocked);
9319a747e4fSDavid du Colombier }
9329a747e4fSDavid du Colombier
9339a747e4fSDavid du Colombier if(bLocked)
9349a747e4fSDavid du Colombier {
9359a747e4fSDavid du Colombier G450WriteMNP(mga, ulTryMNP + 0x100);
9369a747e4fSDavid du Colombier G450IsPllLocked(mga, &bLocked);
9379a747e4fSDavid du Colombier }
9389a747e4fSDavid du Colombier
9399a747e4fSDavid du Colombier if(bLocked)
9409a747e4fSDavid du Colombier {
9419a747e4fSDavid du Colombier G450WriteMNP(mga, ulTryMNP);
9429a747e4fSDavid du Colombier G450IsPllLocked(mga, &bLocked);
9439a747e4fSDavid du Colombier }
9449a747e4fSDavid du Colombier else if(!ulMNP)
9459a747e4fSDavid du Colombier {
9469a747e4fSDavid du Colombier G450WriteMNP(mga, ulTryMNP);
9479a747e4fSDavid du Colombier G450IsPllLocked(mga, &bLocked);
9489a747e4fSDavid du Colombier if(bLocked)
9499a747e4fSDavid du Colombier {
9509a747e4fSDavid du Colombier ulMNP = ulMNPTable[ulIndex];
9519a747e4fSDavid du Colombier }
9529a747e4fSDavid du Colombier bLocked = FALSE;
9539a747e4fSDavid du Colombier }
9549a747e4fSDavid du Colombier
9559a747e4fSDavid du Colombier if(bLocked)
9569a747e4fSDavid du Colombier {
9579a747e4fSDavid du Colombier bFoundValidPLL = TRUE;
9589a747e4fSDavid du Colombier }
9599a747e4fSDavid du Colombier }
9609a747e4fSDavid du Colombier }
9619a747e4fSDavid du Colombier
9629a747e4fSDavid du Colombier if(!bFoundValidPLL)
9639a747e4fSDavid du Colombier {
9649a747e4fSDavid du Colombier if(ulMNP)
9659a747e4fSDavid du Colombier {
9669a747e4fSDavid du Colombier G450WriteMNP(mga, ulMNP);
9679a747e4fSDavid du Colombier }
9689a747e4fSDavid du Colombier else
9699a747e4fSDavid du Colombier {
9709a747e4fSDavid du Colombier G450WriteMNP(mga, ulMNPTable[0]);
9719a747e4fSDavid du Colombier }
9729a747e4fSDavid du Colombier }
9739a747e4fSDavid du Colombier }
9749a747e4fSDavid du Colombier
9759a747e4fSDavid du Colombier
9769a747e4fSDavid du Colombier /* ************************************************************ */
9779a747e4fSDavid du Colombier
9789a747e4fSDavid du Colombier /*
9799a747e4fSDavid du Colombier calcclock - Calculate the PLL settings (m, n, p, s).
9809a747e4fSDavid du Colombier */
9819a747e4fSDavid du Colombier static double
g400_calcclock(Mga * mga,long Fneeded)9829a747e4fSDavid du Colombier g400_calcclock(Mga* mga, long Fneeded)
9839a747e4fSDavid du Colombier {
9849a747e4fSDavid du Colombier double Fpll;
9859a747e4fSDavid du Colombier double Fvco;
9869a747e4fSDavid du Colombier double Fref;
9879a747e4fSDavid du Colombier int pixpll_m_min;
9889a747e4fSDavid du Colombier int pixpll_m_max;
9899a747e4fSDavid du Colombier int pixpll_n_min;
9909a747e4fSDavid du Colombier int pixpll_n_max;
9919a747e4fSDavid du Colombier int pixpll_p_max;
9929a747e4fSDavid du Colombier double Ferr, Fcalc;
9939a747e4fSDavid du Colombier int m, n, p;
9949a747e4fSDavid du Colombier
995816336a7SDavid du Colombier if (mga->devid == MGA4XX || mga->devid == MGA550) {
9969a747e4fSDavid du Colombier /* These values are taken from Matrox G400 Specification - p 4-91 */
9979a747e4fSDavid du Colombier Fref = 27000000.0;
9989a747e4fSDavid du Colombier pixpll_n_min = 7;
9999a747e4fSDavid du Colombier pixpll_n_max = 127;
10009a747e4fSDavid du Colombier pixpll_m_min = 1;
10019a747e4fSDavid du Colombier pixpll_m_max = 31;
10029a747e4fSDavid du Colombier pixpll_p_max = 7;
1003816336a7SDavid du Colombier } else { /* MGA200 */
10049a747e4fSDavid du Colombier /* These values are taken from Matrox G200 Specification - p 4-77 */
10059a747e4fSDavid du Colombier //Fref = 14318180.0;
10069a747e4fSDavid du Colombier Fref = 27050500.0;
10079a747e4fSDavid du Colombier pixpll_n_min = 7;
10089a747e4fSDavid du Colombier pixpll_n_max = 127;
10099a747e4fSDavid du Colombier pixpll_m_min = 1;
10109a747e4fSDavid du Colombier pixpll_m_max = 6;
10119a747e4fSDavid du Colombier pixpll_p_max = 7;
10129a747e4fSDavid du Colombier }
10139a747e4fSDavid du Colombier
10149a747e4fSDavid du Colombier Fvco = ( double ) Fneeded;
10159a747e4fSDavid du Colombier for (p = 0; p <= pixpll_p_max && Fvco < mga->maxpclk; p = p * 2 + 1, Fvco *= 2.0)
10169a747e4fSDavid du Colombier ;
10179a747e4fSDavid du Colombier mga->pixpll_p = p;
10189a747e4fSDavid du Colombier
10199a747e4fSDavid du Colombier Ferr = Fneeded;
10209a747e4fSDavid du Colombier for ( m = pixpll_m_min ; m <= pixpll_m_max ; m++ )
10219a747e4fSDavid du Colombier for ( n = pixpll_n_min; n <= pixpll_n_max; n++ )
10229a747e4fSDavid du Colombier {
10239a747e4fSDavid du Colombier Fcalc = Fref * (n + 1) / (m + 1) ;
10249a747e4fSDavid du Colombier
10259a747e4fSDavid du Colombier /*
10269a747e4fSDavid du Colombier * Pick the closest frequency.
10279a747e4fSDavid du Colombier */
10289a747e4fSDavid du Colombier if ( labs(Fcalc - Fvco) < Ferr ) {
10299a747e4fSDavid du Colombier Ferr = abs(Fcalc - Fvco);
10309a747e4fSDavid du Colombier mga->pixpll_m = m;
10319a747e4fSDavid du Colombier mga->pixpll_n = n;
10329a747e4fSDavid du Colombier }
10339a747e4fSDavid du Colombier }
10349a747e4fSDavid du Colombier
10359a747e4fSDavid du Colombier Fvco = Fref * (mga->pixpll_n + 1) / (mga->pixpll_m + 1);
10369a747e4fSDavid du Colombier
1037816336a7SDavid du Colombier if (mga->devid == MGA4XX || mga->devid == MGA550) {
10389a747e4fSDavid du Colombier if ( (50000000.0 <= Fvco) && (Fvco < 110000000.0) )
10399a747e4fSDavid du Colombier mga->pixpll_p |= 0;
10409a747e4fSDavid du Colombier if ( (110000000.0 <= Fvco) && (Fvco < 170000000.0) )
10419a747e4fSDavid du Colombier mga->pixpll_p |= (1<<3);
10429a747e4fSDavid du Colombier if ( (170000000.0 <= Fvco) && (Fvco < 240000000.0) )
10439a747e4fSDavid du Colombier mga->pixpll_p |= (2<<3);
10449a747e4fSDavid du Colombier if ( (300000000.0 <= Fvco) )
10459a747e4fSDavid du Colombier mga->pixpll_p |= (3<<3);
10469a747e4fSDavid du Colombier } else {
10479a747e4fSDavid du Colombier if ( (50000000.0 <= Fvco) && (Fvco < 100000000.0) )
10489a747e4fSDavid du Colombier mga->pixpll_p |= 0;
10499a747e4fSDavid du Colombier if ( (100000000.0 <= Fvco) && (Fvco < 140000000.0) )
10509a747e4fSDavid du Colombier mga->pixpll_p |= (1<<3);
10519a747e4fSDavid du Colombier if ( (140000000.0 <= Fvco) && (Fvco < 180000000.0) )
10529a747e4fSDavid du Colombier mga->pixpll_p |= (2<<3);
10539a747e4fSDavid du Colombier if ( (250000000.0 <= Fvco) )
10549a747e4fSDavid du Colombier mga->pixpll_p |= (3<<3);
10559a747e4fSDavid du Colombier }
10569a747e4fSDavid du Colombier
10579a747e4fSDavid du Colombier Fpll = Fvco / (p + 1);
10589a747e4fSDavid du Colombier
10599a747e4fSDavid du Colombier return Fpll;
10609a747e4fSDavid du Colombier }
10619a747e4fSDavid du Colombier
10629a747e4fSDavid du Colombier /* ************************************************************ */
10639a747e4fSDavid du Colombier
10649a747e4fSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)10659a747e4fSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
10669a747e4fSDavid du Colombier {
10679a747e4fSDavid du Colombier Mode* mode;
10689a747e4fSDavid du Colombier Mga* mga;
10699a747e4fSDavid du Colombier double Fpll;
10709a747e4fSDavid du Colombier Ctlr* c;
10719a747e4fSDavid du Colombier int i;
10729a747e4fSDavid du Colombier ulong t;
10731066d6deSDavid du Colombier int bppShift;
10749a747e4fSDavid du Colombier
10759a747e4fSDavid du Colombier mga = vga->private;
10769a747e4fSDavid du Colombier mode = vga->mode;
10779a747e4fSDavid du Colombier
107874f16c81SDavid du Colombier trace("mga mmio at %#p\n", mga->mmio);
10799a747e4fSDavid du Colombier
10809a747e4fSDavid du Colombier ctlr->flag |= Ulinear;
10819a747e4fSDavid du Colombier
10821066d6deSDavid du Colombier /*
1083*0792d947SDavid du Colombier * Set the right bppShift based on depth
10841066d6deSDavid du Colombier */
10851066d6deSDavid du Colombier
10861066d6deSDavid du Colombier switch(mode->z) {
10871066d6deSDavid du Colombier case 8:
10881066d6deSDavid du Colombier bppShift = 0;
10891066d6deSDavid du Colombier break;
10901066d6deSDavid du Colombier case 16:
10911066d6deSDavid du Colombier bppShift = 1;
10921066d6deSDavid du Colombier break;
10931066d6deSDavid du Colombier case 24:
10941066d6deSDavid du Colombier bppShift = 0;
10951066d6deSDavid du Colombier break;
10961066d6deSDavid du Colombier case 32:
10971066d6deSDavid du Colombier bppShift = 2;
10981066d6deSDavid du Colombier break;
10991066d6deSDavid du Colombier default:
11001066d6deSDavid du Colombier bppShift = 0;
11019a747e4fSDavid du Colombier error("depth %d not supported !\n", mode->z);
11021066d6deSDavid du Colombier }
11039a747e4fSDavid du Colombier
11049a747e4fSDavid du Colombier if (mode->interlace)
11059a747e4fSDavid du Colombier error("interlaced mode not supported !\n");
11069a747e4fSDavid du Colombier
11079a747e4fSDavid du Colombier trace("%s: Initializing mode %dx%dx%d on %s\n", ctlr->name, mode->x, mode->y, mode->z, mode->type);
11089a747e4fSDavid du Colombier trace("%s: Suggested Dot Clock : %d\n", ctlr->name, mode->frequency);
11099a747e4fSDavid du Colombier trace("%s: Horizontal Total = %d\n", ctlr->name, mode->ht);
11109a747e4fSDavid du Colombier trace("%s: Start Horizontal Blank = %d\n", ctlr->name, mode->shb);
11119a747e4fSDavid du Colombier trace("%s: End Horizontal Blank = %d\n", ctlr->name, mode->ehb);
11129a747e4fSDavid du Colombier trace("%s: Vertical Total = %d\n", ctlr->name, mode->vt);
11139a747e4fSDavid du Colombier trace("%s: Vertical Retrace Start = %d\n", ctlr->name, mode->vrs);
11149a747e4fSDavid du Colombier trace("%s: Vertical Retrace End = %d\n", ctlr->name, mode->vre);
11159a747e4fSDavid du Colombier trace("%s: Start Horizontal Sync = %d\n", ctlr->name, mode->shs);
11169a747e4fSDavid du Colombier trace("%s: End Horizontal Sync = %d\n", ctlr->name, mode->ehs);
11179a747e4fSDavid du Colombier trace("%s: HSync = %c\n", ctlr->name, mode->hsync);
11189a747e4fSDavid du Colombier trace("%s: VSync = %c\n", ctlr->name, mode->vsync);
11199a747e4fSDavid du Colombier trace("%s: Interlace = %d\n", ctlr->name, mode->interlace);
11209a747e4fSDavid du Colombier
11219a747e4fSDavid du Colombier /* TODO : G400 Max : 360000000 */
1122816336a7SDavid du Colombier if (mga->devid == MGA4XX || mga->devid == MGA550)
11239a747e4fSDavid du Colombier mga->maxpclk = 300000000;
11249a747e4fSDavid du Colombier else
11259a747e4fSDavid du Colombier mga->maxpclk = 250000000;
11269a747e4fSDavid du Colombier
11279a747e4fSDavid du Colombier if (mode->frequency < 50000)
11288cf6001eSDavid du Colombier error("mga: Too little Frequency %d : Minimum supported by PLL is %d\n",
11299a747e4fSDavid du Colombier mode->frequency, 50000);
11309a747e4fSDavid du Colombier
11319a747e4fSDavid du Colombier if (mode->frequency > mga->maxpclk)
11328cf6001eSDavid du Colombier error("mga: Too big Frequency %d : Maximum supported by PLL is %ld\n",
11339a747e4fSDavid du Colombier mode->frequency, mga->maxpclk);
11349a747e4fSDavid du Colombier
11359a747e4fSDavid du Colombier trace("mga: revision ID is %x\n", mga->revid);
1136816336a7SDavid du Colombier if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
11379a747e4fSDavid du Colombier /* Is it G200/G400 or G450 ? */
11389a747e4fSDavid du Colombier Fpll = g400_calcclock(mga, mode->frequency);
11399a747e4fSDavid du Colombier trace("Fpll set to %f\n", Fpll);
11409a747e4fSDavid du Colombier trace("pixclks : n = %d m = %d p = %d\n", mga->pixpll_n, mga->pixpll_m, mga->pixpll_p & 0x7);
11419a747e4fSDavid du Colombier } else
11429a747e4fSDavid du Colombier mga->Fneeded = mode->frequency;
11439a747e4fSDavid du Colombier
11449a747e4fSDavid du Colombier trace("PCI Option1 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption1));
11459a747e4fSDavid du Colombier trace("PCI Option2 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption2));
11469a747e4fSDavid du Colombier trace("PCI Option3 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption3));
11479a747e4fSDavid du Colombier
11489a747e4fSDavid du Colombier mga->htotal = (mode->ht >> 3) - 5;
11499a747e4fSDavid du Colombier mga->hdispend = (mode->x >> 3) - 1;
11509a747e4fSDavid du Colombier mga->hblkstr = mga->hdispend; /* (mode->shb >> 3); */
11519a747e4fSDavid du Colombier mga->hblkend = mga->htotal + 4; /* (mode->ehb >> 3); */
11529a747e4fSDavid du Colombier mga->hsyncstr = (mode->shs >> 3) - 1; // Was (mode->shs >> 3);
11539a747e4fSDavid du Colombier mga->hsyncend = (mode->ehs >> 3) - 1; // Was (mode->ehs >> 3);
11549a747e4fSDavid du Colombier mga->hsyncdel = 0;
11559a747e4fSDavid du Colombier mga->vtotal = mode->vt - 2;
11569a747e4fSDavid du Colombier mga->vdispend = mode->y - 1;
11579a747e4fSDavid du Colombier mga->vblkstr = mode->y - 1;
11589a747e4fSDavid du Colombier mga->vblkend = mode->vt - 1;
11599a747e4fSDavid du Colombier mga->vsyncstr = mode->vrs;
11609a747e4fSDavid du Colombier mga->vsyncend = mode->vre;
11619a747e4fSDavid du Colombier mga->linecomp = mode->y;
11629a747e4fSDavid du Colombier mga->hsyncsel = 0; /* Do not double lines ... */
11639a747e4fSDavid du Colombier mga->startadd = 0;
11641066d6deSDavid du Colombier mga->offset = (mode->z==24) ? (vga->virtx * 3) >> (4 - bppShift) : vga->virtx >> (4-bppShift);
11659a747e4fSDavid du Colombier /* No Zoom */
11669a747e4fSDavid du Colombier mga->maxscan = 0;
11679a747e4fSDavid du Colombier /* Not used in Power Graphic mode */
11689a747e4fSDavid du Colombier mga->curloc = 0;
11699a747e4fSDavid du Colombier mga->prowscan = 0;
11709a747e4fSDavid du Colombier mga->currowstr = 0;
11719a747e4fSDavid du Colombier mga->currowend = 0;
11729a747e4fSDavid du Colombier mga->curoff = 1;
11739a747e4fSDavid du Colombier mga->undrow = 0;
11749a747e4fSDavid du Colombier mga->curskew = 0;
11759a747e4fSDavid du Colombier mga->conv2t4 = 0;
11769a747e4fSDavid du Colombier mga->interlace = 0;
11779a747e4fSDavid du Colombier mga->hdispskew = 0;
11789a747e4fSDavid du Colombier mga->bytepan = 0;
11799a747e4fSDavid du Colombier mga->dotclkrt = 0;
11809a747e4fSDavid du Colombier mga->dword = 0;
11819a747e4fSDavid du Colombier mga->wbmode = 1;
11829a747e4fSDavid du Colombier mga->addwrap = 0; /* Not Used ! */
11839a747e4fSDavid du Colombier mga->selrowscan = 1;
11849a747e4fSDavid du Colombier mga->cms = 1;
11859a747e4fSDavid du Colombier mga->csynccen = 0; /* Disable composite sync */
11869a747e4fSDavid du Colombier
11879a747e4fSDavid du Colombier /* VIDRST Pin */
11889a747e4fSDavid du Colombier mga->hrsten = 0; // Was 1;
11899a747e4fSDavid du Colombier mga->vrsten = 0; // Was 1;
11909a747e4fSDavid du Colombier
11919a747e4fSDavid du Colombier /* vertical interrupt control ... disabled */
11929a747e4fSDavid du Colombier mga->vinten = 1;
11939a747e4fSDavid du Colombier mga->vintclr = 0;
11949a747e4fSDavid du Colombier
11959a747e4fSDavid du Colombier /* Let [hv]sync run freely */
11969a747e4fSDavid du Colombier mga->hsyncoff = 0;
11979a747e4fSDavid du Colombier mga->vsyncoff = 0;
11989a747e4fSDavid du Colombier
11999a747e4fSDavid du Colombier mga->crtcrstN = 1;
12009a747e4fSDavid du Colombier
12019a747e4fSDavid du Colombier mga->mgamode = 1;
12021066d6deSDavid du Colombier mga->scale = (mode->z == 24) ? ((1 << bppShift)*3)-1 : (1 << bppShift)-1;
12039a747e4fSDavid du Colombier
12049a747e4fSDavid du Colombier mga->crtcprotect = 1;
12059a747e4fSDavid du Colombier mga->winsize = 0;
12069a747e4fSDavid du Colombier mga->winfreq = 0;
12079a747e4fSDavid du Colombier
12089a747e4fSDavid du Colombier if ((mga->htotal == 0)
12099a747e4fSDavid du Colombier || (mga->hblkend <= (mga->hblkstr + 1))
12109a747e4fSDavid du Colombier || ((mga->htotal - mga->hdispend) == 0)
12119a747e4fSDavid du Colombier || ((mga->htotal - mga->bytepan + 2) <= mga->hdispend)
12129a747e4fSDavid du Colombier || (mga->hsyncstr <= (mga->hdispend + 2))
12139a747e4fSDavid du Colombier || (mga->vtotal == 0))
12149a747e4fSDavid du Colombier {
12159a747e4fSDavid du Colombier error("Invalid Power Graphic Mode :\n"
12169a747e4fSDavid du Colombier "mga->htotal = %ld\n"
12179a747e4fSDavid du Colombier "mga->hdispend = %ld\n"
12189a747e4fSDavid du Colombier "mga->hblkstr = %ld\n"
12199a747e4fSDavid du Colombier "mga->hblkend = %ld\n"
12209a747e4fSDavid du Colombier "mga->hsyncstr = %ld\n"
12219a747e4fSDavid du Colombier "mga->hsyncend = %ld\n"
12229a747e4fSDavid du Colombier "mga->hsyncdel = %ld\n"
12239a747e4fSDavid du Colombier "mga->vtotal = %ld\n"
12249a747e4fSDavid du Colombier "mga->vdispend = %ld\n"
12259a747e4fSDavid du Colombier "mga->vblkstr = %ld\n"
12269a747e4fSDavid du Colombier "mga->vblkend = %ld\n"
12279a747e4fSDavid du Colombier "mga->vsyncstr = %ld\n"
12289a747e4fSDavid du Colombier "mga->vsyncend = %ld\n"
12299a747e4fSDavid du Colombier "mga->linecomp = %ld\n",
12309a747e4fSDavid du Colombier mga->htotal,
12319a747e4fSDavid du Colombier mga->hdispend,
12329a747e4fSDavid du Colombier mga->hblkstr,
12339a747e4fSDavid du Colombier mga->hblkend,
12349a747e4fSDavid du Colombier mga->hsyncstr,
12359a747e4fSDavid du Colombier mga->hsyncend,
12369a747e4fSDavid du Colombier mga->hsyncdel,
12379a747e4fSDavid du Colombier mga->vtotal,
12389a747e4fSDavid du Colombier mga->vdispend,
12399a747e4fSDavid du Colombier mga->vblkstr,
12409a747e4fSDavid du Colombier mga->vblkend,
12419a747e4fSDavid du Colombier mga->vsyncstr,
12429a747e4fSDavid du Colombier mga->vsyncend,
12439a747e4fSDavid du Colombier mga->linecomp
12449a747e4fSDavid du Colombier );
12459a747e4fSDavid du Colombier }
12469a747e4fSDavid du Colombier
12479a747e4fSDavid du Colombier mga->hiprilvl = 0;
12489a747e4fSDavid du Colombier mga->maxhipri = 0;
12499a747e4fSDavid du Colombier mga->c2hiprilvl = 0;
12509a747e4fSDavid du Colombier mga->c2maxhipri = 0;
12519a747e4fSDavid du Colombier
12529a747e4fSDavid du Colombier mga->misc = ((mode->hsync != '-')?0:(1<<6)) | ((mode->vsync != '-')?0:(1<<7));
12539a747e4fSDavid du Colombier
12549a747e4fSDavid du Colombier trace("mga->htotal = %ld\n"
12559a747e4fSDavid du Colombier "mga->hdispend = %ld\n"
12569a747e4fSDavid du Colombier "mga->hblkstr = %ld\n"
12579a747e4fSDavid du Colombier "mga->hblkend = %ld\n"
12589a747e4fSDavid du Colombier "mga->hsyncstr = %ld\n"
12599a747e4fSDavid du Colombier "mga->hsyncend = %ld\n"
12609a747e4fSDavid du Colombier "mga->hsyncdel = %ld\n"
12619a747e4fSDavid du Colombier "mga->vtotal = %ld\n"
12629a747e4fSDavid du Colombier "mga->vdispend = %ld\n"
12639a747e4fSDavid du Colombier "mga->vblkstr = %ld\n"
12649a747e4fSDavid du Colombier "mga->vblkend = %ld\n"
12659a747e4fSDavid du Colombier "mga->vsyncstr = %ld\n"
12669a747e4fSDavid du Colombier "mga->vsyncend = %ld\n"
12679a747e4fSDavid du Colombier "mga->linecomp = %ld\n",
12689a747e4fSDavid du Colombier mga->htotal,
12699a747e4fSDavid du Colombier mga->hdispend,
12709a747e4fSDavid du Colombier mga->hblkstr,
12719a747e4fSDavid du Colombier mga->hblkend,
12729a747e4fSDavid du Colombier mga->hsyncstr,
12739a747e4fSDavid du Colombier mga->hsyncend,
12749a747e4fSDavid du Colombier mga->hsyncdel,
12759a747e4fSDavid du Colombier mga->vtotal,
12769a747e4fSDavid du Colombier mga->vdispend,
12779a747e4fSDavid du Colombier mga->vblkstr,
12789a747e4fSDavid du Colombier mga->vblkend,
12799a747e4fSDavid du Colombier mga->vsyncstr,
12809a747e4fSDavid du Colombier mga->vsyncend,
12819a747e4fSDavid du Colombier mga->linecomp
12829a747e4fSDavid du Colombier );
12839a747e4fSDavid du Colombier
12849a747e4fSDavid du Colombier mga->crtc[0x00] = 0xff & mga->htotal;
12859a747e4fSDavid du Colombier
12869a747e4fSDavid du Colombier mga->crtc[0x01] = 0xff & mga->hdispend;
12879a747e4fSDavid du Colombier
12889a747e4fSDavid du Colombier mga->crtc[0x02] = 0xff & mga->hblkstr;
12899a747e4fSDavid du Colombier
12909a747e4fSDavid du Colombier mga->crtc[0x03] = (0x1f & mga->hblkend)
12919a747e4fSDavid du Colombier | ((0x03 & mga->hdispskew) << 5)
12929a747e4fSDavid du Colombier | 0x80 /* cf 3-304 */
12939a747e4fSDavid du Colombier ;
12949a747e4fSDavid du Colombier
12959a747e4fSDavid du Colombier mga->crtc[0x04] = 0xff & mga->hsyncstr;
12969a747e4fSDavid du Colombier
12979a747e4fSDavid du Colombier mga->crtc[0x05] = (0x1f & mga->hsyncend)
12989a747e4fSDavid du Colombier | ((0x03 & mga->hsyncdel) << 5)
12999a747e4fSDavid du Colombier | ((0x01 & (mga->hblkend >> 5)) << 7)
13009a747e4fSDavid du Colombier ;
13019a747e4fSDavid du Colombier
13029a747e4fSDavid du Colombier mga->crtc[0x06] = 0xff & mga->vtotal;
13039a747e4fSDavid du Colombier
13049a747e4fSDavid du Colombier t = ((0x01 & (mga->vtotal >> 8)) << 0)
13059a747e4fSDavid du Colombier | ((0x01 & (mga->vdispend >> 8)) << 1)
13069a747e4fSDavid du Colombier | ((0x01 & (mga->vsyncstr >> 8)) << 2)
13079a747e4fSDavid du Colombier | ((0x01 & (mga->vblkstr >> 8)) << 3)
13089a747e4fSDavid du Colombier | ((0x01 & (mga->linecomp >> 8)) << 4)
13099a747e4fSDavid du Colombier | ((0x01 & (mga->vtotal >> 9)) << 5)
13109a747e4fSDavid du Colombier | ((0x01 & (mga->vdispend >> 9)) << 6)
13119a747e4fSDavid du Colombier | ((0x01 & (mga->vsyncstr >> 9)) << 7)
13129a747e4fSDavid du Colombier ;
13139a747e4fSDavid du Colombier mga->crtc[0x07] = 0xff & t;
13149a747e4fSDavid du Colombier
13159a747e4fSDavid du Colombier mga->crtc[0x08] = (0x1f & mga->prowscan)
13169a747e4fSDavid du Colombier | ((0x03 & mga->bytepan) << 5)
13179a747e4fSDavid du Colombier ;
13189a747e4fSDavid du Colombier
13199a747e4fSDavid du Colombier mga->crtc[0x09] = (0x1f & mga->maxscan)
13209a747e4fSDavid du Colombier | ((0x01 & (mga->vblkstr >> 9)) << 5)
13219a747e4fSDavid du Colombier | ((0x01 & (mga->linecomp >> 9)) << 6)
13229a747e4fSDavid du Colombier | ((0x01 & mga->conv2t4) << 7)
13239a747e4fSDavid du Colombier ;
13249a747e4fSDavid du Colombier
13259a747e4fSDavid du Colombier mga->crtc[0x0a] = (0x1f & mga->currowstr)
13269a747e4fSDavid du Colombier | ((0x01 & mga->curoff) << 5)
13279a747e4fSDavid du Colombier ;
13289a747e4fSDavid du Colombier
13299a747e4fSDavid du Colombier mga->crtc[0x0b] = (0x1f & mga->currowend)
13309a747e4fSDavid du Colombier | ((0x03 & mga->curskew) << 5)
13319a747e4fSDavid du Colombier ;
13329a747e4fSDavid du Colombier
13339a747e4fSDavid du Colombier mga->crtc[0x0c] = 0xff & (mga->startadd >> 8);
13349a747e4fSDavid du Colombier
13359a747e4fSDavid du Colombier mga->crtc[0x0d] = 0xff & mga->startadd;
13369a747e4fSDavid du Colombier
13379a747e4fSDavid du Colombier mga->crtc[0x0e] = 0xff & (mga->curloc >> 8);
13389a747e4fSDavid du Colombier
13399a747e4fSDavid du Colombier mga->crtc[0x0f] = 0xff & mga->curloc;
13409a747e4fSDavid du Colombier
13419a747e4fSDavid du Colombier mga->crtc[0x10] = 0xff & mga->vsyncstr;
13429a747e4fSDavid du Colombier
13439a747e4fSDavid du Colombier mga->crtc[0x11] = (0x0f & mga->vsyncend)
13449a747e4fSDavid du Colombier | ((0x01 & mga->vintclr) << 4)
13459a747e4fSDavid du Colombier | ((0x01 & mga->vinten) << 5)
13469a747e4fSDavid du Colombier | ((0x01 & mga->crtcprotect) << 7)
13479a747e4fSDavid du Colombier ;
13489a747e4fSDavid du Colombier
13499a747e4fSDavid du Colombier mga->crtc[0x12] = 0xff & mga->vdispend;
13509a747e4fSDavid du Colombier
13519a747e4fSDavid du Colombier mga->crtc[0x13] = 0xff & mga->offset;
13529a747e4fSDavid du Colombier
13539a747e4fSDavid du Colombier mga->crtc[0x14] = 0x1f & mga->undrow; /* vga only */
13549a747e4fSDavid du Colombier
13559a747e4fSDavid du Colombier mga->crtc[0x15] = 0xff & mga->vblkstr;
13569a747e4fSDavid du Colombier
13579a747e4fSDavid du Colombier mga->crtc[0x16] = 0xff & mga->vblkend;
13589a747e4fSDavid du Colombier
13599a747e4fSDavid du Colombier mga->crtc[0x17] = ((0x01 & mga->cms) << 0)
13609a747e4fSDavid du Colombier | ((0x01 & mga->selrowscan) << 1)
13619a747e4fSDavid du Colombier | ((0x01 & mga->hsyncsel) << 2)
13629a747e4fSDavid du Colombier | ((0x01 & mga->addwrap) << 5)
13639a747e4fSDavid du Colombier | ((0x01 & mga->wbmode) << 6)
13649a747e4fSDavid du Colombier | ((0x01 & mga->crtcrstN) << 7)
13659a747e4fSDavid du Colombier ;
13669a747e4fSDavid du Colombier
13679a747e4fSDavid du Colombier mga->crtc[0x18] = 0xff & mga->linecomp;
13689a747e4fSDavid du Colombier
13699a747e4fSDavid du Colombier mga->crtcext[0] = (0x0f & (mga->startadd >> 16))
13709a747e4fSDavid du Colombier | ((0x03 & (mga->offset >> 8)) << 4)
13719a747e4fSDavid du Colombier | ((0x01 & (mga->startadd >> 20)) << 6)
13729a747e4fSDavid du Colombier | ((0x01 & mga->interlace) << 7)
13739a747e4fSDavid du Colombier ;
13749a747e4fSDavid du Colombier
13759a747e4fSDavid du Colombier mga->crtcext[1] = ((0x01 & (mga->htotal >> 8)) << 0)
13769a747e4fSDavid du Colombier | ((0x01 & (mga->hblkstr >> 8)) << 1)
13779a747e4fSDavid du Colombier | ((0x01 & (mga->hsyncstr >> 8)) << 2)
13789a747e4fSDavid du Colombier | ((0x01 & mga->hrsten) << 3)
13799a747e4fSDavid du Colombier | ((0x01 & mga->hsyncoff) << 4)
13809a747e4fSDavid du Colombier | ((0x01 & mga->vsyncoff) << 5)
13819a747e4fSDavid du Colombier | ((0x01 & (mga->hblkend >> 6)) << 6)
13829a747e4fSDavid du Colombier | ((0x01 & mga->vrsten) << 7)
13839a747e4fSDavid du Colombier ;
13849a747e4fSDavid du Colombier
13859a747e4fSDavid du Colombier mga->crtcext[2] = ((0x03 & (mga->vtotal >> 10)) << 0)
13869a747e4fSDavid du Colombier | ((0x01 & (mga->vdispend >> 10)) << 2)
13879a747e4fSDavid du Colombier | ((0x03 & (mga->vblkstr >> 10)) << 3)
13889a747e4fSDavid du Colombier | ((0x03 & (mga->vsyncstr >> 10)) << 5)
13899a747e4fSDavid du Colombier | ((0x01 & (mga->linecomp >> 10)) << 7)
13909a747e4fSDavid du Colombier ;
13919a747e4fSDavid du Colombier
13929a747e4fSDavid du Colombier mga->crtcext[3] = ((0x07 & mga->scale) << 0)
13939a747e4fSDavid du Colombier | ((0x01 & mga->csynccen) << 6)
13949a747e4fSDavid du Colombier | ((0x01 & mga->mgamode) << 7)
13959a747e4fSDavid du Colombier ;
13969a747e4fSDavid du Colombier
13979a747e4fSDavid du Colombier mga->crtcext[4] = 0; /* memory page ... not used in Power Graphic Mode */
13989a747e4fSDavid du Colombier
13999a747e4fSDavid du Colombier mga->crtcext[5] = 0; /* Not used in non-interlaced mode */
14009a747e4fSDavid du Colombier
14019a747e4fSDavid du Colombier mga->crtcext[6] = ((0x07 & mga->hiprilvl) << 0)
14029a747e4fSDavid du Colombier | ((0x07 & mga->maxhipri) << 4)
14039a747e4fSDavid du Colombier ;
14049a747e4fSDavid du Colombier
14059a747e4fSDavid du Colombier mga->crtcext[7] = ((0x07 & mga->winsize) << 1)
14069a747e4fSDavid du Colombier | ((0x07 & mga->winfreq) << 5)
14079a747e4fSDavid du Colombier ;
14089a747e4fSDavid du Colombier
14099a747e4fSDavid du Colombier mga->crtcext[8] = (0x01 & (mga->startadd >> 21)) << 0;
14109a747e4fSDavid du Colombier
14119a747e4fSDavid du Colombier /* Initialize Sequencer */
14129a747e4fSDavid du Colombier mga->sequencer[0] = 0;
14139a747e4fSDavid du Colombier mga->sequencer[1] = 0;
14149a747e4fSDavid du Colombier mga->sequencer[2] = 0x03;
14159a747e4fSDavid du Colombier mga->sequencer[3] = 0;
14169a747e4fSDavid du Colombier mga->sequencer[4] = 0x02;
14179a747e4fSDavid du Colombier
14189a747e4fSDavid du Colombier /* Graphic Control registers are ignored when not using 0xA0000 aperture */
14199a747e4fSDavid du Colombier for (i = 0; i < 9; i++)
14209a747e4fSDavid du Colombier mga->graphics[i] = 0;
14219a747e4fSDavid du Colombier
14229a747e4fSDavid du Colombier /* The Attribute Controler is not available in Power Graphics mode */
14239a747e4fSDavid du Colombier for (i = 0; i < 0x15; i++)
14249a747e4fSDavid du Colombier mga->attribute[i] = i;
14259a747e4fSDavid du Colombier
14269a747e4fSDavid du Colombier /* disable vga load (want to do fields in different order) */
14279a747e4fSDavid du Colombier for(c = vga->link; c; c = c->link)
14289a747e4fSDavid du Colombier if (strncmp(c->name, "vga", 3) == 0)
14299a747e4fSDavid du Colombier c->load = nil;
14309a747e4fSDavid du Colombier }
14319a747e4fSDavid du Colombier
14329a747e4fSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)14339a747e4fSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
14349a747e4fSDavid du Colombier {
14359a747e4fSDavid du Colombier Mga* mga;
14369a747e4fSDavid du Colombier int i;
14379a747e4fSDavid du Colombier uchar* p;
14389a747e4fSDavid du Colombier Mode* mode;
14399a747e4fSDavid du Colombier uchar cursor;
14409a747e4fSDavid du Colombier
14419a747e4fSDavid du Colombier mga = vga->private;
14429a747e4fSDavid du Colombier mode = vga->mode;
14439a747e4fSDavid du Colombier
14449a747e4fSDavid du Colombier trace("mga: Loading ...\n");
14459a747e4fSDavid du Colombier dump_all_regs(mga);
14469a747e4fSDavid du Colombier
14479a747e4fSDavid du Colombier if (mode->z == 8)
14489a747e4fSDavid du Colombier setpalettedepth(mode->z);
14499a747e4fSDavid du Colombier
145074f16c81SDavid du Colombier trace("mga mmio at %#p\n", mga->mmio);
14519a747e4fSDavid du Colombier trace("mga: loading vga registers ...\n" );
14529a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
14539a747e4fSDavid du Colombier
14549a747e4fSDavid du Colombier /* Initialize Sequencer registers */
14559a747e4fSDavid du Colombier for(i = 0; i < 5; i++)
14569a747e4fSDavid du Colombier seqset(mga, i, mga->sequencer[i], 0xff);
14579a747e4fSDavid du Colombier
14589a747e4fSDavid du Colombier /* Initialize Attribute register */
14599a747e4fSDavid du Colombier for(i = 0; i < 0x15; i++)
14609a747e4fSDavid du Colombier attrset(mga, i, mga->attribute[i], 0xff);
14619a747e4fSDavid du Colombier
14629a747e4fSDavid du Colombier /* Initialize Graphic Control registers */
14639a747e4fSDavid du Colombier for(i = 0; i < 9; i++)
14649a747e4fSDavid du Colombier gctlset(mga, i, mga->graphics[i], 0xff);
14659a747e4fSDavid du Colombier
14669a747e4fSDavid du Colombier /* Wait VSYNC */
14679a747e4fSDavid du Colombier while (mgaread8(mga, STATUS1) & 0x08);
14689a747e4fSDavid du Colombier while (! (mgaread8(mga, STATUS1) & ~0x08));
14699a747e4fSDavid du Colombier
14709a747e4fSDavid du Colombier /* Turn off the video. */
14719a747e4fSDavid du Colombier seqset(mga, Seq_ClockingMode, Scroff, 0);
14729a747e4fSDavid du Colombier
14739a747e4fSDavid du Colombier /* Crtc2 Off */
14749a747e4fSDavid du Colombier mgawrite32(mga, C2_CTL, 0);
14759a747e4fSDavid du Colombier
14769a747e4fSDavid du Colombier /* Disable Cursor */
14779a747e4fSDavid du Colombier cursor = dacset(mga, Dac_Xcurctrl, CursorDis, 0xff);
14789a747e4fSDavid du Colombier
14799a747e4fSDavid du Colombier /* Pixel Pll UP and set Pixel clock source to Pixel Clock PLL */
14809a747e4fSDavid du Colombier dacset(mga, Dac_Xpixclkctrl, 0x01 | 0x08, 0x0f);
14819a747e4fSDavid du Colombier
14829a747e4fSDavid du Colombier trace("mga: waiting for the clock source becomes stable ...\n");
14839a747e4fSDavid du Colombier while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
14849a747e4fSDavid du Colombier ;
14859a747e4fSDavid du Colombier trace("mga: pixpll locked !\n");
14869a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
14879a747e4fSDavid du Colombier
14889a747e4fSDavid du Colombier /* Enable LUT, Disable MAFC */
14899a747e4fSDavid du Colombier dacset(mga, Dac_Xmiscctrl, Ramcs | Mfcsel, Vdoutsel);
14909a747e4fSDavid du Colombier
14919a747e4fSDavid du Colombier /* Disable Dac */
14929a747e4fSDavid du Colombier dacset(mga, Dac_Xmiscctrl, 0, Dacpdn);
14939a747e4fSDavid du Colombier
14949a747e4fSDavid du Colombier /* Initialize Panel Mode */
14959a747e4fSDavid du Colombier dacset(mga, Dac_Xpanelmode, 0, 0xff);
14969a747e4fSDavid du Colombier
14979a747e4fSDavid du Colombier /* Disable the PIXCLK and set Pixel clock source to Pixel Clock PLL */
14989a747e4fSDavid du Colombier dacset(mga, Dac_Xpixclkctrl, Pixclkdis | 0x01, 0x3);
14999a747e4fSDavid du Colombier
15009a747e4fSDavid du Colombier /* Disable mapping of the memory */
15019a747e4fSDavid du Colombier miscset(mga, 0, Misc_rammapen);
15029a747e4fSDavid du Colombier
15039a747e4fSDavid du Colombier /* Enable 8 bit palette */
15049a747e4fSDavid du Colombier dacset(mga, Dac_Xmiscctrl, Vga8dac, 0);
15059a747e4fSDavid du Colombier
15069a747e4fSDavid du Colombier /* Select MGA Pixel Clock */
15079a747e4fSDavid du Colombier miscset(mga, Misc_clksel, 0);
15089a747e4fSDavid du Colombier
15099a747e4fSDavid du Colombier /* Initialize Z Buffer ... (useful?) */
15109a747e4fSDavid du Colombier mgawrite32(mga, Z_DEPTH_ORG, 0);
15119a747e4fSDavid du Colombier
15129a747e4fSDavid du Colombier /* Wait */
15139a747e4fSDavid du Colombier for (i = 0; i < 50; i++)
15149a747e4fSDavid du Colombier mgaread32(mga, MGA_STATUS);
15159a747e4fSDavid du Colombier
1516816336a7SDavid du Colombier if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
15179a747e4fSDavid du Colombier dacset(mga, Dac_Xpixpllcm, mga->pixpll_m, 0xff);
15189a747e4fSDavid du Colombier dacset(mga, Dac_Xpixpllcn, mga->pixpll_n, 0xff);
15199a747e4fSDavid du Colombier dacset(mga, Dac_Xpixpllcp, mga->pixpll_p, 0xff);
15209a747e4fSDavid du Colombier
15219a747e4fSDavid du Colombier /* Wait until new clock becomes stable */
15229a747e4fSDavid du Colombier trace("mga: waiting for the clock source becomes stable ...\n");
15239a747e4fSDavid du Colombier while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
15249a747e4fSDavid du Colombier ;
15259a747e4fSDavid du Colombier trace("mga: pixpll locked !\n");
15269a747e4fSDavid du Colombier } else {
1527816336a7SDavid du Colombier /* MGA450 and MGA550 */
15289a747e4fSDavid du Colombier /* Wait until new clock becomes stable */
15299a747e4fSDavid du Colombier trace("mga450: waiting for the clock source becomes stable ...\n");
15309a747e4fSDavid du Colombier while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
15319a747e4fSDavid du Colombier ;
15329a747e4fSDavid du Colombier trace("mga: pixpll locked !\n");
15339a747e4fSDavid du Colombier
15349a747e4fSDavid du Colombier G450SetPLLFreq(mga, (long) mga->Fneeded / 1000);
15359a747e4fSDavid du Colombier }
15369a747e4fSDavid du Colombier
15379a747e4fSDavid du Colombier /* Enable Pixel Clock Oscillation */
15389a747e4fSDavid du Colombier dacset(mga, Dac_Xpixclkctrl, 0, Pixclkdis);
15399a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
15409a747e4fSDavid du Colombier
15419a747e4fSDavid du Colombier /* Enable Dac */
15429a747e4fSDavid du Colombier dacset(mga, Dac_Xmiscctrl, Dacpdn, 0);
15439a747e4fSDavid du Colombier
15449a747e4fSDavid du Colombier /* Set Video Mode */
15459a747e4fSDavid du Colombier switch (mode->z) {
15469a747e4fSDavid du Colombier case 8:
15479a747e4fSDavid du Colombier dacset(mga, Dac_Xmulctrl, _8bitsPerPixel, ColorDepth);
15489a747e4fSDavid du Colombier break;
15491066d6deSDavid du Colombier case 16:
15501066d6deSDavid du Colombier dacset(mga, Dac_Xmulctrl, _16bitsPerPixel, ColorDepth);
15511066d6deSDavid du Colombier break;
15521066d6deSDavid du Colombier case 24:
15531066d6deSDavid du Colombier dacset(mga, Dac_Xmulctrl, _24bitsPerPixel, ColorDepth);
15541066d6deSDavid du Colombier break;
15559a747e4fSDavid du Colombier case 32:
15569a747e4fSDavid du Colombier dacset(mga, Dac_Xmulctrl, _32bitsPerPixel, ColorDepth);
15579a747e4fSDavid du Colombier break;
15589a747e4fSDavid du Colombier default:
15599a747e4fSDavid du Colombier error("Unsupported depth %d\n", mode->z);
15609a747e4fSDavid du Colombier }
15619a747e4fSDavid du Colombier
15629a747e4fSDavid du Colombier /* Wait */
15639a747e4fSDavid du Colombier for (i = 0; i < 50; i++)
15649a747e4fSDavid du Colombier mgaread32(mga, MGA_STATUS);
15659a747e4fSDavid du Colombier
15669a747e4fSDavid du Colombier /* Wait until new clock becomes stable */
15679a747e4fSDavid du Colombier trace("mga: waiting for the clock source becomes stable ...\n");
15689a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
15699a747e4fSDavid du Colombier while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
15709a747e4fSDavid du Colombier ;
15719a747e4fSDavid du Colombier trace("mga: pixpll locked !\n");
15729a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
15739a747e4fSDavid du Colombier
15749a747e4fSDavid du Colombier /* Initialize CRTC registers and remove irq */
15759a747e4fSDavid du Colombier crtcset(mga, 0x11, (1<<4), (1<<5)|0x80);
15769a747e4fSDavid du Colombier for (i = 0; i < 25; i++)
15779a747e4fSDavid du Colombier crtcset(mga, i, mga->crtc[i], 0xff);
15789a747e4fSDavid du Colombier
15799a747e4fSDavid du Colombier trace("mga: crtc loaded !\n");
15809a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
15819a747e4fSDavid du Colombier
15829a747e4fSDavid du Colombier /* Initialize CRTC Extension registers */
15839a747e4fSDavid du Colombier for (i = 0; i < 9; i++)
15849a747e4fSDavid du Colombier crtcextset(mga, i, mga->crtcext[i], 0xff);
15859a747e4fSDavid du Colombier
15869a747e4fSDavid du Colombier trace("mga: ext loaded !\n");
15879a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
15889a747e4fSDavid du Colombier
15899a747e4fSDavid du Colombier /* Disable Zoom */
15909a747e4fSDavid du Colombier dacset(mga, Dac_Xzoomctrl, 0, 0xff);
15919a747e4fSDavid du Colombier
15929a747e4fSDavid du Colombier trace("mga: XzoomCtrl Loaded !\n");
15939a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
15949a747e4fSDavid du Colombier
15959a747e4fSDavid du Colombier /* Enable mga mode again ... Just in case :) */
15969a747e4fSDavid du Colombier crtcextset(mga, CrtcExt_Miscellaneous, Mgamode, 0);
15979a747e4fSDavid du Colombier
15989a747e4fSDavid du Colombier trace("mga: crtcext MgaMode loaded !\n");
15999a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
16009a747e4fSDavid du Colombier
16011066d6deSDavid du Colombier if (mode->z == 32 || mode->z == 24 ) {
16029a747e4fSDavid du Colombier /* Initialize Big Endian Mode ! */
16039a747e4fSDavid du Colombier mgawrite32(mga, 0x1e54, 0x02 << 16);
16049a747e4fSDavid du Colombier }
16059a747e4fSDavid du Colombier
16061066d6deSDavid du Colombier
16079a747e4fSDavid du Colombier /* Set final misc ... enable mapping ... */
16089a747e4fSDavid du Colombier miscset(mga, mga->misc | Misc_rammapen, 0);
16099a747e4fSDavid du Colombier
16109a747e4fSDavid du Colombier trace("mga: mapping enabled !\n");
16119a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
16129a747e4fSDavid du Colombier
16139a747e4fSDavid du Colombier /* Enable Screen */
16149a747e4fSDavid du Colombier seqset(mga, 1, 0, 0xff);
16159a747e4fSDavid du Colombier
16169a747e4fSDavid du Colombier trace("screen enabled ...\n");
16179a747e4fSDavid du Colombier
16189a747e4fSDavid du Colombier if (0) {
161974f16c81SDavid du Colombier p = mga->mmfb;
16209a747e4fSDavid du Colombier for (i = 0; i < mga->fbsize; i++)
16219a747e4fSDavid du Colombier *p++ = (0xff & i);
16229a747e4fSDavid du Colombier }
16239a747e4fSDavid du Colombier
16249a747e4fSDavid du Colombier trace("mga: Loaded !\n" );
16259a747e4fSDavid du Colombier dump_all_regs(mga);
16269a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
16279a747e4fSDavid du Colombier
16289a747e4fSDavid du Colombier trace("mga: Loaded [bis]!\n" );
16299a747e4fSDavid du Colombier
16301066d6deSDavid du Colombier /*
16311066d6deSDavid du Colombier * TODO: In 16bpp mode, what is the correct palette ?
16321066d6deSDavid du Colombier * in the meantime lets use the default one,
16331066d6deSDavid du Colombier * which has a weird color combination.
16341066d6deSDavid du Colombier */
16351066d6deSDavid du Colombier
16361066d6deSDavid du Colombier if (mode->z != 8 && mode ->z != 16) {
16379a747e4fSDavid du Colombier /* Initialize Palette */
16389a747e4fSDavid du Colombier mgawrite8(mga, RAMDACIDX, 0);
16399a747e4fSDavid du Colombier for (i = 0; i < 0x100; i++) {
16409a747e4fSDavid du Colombier mgawrite8(mga, RAMDACPALDATA, i);
16419a747e4fSDavid du Colombier mgawrite8(mga, RAMDACPALDATA, i);
16429a747e4fSDavid du Colombier mgawrite8(mga, RAMDACPALDATA, i);
16439a747e4fSDavid du Colombier }
16449a747e4fSDavid du Colombier }
16451066d6deSDavid du Colombier
16469a747e4fSDavid du Colombier trace("mga: Palette initialised !\n");
16479a747e4fSDavid du Colombier
16489a747e4fSDavid du Colombier /* Enable Cursor */
16499a747e4fSDavid du Colombier dacset(mga, Dac_Xcurctrl, cursor, 0xff);
16509a747e4fSDavid du Colombier
16519a747e4fSDavid du Colombier ctlr->flag |= Fload;
16529a747e4fSDavid du Colombier if (ultradebug) Bflush(&stdout);
16539a747e4fSDavid du Colombier }
16549a747e4fSDavid du Colombier
16559a747e4fSDavid du Colombier Ctlr mga4xx = {
16569a747e4fSDavid du Colombier "mga4xx", /* name */
16579a747e4fSDavid du Colombier snarf, /* snarf */
16589a747e4fSDavid du Colombier options, /* options */
16599a747e4fSDavid du Colombier init, /* init */
16609a747e4fSDavid du Colombier load, /* load */
16619a747e4fSDavid du Colombier dump, /* dump */
16629a747e4fSDavid du Colombier };
16639a747e4fSDavid du Colombier
16649a747e4fSDavid du Colombier Ctlr mga4xxhwgc = {
16659a747e4fSDavid du Colombier "mga4xxhwgc", /* name */
16669a747e4fSDavid du Colombier 0, /* snarf */
16679a747e4fSDavid du Colombier 0, /* options */
16689a747e4fSDavid du Colombier 0, /* init */
16699a747e4fSDavid du Colombier 0, /* load */
16709a747e4fSDavid du Colombier dump, /* dump */
16719a747e4fSDavid du Colombier };
1672