mga4xx.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. /* Philippe Anel <philippe.anel@noos.fr>
  2. - 2001-08-12 : First release.
  3. - 2001-08-15 : Added G450, with source code "adapted from" from Xfree86 4.1.0
  4. - 2001-08-23 : Added 'palettedepth 8' and a few 'ultradebug' ...
  5. - 2001-08-24 : Removed a possible lock in initialization.
  6. - 2001-08-30 : Hey ! The 32 bits mode is PALETIZED (Gamma Control I presume) !
  7. And it seems plan9 assume the frame buffer is organized in
  8. Big Endian format ! (+ Fix for the palette init. )
  9. - 2001-09-06 : Added Full 2D Accel ! (see drivers in /sys/src/9/pc)
  10. - 2001-10-01 : Rid Fix.
  11. - 2006-04-01 : Add MGA550 support.
  12. - 2006-08-07 : Add support for 16 and 24bits modes.
  13. HW accel now works for the G200 cards too (see kernel).
  14. by Leonardo Valencia <leoval@anixcorp.com>
  15. Greets and Acknowledgements go to :
  16. - Sylvain Chipaux <a.k.a. asle>.
  17. - Nigel Roles.
  18. - Jean Mehat (the man who introduced me into the world of plan9).
  19. - Nicolas Stojanovic.
  20. ... and for those who wrote plan9 of course ... :)
  21. */
  22. #include <u.h>
  23. #include <libc.h>
  24. #include <bio.h>
  25. #include "pci.h"
  26. #include "vga.h"
  27. static int ultradebug = 0;
  28. /*
  29. * Matrox G4xx 3D graphics accelerators
  30. */
  31. enum {
  32. Kilo = 1024,
  33. Meg = 1024*1024,
  34. MATROX = 0x102B, /* pci chip manufacturer */
  35. MGA550 = 0x2527, /* pci chip device ids */
  36. MGA4XX = 0x0525,
  37. MGA200 = 0x0521,
  38. /* Pci configuration space mapping */
  39. PCfgMgaFBAA = 0x10, /* Frame buffer Aperture Address */
  40. PCfgMgaCAA = 0x14, /* Control Aperture Address base */
  41. PCfgMgaIAA = 0x18, /* ILOAD Aperture base Address */
  42. PCfgMgaOption1 = 0x40, /* Option Register 1 */
  43. PCfgMgaOption2 = 0x50, /* Option Register 2 */
  44. PCfgMgaOption3 = 0x54, /* Option Register 3 */
  45. PCfgMgaDevCtrl = 0x04, /* Device Control */
  46. /* control aperture offsets */
  47. DMAWIN = 0x0000, /* 7KByte Pseudo-DMA Window */
  48. STATUS0 = 0x1FC2, /* Input Status 0 */
  49. STATUS1 = 0x1FDA, /* Input Status 1 */
  50. SEQIDX = 0x1FC4, /* Sequencer Index */
  51. SEQDATA = 0x1FC5, /* Sequencer Data */
  52. MISC_W = 0x1FC2, /* Misc. WO */
  53. MISC_R = 0x1FCC, /* Misc. RO */
  54. GCTLIDX = 0x1FCE, /* Graphic Controler Index */
  55. GCTLDATA = 0x1FCF, /* Graphic Controler Data */
  56. CRTCIDX = 0x1FD4, /* CRTC Index */
  57. CRTCDATA = 0x1FD5, /* CRTC Data */
  58. CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */
  59. CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */
  60. RAMDACIDX = 0x3C00, /* RAMDAC registers Index */
  61. RAMDACDATA = 0x3C0A, /* RAMDAC Indexed Data */
  62. RAMDACPALDATA = 0x3C01,
  63. ATTRIDX = 0x1FC0, /* Attribute Index */
  64. ATTRDATA = 0x1FC1, /* Attribute Data */
  65. CACHEFLUSH = 0x1FFF,
  66. C2_CTL = 0X3C10,
  67. MGA_STATUS = 0X1E14,
  68. Z_DEPTH_ORG = 0X1C0C,
  69. /* ... */
  70. Seq_ClockingMode = 0x01,
  71. Dotmode = (1<<0),
  72. Shftldrt = (1<<2),
  73. Dotclkrt = (1<<3),
  74. Shiftfour = (1<<4),
  75. Scroff = (1<<5),
  76. CrtcExt_Horizontcount = 0x01,
  77. Htotal = (1<<0),
  78. Hblkstr = (1<<1),
  79. Hsyncstr = (1<<2),
  80. Hrsten = (1<<3),
  81. Hsyncoff = (1<<4),
  82. Vsyncoff = (1<<5),
  83. Hblkend = (1<<6),
  84. Vrsten = (1<<7),
  85. CrtcExt_Miscellaneous = 0x03,
  86. Mgamode = (1<<7),
  87. Dac_Xpixclkctrl = 0x1a,
  88. Pixclksl = (3<<0),
  89. Pixclkdis = (1<<2),
  90. Pixpllpdn = (1<<3),
  91. Dac_Xpixpllstat = 0x4f,
  92. Pixlock = (1<<6),
  93. Dac_Xpixpllan = 0x45,
  94. Dac_Xpixpllbn = 0x49,
  95. Dac_Xpixpllcn = 0x4d,
  96. Dac_Xpixpllam = 0x44,
  97. Dac_Xpixpllbm = 0x48,
  98. Dac_Xpixpllcm = 0x4c,
  99. Dac_Xpixpllap = 0x46,
  100. Dac_Xpixpllbp = 0x4a,
  101. Dac_Xpixpllcp = 0x4e,
  102. Dac_Xmulctrl = 0x19,
  103. ColorDepth = (7<<0),
  104. _8bitsPerPixel = 0,
  105. _15bitsPerPixel = 1,
  106. _16bitsPerPixel = 2,
  107. _24bitsPerPixel = 3,
  108. _32bitsPerPixelWithOv = 4,
  109. _32bitsPerPixel = 7,
  110. Dac_Xpanelmode = 0x1f,
  111. Dac_Xmiscctrl = 0x1e,
  112. Dacpdn = (1<<0),
  113. Mfcsel = (3<<1),
  114. Vga8dac = (1<<3),
  115. Ramcs = (1<<4),
  116. Vdoutsel = (7<<5),
  117. Dac_Xcurctrl = 0x06,
  118. CursorDis = 0,
  119. Cursor3Color = 1,
  120. CursorXGA = 2,
  121. CursorX11 = 3,
  122. Cursor16Color = 4,
  123. Dac_Xzoomctrl = 0x38,
  124. Misc_loaddsel = (1<<0),
  125. Misc_rammapen = (1<<1),
  126. Misc_clksel = (3<<2),
  127. Misc_videodis = (1<<4),
  128. Misc_hpgoddev = (1<<5),
  129. Misc_hsyncpol = (1<<6),
  130. Misc_vsyncpol = (1<<7),
  131. MNP_TABLE_SIZE = 64,
  132. TRUE = (1 == 1),
  133. FALSE = (1 == 0),
  134. };
  135. typedef struct {
  136. Pcidev* pci;
  137. int devid;
  138. int revid;
  139. uchar* mmio;
  140. uchar* mmfb;
  141. int fbsize;
  142. ulong iload;
  143. uchar syspll_m;
  144. uchar syspll_n;
  145. uchar syspll_p;
  146. uchar syspll_s;
  147. uchar pixpll_m;
  148. uchar pixpll_n;
  149. uchar pixpll_p;
  150. uchar pixpll_s;
  151. ulong option1;
  152. ulong option2;
  153. ulong option3;
  154. ulong Fneeded;
  155. /* From plan9.ini ... later */
  156. uchar sdram;
  157. uchar colorkey;
  158. uchar maskkey;
  159. ulong maxpclk;
  160. uchar graphics[9];
  161. uchar attribute[0x14];
  162. uchar sequencer[5];
  163. uchar crtc[0x19];
  164. uchar crtcext[9];
  165. ulong htotal;
  166. ulong hdispend;
  167. ulong hblkstr;
  168. ulong hblkend;
  169. ulong hsyncstr;
  170. ulong hsyncend;
  171. ulong vtotal;
  172. ulong vdispend;
  173. ulong vblkstr;
  174. ulong vblkend;
  175. ulong vsyncstr;
  176. ulong vsyncend;
  177. ulong linecomp;
  178. ulong hsyncsel;
  179. ulong startadd;
  180. ulong offset;
  181. ulong maxscan;
  182. ulong curloc;
  183. ulong prowscan;
  184. ulong currowstr;
  185. ulong currowend;
  186. ulong curoff;
  187. ulong undrow;
  188. ulong curskew;
  189. ulong conv2t4;
  190. ulong interlace;
  191. ulong hsyncdel;
  192. ulong hdispskew;
  193. ulong bytepan;
  194. ulong dotclkrt;
  195. ulong dword;
  196. ulong wbmode;
  197. ulong addwrap;
  198. ulong selrowscan;
  199. ulong cms;
  200. ulong csynccen;
  201. ulong hrsten;
  202. ulong vrsten;
  203. ulong vinten;
  204. ulong vintclr;
  205. ulong hsyncoff;
  206. ulong vsyncoff;
  207. ulong crtcrstN;
  208. ulong mgamode;
  209. ulong scale;
  210. ulong hiprilvl;
  211. ulong maxhipri;
  212. ulong c2hiprilvl;
  213. ulong c2maxhipri;
  214. ulong misc;
  215. ulong crtcprotect;
  216. ulong winsize;
  217. ulong winfreq;
  218. ulong mgaapsize;
  219. } Mga;
  220. static void
  221. mgawrite32(Mga* mga, int index, ulong val)
  222. {
  223. ((ulong*)mga->mmio)[index] = val;
  224. }
  225. static ulong
  226. mgaread32(Mga* mga, int index)
  227. {
  228. return ((ulong*)mga->mmio)[index];
  229. }
  230. static void
  231. mgawrite8(Mga* mga, int index, uchar val)
  232. {
  233. mga->mmio[index] = val;
  234. }
  235. static uchar
  236. mgaread8(Mga* mga, int index)
  237. {
  238. return mga->mmio[index];
  239. }
  240. static uchar
  241. seqget(Mga* mga, int index)
  242. {
  243. mgawrite8(mga, SEQIDX, index);
  244. return mgaread8(mga, SEQDATA);
  245. }
  246. static uchar
  247. seqset(Mga* mga, int index, uchar set, uchar clr)
  248. {
  249. uchar tmp;
  250. mgawrite8(mga, SEQIDX, index);
  251. tmp = mgaread8(mga, SEQDATA);
  252. mgawrite8(mga, SEQIDX, index);
  253. mgawrite8(mga, SEQDATA, (tmp & ~clr) | set);
  254. return tmp;
  255. }
  256. static uchar
  257. crtcget(Mga* mga, int index)
  258. {
  259. mgawrite8(mga, CRTCIDX, index);
  260. return mgaread8(mga, CRTCDATA);
  261. }
  262. static uchar
  263. crtcset(Mga* mga, int index, uchar set, uchar clr)
  264. {
  265. uchar tmp;
  266. mgawrite8(mga, CRTCIDX, index);
  267. tmp = mgaread8(mga, CRTCDATA);
  268. mgawrite8(mga, CRTCIDX, index);
  269. mgawrite8(mga, CRTCDATA, (tmp & ~clr) | set);
  270. return tmp;
  271. }
  272. static uchar
  273. crtcextget(Mga* mga, int index)
  274. {
  275. mgawrite8(mga, CRTCEXTIDX, index);
  276. return mgaread8(mga, CRTCEXTDATA);
  277. }
  278. static uchar
  279. crtcextset(Mga* mga, int index, uchar set, uchar clr)
  280. {
  281. uchar tmp;
  282. mgawrite8(mga, CRTCEXTIDX, index);
  283. tmp = mgaread8(mga, CRTCEXTDATA);
  284. mgawrite8(mga, CRTCEXTIDX, index);
  285. mgawrite8(mga, CRTCEXTDATA, (tmp & ~clr) | set);
  286. return tmp;
  287. }
  288. static uchar
  289. dacget(Mga* mga, int index)
  290. {
  291. mgawrite8(mga, RAMDACIDX, index);
  292. return mgaread8(mga, RAMDACDATA);
  293. }
  294. static uchar
  295. dacset(Mga* mga, int index, uchar set, uchar clr)
  296. {
  297. uchar tmp;
  298. mgawrite8(mga, RAMDACIDX, index);
  299. tmp = mgaread8(mga, RAMDACDATA);
  300. mgawrite8(mga, RAMDACIDX, index);
  301. mgawrite8(mga, RAMDACDATA, (tmp & ~clr) | set);
  302. return tmp;
  303. }
  304. static uchar
  305. gctlget(Mga* mga, int index)
  306. {
  307. mgawrite8(mga, GCTLIDX, index);
  308. return mgaread8(mga, GCTLDATA);
  309. }
  310. static uchar
  311. gctlset(Mga* mga, int index, uchar set, uchar clr)
  312. {
  313. uchar tmp;
  314. mgawrite8(mga, GCTLIDX, index);
  315. tmp = mgaread8(mga, GCTLDATA);
  316. mgawrite8(mga, GCTLIDX, index);
  317. mgawrite8(mga, GCTLDATA, (tmp & ~clr) | set);
  318. return tmp;
  319. }
  320. static uchar
  321. attrget(Mga* mga, int index)
  322. {
  323. mgawrite8(mga, ATTRIDX, index);
  324. return mgaread8(mga, ATTRDATA);
  325. }
  326. static uchar
  327. attrset(Mga* mga, int index, uchar set, uchar clr)
  328. {
  329. uchar tmp;
  330. mgawrite8(mga, ATTRIDX, index);
  331. tmp = mgaread8(mga, ATTRDATA);
  332. mgawrite8(mga, ATTRIDX, index);
  333. mgawrite8(mga, ATTRDATA, (tmp & ~clr) | set);
  334. return tmp;
  335. }
  336. static uchar
  337. miscget(Mga* mga)
  338. {
  339. return mgaread8(mga, MISC_R);
  340. }
  341. static uchar
  342. miscset(Mga* mga, uchar set, uchar clr)
  343. {
  344. uchar tmp;
  345. tmp = mgaread8(mga, MISC_R);
  346. mgawrite8(mga, MISC_W, (tmp & ~clr) | set);
  347. return tmp;
  348. }
  349. /* ************************************************************ */
  350. static void
  351. dump_all_regs(Mga* mga)
  352. {
  353. int i;
  354. for (i = 0; i < 25; i++)
  355. trace("crtc[%d] = 0x%x\n", i, crtcget(mga, i));
  356. for (i = 0; i < 9; i++)
  357. trace("crtcext[%d] = 0x%x\n", i, crtcextget(mga, i));
  358. for (i = 0; i < 5; i++)
  359. trace("seq[%d] = 0x%x\n", i, seqget(mga, i));
  360. for (i = 0; i < 9; i++)
  361. trace("gctl[%d] = 0x%x\n", i, gctlget(mga, i));
  362. trace("misc = 0x%x\n", mgaread8(mga, MISC_R));
  363. for (i = 0; i < 0x87; i++)
  364. trace("dac[%d] = 0x%x\n", i, dacget(mga, i));
  365. }
  366. /* ************************************************************ */
  367. static void
  368. dump(Vga* vga, Ctlr* ctlr)
  369. {
  370. dump_all_regs(vga->private);
  371. ctlr->flag |= Fdump;
  372. }
  373. static void
  374. setpalettedepth(int depth)
  375. {
  376. int fd;
  377. char *cmd = strdup("palettedepth X");
  378. if ((depth != 8) && (depth != 6) && (depth != 16))
  379. error("mga: invalid palette depth %d\n", depth);
  380. fd = open("#v/vgactl", OWRITE);
  381. if(fd < 0)
  382. error("mga: can't open vgactl\n");
  383. cmd[13] = '0' + depth;
  384. if(write(fd, cmd, 14) != 14)
  385. error("mga: can't set palette depth to %d\n", depth);
  386. close(fd);
  387. }
  388. static void
  389. mapmga4xx(Vga* vga, Ctlr* ctlr)
  390. {
  391. int f;
  392. uchar* m;
  393. Mga * mga;
  394. if(vga->private == nil)
  395. error("%s: g4xxio: no *mga4xx\n", ctlr->name);
  396. mga = vga->private;
  397. f = open("#v/vgactl", OWRITE);
  398. if(f < 0)
  399. error("%s: can't open vgactl\n", ctlr->name);
  400. if(write(f, "type mga4xx", 11) != 11)
  401. error("%s: can't set mga type\n", ctlr->name);
  402. m = segattach(0, "mga4xxmmio", 0, 16*Kilo);
  403. if(m == (void*)-1)
  404. error("%s: can't attach mga4xxmmio segment\n", ctlr->name);
  405. mga->mmio = m;
  406. trace("%s: mmio at %#p\n", ctlr->name, mga->mmio);
  407. m = segattach(0, "mga4xxscreen", 0, 32*Meg);
  408. if(m == (void*)-1) {
  409. mga->mgaapsize = 8*Meg;
  410. m = segattach(0, "mga4xxscreen", 0, 8*Meg);
  411. if(m == (void*)-1)
  412. error("%s: can't attach mga4xxscreen segment\n", ctlr->name);
  413. } else {
  414. mga->mgaapsize = 32*Meg;
  415. }
  416. mga->mmfb = m;
  417. trace("%s: frame buffer at %#p\n", ctlr->name, mga->mmfb);
  418. close(f);
  419. }
  420. static void
  421. snarf(Vga* vga, Ctlr* ctlr)
  422. {
  423. int i, k, n;
  424. uchar * p;
  425. uchar x[16];
  426. Pcidev * pci;
  427. Mga * mga;
  428. uchar crtcext3;
  429. uchar rid;
  430. trace("%s->snarf\n", ctlr->name);
  431. if(vga->private == nil) {
  432. pci = pcimatch(nil, MATROX, MGA4XX);
  433. if(pci == nil)
  434. pci = pcimatch(nil, MATROX, MGA550);
  435. if(pci == nil)
  436. pci = pcimatch(nil, MATROX, MGA200);
  437. if(pci == nil)
  438. error("%s: cannot find matrox adapter\n", ctlr->name);
  439. rid = pcicfgr8(pci, PciRID); // PciRID = 0x08
  440. trace("%s: G%d%d0 rev %d\n", ctlr->name,
  441. 2*(pci->did==MGA200)
  442. +4*(pci->did==MGA4XX)
  443. +5*(pci->did==MGA550),
  444. rid&0x80 ? 5 : 0,
  445. rid&~0x80);
  446. i = pcicfgr32(pci, PCfgMgaDevCtrl);
  447. if ((i & 2) != 2)
  448. error("%s: Memory Space not enabled ... Aborting ...\n", ctlr->name);
  449. vga->private = alloc(sizeof(Mga));
  450. mga = (Mga*)vga->private;
  451. mga->devid = pci->did;
  452. mga->revid = rid;
  453. mga->pci = pci;
  454. mapmga4xx(vga, ctlr);
  455. }
  456. else {
  457. mga = (Mga*)vga->private;
  458. }
  459. /* Find out how much memory is here, some multiple of 2Meg */
  460. /* First Set MGA Mode ... */
  461. crtcext3 = crtcextset(mga, 3, 0x80, 0x00);
  462. p = mga->mmfb;
  463. n = (mga->mgaapsize / Meg) / 2;
  464. for (i = 0; i < n; i++) {
  465. k = (2*i+1)*Meg;
  466. p[k] = 0;
  467. p[k] = i+1;
  468. *(mga->mmio + CACHEFLUSH) = 0;
  469. x[i] = p[k];
  470. trace("x[%d]=%d\n", i, x[i]);
  471. }
  472. for(i = 1; i < n; i++)
  473. if(x[i] != i+1)
  474. break;
  475. vga->vmz = mga->fbsize = 2*i*Meg;
  476. trace("probe found %d megabytes\n", 2*i);
  477. crtcextset(mga, 3, crtcext3, 0xff);
  478. ctlr->flag |= Fsnarf;
  479. }
  480. static void
  481. options(Vga* vga, Ctlr* ctlr)
  482. {
  483. if(vga->virtx & 127)
  484. vga->virtx = (vga->virtx+127)&~127;
  485. ctlr->flag |= Foptions;
  486. }
  487. /* ************************************************************ */
  488. static void
  489. G450ApplyPFactor(Mga*, uchar ucP, ulong *pulFIn)
  490. {
  491. if(!(ucP & 0x40))
  492. {
  493. *pulFIn = *pulFIn / (2L << (ucP & 3));
  494. }
  495. }
  496. static void
  497. G450RemovePFactor(Mga*, uchar ucP, ulong *pulFIn)
  498. {
  499. if(!(ucP & 0x40))
  500. {
  501. *pulFIn = *pulFIn * (2L << (ucP & 3));
  502. }
  503. }
  504. static void
  505. G450CalculVCO(Mga*, ulong ulMNP, ulong *pulF)
  506. {
  507. uchar ucM, ucN;
  508. ucM = (uchar)((ulMNP >> 16) & 0xff);
  509. ucN = (uchar)((ulMNP >> 8) & 0xff);
  510. *pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1);
  511. trace("G450CalculVCO: ulMNP %lx, pulF %ld\n", ulMNP, *pulF);
  512. }
  513. static void
  514. G450CalculDeltaFreq(Mga*, ulong ulF1, ulong ulF2, ulong *pulDelta)
  515. {
  516. if(ulF2 < ulF1)
  517. {
  518. *pulDelta = ((ulF1 - ulF2) * 1000) / ulF1;
  519. }
  520. else
  521. {
  522. *pulDelta = ((ulF2 - ulF1) * 1000) / ulF1;
  523. }
  524. trace("G450CalculDeltaFreq: ulF1 %ld, ulF2 %ld, pulDelta %ld\n", ulF1, ulF2, *pulDelta);
  525. }
  526. static void
  527. G450FindNextPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
  528. {
  529. uchar ucM, ucN, ucP, ucS;
  530. ulong ulVCO, ulVCOMin;
  531. ucM = (uchar)((*pulPLLMNP >> 16) & 0xff);
  532. /* ucN = (uchar)((*pulPLLMNP >> 8) & 0xff); */
  533. ucP = (uchar)(*pulPLLMNP & 0x43);
  534. ulVCOMin = 256000;
  535. if(ulVCOMin >= (255L * 8000))
  536. {
  537. ulVCOMin = 230000;
  538. }
  539. if((ucM == 9) && (ucP & 0x40))
  540. {
  541. *pulPLLMNP = 0xffffffff;
  542. } else if (ucM == 9)
  543. {
  544. if(ucP)
  545. {
  546. ucP--;
  547. }
  548. else
  549. {
  550. ucP = 0x40;
  551. }
  552. ucM = 0;
  553. }
  554. else
  555. {
  556. ucM++;
  557. }
  558. ulVCO = ulFout;
  559. G450RemovePFactor(mga, ucP, &ulVCO);
  560. if(ulVCO < ulVCOMin)
  561. {
  562. *pulPLLMNP = 0xffffffff;
  563. }
  564. if(*pulPLLMNP != 0xffffffff)
  565. {
  566. ucN = (uchar)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2);
  567. ucS = 5;
  568. if(ulVCO < 1300000) ucS = 4;
  569. if(ulVCO < 1100000) ucS = 3;
  570. if(ulVCO < 900000) ucS = 2;
  571. if(ulVCO < 700000) ucS = 1;
  572. if(ulVCO < 550000) ucS = 0;
  573. ucP |= (uchar)(ucS << 3);
  574. *pulPLLMNP &= 0xff000000;
  575. *pulPLLMNP |= (ulong)ucM << 16;
  576. *pulPLLMNP |= (ulong)ucN << 8;
  577. *pulPLLMNP |= (ulong)ucP;
  578. }
  579. }
  580. static void
  581. G450FindFirstPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
  582. {
  583. uchar ucP;
  584. ulong ulVCO;
  585. ulong ulVCOMax;
  586. /* Default value */
  587. ulVCOMax = 1300000;
  588. if(ulFout > (ulVCOMax/2))
  589. {
  590. ucP = 0x40;
  591. ulVCO = ulFout;
  592. }
  593. else
  594. {
  595. ucP = 3;
  596. ulVCO = ulFout;
  597. G450RemovePFactor(mga, ucP, &ulVCO);
  598. while(ucP && (ulVCO > ulVCOMax))
  599. {
  600. ucP--;
  601. ulVCO = ulFout;
  602. G450RemovePFactor(mga, ucP, &ulVCO);
  603. }
  604. }
  605. if(ulVCO > ulVCOMax)
  606. {
  607. *pulPLLMNP = 0xffffffff;
  608. }
  609. else
  610. {
  611. /* Pixel clock: 1 */
  612. *pulPLLMNP = (1 << 24) + 0xff0000 + ucP;
  613. G450FindNextPLLParam(mga, ulFout, pulPLLMNP);
  614. }
  615. }
  616. static void
  617. G450WriteMNP(Mga* mga, ulong ulMNP)
  618. {
  619. if (0) trace("G450WriteMNP : 0x%lx\n", ulMNP);
  620. dacset(mga, Dac_Xpixpllcm, (uchar)(ulMNP >> 16), 0xff);
  621. dacset(mga, Dac_Xpixpllcn, (uchar)(ulMNP >> 8), 0xff);
  622. dacset(mga, Dac_Xpixpllcp, (uchar)ulMNP, 0xff);
  623. }
  624. static void
  625. G450CompareMNP(Mga* mga, ulong ulFout, ulong ulMNP1,
  626. ulong ulMNP2, long *pulResult)
  627. {
  628. ulong ulFreq, ulDelta1, ulDelta2;
  629. G450CalculVCO(mga, ulMNP1, &ulFreq);
  630. G450ApplyPFactor(mga, (uchar) ulMNP1, &ulFreq);
  631. G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta1);
  632. G450CalculVCO(mga, ulMNP2, &ulFreq);
  633. G450ApplyPFactor(mga, (uchar) ulMNP2, &ulFreq);
  634. G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta2);
  635. if(ulDelta1 < ulDelta2)
  636. {
  637. *pulResult = -1;
  638. }
  639. else if(ulDelta1 > ulDelta2)
  640. {
  641. *pulResult = 1;
  642. }
  643. else
  644. {
  645. *pulResult = 0;
  646. }
  647. if((ulDelta1 <= 5) && (ulDelta2 <= 5))
  648. {
  649. if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000))
  650. {
  651. *pulResult = -1;
  652. }
  653. else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000))
  654. {
  655. *pulResult = 1;
  656. }
  657. }
  658. }
  659. static void
  660. G450IsPllLocked(Mga* mga, int *lpbLocked)
  661. {
  662. ulong ulFallBackCounter, ulLockCount, ulCount;
  663. uchar ucPLLStatus;
  664. /* Pixel PLL */
  665. mgawrite8(mga, 0x3c00, 0x4f);
  666. ulFallBackCounter = 0;
  667. do
  668. {
  669. ucPLLStatus = mgaread8(mga, 0x3c0a);
  670. if (0) trace("ucPLLStatus[1] : 0x%x\n", ucPLLStatus);
  671. ulFallBackCounter++;
  672. } while(!(ucPLLStatus & 0x40) && (ulFallBackCounter < 1000));
  673. ulLockCount = 0;
  674. if(ulFallBackCounter < 1000)
  675. {
  676. for(ulCount = 0; ulCount < 100; ulCount++)
  677. {
  678. ucPLLStatus = mgaread8(mga, 0x3c0a);
  679. if (0) trace("ucPLLStatus[2] : 0x%x\n", ucPLLStatus);
  680. if(ucPLLStatus & 0x40)
  681. {
  682. ulLockCount++;
  683. }
  684. }
  685. }
  686. *lpbLocked = ulLockCount >= 90;
  687. }
  688. static void
  689. G450SetPLLFreq(Mga* mga, long f_out)
  690. {
  691. int bFoundValidPLL;
  692. int bLocked;
  693. ulong ulMaxIndex;
  694. ulong ulMNP;
  695. ulong ulMNPTable[MNP_TABLE_SIZE];
  696. ulong ulIndex;
  697. ulong ulTryMNP;
  698. long lCompareResult;
  699. trace("f_out : %ld\n", f_out);
  700. G450FindFirstPLLParam(mga, f_out, &ulMNP);
  701. ulMNPTable[0] = ulMNP;
  702. G450FindNextPLLParam(mga, f_out, &ulMNP);
  703. ulMaxIndex = 1;
  704. while(ulMNP != 0xffffffff)
  705. {
  706. int ulIndex;
  707. int bSkipValue;
  708. bSkipValue = FALSE;
  709. if(ulMaxIndex == MNP_TABLE_SIZE)
  710. {
  711. G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1],
  712. &lCompareResult);
  713. if(lCompareResult > 0)
  714. {
  715. bSkipValue = TRUE;
  716. }
  717. else
  718. {
  719. ulMaxIndex--;
  720. }
  721. }
  722. if(!bSkipValue)
  723. {
  724. for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--)
  725. {
  726. G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[ulIndex - 1],
  727. &lCompareResult);
  728. if(lCompareResult < 0)
  729. {
  730. ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1];
  731. }
  732. else
  733. {
  734. break;
  735. }
  736. }
  737. ulMNPTable[ulIndex] = ulMNP;
  738. ulMaxIndex++;
  739. }
  740. G450FindNextPLLParam(mga, f_out, &ulMNP);
  741. }
  742. bFoundValidPLL = FALSE;
  743. ulMNP = 0;
  744. for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++)
  745. {
  746. ulTryMNP = ulMNPTable[ulIndex];
  747. {
  748. bLocked = TRUE;
  749. if((ulMNPTable[ulIndex] & 0xff00) < 0x300 ||
  750. (ulMNPTable[ulIndex] & 0xff00) > 0x7a00)
  751. {
  752. bLocked = FALSE;
  753. }
  754. if(bLocked)
  755. {
  756. G450WriteMNP(mga, ulTryMNP - 0x300);
  757. G450IsPllLocked(mga, &bLocked);
  758. }
  759. if(bLocked)
  760. {
  761. G450WriteMNP(mga, ulTryMNP + 0x300);
  762. G450IsPllLocked(mga, &bLocked);
  763. }
  764. if(bLocked)
  765. {
  766. G450WriteMNP(mga, ulTryMNP - 0x200);
  767. G450IsPllLocked(mga, &bLocked);
  768. }
  769. if(bLocked)
  770. {
  771. G450WriteMNP(mga, ulTryMNP + 0x200);
  772. G450IsPllLocked(mga, &bLocked);
  773. }
  774. if(bLocked)
  775. {
  776. G450WriteMNP(mga, ulTryMNP - 0x100);
  777. G450IsPllLocked(mga, &bLocked);
  778. }
  779. if(bLocked)
  780. {
  781. G450WriteMNP(mga, ulTryMNP + 0x100);
  782. G450IsPllLocked(mga, &bLocked);
  783. }
  784. if(bLocked)
  785. {
  786. G450WriteMNP(mga, ulTryMNP);
  787. G450IsPllLocked(mga, &bLocked);
  788. }
  789. else if(!ulMNP)
  790. {
  791. G450WriteMNP(mga, ulTryMNP);
  792. G450IsPllLocked(mga, &bLocked);
  793. if(bLocked)
  794. {
  795. ulMNP = ulMNPTable[ulIndex];
  796. }
  797. bLocked = FALSE;
  798. }
  799. if(bLocked)
  800. {
  801. bFoundValidPLL = TRUE;
  802. }
  803. }
  804. }
  805. if(!bFoundValidPLL)
  806. {
  807. if(ulMNP)
  808. {
  809. G450WriteMNP(mga, ulMNP);
  810. }
  811. else
  812. {
  813. G450WriteMNP(mga, ulMNPTable[0]);
  814. }
  815. }
  816. }
  817. /* ************************************************************ */
  818. /*
  819. calcclock - Calculate the PLL settings (m, n, p, s).
  820. */
  821. static double
  822. g400_calcclock(Mga* mga, long Fneeded)
  823. {
  824. double Fpll;
  825. double Fvco;
  826. double Fref;
  827. int pixpll_m_min;
  828. int pixpll_m_max;
  829. int pixpll_n_min;
  830. int pixpll_n_max;
  831. int pixpll_p_max;
  832. double Ferr, Fcalc;
  833. int m, n, p;
  834. if (mga->devid == MGA4XX || mga->devid == MGA550) {
  835. /* These values are taken from Matrox G400 Specification - p 4-91 */
  836. Fref = 27000000.0;
  837. pixpll_n_min = 7;
  838. pixpll_n_max = 127;
  839. pixpll_m_min = 1;
  840. pixpll_m_max = 31;
  841. pixpll_p_max = 7;
  842. } else { /* MGA200 */
  843. /* These values are taken from Matrox G200 Specification - p 4-77 */
  844. //Fref = 14318180.0;
  845. Fref = 27050500.0;
  846. pixpll_n_min = 7;
  847. pixpll_n_max = 127;
  848. pixpll_m_min = 1;
  849. pixpll_m_max = 6;
  850. pixpll_p_max = 7;
  851. }
  852. Fvco = ( double ) Fneeded;
  853. for (p = 0; p <= pixpll_p_max && Fvco < mga->maxpclk; p = p * 2 + 1, Fvco *= 2.0)
  854. ;
  855. mga->pixpll_p = p;
  856. Ferr = Fneeded;
  857. for ( m = pixpll_m_min ; m <= pixpll_m_max ; m++ )
  858. for ( n = pixpll_n_min; n <= pixpll_n_max; n++ )
  859. {
  860. Fcalc = Fref * (n + 1) / (m + 1) ;
  861. /*
  862. * Pick the closest frequency.
  863. */
  864. if ( labs(Fcalc - Fvco) < Ferr ) {
  865. Ferr = abs(Fcalc - Fvco);
  866. mga->pixpll_m = m;
  867. mga->pixpll_n = n;
  868. }
  869. }
  870. Fvco = Fref * (mga->pixpll_n + 1) / (mga->pixpll_m + 1);
  871. if (mga->devid == MGA4XX || mga->devid == MGA550) {
  872. if ( (50000000.0 <= Fvco) && (Fvco < 110000000.0) )
  873. mga->pixpll_p |= 0;
  874. if ( (110000000.0 <= Fvco) && (Fvco < 170000000.0) )
  875. mga->pixpll_p |= (1<<3);
  876. if ( (170000000.0 <= Fvco) && (Fvco < 240000000.0) )
  877. mga->pixpll_p |= (2<<3);
  878. if ( (300000000.0 <= Fvco) )
  879. mga->pixpll_p |= (3<<3);
  880. } else {
  881. if ( (50000000.0 <= Fvco) && (Fvco < 100000000.0) )
  882. mga->pixpll_p |= 0;
  883. if ( (100000000.0 <= Fvco) && (Fvco < 140000000.0) )
  884. mga->pixpll_p |= (1<<3);
  885. if ( (140000000.0 <= Fvco) && (Fvco < 180000000.0) )
  886. mga->pixpll_p |= (2<<3);
  887. if ( (250000000.0 <= Fvco) )
  888. mga->pixpll_p |= (3<<3);
  889. }
  890. Fpll = Fvco / (p + 1);
  891. return Fpll;
  892. }
  893. /* ************************************************************ */
  894. static void
  895. init(Vga* vga, Ctlr* ctlr)
  896. {
  897. Mode* mode;
  898. Mga* mga;
  899. double Fpll;
  900. Ctlr* c;
  901. int i;
  902. ulong t;
  903. int bppShift;
  904. mga = vga->private;
  905. mode = vga->mode;
  906. trace("mga mmio at %#p\n", mga->mmio);
  907. ctlr->flag |= Ulinear;
  908. /*
  909. * Set the right bppShitf based on depth
  910. */
  911. switch(mode->z) {
  912. case 8:
  913. bppShift = 0;
  914. break;
  915. case 16:
  916. bppShift = 1;
  917. break;
  918. case 24:
  919. bppShift = 0;
  920. break;
  921. case 32:
  922. bppShift = 2;
  923. break;
  924. default:
  925. bppShift = 0;
  926. error("depth %d not supported !\n", mode->z);
  927. }
  928. if (mode->interlace)
  929. error("interlaced mode not supported !\n");
  930. trace("%s: Initializing mode %dx%dx%d on %s\n", ctlr->name, mode->x, mode->y, mode->z, mode->type);
  931. trace("%s: Suggested Dot Clock : %d\n", ctlr->name, mode->frequency);
  932. trace("%s: Horizontal Total = %d\n", ctlr->name, mode->ht);
  933. trace("%s: Start Horizontal Blank = %d\n", ctlr->name, mode->shb);
  934. trace("%s: End Horizontal Blank = %d\n", ctlr->name, mode->ehb);
  935. trace("%s: Vertical Total = %d\n", ctlr->name, mode->vt);
  936. trace("%s: Vertical Retrace Start = %d\n", ctlr->name, mode->vrs);
  937. trace("%s: Vertical Retrace End = %d\n", ctlr->name, mode->vre);
  938. trace("%s: Start Horizontal Sync = %d\n", ctlr->name, mode->shs);
  939. trace("%s: End Horizontal Sync = %d\n", ctlr->name, mode->ehs);
  940. trace("%s: HSync = %c\n", ctlr->name, mode->hsync);
  941. trace("%s: VSync = %c\n", ctlr->name, mode->vsync);
  942. trace("%s: Interlace = %d\n", ctlr->name, mode->interlace);
  943. /* TODO : G400 Max : 360000000 */
  944. if (mga->devid == MGA4XX || mga->devid == MGA550)
  945. mga->maxpclk = 300000000;
  946. else
  947. mga->maxpclk = 250000000;
  948. if (mode->frequency < 50000)
  949. error("mga: Too little Frequency %d : Minimum supported by PLL is %d",
  950. mode->frequency, 50000);
  951. if (mode->frequency > mga->maxpclk)
  952. error("mga: Too big Frequency %d : Maximum supported by PLL is %ld",
  953. mode->frequency, mga->maxpclk);
  954. trace("mga: revision ID is %x\n", mga->revid);
  955. if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
  956. /* Is it G200/G400 or G450 ? */
  957. Fpll = g400_calcclock(mga, mode->frequency);
  958. trace("Fpll set to %f\n", Fpll);
  959. trace("pixclks : n = %d m = %d p = %d\n", mga->pixpll_n, mga->pixpll_m, mga->pixpll_p & 0x7);
  960. } else
  961. mga->Fneeded = mode->frequency;
  962. trace("PCI Option1 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption1));
  963. trace("PCI Option2 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption2));
  964. trace("PCI Option3 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption3));
  965. mga->htotal = (mode->ht >> 3) - 5;
  966. mga->hdispend = (mode->x >> 3) - 1;
  967. mga->hblkstr = mga->hdispend; /* (mode->shb >> 3); */
  968. mga->hblkend = mga->htotal + 4; /* (mode->ehb >> 3); */
  969. mga->hsyncstr = (mode->shs >> 3) - 1; // Was (mode->shs >> 3);
  970. mga->hsyncend = (mode->ehs >> 3) - 1; // Was (mode->ehs >> 3);
  971. mga->hsyncdel = 0;
  972. mga->vtotal = mode->vt - 2;
  973. mga->vdispend = mode->y - 1;
  974. mga->vblkstr = mode->y - 1;
  975. mga->vblkend = mode->vt - 1;
  976. mga->vsyncstr = mode->vrs;
  977. mga->vsyncend = mode->vre;
  978. mga->linecomp = mode->y;
  979. mga->hsyncsel = 0; /* Do not double lines ... */
  980. mga->startadd = 0;
  981. mga->offset = (mode->z==24) ? (vga->virtx * 3) >> (4 - bppShift) : vga->virtx >> (4-bppShift);
  982. /* No Zoom */
  983. mga->maxscan = 0;
  984. /* Not used in Power Graphic mode */
  985. mga->curloc = 0;
  986. mga->prowscan = 0;
  987. mga->currowstr = 0;
  988. mga->currowend = 0;
  989. mga->curoff = 1;
  990. mga->undrow = 0;
  991. mga->curskew = 0;
  992. mga->conv2t4 = 0;
  993. mga->interlace = 0;
  994. mga->hdispskew = 0;
  995. mga->bytepan = 0;
  996. mga->dotclkrt = 0;
  997. mga->dword = 0;
  998. mga->wbmode = 1;
  999. mga->addwrap = 0; /* Not Used ! */
  1000. mga->selrowscan = 1;
  1001. mga->cms = 1;
  1002. mga->csynccen = 0; /* Disable composite sync */
  1003. /* VIDRST Pin */
  1004. mga->hrsten = 0; // Was 1;
  1005. mga->vrsten = 0; // Was 1;
  1006. /* vertical interrupt control ... disabled */
  1007. mga->vinten = 1;
  1008. mga->vintclr = 0;
  1009. /* Let [hv]sync run freely */
  1010. mga->hsyncoff = 0;
  1011. mga->vsyncoff = 0;
  1012. mga->crtcrstN = 1;
  1013. mga->mgamode = 1;
  1014. mga->scale = (mode->z == 24) ? ((1 << bppShift)*3)-1 : (1 << bppShift)-1;
  1015. mga->crtcprotect = 1;
  1016. mga->winsize = 0;
  1017. mga->winfreq = 0;
  1018. if ((mga->htotal == 0)
  1019. || (mga->hblkend <= (mga->hblkstr + 1))
  1020. || ((mga->htotal - mga->hdispend) == 0)
  1021. || ((mga->htotal - mga->bytepan + 2) <= mga->hdispend)
  1022. || (mga->hsyncstr <= (mga->hdispend + 2))
  1023. || (mga->vtotal == 0))
  1024. {
  1025. error("Invalid Power Graphic Mode :\n"
  1026. "mga->htotal = %ld\n"
  1027. "mga->hdispend = %ld\n"
  1028. "mga->hblkstr = %ld\n"
  1029. "mga->hblkend = %ld\n"
  1030. "mga->hsyncstr = %ld\n"
  1031. "mga->hsyncend = %ld\n"
  1032. "mga->hsyncdel = %ld\n"
  1033. "mga->vtotal = %ld\n"
  1034. "mga->vdispend = %ld\n"
  1035. "mga->vblkstr = %ld\n"
  1036. "mga->vblkend = %ld\n"
  1037. "mga->vsyncstr = %ld\n"
  1038. "mga->vsyncend = %ld\n"
  1039. "mga->linecomp = %ld\n",
  1040. mga->htotal,
  1041. mga->hdispend,
  1042. mga->hblkstr,
  1043. mga->hblkend,
  1044. mga->hsyncstr,
  1045. mga->hsyncend,
  1046. mga->hsyncdel,
  1047. mga->vtotal,
  1048. mga->vdispend,
  1049. mga->vblkstr,
  1050. mga->vblkend,
  1051. mga->vsyncstr,
  1052. mga->vsyncend,
  1053. mga->linecomp
  1054. );
  1055. }
  1056. mga->hiprilvl = 0;
  1057. mga->maxhipri = 0;
  1058. mga->c2hiprilvl = 0;
  1059. mga->c2maxhipri = 0;
  1060. mga->misc = ((mode->hsync != '-')?0:(1<<6)) | ((mode->vsync != '-')?0:(1<<7));
  1061. trace("mga->htotal = %ld\n"
  1062. "mga->hdispend = %ld\n"
  1063. "mga->hblkstr = %ld\n"
  1064. "mga->hblkend = %ld\n"
  1065. "mga->hsyncstr = %ld\n"
  1066. "mga->hsyncend = %ld\n"
  1067. "mga->hsyncdel = %ld\n"
  1068. "mga->vtotal = %ld\n"
  1069. "mga->vdispend = %ld\n"
  1070. "mga->vblkstr = %ld\n"
  1071. "mga->vblkend = %ld\n"
  1072. "mga->vsyncstr = %ld\n"
  1073. "mga->vsyncend = %ld\n"
  1074. "mga->linecomp = %ld\n",
  1075. mga->htotal,
  1076. mga->hdispend,
  1077. mga->hblkstr,
  1078. mga->hblkend,
  1079. mga->hsyncstr,
  1080. mga->hsyncend,
  1081. mga->hsyncdel,
  1082. mga->vtotal,
  1083. mga->vdispend,
  1084. mga->vblkstr,
  1085. mga->vblkend,
  1086. mga->vsyncstr,
  1087. mga->vsyncend,
  1088. mga->linecomp
  1089. );
  1090. mga->crtc[0x00] = 0xff & mga->htotal;
  1091. mga->crtc[0x01] = 0xff & mga->hdispend;
  1092. mga->crtc[0x02] = 0xff & mga->hblkstr;
  1093. mga->crtc[0x03] = (0x1f & mga->hblkend)
  1094. | ((0x03 & mga->hdispskew) << 5)
  1095. | 0x80 /* cf 3-304 */
  1096. ;
  1097. mga->crtc[0x04] = 0xff & mga->hsyncstr;
  1098. mga->crtc[0x05] = (0x1f & mga->hsyncend)
  1099. | ((0x03 & mga->hsyncdel) << 5)
  1100. | ((0x01 & (mga->hblkend >> 5)) << 7)
  1101. ;
  1102. mga->crtc[0x06] = 0xff & mga->vtotal;
  1103. t = ((0x01 & (mga->vtotal >> 8)) << 0)
  1104. | ((0x01 & (mga->vdispend >> 8)) << 1)
  1105. | ((0x01 & (mga->vsyncstr >> 8)) << 2)
  1106. | ((0x01 & (mga->vblkstr >> 8)) << 3)
  1107. | ((0x01 & (mga->linecomp >> 8)) << 4)
  1108. | ((0x01 & (mga->vtotal >> 9)) << 5)
  1109. | ((0x01 & (mga->vdispend >> 9)) << 6)
  1110. | ((0x01 & (mga->vsyncstr >> 9)) << 7)
  1111. ;
  1112. mga->crtc[0x07] = 0xff & t;
  1113. mga->crtc[0x08] = (0x1f & mga->prowscan)
  1114. | ((0x03 & mga->bytepan) << 5)
  1115. ;
  1116. mga->crtc[0x09] = (0x1f & mga->maxscan)
  1117. | ((0x01 & (mga->vblkstr >> 9)) << 5)
  1118. | ((0x01 & (mga->linecomp >> 9)) << 6)
  1119. | ((0x01 & mga->conv2t4) << 7)
  1120. ;
  1121. mga->crtc[0x0a] = (0x1f & mga->currowstr)
  1122. | ((0x01 & mga->curoff) << 5)
  1123. ;
  1124. mga->crtc[0x0b] = (0x1f & mga->currowend)
  1125. | ((0x03 & mga->curskew) << 5)
  1126. ;
  1127. mga->crtc[0x0c] = 0xff & (mga->startadd >> 8);
  1128. mga->crtc[0x0d] = 0xff & mga->startadd;
  1129. mga->crtc[0x0e] = 0xff & (mga->curloc >> 8);
  1130. mga->crtc[0x0f] = 0xff & mga->curloc;
  1131. mga->crtc[0x10] = 0xff & mga->vsyncstr;
  1132. mga->crtc[0x11] = (0x0f & mga->vsyncend)
  1133. | ((0x01 & mga->vintclr) << 4)
  1134. | ((0x01 & mga->vinten) << 5)
  1135. | ((0x01 & mga->crtcprotect) << 7)
  1136. ;
  1137. mga->crtc[0x12] = 0xff & mga->vdispend;
  1138. mga->crtc[0x13] = 0xff & mga->offset;
  1139. mga->crtc[0x14] = 0x1f & mga->undrow; /* vga only */
  1140. mga->crtc[0x15] = 0xff & mga->vblkstr;
  1141. mga->crtc[0x16] = 0xff & mga->vblkend;
  1142. mga->crtc[0x17] = ((0x01 & mga->cms) << 0)
  1143. | ((0x01 & mga->selrowscan) << 1)
  1144. | ((0x01 & mga->hsyncsel) << 2)
  1145. | ((0x01 & mga->addwrap) << 5)
  1146. | ((0x01 & mga->wbmode) << 6)
  1147. | ((0x01 & mga->crtcrstN) << 7)
  1148. ;
  1149. mga->crtc[0x18] = 0xff & mga->linecomp;
  1150. mga->crtcext[0] = (0x0f & (mga->startadd >> 16))
  1151. | ((0x03 & (mga->offset >> 8)) << 4)
  1152. | ((0x01 & (mga->startadd >> 20)) << 6)
  1153. | ((0x01 & mga->interlace) << 7)
  1154. ;
  1155. mga->crtcext[1] = ((0x01 & (mga->htotal >> 8)) << 0)
  1156. | ((0x01 & (mga->hblkstr >> 8)) << 1)
  1157. | ((0x01 & (mga->hsyncstr >> 8)) << 2)
  1158. | ((0x01 & mga->hrsten) << 3)
  1159. | ((0x01 & mga->hsyncoff) << 4)
  1160. | ((0x01 & mga->vsyncoff) << 5)
  1161. | ((0x01 & (mga->hblkend >> 6)) << 6)
  1162. | ((0x01 & mga->vrsten) << 7)
  1163. ;
  1164. mga->crtcext[2] = ((0x03 & (mga->vtotal >> 10)) << 0)
  1165. | ((0x01 & (mga->vdispend >> 10)) << 2)
  1166. | ((0x03 & (mga->vblkstr >> 10)) << 3)
  1167. | ((0x03 & (mga->vsyncstr >> 10)) << 5)
  1168. | ((0x01 & (mga->linecomp >> 10)) << 7)
  1169. ;
  1170. mga->crtcext[3] = ((0x07 & mga->scale) << 0)
  1171. | ((0x01 & mga->csynccen) << 6)
  1172. | ((0x01 & mga->mgamode) << 7)
  1173. ;
  1174. mga->crtcext[4] = 0; /* memory page ... not used in Power Graphic Mode */
  1175. mga->crtcext[5] = 0; /* Not used in non-interlaced mode */
  1176. mga->crtcext[6] = ((0x07 & mga->hiprilvl) << 0)
  1177. | ((0x07 & mga->maxhipri) << 4)
  1178. ;
  1179. mga->crtcext[7] = ((0x07 & mga->winsize) << 1)
  1180. | ((0x07 & mga->winfreq) << 5)
  1181. ;
  1182. mga->crtcext[8] = (0x01 & (mga->startadd >> 21)) << 0;
  1183. /* Initialize Sequencer */
  1184. mga->sequencer[0] = 0;
  1185. mga->sequencer[1] = 0;
  1186. mga->sequencer[2] = 0x03;
  1187. mga->sequencer[3] = 0;
  1188. mga->sequencer[4] = 0x02;
  1189. /* Graphic Control registers are ignored when not using 0xA0000 aperture */
  1190. for (i = 0; i < 9; i++)
  1191. mga->graphics[i] = 0;
  1192. /* The Attribute Controler is not available in Power Graphics mode */
  1193. for (i = 0; i < 0x15; i++)
  1194. mga->attribute[i] = i;
  1195. /* disable vga load (want to do fields in different order) */
  1196. for(c = vga->link; c; c = c->link)
  1197. if (strncmp(c->name, "vga", 3) == 0)
  1198. c->load = nil;
  1199. }
  1200. static void
  1201. load(Vga* vga, Ctlr* ctlr)
  1202. {
  1203. Mga* mga;
  1204. int i;
  1205. uchar* p;
  1206. Mode* mode;
  1207. uchar cursor;
  1208. mga = vga->private;
  1209. mode = vga->mode;
  1210. trace("mga: Loading ...\n");
  1211. dump_all_regs(mga);
  1212. if (mode->z == 8)
  1213. setpalettedepth(mode->z);
  1214. trace("mga mmio at %#p\n", mga->mmio);
  1215. trace("mga: loading vga registers ...\n" );
  1216. if (ultradebug) Bflush(&stdout);
  1217. /* Initialize Sequencer registers */
  1218. for(i = 0; i < 5; i++)
  1219. seqset(mga, i, mga->sequencer[i], 0xff);
  1220. /* Initialize Attribute register */
  1221. for(i = 0; i < 0x15; i++)
  1222. attrset(mga, i, mga->attribute[i], 0xff);
  1223. /* Initialize Graphic Control registers */
  1224. for(i = 0; i < 9; i++)
  1225. gctlset(mga, i, mga->graphics[i], 0xff);
  1226. /* Wait VSYNC */
  1227. while (mgaread8(mga, STATUS1) & 0x08);
  1228. while (! (mgaread8(mga, STATUS1) & ~0x08));
  1229. /* Turn off the video. */
  1230. seqset(mga, Seq_ClockingMode, Scroff, 0);
  1231. /* Crtc2 Off */
  1232. mgawrite32(mga, C2_CTL, 0);
  1233. /* Disable Cursor */
  1234. cursor = dacset(mga, Dac_Xcurctrl, CursorDis, 0xff);
  1235. /* Pixel Pll UP and set Pixel clock source to Pixel Clock PLL */
  1236. dacset(mga, Dac_Xpixclkctrl, 0x01 | 0x08, 0x0f);
  1237. trace("mga: waiting for the clock source becomes stable ...\n");
  1238. while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
  1239. ;
  1240. trace("mga: pixpll locked !\n");
  1241. if (ultradebug) Bflush(&stdout);
  1242. /* Enable LUT, Disable MAFC */
  1243. dacset(mga, Dac_Xmiscctrl, Ramcs | Mfcsel, Vdoutsel);
  1244. /* Disable Dac */
  1245. dacset(mga, Dac_Xmiscctrl, 0, Dacpdn);
  1246. /* Initialize Panel Mode */
  1247. dacset(mga, Dac_Xpanelmode, 0, 0xff);
  1248. /* Disable the PIXCLK and set Pixel clock source to Pixel Clock PLL */
  1249. dacset(mga, Dac_Xpixclkctrl, Pixclkdis | 0x01, 0x3);
  1250. /* Disable mapping of the memory */
  1251. miscset(mga, 0, Misc_rammapen);
  1252. /* Enable 8 bit palette */
  1253. dacset(mga, Dac_Xmiscctrl, Vga8dac, 0);
  1254. /* Select MGA Pixel Clock */
  1255. miscset(mga, Misc_clksel, 0);
  1256. /* Initialize Z Buffer ... (useful?) */
  1257. mgawrite32(mga, Z_DEPTH_ORG, 0);
  1258. /* Wait */
  1259. for (i = 0; i < 50; i++)
  1260. mgaread32(mga, MGA_STATUS);
  1261. if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
  1262. dacset(mga, Dac_Xpixpllcm, mga->pixpll_m, 0xff);
  1263. dacset(mga, Dac_Xpixpllcn, mga->pixpll_n, 0xff);
  1264. dacset(mga, Dac_Xpixpllcp, mga->pixpll_p, 0xff);
  1265. /* Wait until new clock becomes stable */
  1266. trace("mga: waiting for the clock source becomes stable ...\n");
  1267. while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
  1268. ;
  1269. trace("mga: pixpll locked !\n");
  1270. } else {
  1271. /* MGA450 and MGA550 */
  1272. /* Wait until new clock becomes stable */
  1273. trace("mga450: waiting for the clock source becomes stable ...\n");
  1274. while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
  1275. ;
  1276. trace("mga: pixpll locked !\n");
  1277. G450SetPLLFreq(mga, (long) mga->Fneeded / 1000);
  1278. }
  1279. /* Enable Pixel Clock Oscillation */
  1280. dacset(mga, Dac_Xpixclkctrl, 0, Pixclkdis);
  1281. if (ultradebug) Bflush(&stdout);
  1282. /* Enable Dac */
  1283. dacset(mga, Dac_Xmiscctrl, Dacpdn, 0);
  1284. /* Set Video Mode */
  1285. switch (mode->z) {
  1286. case 8:
  1287. dacset(mga, Dac_Xmulctrl, _8bitsPerPixel, ColorDepth);
  1288. break;
  1289. case 16:
  1290. dacset(mga, Dac_Xmulctrl, _16bitsPerPixel, ColorDepth);
  1291. break;
  1292. case 24:
  1293. dacset(mga, Dac_Xmulctrl, _24bitsPerPixel, ColorDepth);
  1294. break;
  1295. case 32:
  1296. dacset(mga, Dac_Xmulctrl, _32bitsPerPixel, ColorDepth);
  1297. break;
  1298. default:
  1299. error("Unsupported depth %d\n", mode->z);
  1300. }
  1301. /* Wait */
  1302. for (i = 0; i < 50; i++)
  1303. mgaread32(mga, MGA_STATUS);
  1304. /* Wait until new clock becomes stable */
  1305. trace("mga: waiting for the clock source becomes stable ...\n");
  1306. if (ultradebug) Bflush(&stdout);
  1307. while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
  1308. ;
  1309. trace("mga: pixpll locked !\n");
  1310. if (ultradebug) Bflush(&stdout);
  1311. /* Initialize CRTC registers and remove irq */
  1312. crtcset(mga, 0x11, (1<<4), (1<<5)|0x80);
  1313. for (i = 0; i < 25; i++)
  1314. crtcset(mga, i, mga->crtc[i], 0xff);
  1315. trace("mga: crtc loaded !\n");
  1316. if (ultradebug) Bflush(&stdout);
  1317. /* Initialize CRTC Extension registers */
  1318. for (i = 0; i < 9; i++)
  1319. crtcextset(mga, i, mga->crtcext[i], 0xff);
  1320. trace("mga: ext loaded !\n");
  1321. if (ultradebug) Bflush(&stdout);
  1322. /* Disable Zoom */
  1323. dacset(mga, Dac_Xzoomctrl, 0, 0xff);
  1324. trace("mga: XzoomCtrl Loaded !\n");
  1325. if (ultradebug) Bflush(&stdout);
  1326. /* Enable mga mode again ... Just in case :) */
  1327. crtcextset(mga, CrtcExt_Miscellaneous, Mgamode, 0);
  1328. trace("mga: crtcext MgaMode loaded !\n");
  1329. if (ultradebug) Bflush(&stdout);
  1330. if (mode->z == 32 || mode->z == 24 ) {
  1331. /* Initialize Big Endian Mode ! */
  1332. mgawrite32(mga, 0x1e54, 0x02 << 16);
  1333. }
  1334. /* Set final misc ... enable mapping ... */
  1335. miscset(mga, mga->misc | Misc_rammapen, 0);
  1336. trace("mga: mapping enabled !\n");
  1337. if (ultradebug) Bflush(&stdout);
  1338. /* Enable Screen */
  1339. seqset(mga, 1, 0, 0xff);
  1340. trace("screen enabled ...\n");
  1341. if (0) {
  1342. p = mga->mmfb;
  1343. for (i = 0; i < mga->fbsize; i++)
  1344. *p++ = (0xff & i);
  1345. }
  1346. trace("mga: Loaded !\n" );
  1347. dump_all_regs(mga);
  1348. if (ultradebug) Bflush(&stdout);
  1349. trace("mga: Loaded [bis]!\n" );
  1350. /*
  1351. * TODO: In 16bpp mode, what is the correct palette ?
  1352. * in the meantime lets use the default one,
  1353. * which has a weird color combination.
  1354. */
  1355. if (mode->z != 8 && mode ->z != 16) {
  1356. /* Initialize Palette */
  1357. mgawrite8(mga, RAMDACIDX, 0);
  1358. for (i = 0; i < 0x100; i++) {
  1359. mgawrite8(mga, RAMDACPALDATA, i);
  1360. mgawrite8(mga, RAMDACPALDATA, i);
  1361. mgawrite8(mga, RAMDACPALDATA, i);
  1362. }
  1363. }
  1364. trace("mga: Palette initialised !\n");
  1365. /* Enable Cursor */
  1366. dacset(mga, Dac_Xcurctrl, cursor, 0xff);
  1367. ctlr->flag |= Fload;
  1368. if (ultradebug) Bflush(&stdout);
  1369. }
  1370. Ctlr mga4xx = {
  1371. "mga4xx", /* name */
  1372. snarf, /* snarf */
  1373. options, /* options */
  1374. init, /* init */
  1375. load, /* load */
  1376. dump, /* dump */
  1377. };
  1378. Ctlr mga4xxhwgc = {
  1379. "mga4xxhwgc", /* name */
  1380. 0, /* snarf */
  1381. 0, /* options */
  1382. 0, /* init */
  1383. 0, /* load */
  1384. dump, /* dump */
  1385. };