au88x0_synth.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. */
  4. /*
  5. * Someday its supposed to make use of the WT DMA engine
  6. * for a Wavetable synthesizer.
  7. */
  8. #include "au88x0.h"
  9. #include "au88x0_wt.h"
  10. static void vortex_fifo_setwtvalid(vortex_t * vortex, int fifo, int en);
  11. static void vortex_connection_adb_mixin(vortex_t * vortex, int en,
  12. unsigned char channel,
  13. unsigned char source,
  14. unsigned char mixin);
  15. static void vortex_connection_mixin_mix(vortex_t * vortex, int en,
  16. unsigned char mixin,
  17. unsigned char mix, int a);
  18. static void vortex_fifo_wtinitialize(vortex_t * vortex, int fifo, int j);
  19. static int vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
  20. u32 val);
  21. /* WT */
  22. /* Put 2 WT channels together for one stereo interlaced channel. */
  23. static void vortex_wt_setstereo(vortex_t * vortex, u32 wt, u32 stereo)
  24. {
  25. int temp;
  26. //temp = hwread(vortex->mmio, 0x80 + ((wt >> 0x5)<< 0xf) + (((wt & 0x1f) >> 1) << 2));
  27. temp = hwread(vortex->mmio, WT_STEREO(wt));
  28. temp = (temp & 0xfe) | (stereo & 1);
  29. //hwwrite(vortex->mmio, 0x80 + ((wt >> 0x5)<< 0xf) + (((wt & 0x1f) >> 1) << 2), temp);
  30. hwwrite(vortex->mmio, WT_STEREO(wt), temp);
  31. }
  32. /* Join to mixdown route. */
  33. static void vortex_wt_setdsout(vortex_t * vortex, u32 wt, int en)
  34. {
  35. int temp;
  36. /* There is one DSREG register for each bank (32 voices each). */
  37. temp = hwread(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0));
  38. if (en)
  39. temp |= (1 << (wt & 0x1f));
  40. else
  41. temp &= ~(1 << (wt & 0x1f));
  42. hwwrite(vortex->mmio, WT_DSREG((wt >= 0x20) ? 1 : 0), temp);
  43. }
  44. /* Setup WT route. */
  45. static int vortex_wt_allocroute(vortex_t * vortex, int wt, int nr_ch)
  46. {
  47. wt_voice_t *voice = &(vortex->wt_voice[wt]);
  48. int temp;
  49. //FIXME: WT audio routing.
  50. if (nr_ch) {
  51. vortex_fifo_wtinitialize(vortex, wt, 1);
  52. vortex_fifo_setwtvalid(vortex, wt, 1);
  53. vortex_wt_setstereo(vortex, wt, nr_ch - 1);
  54. } else
  55. vortex_fifo_setwtvalid(vortex, wt, 0);
  56. /* Set mixdown mode. */
  57. vortex_wt_setdsout(vortex, wt, 1);
  58. /* Set other parameter registers. */
  59. hwwrite(vortex->mmio, WT_SRAMP(0), 0x880000);
  60. //hwwrite(vortex->mmio, WT_GMODE(0), 0xffffffff);
  61. #ifdef CHIP_AU8830
  62. hwwrite(vortex->mmio, WT_SRAMP(1), 0x880000);
  63. //hwwrite(vortex->mmio, WT_GMODE(1), 0xffffffff);
  64. #endif
  65. hwwrite(vortex->mmio, WT_PARM(wt, 0), 0);
  66. hwwrite(vortex->mmio, WT_PARM(wt, 1), 0);
  67. hwwrite(vortex->mmio, WT_PARM(wt, 2), 0);
  68. temp = hwread(vortex->mmio, WT_PARM(wt, 3));
  69. dev_dbg(vortex->card->dev, "WT PARM3: %x\n", temp);
  70. //hwwrite(vortex->mmio, WT_PARM(wt, 3), temp);
  71. hwwrite(vortex->mmio, WT_DELAY(wt, 0), 0);
  72. hwwrite(vortex->mmio, WT_DELAY(wt, 1), 0);
  73. hwwrite(vortex->mmio, WT_DELAY(wt, 2), 0);
  74. hwwrite(vortex->mmio, WT_DELAY(wt, 3), 0);
  75. dev_dbg(vortex->card->dev, "WT GMODE: %x\n",
  76. hwread(vortex->mmio, WT_GMODE(wt)));
  77. hwwrite(vortex->mmio, WT_PARM(wt, 2), 0xffffffff);
  78. hwwrite(vortex->mmio, WT_PARM(wt, 3), 0xcff1c810);
  79. voice->parm0 = voice->parm1 = 0xcfb23e2f;
  80. hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0);
  81. hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1);
  82. dev_dbg(vortex->card->dev, "WT GMODE 2 : %x\n",
  83. hwread(vortex->mmio, WT_GMODE(wt)));
  84. return 0;
  85. }
  86. static void vortex_wt_connect(vortex_t * vortex, int en)
  87. {
  88. int i, ii, mix;
  89. #define NR_WTROUTES 6
  90. #ifdef CHIP_AU8830
  91. #define NR_WTBLOCKS 2
  92. #else
  93. #define NR_WTBLOCKS 1
  94. #endif
  95. for (i = 0; i < NR_WTBLOCKS; i++) {
  96. for (ii = 0; ii < NR_WTROUTES; ii++) {
  97. mix =
  98. vortex_adb_checkinout(vortex,
  99. vortex->fixed_res, en,
  100. VORTEX_RESOURCE_MIXIN);
  101. vortex->mixwt[(i * NR_WTROUTES) + ii] = mix;
  102. vortex_route(vortex, en, 0x11,
  103. ADB_WTOUT(i, ii + 0x20), ADB_MIXIN(mix));
  104. vortex_connection_mixin_mix(vortex, en, mix,
  105. vortex->mixplayb[ii % 2], 0);
  106. if (VORTEX_IS_QUAD(vortex))
  107. vortex_connection_mixin_mix(vortex, en,
  108. mix,
  109. vortex->mixplayb[2 +
  110. (ii % 2)], 0);
  111. }
  112. }
  113. for (i = 0; i < NR_WT; i++) {
  114. hwwrite(vortex->mmio, WT_RUN(i), 1);
  115. }
  116. }
  117. /* Read WT Register */
  118. #if 0
  119. static int vortex_wt_GetReg(vortex_t * vortex, char reg, int wt)
  120. {
  121. //int eax, esi;
  122. if (reg == 4) {
  123. return hwread(vortex->mmio, WT_PARM(wt, 3));
  124. }
  125. if (reg == 7) {
  126. return hwread(vortex->mmio, WT_GMODE(wt));
  127. }
  128. return 0;
  129. }
  130. /* WT hardware abstraction layer generic register interface. */
  131. static int
  132. vortex_wt_SetReg2(vortex_t * vortex, unsigned char reg, int wt,
  133. u16 val)
  134. {
  135. /*
  136. int eax, edx;
  137. if (wt >= NR_WT) // 0x40 -> NR_WT
  138. return 0;
  139. if ((reg - 0x20) > 0) {
  140. if ((reg - 0x21) != 0)
  141. return 0;
  142. eax = ((((b & 0xff) << 0xb) + (edx & 0xff)) << 4) + 0x208; // param 2
  143. } else {
  144. eax = ((((b & 0xff) << 0xb) + (edx & 0xff)) << 4) + 0x20a; // param 3
  145. }
  146. hwwrite(vortex->mmio, eax, c);
  147. */
  148. return 1;
  149. }
  150. /*public: static void __thiscall CWTHal::SetReg(unsigned char,int,unsigned long) */
  151. #endif
  152. static int
  153. vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
  154. u32 val)
  155. {
  156. int ecx;
  157. if ((reg == 5) || ((reg >= 7) && (reg <= 10)) || (reg == 0xc)) {
  158. if (wt >= (NR_WT / NR_WT_PB)) {
  159. dev_warn(vortex->card->dev,
  160. "WT SetReg: bank out of range. reg=0x%x, wt=%d\n",
  161. reg, wt);
  162. return 0;
  163. }
  164. } else {
  165. if (wt >= NR_WT) {
  166. dev_err(vortex->card->dev,
  167. "WT SetReg: voice out of range\n");
  168. return 0;
  169. }
  170. }
  171. if (reg > 0xc)
  172. return 0;
  173. switch (reg) {
  174. /* Voice specific parameters */
  175. case 0: /* running */
  176. /*
  177. pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
  178. WT_RUN(wt), (int)val);
  179. */
  180. hwwrite(vortex->mmio, WT_RUN(wt), val);
  181. return 0xc;
  182. case 1: /* param 0 */
  183. /*
  184. pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
  185. WT_PARM(wt,0), (int)val);
  186. */
  187. hwwrite(vortex->mmio, WT_PARM(wt, 0), val);
  188. return 0xc;
  189. case 2: /* param 1 */
  190. /*
  191. pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
  192. WT_PARM(wt,1), (int)val);
  193. */
  194. hwwrite(vortex->mmio, WT_PARM(wt, 1), val);
  195. return 0xc;
  196. case 3: /* param 2 */
  197. /*
  198. pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
  199. WT_PARM(wt,2), (int)val);
  200. */
  201. hwwrite(vortex->mmio, WT_PARM(wt, 2), val);
  202. return 0xc;
  203. case 4: /* param 3 */
  204. /*
  205. pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
  206. WT_PARM(wt,3), (int)val);
  207. */
  208. hwwrite(vortex->mmio, WT_PARM(wt, 3), val);
  209. return 0xc;
  210. case 6: /* mute */
  211. /*
  212. pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
  213. WT_MUTE(wt), (int)val);
  214. */
  215. hwwrite(vortex->mmio, WT_MUTE(wt), val);
  216. return 0xc;
  217. case 0xb:
  218. /* delay */
  219. /*
  220. pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n",
  221. WT_DELAY(wt,0), (int)val);
  222. */
  223. hwwrite(vortex->mmio, WT_DELAY(wt, 3), val);
  224. hwwrite(vortex->mmio, WT_DELAY(wt, 2), val);
  225. hwwrite(vortex->mmio, WT_DELAY(wt, 1), val);
  226. hwwrite(vortex->mmio, WT_DELAY(wt, 0), val);
  227. return 0xc;
  228. /* Global WT block parameters */
  229. case 5: /* sramp */
  230. ecx = WT_SRAMP(wt);
  231. break;
  232. case 8: /* aramp */
  233. ecx = WT_ARAMP(wt);
  234. break;
  235. case 9: /* mramp */
  236. ecx = WT_MRAMP(wt);
  237. break;
  238. case 0xa: /* ctrl */
  239. ecx = WT_CTRL(wt);
  240. break;
  241. case 0xc: /* ds_reg */
  242. ecx = WT_DSREG(wt);
  243. break;
  244. default:
  245. return 0;
  246. }
  247. /*
  248. pr_debug( "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val);
  249. */
  250. hwwrite(vortex->mmio, ecx, val);
  251. return 1;
  252. }
  253. static void vortex_wt_init(vortex_t * vortex)
  254. {
  255. u32 var4, var8, varc, var10 = 0, edi;
  256. var10 &= 0xFFFFFFE3;
  257. var10 |= 0x22;
  258. var10 &= 0xFFFFFEBF;
  259. var10 |= 0x80;
  260. var10 |= 0x200;
  261. var10 &= 0xfffffffe;
  262. var10 &= 0xfffffbff;
  263. var10 |= 0x1800;
  264. // var10 = 0x1AA2
  265. var4 = 0x10000000;
  266. varc = 0x00830000;
  267. var8 = 0x00830000;
  268. /* Init Bank registers. */
  269. for (edi = 0; edi < (NR_WT / NR_WT_PB); edi++) {
  270. vortex_wt_SetReg(vortex, 0xc, edi, 0); /* ds_reg */
  271. vortex_wt_SetReg(vortex, 0xa, edi, var10); /* ctrl */
  272. vortex_wt_SetReg(vortex, 0x9, edi, var4); /* mramp */
  273. vortex_wt_SetReg(vortex, 0x8, edi, varc); /* aramp */
  274. vortex_wt_SetReg(vortex, 0x5, edi, var8); /* sramp */
  275. }
  276. /* Init Voice registers. */
  277. for (edi = 0; edi < NR_WT; edi++) {
  278. vortex_wt_SetReg(vortex, 0x4, edi, 0); /* param 3 0x20c */
  279. vortex_wt_SetReg(vortex, 0x3, edi, 0); /* param 2 0x208 */
  280. vortex_wt_SetReg(vortex, 0x2, edi, 0); /* param 1 0x204 */
  281. vortex_wt_SetReg(vortex, 0x1, edi, 0); /* param 0 0x200 */
  282. vortex_wt_SetReg(vortex, 0xb, edi, 0); /* delay 0x400 - 0x40c */
  283. }
  284. var10 |= 1;
  285. for (edi = 0; edi < (NR_WT / NR_WT_PB); edi++)
  286. vortex_wt_SetReg(vortex, 0xa, edi, var10); /* ctrl */
  287. }
  288. /* Extract of CAdbTopology::SetVolume(struct _ASPVOLUME *) */
  289. #if 0
  290. static void vortex_wt_SetVolume(vortex_t * vortex, int wt, int vol[])
  291. {
  292. wt_voice_t *voice = &(vortex->wt_voice[wt]);
  293. int ecx = vol[1], eax = vol[0];
  294. /* This is pure guess */
  295. voice->parm0 &= 0xff00ffff;
  296. voice->parm0 |= (vol[0] & 0xff) << 0x10;
  297. voice->parm1 &= 0xff00ffff;
  298. voice->parm1 |= (vol[1] & 0xff) << 0x10;
  299. /* This is real */
  300. hwwrite(vortex, WT_PARM(wt, 0), voice->parm0);
  301. hwwrite(vortex, WT_PARM(wt, 1), voice->parm0);
  302. if (voice->this_1D0 & 4) {
  303. eax >>= 8;
  304. ecx = eax;
  305. if (ecx < 0x80)
  306. ecx = 0x7f;
  307. voice->parm3 &= 0xFFFFC07F;
  308. voice->parm3 |= (ecx & 0x7f) << 7;
  309. voice->parm3 &= 0xFFFFFF80;
  310. voice->parm3 |= (eax & 0x7f);
  311. } else {
  312. voice->parm3 &= 0xFFE03FFF;
  313. voice->parm3 |= (eax & 0xFE00) << 5;
  314. }
  315. hwwrite(vortex, WT_PARM(wt, 3), voice->parm3);
  316. }
  317. /* Extract of CAdbTopology::SetFrequency(unsigned long arg_0) */
  318. static void vortex_wt_SetFrequency(vortex_t * vortex, int wt, unsigned int sr)
  319. {
  320. wt_voice_t *voice = &(vortex->wt_voice[wt]);
  321. u32 eax, edx;
  322. //FIXME: 64 bit operation.
  323. eax = ((sr << 0xf) * 0x57619F1) & 0xffffffff;
  324. edx = (((sr << 0xf) * 0x57619F1)) >> 0x20;
  325. edx >>= 0xa;
  326. edx <<= 1;
  327. if (edx) {
  328. if (edx & 0x0FFF80000)
  329. eax = 0x7fff;
  330. else {
  331. edx <<= 0xd;
  332. eax = 7;
  333. while ((edx & 0x80000000) == 0) {
  334. edx <<= 1;
  335. eax--;
  336. if (eax == 0)
  337. break;
  338. }
  339. if (eax)
  340. edx <<= 1;
  341. eax <<= 0xc;
  342. edx >>= 0x14;
  343. eax |= edx;
  344. }
  345. } else
  346. eax = 0;
  347. voice->parm0 &= 0xffff0001;
  348. voice->parm0 |= (eax & 0x7fff) << 1;
  349. voice->parm1 = voice->parm0 | 1;
  350. // Wt: this_1D4
  351. //AuWt::WriteReg((ulong)(this_1DC<<4)+0x200, (ulong)this_1E4);
  352. //AuWt::WriteReg((ulong)(this_1DC<<4)+0x204, (ulong)this_1E8);
  353. hwwrite(vortex->mmio, WT_PARM(wt, 0), voice->parm0);
  354. hwwrite(vortex->mmio, WT_PARM(wt, 1), voice->parm1);
  355. }
  356. #endif
  357. /* End of File */