rgb524mn.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * IBM RGB52x and compatibles.
  8. * High Performance Palette DAC.
  9. */
  10. uchar (*rgb524mnxi)(Vga*, int);
  11. void (*rgb524mnxo)(Vga*, int, uchar);
  12. enum { /* index registers */
  13. MiscClock = 0x02,
  14. SyncControl = 0x03,
  15. HSyncControl = 0x04,
  16. PowerMgmnt = 0x05,
  17. PaletteControl = 0x07,
  18. SYSCLKControl = 0x08,
  19. PixelFormat = 0x0A,
  20. Pixel8Control = 0x0B,
  21. Pixel16Control = 0x0C,
  22. Pixel32Control = 0x0E,
  23. PLLControl1 = 0x10,
  24. PLLControl2 = 0x11,
  25. SYSCLKN = 0x15,
  26. SYSCLKM = 0x16,
  27. M0 = 0x20,
  28. N0 = 0x21,
  29. MiscControl1 = 0x70,
  30. MiscControl2 = 0x71,
  31. };
  32. static void
  33. clock(Vga* vga, Ctlr*, ulong fref, ulong maxpclk)
  34. {
  35. int d, mind;
  36. ulong df, f, m, n, vrf;
  37. mind = vga->f[0]+1;
  38. for(df = 0; df < 4; df++){
  39. for(m = 2; m < 64; m++){
  40. for(n = 2; n < 32; n++){
  41. f = (fref*(m+65))/n;
  42. switch(df){
  43. case 0:
  44. vrf = fref/(n*2);
  45. if(vrf > maxpclk/4 || vrf < 1000000)
  46. continue;
  47. f /= 8;
  48. break;
  49. case 1:
  50. vrf = fref/(n*2);
  51. if(vrf > maxpclk/2 || vrf < 1000000)
  52. continue;
  53. f /= 4;
  54. break;
  55. case 2:
  56. vrf = fref/(n*2);
  57. if(vrf > maxpclk || vrf < 1000000)
  58. continue;
  59. f /= 2;
  60. break;
  61. case 3:
  62. vrf = fref/n;
  63. if(vrf > maxpclk || vrf < 1000000)
  64. continue;
  65. break;
  66. }
  67. if(f > maxpclk)
  68. continue;
  69. d = vga->f[0] - f;
  70. if(d < 0)
  71. d = -d;
  72. if(d <= mind){
  73. vga->m[0] = m;
  74. vga->n[0] = n;
  75. vga->d[0] = df;
  76. mind = d;
  77. }
  78. }
  79. }
  80. }
  81. }
  82. static void
  83. init(Vga* vga, Ctlr* ctlr)
  84. {
  85. ulong fref, maxpclk;
  86. char *p, *val;
  87. /*
  88. * Part comes in at least a -170MHz speed-grade.
  89. */
  90. maxpclk = 170000000;
  91. if(p = strrchr(ctlr->name, '-'))
  92. maxpclk = strtoul(p+1, 0, 0) * 1000000;
  93. /*
  94. * If we don't already have a desired pclk,
  95. * take it from the mode.
  96. * Check it's within range.
  97. */
  98. if(vga->f[0] == 0)
  99. vga->f[0] = vga->mode->frequency;
  100. if(vga->f[0] > maxpclk)
  101. error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
  102. if(val = dbattr(vga->attr, "rgb524mnrefclk"))
  103. fref = strtol(val, 0, 0);
  104. else
  105. fref = RefFreq;
  106. /*
  107. * Initialise the PLL parameters.
  108. * Use m/n pair 2.
  109. */
  110. clock(vga, ctlr, fref, maxpclk);
  111. vga->i[0] = 2;
  112. ctlr->flag |= Finit;
  113. }
  114. static void
  115. load(Vga* vga, Ctlr* ctlr)
  116. {
  117. char *val;
  118. int hsyncdelay, x;
  119. if(rgb524mnxi == nil && rgb524mnxo == nil)
  120. error("%s->load: no access routines\n", ctlr->name);
  121. /*
  122. * Set the m/n values for the desired frequency and
  123. * set pixel control to use compatibility mode with
  124. * internal frequency select using the specified set
  125. * of m/n registers.
  126. */
  127. rgb524mnxo(vga, M0+vga->i[0]*2, vga->d[0]<<6|vga->m[0]);
  128. rgb524mnxo(vga, N0+vga->i[0]*2, vga->n[0]);
  129. rgb524mnxo(vga, PLLControl2, vga->i[0]);
  130. rgb524mnxo(vga, PLLControl1, 0x03);
  131. /*
  132. * Enable pixel programming in MiscClock;
  133. * nothing to do in MiscControl1;
  134. * set internal PLL clock and !vga in MiscControl2;
  135. */
  136. x = rgb524mnxi(vga, MiscClock) & ~0x01;
  137. x |= 0x01;
  138. rgb524mnxo(vga, MiscClock, x);
  139. x = rgb524mnxi(vga, MiscControl2) & ~0x41;
  140. x |= 0x41;
  141. rgb524mnxo(vga, MiscControl2, x);
  142. /*
  143. * Syncs.
  144. */
  145. x = 0;
  146. if(vga->mode->hsync == '+')
  147. x |= 0x10;
  148. if(vga->mode->vsync == '+')
  149. x |= 0x20;
  150. rgb524mnxo(vga, SyncControl, x);
  151. if(val = dbattr(vga->mode->attr, "hsyncdelay"))
  152. hsyncdelay = strtol(val, 0, 0);
  153. else switch(vga->mode->z){
  154. default:
  155. case 8:
  156. hsyncdelay = 1;
  157. break;
  158. case 15:
  159. case 16:
  160. hsyncdelay = 5;
  161. break;
  162. case 32:
  163. hsyncdelay = 7;
  164. break;
  165. }
  166. rgb524mnxo(vga, HSyncControl, hsyncdelay);
  167. rgb524mnxo(vga, SYSCLKM, 0x50);
  168. rgb524mnxo(vga, SYSCLKN, 0x08);
  169. sleep(50);
  170. //rgb524mnxo(vga, SYSCLKM, 0x6F);
  171. //rgb524mnxo(vga, SYSCLKN, 0x0F);
  172. //sleep(500);
  173. /*
  174. * Set the palette for the desired format.
  175. * ****NEEDS WORK FOR OTHER THAN 8-BITS****
  176. */
  177. rgb524mnxo(vga, PaletteControl, 0x00);
  178. switch(vga->mode->z){
  179. case 8:
  180. rgb524mnxo(vga, PixelFormat, 0x03);
  181. rgb524mnxo(vga, Pixel8Control, 0x00);
  182. break;
  183. case 15:
  184. rgb524mnxo(vga, PixelFormat, 0x04);
  185. rgb524mnxo(vga, Pixel16Control, 0xC4);
  186. case 16:
  187. rgb524mnxo(vga, PixelFormat, 0x04);
  188. rgb524mnxo(vga, Pixel16Control, 0xC6);
  189. break;
  190. case 32:
  191. rgb524mnxo(vga, PixelFormat, 0x06);
  192. rgb524mnxo(vga, Pixel32Control, 0x03);
  193. break;
  194. }
  195. }
  196. static void
  197. dumpclock(Vga*, Ctlr* ctlr, ulong fref, ulong m, ulong n, char* name)
  198. {
  199. ulong df, f;
  200. df = (m>>6) & 0x03;
  201. m &= 0x3F;
  202. n &= 0x1F;
  203. if(m == 0 || n == 0)
  204. return;
  205. f = (fref*(m+65))/n;
  206. switch(df){
  207. case 0:
  208. f /= 8;
  209. break;
  210. case 1:
  211. f /= 4;
  212. break;
  213. case 2:
  214. f /= 2;
  215. break;
  216. case 3:
  217. break;
  218. }
  219. printitem(ctlr->name, name);
  220. Bprint(&stdout, "%12lud\n", f);
  221. }
  222. static void
  223. dump(Vga* vga, Ctlr* ctlr)
  224. {
  225. int i;
  226. char *val;
  227. uchar x[256];
  228. ulong fref, fs;
  229. if(rgb524mnxi == nil && rgb524mnxo == nil)
  230. error("%s->dump: no access routines\n", ctlr->name);
  231. printitem(ctlr->name, "index00");
  232. for(i = 0x00; i < 0x0F; i++){
  233. x[i] = rgb524mnxi(vga, i);
  234. printreg(x[i]);
  235. }
  236. printitem(ctlr->name, "index10");
  237. for(i = 0x10; i < 0x18; i++){
  238. x[i] = rgb524mnxi(vga, i);
  239. printreg(x[i]);
  240. }
  241. printitem(ctlr->name, "index20");
  242. for(i = 0x20; i < 0x30; i++){
  243. x[i] = rgb524mnxi(vga, i);
  244. printreg(x[i]);
  245. }
  246. printitem(ctlr->name, "index30");
  247. for(i = 0x30; i < 0x39; i++){
  248. x[i] = rgb524mnxi(vga, i);
  249. printreg(x[i]);
  250. }
  251. printitem(ctlr->name, "index40");
  252. for(i = 0x40; i < 0x49; i++){
  253. x[i] = rgb524mnxi(vga, i);
  254. printreg(x[i]);
  255. }
  256. printitem(ctlr->name, "index60");
  257. for(i = 0x60; i < 0x63; i++){
  258. x[i] = rgb524mnxi(vga, i);
  259. printreg(x[i]);
  260. }
  261. printitem(ctlr->name, "index70");
  262. for(i = 0x70; i < 0x73; i++){
  263. x[i] = rgb524mnxi(vga, i);
  264. printreg(x[i]);
  265. }
  266. printitem(ctlr->name, "index8E");
  267. for(i = 0x8E; i < 0x92; i++){
  268. x[i] = rgb524mnxi(vga, i);
  269. printreg(x[i]);
  270. }
  271. if(val = dbattr(vga->attr, "rgb524mnrefclk"))
  272. fref = strtol(val, 0, 0);
  273. else
  274. fref = RefFreq;
  275. if(!(x[SYSCLKControl] & 0x04))
  276. dumpclock(vga, ctlr, fref, x[0x16], x[0x15], "sysclk");
  277. fs = x[PLLControl1] & 0x07;
  278. if(fs == 0x01 || fs == 0x03){
  279. if(fs == 0x01)
  280. i = ((vga->misc>>2) & 0x03)*2;
  281. else
  282. i = x[PLLControl2] & 0x07;
  283. dumpclock(vga, ctlr, fref, x[M0+i*2], x[N0+i*2], "pllclk");
  284. }
  285. }
  286. Ctlr rgb524mn = {
  287. "rgb524mn", /* name */
  288. 0, /* snarf */
  289. 0, /* options */
  290. init, /* init */
  291. load, /* load */
  292. dump, /* dump */
  293. };