tvp3026.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * Tvp3026 Viewpoint Video Interface Palette.
  8. * Assumes hooked up to an S3 chip of some kind.
  9. * Why is register access different from the
  10. * Tvp302[05]?
  11. */
  12. enum {
  13. Index = 0x00, /* Index register */
  14. Data = 0x0A, /* Data register */
  15. Id = 0x3F, /* ID Register */
  16. Tvp3026 = 0x26,
  17. };
  18. static uchar
  19. tvp3026io(uchar reg, uchar data)
  20. {
  21. uchar crt55;
  22. crt55 = vgaxi(Crtx, 0x55) & 0xFC;
  23. vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
  24. vgao(dacxreg[reg & 0x03], data);
  25. return crt55;
  26. }
  27. static uchar
  28. tvp3026i(uchar reg)
  29. {
  30. uchar crt55, r;
  31. crt55 = vgaxi(Crtx, 0x55) & 0xFC;
  32. vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
  33. r = vgai(dacxreg[reg & 0x03]);
  34. vgaxo(Crtx, 0x55, crt55);
  35. return r;
  36. }
  37. uchar
  38. tvp3026xi(uchar index)
  39. {
  40. uchar crt55, r;
  41. crt55 = tvp3026io(Index, index);
  42. vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
  43. r = vgai(dacxreg[Data & 0x03]);
  44. vgaxo(Crtx, 0x55, crt55);
  45. return r;
  46. }
  47. static void
  48. tvp3026o(uchar reg, uchar data)
  49. {
  50. uchar crt55;
  51. crt55 = tvp3026io(reg, data);
  52. vgaxo(Crtx, 0x55, crt55);
  53. }
  54. void
  55. tvp3026xo(uchar index, uchar data)
  56. {
  57. uchar crt55;
  58. crt55 = tvp3026io(Index, index);
  59. vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03));
  60. vgao(dacxreg[Data & 0x03], data);
  61. vgaxo(Crtx, 0x55, crt55);
  62. }
  63. static void
  64. options(Vga*, Ctlr* ctlr)
  65. {
  66. ctlr->flag |= Hclk2|Hextsid|Henhanced|Foptions;
  67. }
  68. static void
  69. init(Vga* vga, Ctlr* ctlr)
  70. {
  71. ulong grade;
  72. char *p;
  73. /*
  74. * Work out the part speed-grade from name. Name can have,
  75. * e.g. '-135' on the end for 135MHz part.
  76. */
  77. grade = 110000000;
  78. if(p = strrchr(ctlr->name, '-'))
  79. grade = strtoul(p+1, 0, 0) * 1000000;
  80. /*
  81. * If we don't already have a desired pclk,
  82. * take it from the mode.
  83. * Check it's within range.
  84. */
  85. if(vga->f[0] == 0)
  86. vga->f[0] = vga->mode->frequency;
  87. if(vga->f[0] > grade)
  88. error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
  89. /*
  90. * Determine whether to use clock-doubler or not.
  91. */
  92. if((ctlr->flag & Uclk2) == 0 && vga->mode->z == 8 && vga->f[0] > 85000000)
  93. resyncinit(vga, ctlr, Uclk2, 0);
  94. ctlr->flag |= Finit;
  95. }
  96. static void
  97. load(Vga* vga, Ctlr* ctlr)
  98. {
  99. uchar x;
  100. /*
  101. * General Control:
  102. * output sync polarity
  103. * It's important to set this properly and to turn off the
  104. * VGA controller H and V syncs. Can't be set in VGA mode.
  105. */
  106. x = 0x00;
  107. if((vga->misc & 0x40) == 0)
  108. x |= 0x01;
  109. if((vga->misc & 0x80) == 0)
  110. x |= 0x02;
  111. tvp3026xo(0x1D, x);
  112. vga->misc |= 0xC0;
  113. vgao(MiscW, vga->misc);
  114. ctlr->flag |= Fload;
  115. }
  116. static void
  117. dump(Vga*, Ctlr* ctlr)
  118. {
  119. int i;
  120. ulong clock[4], f;
  121. printitem(ctlr->name, "direct");
  122. for(i = 0; i < 16; i++)
  123. printreg(tvp3026i(i));
  124. printitem(ctlr->name, "index");
  125. for(i = 0; i < 64; i++)
  126. printreg(tvp3026xi(i));
  127. printitem(ctlr->name, "PCLK");
  128. for(i = 0; i < 3; i++){
  129. tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
  130. printreg(clock[i] = tvp3026xi(0x2D));
  131. }
  132. f = (RefFreq*(65-clock[1]))/(65-(clock[0] & 0x3F));
  133. f >>= clock[2] & 0x03;
  134. Bprint(&stdout, "%23ld", f);
  135. printitem(ctlr->name, "MCLK");
  136. for(i = 0; i < 3; i++){
  137. tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
  138. printreg(clock[i] = tvp3026xi(0x2E));
  139. }
  140. f = (RefFreq*(65-clock[1]))/(65-(clock[0] & 0x3F));
  141. f >>= clock[2] & 0x03;
  142. Bprint(&stdout, "%23ld", f);
  143. printitem(ctlr->name, "LCLK");
  144. for(i = 0; i < 3; i++){
  145. tvp3026xo(0x2C, (i<<4)|(i<<2)|i);
  146. printreg(clock[i] = tvp3026xi(0x2F));
  147. }
  148. Bprint(&stdout, "\n");
  149. }
  150. Ctlr tvp3026 = {
  151. "tvp3026", /* name */
  152. 0, /* snarf */
  153. options, /* options */
  154. init, /* init */
  155. 0, /* load */
  156. dump, /* dump */
  157. };