rgb524.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * IBM RGB524.
  8. * 170/220MHz High Performance Palette DAC.
  9. *
  10. * Assumes hooked up to an S3 Vision96[48].
  11. */
  12. enum {
  13. IndexLo = 0x00,
  14. IndexHi = 0x01,
  15. Data = 0x02,
  16. IndexCtl = 0x03,
  17. };
  18. enum { /* index registers */
  19. MiscClock = 0x02,
  20. PixelFormat = 0x0A,
  21. PLLControl1 = 0x10,
  22. PLLControl2 = 0x11,
  23. PLLReference = 0x14,
  24. Frequency0 = 0x20,
  25. MiscControl1 = 0x70,
  26. MiscControl2 = 0x71,
  27. };
  28. static uchar
  29. setrs2(void)
  30. {
  31. uchar rs2;
  32. rs2 = vgaxi(Crtx, 0x55);
  33. vgaxo(Crtx, 0x55, (rs2 & 0xFC)|0x01);
  34. return rs2;
  35. }
  36. static uchar
  37. rgb524xi(int index)
  38. {
  39. outportb(dacxreg[IndexLo], index & 0xFF);
  40. outportb(dacxreg[IndexHi], (index>>8) & 0xFF);
  41. return inportb(dacxreg[Data]);
  42. }
  43. static void
  44. rgb524xo(int index, uchar data)
  45. {
  46. outportb(dacxreg[IndexLo], index & 0xFF);
  47. outportb(dacxreg[IndexHi], (index>>8) & 0xFF);
  48. outportb(dacxreg[Data], data);
  49. }
  50. static void
  51. restorers2(uchar rs2)
  52. {
  53. vgaxo(Crtx, 0x55, rs2);
  54. }
  55. static void
  56. clock(Vga* vga, Ctlr* ctlr)
  57. {
  58. if(vga->f[0] >= 16250000 && vga->f[0] <= 32000000){
  59. vga->f[0] = (vga->f[0]/250000)*250000;
  60. vga->d[0] = (4*vga->f[0])/1000000 - 65;
  61. }
  62. else if(vga->f[0] >= 32500000 && vga->f[0] <= 64000000){
  63. vga->f[0] = (vga->f[0]/500000)*500000;
  64. vga->d[0] = 0x40|((2*vga->f[0])/1000000 - 65);
  65. }
  66. else if(vga->f[0] >= 65000000 && vga->f[0] <= 128000000){
  67. vga->f[0] = (vga->f[0]/1000000)*1000000;
  68. vga->d[0] = 0x80|(vga->f[0]/1000000 - 65);
  69. }
  70. else if(vga->f[0] >= 130000000 && vga->f[0] <= 220000000){
  71. vga->f[0] = (vga->f[0]/2000000)*2000000;
  72. vga->d[0] = 0xC0|((vga->f[0]/2)/1000000 - 65);
  73. }
  74. else
  75. error("%s: pclk %lud out of range\n",
  76. ctlr->name, vga->f[0]);
  77. }
  78. static void
  79. init(Vga* vga, Ctlr* ctlr)
  80. {
  81. ulong pclk;
  82. char *p;
  83. /*
  84. * Part comes in -170 and -220MHz speed-grades.
  85. */
  86. pclk = 170000000;
  87. if(p = strrchr(ctlr->name, '-'))
  88. pclk = strtoul(p+1, 0, 0) * 1000000;
  89. /*
  90. * If we don't already have a desired pclk,
  91. * take it from the mode.
  92. * Check it's within range.
  93. */
  94. if(vga->f[0] == 0)
  95. vga->f[0] = vga->mode->frequency;
  96. if(vga->f[0] > pclk)
  97. error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
  98. /*
  99. * Determine whether to use clock-doubler or not.
  100. */
  101. if((ctlr->flag & Uclk2) == 0 && vga->mode->z == 8)
  102. resyncinit(vga, ctlr, Uclk2, 0);
  103. /*
  104. * Clock bits. If the desired video clock is
  105. * one of the two standard VGA clocks it can just be
  106. * set using bits <3:2> of vga->misc, otherwise we
  107. * need to programme the PLL.
  108. */
  109. vga->misc &= ~0x0C;
  110. if(vga->mode->z == 8 || (vga->f[0] != VgaFreq0 && vga->f[0] != VgaFreq1)){
  111. /*
  112. * Initialise the PLL parameters.
  113. * Use internal FS3 fixed-reference divider.
  114. */
  115. clock(vga, ctlr);
  116. vga->i[0] = 0x03;
  117. }
  118. else if(vga->f[0] == VgaFreq0)
  119. vga->i[0] = 0;
  120. else if(vga->f[0] == VgaFreq1){
  121. vga->misc |= 0x04;
  122. vga->i[0] = 1;
  123. }
  124. ctlr->flag |= Finit;
  125. }
  126. static void
  127. load(Vga* vga, Ctlr* ctlr)
  128. {
  129. uchar mc2, rs2, x;
  130. char *val;
  131. int f;
  132. rs2 = setrs2();
  133. /*
  134. * Set VgaFreq[01].
  135. */
  136. rgb524xo(PLLControl1, 0x00);
  137. rgb524xo(Frequency0, 0x24);
  138. rgb524xo(Frequency0+1, 0x30);
  139. if(val = dbattr(vga->attr, "rgb524refclk")){
  140. f = strtol(val, 0, 0);
  141. if(f > 1000000)
  142. f /= 1000000;
  143. rgb524xo(PLLReference, f/2);
  144. }
  145. /*
  146. * Enable pixel programming and clock divide
  147. * factor.
  148. */
  149. x = rgb524xi(MiscClock) & ~0x0E;
  150. x |= 0x01;
  151. if(ctlr->flag & Uclk2)
  152. x |= 0x02;
  153. rgb524xo(MiscClock, x);
  154. if(vga->mode->z == 1)
  155. rgb524xo(PixelFormat, 0x02);
  156. else if(vga->mode->z == 8)
  157. rgb524xo(PixelFormat, 0x03);
  158. x = rgb524xi(MiscControl1) & ~0x41;
  159. x |= 0x01;
  160. rgb524xo(MiscControl1, x);
  161. mc2 = rgb524xi(MiscControl2) & ~0x41;
  162. vga->crt[0x22] &= ~0x08;
  163. if(vga->i[0] == 3){
  164. rgb524xo(Frequency0+3, vga->d[0]);
  165. rgb524xo(PLLControl1, 0x02);
  166. rgb524xo(PLLControl2, vga->i[0]);
  167. mc2 |= 0x41;
  168. vga->crt[0x22] |= 0x08;
  169. }
  170. rgb524xo(MiscControl2, mc2);
  171. vgaxo(Crtx, 0x22, vga->crt[0x22]);
  172. restorers2(rs2);
  173. ctlr->flag |= Fload;
  174. }
  175. static void
  176. dump(Vga*, Ctlr* ctlr)
  177. {
  178. uchar rs2, r, x[256];
  179. char buf[32];
  180. int df, i, maxf, vcodc, vf;
  181. rs2 = setrs2();
  182. printitem(ctlr->name, "index00");
  183. for(i = 0x00; i < 0x0F; i++){
  184. x[i] = rgb524xi(i);
  185. printreg(x[i]);
  186. }
  187. printitem(ctlr->name, "index10");
  188. for(i = 0x10; i < 0x17; i++){
  189. x[i] = rgb524xi(i);
  190. printreg(x[i]);
  191. }
  192. printitem(ctlr->name, "index20");
  193. for(i = 0x20; i < 0x30; i++){
  194. x[i] = rgb524xi(i);
  195. printreg(x[i]);
  196. }
  197. printitem(ctlr->name, "index30");
  198. for(i = 0x30; i < 0x37; i++){
  199. x[i] = rgb524xi(i);
  200. printreg(x[i]);
  201. }
  202. printitem(ctlr->name, "index40");
  203. for(i = 0x40; i < 0x49; i++){
  204. x[i] = rgb524xi(i);
  205. printreg(x[i]);
  206. }
  207. printitem(ctlr->name, "index60");
  208. for(i = 0x60; i < 0x63; i++){
  209. x[i] = rgb524xi(i);
  210. printreg(x[i]);
  211. }
  212. printitem(ctlr->name, "index70");
  213. for(i = 0x70; i < 0x73; i++){
  214. x[i] = rgb524xi(i);
  215. printreg(x[i]);
  216. }
  217. printitem(ctlr->name, "index8E");
  218. for(i = 0x8E; i < 0x92; i++){
  219. x[i] = rgb524xi(i);
  220. printreg(x[i]);
  221. }
  222. restorers2(rs2);
  223. /*
  224. * x[0x10] pixel clock frequency selection
  225. * 0, 2 for direct programming
  226. * x[0x20-0x2F] pixel frequency 0-15
  227. */
  228. printitem(ctlr->name, "refclk");
  229. Bprint(&stdout, "%12ud\n", x[PLLReference]*2*1000000);
  230. if((i = (x[0x10] & 0x07)) == 0x00 || i == 0x02){
  231. /*
  232. * Direct programming, external frequency select.
  233. * F[0-4] are probably tied directly to the 2 clock-select
  234. * bits in the VGA Misc register.
  235. */
  236. if(i == 0)
  237. maxf = 4;
  238. else
  239. maxf = 16;
  240. for(i = 0; i < maxf; i++){
  241. if((r = x[0x20+i]) == 0)
  242. continue;
  243. sprint(buf, "direct F%X", i);
  244. printitem(ctlr->name, buf);
  245. df = (r>>6) & 0x03;
  246. vcodc = r & 0x3F;
  247. vf = 0;
  248. switch(df){
  249. case 0:
  250. vf = (vcodc+65)/4;
  251. break;
  252. case 1:
  253. vf = (vcodc+65)/2;
  254. break;
  255. case 2:
  256. vf = (vcodc+65);
  257. break;
  258. case 3:
  259. vf = (vcodc+65)*2;
  260. break;
  261. }
  262. Bprint(&stdout, "%12ud\n", vf);
  263. }
  264. }
  265. }
  266. Ctlr rgb524 = {
  267. "rgb524", /* name */
  268. 0, /* snarf */
  269. 0, /* options */
  270. init, /* init */
  271. load, /* load */
  272. dump, /* dump */
  273. };