tvp3020.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * Tvp302[056] Viewpoint Video Interface Palette.
  8. * Assumes hooked up to an S3 86C928 or S3 Vision964.
  9. */
  10. enum {
  11. Index = 0x06, /* Index register */
  12. Data = 0x07, /* Data register */
  13. Id = 0x3F, /* ID Register */
  14. Tvp3020 = 0x20,
  15. Tvp3025 = 0x25,
  16. Tvp3026 = 0x26,
  17. };
  18. /*
  19. * The following two arrays give read (bit 0) and write (bit 1)
  20. * permissions on the direct and index registers. Bits 4 and 5
  21. * are for the Tvp3025. The Tvp3020 has only 8 direct registers.
  22. */
  23. static uchar directreg[32] = {
  24. 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x33, 0x33,
  25. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  26. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
  27. 0x33, 0x33, 0x11, 0x33, 0x33, 0x33, 0x33, 0x33,
  28. };
  29. static uchar indexreg[64] = {
  30. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00,
  31. 0x02, 0x02, 0x33, 0x00, 0x00, 0x00, 0x30, 0x30,
  32. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
  33. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x30, 0x00,
  34. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
  35. 0x33, 0x33, 0x33, 0x33, 0x30, 0x30, 0x30, 0x30,
  36. 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
  37. 0x33, 0x30, 0x33, 0x11, 0x11, 0x11, 0x22, 0x11,
  38. };
  39. /*
  40. * Check the index register access is valid.
  41. * Return the number of direct registers.
  42. */
  43. static uchar
  44. checkindex(uchar index, uchar access)
  45. {
  46. uchar crt55;
  47. static uchar id;
  48. if(id == 0){
  49. crt55 = vgaxi(Crtx, 0x55) & 0xFC;
  50. vgaxo(Crtx, 0x55, crt55|((Index>>2) & 0x03));
  51. vgao(dacxreg[Index & 0x03], Id);
  52. id = vgai(dacxreg[Data & 0x03]);
  53. vgaxo(Crtx, 0x55, crt55);
  54. }
  55. if(index == 0xFF)
  56. return id;
  57. access &= 0x03;
  58. switch(id){
  59. case Tvp3020:
  60. break;
  61. case Tvp3025:
  62. case Tvp3026:
  63. access = access<<4;
  64. break;
  65. default:
  66. Bprint(&stdout, "%s: unknown chip id - 0x%2.2X\n", tvp3020.name, id);
  67. break;
  68. }
  69. if(index > sizeof(indexreg) || (indexreg[index] & access) == 0)
  70. error("%s: bad register index - 0x%2.2X\n", tvp3020.name, index);
  71. return id;
  72. }
  73. static uchar
  74. tvp3020io(uchar reg, uchar data)
  75. {
  76. uchar crt55;
  77. crt55 = vgaxi(Crtx, 0x55) & 0xFC;
  78. vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
  79. vgao(dacxreg[reg & 0x03], data);
  80. return crt55;
  81. }
  82. uchar
  83. tvp3020i(uchar reg)
  84. {
  85. uchar crt55, r;
  86. crt55 = vgaxi(Crtx, 0x55) & 0xFC;
  87. vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
  88. r = vgai(dacxreg[reg & 0x03]);
  89. vgaxo(Crtx, 0x55, crt55);
  90. return r;
  91. }
  92. uchar
  93. tvp3020xi(uchar index)
  94. {
  95. uchar crt55, r;
  96. checkindex(index, 0x01);
  97. crt55 = tvp3020io(Index, index);
  98. r = vgai(dacxreg[Data & 0x03]);
  99. vgaxo(Crtx, 0x55, crt55);
  100. return r;
  101. }
  102. void
  103. tvp3020o(uchar reg, uchar data)
  104. {
  105. uchar crt55;
  106. crt55 = tvp3020io(reg, data);
  107. vgaxo(Crtx, 0x55, crt55);
  108. }
  109. void
  110. tvp3020xo(uchar index, uchar data)
  111. {
  112. uchar crt55;
  113. checkindex(index, 0x02);
  114. crt55 = tvp3020io(Index, index);
  115. vgao(dacxreg[Data & 0x03], data);
  116. vgaxo(Crtx, 0x55, crt55);
  117. }
  118. static void
  119. options(Vga*, Ctlr* ctlr)
  120. {
  121. ctlr->flag |= Hclk2|Hextsid|Hpvram|Henhanced|Foptions;
  122. }
  123. static void
  124. init(Vga* vga, Ctlr* ctlr)
  125. {
  126. ulong grade;
  127. char *p;
  128. /*
  129. * Work out the part speed-grade from name. Name can have,
  130. * e.g. '-135' on the end for 135MHz part.
  131. */
  132. grade = 110000000;
  133. if(p = strrchr(ctlr->name, '-'))
  134. grade = strtoul(p+1, 0, 0) * 1000000;
  135. /*
  136. * If we don't already have a desired pclk,
  137. * take it from the mode.
  138. * Check it's within range.
  139. */
  140. if(vga->f[0] == 0)
  141. vga->f[0] = vga->mode->frequency;
  142. if(vga->f[0] > grade)
  143. error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
  144. /*
  145. * Determine whether to use clock-doubler or not.
  146. */
  147. if(vga->f[0] > 85000000){
  148. vga->f[0] /= 2;
  149. resyncinit(vga, ctlr, Uclk2, 0);
  150. }
  151. ctlr->flag |= Finit;
  152. }
  153. static void
  154. load(Vga* vga, Ctlr* ctlr)
  155. {
  156. uchar x;
  157. /*
  158. * Input Clock Selection:
  159. * VGA CLK0
  160. * enhanced CLK1
  161. * doubled if necessary.
  162. */
  163. x = 0x00;
  164. if(ctlr->flag & Uenhanced)
  165. x |= 0x01;
  166. if(ctlr->flag & Uclk2)
  167. x |= 0x10;
  168. tvp3020xo(0x1A, x);
  169. /*
  170. * Output Clock Selection:
  171. * VGA default VGA
  172. * enhanced RCLK=SCLK=/8, VCLK/4
  173. */
  174. x = 0x3E;
  175. if(ctlr->flag & Uenhanced)
  176. x = 0x53;
  177. tvp3020xo(0x1B, x);
  178. /*
  179. * Auxiliary Control:
  180. * default settings - self-clocked, palette graphics, no zoom
  181. * Colour Key Control:
  182. * default settings - pointing to palette graphics
  183. * Mux Control Register 1:
  184. * pseudo colour
  185. */
  186. tvp3020xo(0x29, 0x09);
  187. tvp3020xo(0x38, 0x10);
  188. tvp3020xo(0x18, 0x80);
  189. /*
  190. * Mux Control Register 2:
  191. * VGA default VGA
  192. * enhanced 8-bpp, 8:1 mux, 64-bit pixel-bus width
  193. */
  194. x = 0x98;
  195. if(ctlr->flag & Uenhanced){
  196. if(vga->mode->z == 8)
  197. x = 0x1C;
  198. else if(vga->mode->z == 1)
  199. x = 0x04;
  200. }
  201. tvp3020xo(0x19, x);
  202. /*
  203. * General Control:
  204. * output sync polarity
  205. * It's important to set this properly and to turn off the
  206. * VGA controller H and V syncs. Can't be set in VGA mode.
  207. */
  208. x = 0x00;
  209. if((vga->misc & 0x40) == 0)
  210. x |= 0x01;
  211. if((vga->misc & 0x80) == 0)
  212. x |= 0x02;
  213. tvp3020xo(0x1D, x);
  214. vga->misc |= 0xC0;
  215. vgao(MiscW, vga->misc);
  216. /*
  217. * Select the DAC via the General Purpose I/O
  218. * Register and Pins.
  219. * Guesswork by looking at register dumps.
  220. */
  221. tvp3020xo(0x2A, 0x1F);
  222. if(ctlr->flag & Uenhanced)
  223. x = 0x1D;
  224. else
  225. x = 0x1C;
  226. tvp3020xo(0x2B, x);
  227. ctlr->flag |= Fload;
  228. }
  229. static void
  230. dump(Vga*, Ctlr* ctlr)
  231. {
  232. uchar access;
  233. int i;
  234. access = 0x01;
  235. if(checkindex(0x00, 0x01) != Tvp3020)
  236. access <<= 4;
  237. printitem(ctlr->name, "direct");
  238. for(i = 0; i < 8; i++){
  239. if(directreg[i] & access)
  240. printreg(tvp3020i(i));
  241. else
  242. printreg(0xFF);
  243. }
  244. printitem(ctlr->name, "index");
  245. for(i = 0; i < sizeof(indexreg); i++){
  246. if(indexreg[i] & access)
  247. printreg(tvp3020xi(i));
  248. else
  249. printreg(0xFF);
  250. }
  251. }
  252. Ctlr tvp3020 = {
  253. "tvp3020", /* name */
  254. 0, /* snarf */
  255. options, /* options */
  256. init, /* init */
  257. load, /* load */
  258. dump, /* dump */
  259. };