clgd546x.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * Laguna Visual Media Accelerators Family CL-GD546x.
  8. */
  9. typedef struct {
  10. Pcidev* pci;
  11. uchar* mmio;
  12. int mem;
  13. int format; /* graphics and video format */
  14. int threshold; /* display threshold */
  15. int tilectrl; /* tiling control */
  16. int vsc; /* vendor specific control */
  17. int control; /* control */
  18. int tilectrl2D3D; /* tiling control 2D3D */
  19. } Laguna;
  20. enum {
  21. Format = 0xC0, /* graphics and video format */
  22. Threshold = 0xEA, /* Display Threshold */
  23. TileCtrl = 0x2C4,
  24. Vsc = 0x3FC, /* Vendor Specific Control (32-bits) */
  25. Control = 0x402, /* 2D Control */
  26. TileCtrl2D3D = 0x407, /* (8-bits) */
  27. };
  28. static int
  29. mmio8r(Laguna* laguna, int offset)
  30. {
  31. return *(laguna->mmio+offset) & 0xFF;
  32. }
  33. static void
  34. mmio8w(Laguna* laguna, int offset, int data)
  35. {
  36. *(laguna->mmio+offset) = data;
  37. }
  38. static int
  39. mmio16r(Laguna* laguna, int offset)
  40. {
  41. return *((ushort*)(laguna->mmio+offset)) & 0xFFFF;
  42. }
  43. static void
  44. mmio16w(Laguna* laguna, int offset, int data)
  45. {
  46. *((ushort*)(laguna->mmio+offset)) = data;
  47. }
  48. static int
  49. mmio32r(Laguna* laguna, int offset)
  50. {
  51. return *((ulong*)(laguna->mmio+offset));
  52. }
  53. static void
  54. mmio32w(Laguna* laguna, int offset, int data)
  55. {
  56. *((ulong*)(laguna->mmio+offset)) = data;
  57. }
  58. static void
  59. snarf(Vga* vga, Ctlr* ctlr)
  60. {
  61. int f, i;
  62. uchar *mmio;
  63. Pcidev *p;
  64. Laguna *laguna;
  65. /*
  66. * Save all the registers, even though we'll only
  67. * change a handful.
  68. */
  69. for(i = 0x06; i < 0x20; i++)
  70. vga->sequencer[i] = vgaxi(Seqx, i);
  71. for(i = 0x09; i < 0x0C; i++)
  72. vga->graphics[i] = vgaxi(Grx, i);
  73. for(i = 0x19; i < 0x20; i++)
  74. vga->crt[i] = vgaxi(Crtx, i);
  75. if(vga->private == nil){
  76. vga->private = alloc(sizeof(Laguna));
  77. if((p = pcimatch(0, 0x1013, 0)) == nil)
  78. error("%s: not found\n", ctlr->name);
  79. switch(p->did){
  80. case 0xD0: /* CL-GD5462 */
  81. vga->f[1] = 170000000;
  82. break;
  83. case 0xD4: /* CL-GD5464 */
  84. case 0xD6: /* CL-GD5465 */
  85. vga->f[1] = 230000000;
  86. break;
  87. default:
  88. error("%s: not found\n", ctlr->name);
  89. }
  90. if((f = open("#v/vgactl", OWRITE)) < 0)
  91. error("%s: can't open vgactl\n", ctlr->name);
  92. if(write(f, "type clgd546x", 13) != 13)
  93. error("%s: can't set type\n", ctlr->name);
  94. close(f);
  95. mmio = segattach(0, "clgd546xmmio", 0, p->mem[1].size);
  96. if(mmio == (void*)-1)
  97. error("%s: can't attach mmio segment\n", ctlr->name);
  98. laguna = vga->private;
  99. laguna->pci = p;
  100. laguna->mmio = mmio;
  101. }
  102. laguna = vga->private;
  103. laguna->mem = (vga->sequencer[0x14] & 0x07)+1;
  104. laguna->format = mmio16r(laguna, Format);
  105. laguna->threshold = mmio16r(laguna, Threshold);
  106. laguna->tilectrl = mmio16r(laguna, TileCtrl);
  107. laguna->vsc = mmio32r(laguna, Vsc);
  108. laguna->control = mmio16r(laguna, Control);
  109. laguna->tilectrl2D3D = mmio8r(laguna, TileCtrl2D3D);
  110. vga->vma = vga->vmz = laguna->pci->mem[0].size;
  111. ctlr->flag |= Hlinear;
  112. ctlr->flag |= Fsnarf;
  113. }
  114. static void
  115. init(Vga* vga, Ctlr* ctlr)
  116. {
  117. Mode *mode;
  118. ushort x;
  119. int format, interleave, fetches, nointerleave, notile, pagesize, tiles;
  120. Laguna *laguna;
  121. nointerleave = 1;
  122. notile = 1;
  123. pagesize = 0;
  124. mode = vga->mode;
  125. if(vga->f[0] == 0)
  126. vga->f[0] = vga->mode->frequency;
  127. if(vga->f[0] > vga->f[1])
  128. error("%s: invalid pclk - %lud\n", ctlr->name, vga->f[0]);
  129. if(mode->z > 8)
  130. error("%s: depth %d not supported\n", ctlr->name, mode->z);
  131. /*
  132. * VCLK3
  133. */
  134. clgd54xxclock(vga, ctlr);
  135. vga->misc |= 0x0C;
  136. vga->sequencer[0x1E] = vga->n[0];
  137. vga->sequencer[0x0E] = (vga->d[0]<<1)|vga->p[0];
  138. vga->sequencer[0x07] = 0x00;
  139. if(mode->z == 8)
  140. vga->sequencer[0x07] |= 0x01;
  141. vga->crt[0x14] = 0;
  142. vga->crt[0x17] = 0xC3;
  143. /*
  144. * Overflow bits.
  145. */
  146. vga->crt[0x1A] = 0x00;
  147. x = mode->ehb>>3;
  148. if(x & 0x40)
  149. vga->crt[0x1A] |= 0x10;
  150. if(x & 0x80)
  151. vga->crt[0x1A] |= 0x20;
  152. if(vga->crt[0x16] & 0x100)
  153. vga->crt[0x1A] |= 0x40;
  154. if(vga->crt[0x16] & 0x200)
  155. vga->crt[0x1A] |= 0x80;
  156. vga->crt[0x1B] = 0x22;
  157. if(vga->crt[0x13] & 0x100)
  158. vga->crt[0x1B] |= 0x10;
  159. vga->crt[0x1D] = 0x00;
  160. if(vga->crt[0x13] & 0x200)
  161. vga->crt[0x1D] |= 0x01;
  162. vga->crt[0x1E] = 0x00;
  163. if(vga->crt[0x10] & 0x400)
  164. vga->crt[0x1E] |= 0x01;
  165. if(vga->crt[0x15] & 0x400)
  166. vga->crt[0x1E] |= 0x02;
  167. if(vga->crt[0x12] & 0x400)
  168. vga->crt[0x1E] |= 0x04;
  169. if(vga->crt[0x06] & 0x400)
  170. vga->crt[0x1E] |= 0x08;
  171. if(vga->crt[0x04] & 0x100)
  172. vga->crt[0x1E] |= 0x10;
  173. if(vga->crt[0x02] & 0x100)
  174. vga->crt[0x1E] |= 0x20;
  175. if(vga->crt[0x01] & 0x100)
  176. vga->crt[0x1E] |= 0x40;
  177. if(vga->crt[0x00] & 0x100)
  178. vga->crt[0x1E] |= 0x80;
  179. vga->graphics[0x0B] = 0x00;
  180. if(vga->vmz > 1024*1024)
  181. vga->graphics[0x0B] |= 0x20;
  182. if(mode->interlace == 'v'){
  183. vga->crt[0x19] = vga->crt[0x00]/2;
  184. vga->crt[0x1A] |= 0x01;
  185. }
  186. if(vga->linear && (ctlr->flag & Hlinear))
  187. ctlr->flag |= Ulinear;
  188. laguna = vga->private;
  189. /*
  190. * Ignore wide tiles for now, this simplifies things.
  191. */
  192. if(mode->x <= 640)
  193. tiles = 5;
  194. else if(mode->x <= 1024)
  195. tiles = 8;
  196. else if(mode->x <= 1280)
  197. tiles = 10;
  198. else if(mode->x <= 1664)
  199. tiles = 13;
  200. else if(mode->x <= 2048)
  201. tiles = 16;
  202. else if(mode->x <= 2560)
  203. tiles = 20;
  204. else if(mode->x <= 3228)
  205. tiles = 26;
  206. else
  207. tiles = 32;
  208. fetches = tiles; /* -1? */
  209. if(nointerleave)
  210. interleave = 0;
  211. else switch(laguna->mem){
  212. default:
  213. interleave = 0;
  214. break;
  215. case 2:
  216. interleave = 1;
  217. break;
  218. case 4:
  219. case 8:
  220. interleave = 2;
  221. break;
  222. }
  223. if(mode->z == 8)
  224. format = 0;
  225. else if(mode->z == 16)
  226. format = (1<<12)|(2<<9);
  227. else if(mode->z == 24)
  228. format = (2<<12)|(2<<9);
  229. else
  230. format = (2<<12)|(2<<9);
  231. //if(ctlr->flag & Ulinear)
  232. // laguna->vsc |= 0x10000000;
  233. //else
  234. laguna->vsc &= ~0x10000000;
  235. laguna->format = format;
  236. laguna->threshold = (interleave<<14)|(fetches<<8)|0x14;
  237. laguna->tilectrl &= 0x3F;
  238. laguna->tilectrl |= (interleave<<14)|(tiles<<8);
  239. if(!notile)
  240. laguna->tilectrl |= 0x80;
  241. if(pagesize == 1)
  242. laguna->tilectrl |= 0x10;
  243. laguna->tilectrl2D3D = (interleave<<6)|tiles;
  244. laguna->control = 0;
  245. if(notile)
  246. laguna->control |= 0x1000;
  247. if(pagesize == 1)
  248. laguna->control |= 0x0200;
  249. }
  250. static void
  251. load(Vga* vga, Ctlr*)
  252. {
  253. Laguna *laguna;
  254. vgaxo(Seqx, 0x0E, vga->sequencer[0x0E]);
  255. vgaxo(Seqx, 0x1E, vga->sequencer[0x1E]);
  256. vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
  257. if(vga->mode->interlace == 'v')
  258. vgaxo(Crtx, 0x19, vga->crt[0x19]);
  259. vgaxo(Crtx, 0x1A, vga->crt[0x1A]);
  260. vgaxo(Crtx, 0x1B, vga->crt[0x1B]);
  261. vgaxo(Crtx, 0x1D, vga->crt[0x1D]);
  262. vgaxo(Crtx, 0x1E, vga->crt[0x1E]);
  263. vgaxo(Grx, 0x0B, vga->graphics[0x0B]);
  264. laguna = vga->private;
  265. mmio16w(laguna, Format, laguna->format);
  266. mmio32w(laguna, Vsc, laguna->vsc);
  267. mmio16w(laguna, Threshold, laguna->threshold);
  268. mmio16w(laguna, TileCtrl, laguna->tilectrl);
  269. mmio8w(laguna, TileCtrl2D3D, laguna->tilectrl2D3D);
  270. mmio16w(laguna, Control, laguna->control);
  271. }
  272. static void
  273. dump(Vga* vga, Ctlr* ctlr)
  274. {
  275. int i;
  276. char *name;
  277. Laguna *laguna;
  278. name = ctlr->name;
  279. printitem(name, "Seq06");
  280. for(i = 0x06; i < 0x20; i++)
  281. printreg(vga->sequencer[i]);
  282. printitem(name, "Crt19");
  283. for(i = 0x19; i < 0x20; i++)
  284. printreg(vga->crt[i]);
  285. printitem(name, "Gr09");
  286. for(i = 0x09; i < 0x0C; i++)
  287. printreg(vga->graphics[i]);
  288. laguna = vga->private;
  289. Bprint(&stdout, "\n");
  290. Bprint(&stdout, "%s mem\t\t%d\n", ctlr->name, laguna->mem*1024*1024);
  291. Bprint(&stdout, "%s Format\t\t%uX\n", ctlr->name, laguna->format);
  292. Bprint(&stdout, "%s Threshold\t\t\t%uX\n",
  293. ctlr->name, laguna->threshold);
  294. Bprint(&stdout, "%s TileCtrl\t\t\t%uX\n", ctlr->name, laguna->tilectrl);
  295. Bprint(&stdout, "%s Vsc\t\t%uX\n", ctlr->name, laguna->vsc);
  296. Bprint(&stdout, "%s Control\t\t%uX\n", ctlr->name, laguna->control);
  297. Bprint(&stdout, "%s TileCtrlC2D3D\t\t%uX\n",
  298. ctlr->name, laguna->tilectrl2D3D);
  299. }
  300. Ctlr clgd546x = {
  301. "clgd546x", /* name */
  302. snarf, /* snarf */
  303. 0, /* options */
  304. init, /* init */
  305. load, /* load */
  306. dump, /* dump */
  307. };
  308. Ctlr clgd546xhwgc = {
  309. "clgd546xhwgc", /* name */
  310. 0, /* snarf */
  311. 0, /* options */
  312. 0, /* init */
  313. 0, /* load */
  314. 0, /* dump */
  315. };