mixer.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. /*
  2. **********************************************************************
  3. * mixer.c - /dev/mixer interface for emu10k1 driver
  4. * Copyright 1999, 2000 Creative Labs, Inc.
  5. *
  6. **********************************************************************
  7. *
  8. * Date Author Summary of changes
  9. * ---- ------ ------------------
  10. * October 20, 1999 Bertrand Lee base code release
  11. * November 2, 1999 Alan Cox cleaned up stuff
  12. *
  13. **********************************************************************
  14. *
  15. * This program is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU General Public License as
  17. * published by the Free Software Foundation; either version 2 of
  18. * the License, or (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public
  26. * License along with this program; if not, write to the Free
  27. * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  28. * USA.
  29. *
  30. **********************************************************************
  31. */
  32. #include <linux/module.h>
  33. #include <asm/uaccess.h>
  34. #include <linux/fs.h>
  35. #include "hwaccess.h"
  36. #include "8010.h"
  37. #include "recmgr.h"
  38. static const u32 bass_table[41][5] = {
  39. { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
  40. { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
  41. { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
  42. { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c },
  43. { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b },
  44. { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 },
  45. { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f },
  46. { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 },
  47. { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 },
  48. { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 },
  49. { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 },
  50. { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be },
  51. { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b },
  52. { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c },
  53. { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b },
  54. { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 },
  55. { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a },
  56. { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 },
  57. { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 },
  58. { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e },
  59. { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee },
  60. { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 },
  61. { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 },
  62. { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 },
  63. { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 },
  64. { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e },
  65. { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 },
  66. { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 },
  67. { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 },
  68. { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 },
  69. { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 },
  70. { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca },
  71. { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 },
  72. { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 },
  73. { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 },
  74. { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 },
  75. { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a },
  76. { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f },
  77. { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 },
  78. { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 },
  79. { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
  80. };
  81. static const u32 treble_table[41][5] = {
  82. { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
  83. { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
  84. { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
  85. { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca },
  86. { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 },
  87. { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 },
  88. { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 },
  89. { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 },
  90. { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 },
  91. { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df },
  92. { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff },
  93. { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 },
  94. { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c },
  95. { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 },
  96. { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 },
  97. { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 },
  98. { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 },
  99. { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d },
  100. { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 },
  101. { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 },
  102. { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f },
  103. { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb },
  104. { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 },
  105. { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 },
  106. { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd },
  107. { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 },
  108. { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad },
  109. { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 },
  110. { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 },
  111. { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c },
  112. { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 },
  113. { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 },
  114. { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 },
  115. { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 },
  116. { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 },
  117. { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 },
  118. { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d },
  119. { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b },
  120. { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 },
  121. { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd },
  122. { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
  123. };
  124. static void set_bass(struct emu10k1_card *card, int l, int r)
  125. {
  126. int i;
  127. l = (l * 40 + 50) / 100;
  128. r = (r * 40 + 50) / 100;
  129. for (i = 0; i < 5; i++)
  130. sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]);
  131. }
  132. static void set_treble(struct emu10k1_card *card, int l, int r)
  133. {
  134. int i;
  135. l = (l * 40 + 50) / 100;
  136. r = (r * 40 + 50) / 100;
  137. for (i = 0; i < 5; i++)
  138. sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]);
  139. }
  140. const char volume_params[SOUND_MIXER_NRDEVICES]= {
  141. /* Used by the ac97 driver */
  142. [SOUND_MIXER_VOLUME] = VOL_6BIT,
  143. [SOUND_MIXER_BASS] = VOL_4BIT,
  144. [SOUND_MIXER_TREBLE] = VOL_4BIT,
  145. [SOUND_MIXER_PCM] = VOL_5BIT,
  146. [SOUND_MIXER_SPEAKER] = VOL_4BIT,
  147. [SOUND_MIXER_LINE] = VOL_5BIT,
  148. [SOUND_MIXER_MIC] = VOL_5BIT,
  149. [SOUND_MIXER_CD] = VOL_5BIT,
  150. [SOUND_MIXER_ALTPCM] = VOL_6BIT,
  151. [SOUND_MIXER_IGAIN] = VOL_4BIT,
  152. [SOUND_MIXER_LINE1] = VOL_5BIT,
  153. [SOUND_MIXER_PHONEIN] = VOL_5BIT,
  154. [SOUND_MIXER_PHONEOUT] = VOL_6BIT,
  155. [SOUND_MIXER_VIDEO] = VOL_5BIT,
  156. /* Not used by the ac97 driver */
  157. [SOUND_MIXER_SYNTH] = VOL_5BIT,
  158. [SOUND_MIXER_IMIX] = VOL_5BIT,
  159. [SOUND_MIXER_RECLEV] = VOL_5BIT,
  160. [SOUND_MIXER_OGAIN] = VOL_5BIT,
  161. [SOUND_MIXER_LINE2] = VOL_5BIT,
  162. [SOUND_MIXER_LINE3] = VOL_5BIT,
  163. [SOUND_MIXER_DIGITAL1] = VOL_5BIT,
  164. [SOUND_MIXER_DIGITAL2] = VOL_5BIT,
  165. [SOUND_MIXER_DIGITAL3] = VOL_5BIT,
  166. [SOUND_MIXER_RADIO] = VOL_5BIT,
  167. [SOUND_MIXER_MONITOR] = VOL_5BIT
  168. };
  169. /* Mixer file operations */
  170. static int emu10k1_private_mixer(struct emu10k1_card *card, unsigned int cmd, unsigned long arg)
  171. {
  172. struct mixer_private_ioctl *ctl;
  173. struct dsp_patch *patch;
  174. u32 size, page;
  175. int addr, size_reg, i, ret;
  176. unsigned int id, ch;
  177. void __user *argp = (void __user *)arg;
  178. switch (cmd) {
  179. case SOUND_MIXER_PRIVATE3:
  180. ctl = (struct mixer_private_ioctl *) kmalloc(sizeof(struct mixer_private_ioctl), GFP_KERNEL);
  181. if (ctl == NULL)
  182. return -ENOMEM;
  183. if (copy_from_user(ctl, argp, sizeof(struct mixer_private_ioctl))) {
  184. kfree(ctl);
  185. return -EFAULT;
  186. }
  187. ret = 0;
  188. switch (ctl->cmd) {
  189. #ifdef DBGEMU
  190. case CMD_WRITEFN0:
  191. emu10k1_writefn0_2(card, ctl->val[0], ctl->val[1], ctl->val[2]);
  192. break;
  193. #endif
  194. case CMD_WRITEPTR:
  195. #ifdef DBGEMU
  196. if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000) {
  197. #else
  198. if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000 || ((ctl->val[0] < 0x100 ) &&
  199. //Any register allowed raw access goes here:
  200. (ctl->val[0] != A_SPDIF_SAMPLERATE) && (ctl->val[0] != A_DBG)
  201. )
  202. ) {
  203. #endif
  204. ret = -EINVAL;
  205. break;
  206. }
  207. sblive_writeptr(card, ctl->val[0], ctl->val[1], ctl->val[2]);
  208. break;
  209. case CMD_READFN0:
  210. ctl->val[2] = emu10k1_readfn0(card, ctl->val[0]);
  211. if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
  212. ret = -EFAULT;
  213. break;
  214. case CMD_READPTR:
  215. if (ctl->val[1] >= 0x40 || (ctl->val[0] & 0x7ff) > 0xff) {
  216. ret = -EINVAL;
  217. break;
  218. }
  219. if ((ctl->val[0] & 0x7ff) > 0x3f)
  220. ctl->val[1] = 0x00;
  221. ctl->val[2] = sblive_readptr(card, ctl->val[0], ctl->val[1]);
  222. if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
  223. ret = -EFAULT;
  224. break;
  225. case CMD_SETRECSRC:
  226. switch (ctl->val[0]) {
  227. case WAVERECORD_AC97:
  228. if (card->is_aps) {
  229. ret = -EINVAL;
  230. break;
  231. }
  232. card->wavein.recsrc = WAVERECORD_AC97;
  233. break;
  234. case WAVERECORD_MIC:
  235. card->wavein.recsrc = WAVERECORD_MIC;
  236. break;
  237. case WAVERECORD_FX:
  238. card->wavein.recsrc = WAVERECORD_FX;
  239. card->wavein.fxwc = ctl->val[1] & 0xffff;
  240. if (!card->wavein.fxwc)
  241. ret = -EINVAL;
  242. break;
  243. default:
  244. ret = -EINVAL;
  245. break;
  246. }
  247. break;
  248. case CMD_GETRECSRC:
  249. ctl->val[0] = card->wavein.recsrc;
  250. ctl->val[1] = card->wavein.fxwc;
  251. if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
  252. ret = -EFAULT;
  253. break;
  254. case CMD_GETVOICEPARAM:
  255. ctl->val[0] = card->waveout.send_routing[0];
  256. ctl->val[1] = card->waveout.send_dcba[0];
  257. ctl->val[2] = card->waveout.send_routing[1];
  258. ctl->val[3] = card->waveout.send_dcba[1];
  259. ctl->val[4] = card->waveout.send_routing[2];
  260. ctl->val[5] = card->waveout.send_dcba[2];
  261. if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
  262. ret = -EFAULT;
  263. break;
  264. case CMD_SETVOICEPARAM:
  265. card->waveout.send_routing[0] = ctl->val[0];
  266. card->waveout.send_dcba[0] = ctl->val[1];
  267. card->waveout.send_routing[1] = ctl->val[2];
  268. card->waveout.send_dcba[1] = ctl->val[3];
  269. card->waveout.send_routing[2] = ctl->val[4];
  270. card->waveout.send_dcba[2] = ctl->val[5];
  271. break;
  272. case CMD_SETMCH_FX:
  273. card->mchannel_fx = ctl->val[0] & 0x000f;
  274. break;
  275. case CMD_GETPATCH:
  276. if (ctl->val[0] == 0) {
  277. if (copy_to_user(argp, &card->mgr.rpatch, sizeof(struct dsp_rpatch)))
  278. ret = -EFAULT;
  279. } else {
  280. if ((ctl->val[0] - 1) / PATCHES_PER_PAGE >= card->mgr.current_pages) {
  281. ret = -EINVAL;
  282. break;
  283. }
  284. if (copy_to_user(argp, PATCH(&card->mgr, ctl->val[0] - 1), sizeof(struct dsp_patch)))
  285. ret = -EFAULT;
  286. }
  287. break;
  288. case CMD_GETGPR:
  289. id = ctl->val[0];
  290. if (id > NUM_GPRS) {
  291. ret = -EINVAL;
  292. break;
  293. }
  294. if (copy_to_user(argp, &card->mgr.gpr[id], sizeof(struct dsp_gpr)))
  295. ret = -EFAULT;
  296. break;
  297. case CMD_GETCTLGPR:
  298. addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, &((char *) ctl->val)[PATCH_NAME_SIZE]);
  299. ctl->val[0] = sblive_readptr(card, addr, 0);
  300. if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
  301. ret = -EFAULT;
  302. break;
  303. case CMD_SETPATCH:
  304. if (ctl->val[0] == 0)
  305. memcpy(&card->mgr.rpatch, &ctl->val[1], sizeof(struct dsp_rpatch));
  306. else {
  307. page = (ctl->val[0] - 1) / PATCHES_PER_PAGE;
  308. if (page > MAX_PATCHES_PAGES) {
  309. ret = -EINVAL;
  310. break;
  311. }
  312. if (page >= card->mgr.current_pages) {
  313. for (i = card->mgr.current_pages; i < page + 1; i++) {
  314. card->mgr.patch[i] = (void *)__get_free_page(GFP_KERNEL);
  315. if(card->mgr.patch[i] == NULL) {
  316. card->mgr.current_pages = i;
  317. ret = -ENOMEM;
  318. break;
  319. }
  320. memset(card->mgr.patch[i], 0, PAGE_SIZE);
  321. }
  322. card->mgr.current_pages = page + 1;
  323. }
  324. patch = PATCH(&card->mgr, ctl->val[0] - 1);
  325. memcpy(patch, &ctl->val[1], sizeof(struct dsp_patch));
  326. if (patch->code_size == 0) {
  327. for(i = page + 1; i < card->mgr.current_pages; i++)
  328. free_page((unsigned long) card->mgr.patch[i]);
  329. card->mgr.current_pages = page + 1;
  330. }
  331. }
  332. break;
  333. case CMD_SETGPR:
  334. if (ctl->val[0] > NUM_GPRS) {
  335. ret = -EINVAL;
  336. break;
  337. }
  338. memcpy(&card->mgr.gpr[ctl->val[0]], &ctl->val[1], sizeof(struct dsp_gpr));
  339. break;
  340. case CMD_SETCTLGPR:
  341. addr = emu10k1_find_control_gpr(&card->mgr, (char *) ctl->val, (char *) ctl->val + PATCH_NAME_SIZE);
  342. emu10k1_set_control_gpr(card, addr, *((s32 *)((char *) ctl->val + 2 * PATCH_NAME_SIZE)), 0);
  343. break;
  344. case CMD_SETGPOUT:
  345. if ( ((ctl->val[0] > 2) && (!card->is_audigy))
  346. || (ctl->val[0] > 15) || ctl->val[1] > 1) {
  347. ret= -EINVAL;
  348. break;
  349. }
  350. if (card->is_audigy)
  351. emu10k1_writefn0(card, (1 << 24) | ((ctl->val[0]) << 16) | A_IOCFG, ctl->val[1]);
  352. else
  353. emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]);
  354. break;
  355. case CMD_GETGPR2OSS:
  356. id = ctl->val[0];
  357. ch = ctl->val[1];
  358. if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) {
  359. ret = -EINVAL;
  360. break;
  361. }
  362. ctl->val[2] = card->mgr.ctrl_gpr[id][ch];
  363. if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
  364. ret = -EFAULT;
  365. break;
  366. case CMD_SETGPR2OSS:
  367. id = ctl->val[0];
  368. /* 0 == left, 1 == right */
  369. ch = ctl->val[1];
  370. addr = ctl->val[2];
  371. if (id >= SOUND_MIXER_NRDEVICES || ch >= 2) {
  372. ret = -EINVAL;
  373. break;
  374. }
  375. card->mgr.ctrl_gpr[id][ch] = addr;
  376. if (card->is_aps)
  377. break;
  378. if (addr >= 0) {
  379. unsigned int state = card->ac97->mixer_state[id];
  380. if (ch == 1) {
  381. state >>= 8;
  382. card->ac97->stereo_mixers |= (1 << id);
  383. }
  384. card->ac97->supported_mixers |= (1 << id);
  385. if (id == SOUND_MIXER_TREBLE) {
  386. set_treble(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff);
  387. } else if (id == SOUND_MIXER_BASS) {
  388. set_bass(card, card->ac97->mixer_state[id] & 0xff, (card->ac97->mixer_state[id] >> 8) & 0xff);
  389. } else
  390. emu10k1_set_volume_gpr(card, addr, state & 0xff,
  391. volume_params[id]);
  392. } else {
  393. card->ac97->stereo_mixers &= ~(1 << id);
  394. card->ac97->stereo_mixers |= card->ac97_stereo_mixers;
  395. if (ch == 0) {
  396. card->ac97->supported_mixers &= ~(1 << id);
  397. card->ac97->supported_mixers |= card->ac97_supported_mixers;
  398. }
  399. }
  400. break;
  401. case CMD_SETPASSTHROUGH:
  402. card->pt.selected = ctl->val[0] ? 1 : 0;
  403. if (card->pt.state != PT_STATE_INACTIVE)
  404. break;
  405. card->pt.spcs_to_use = ctl->val[0] & 0x07;
  406. break;
  407. case CMD_PRIVATE3_VERSION:
  408. ctl->val[0] = PRIVATE3_VERSION; //private3 version
  409. ctl->val[1] = MAJOR_VER; //major driver version
  410. ctl->val[2] = MINOR_VER; //minor driver version
  411. ctl->val[3] = card->is_audigy; //1=card is audigy
  412. if (card->is_audigy)
  413. ctl->val[4]=emu10k1_readfn0(card, 0x18);
  414. if (copy_to_user(argp, ctl, sizeof(struct mixer_private_ioctl)))
  415. ret = -EFAULT;
  416. break;
  417. case CMD_AC97_BOOST:
  418. if (ctl->val[0])
  419. emu10k1_ac97_write(card->ac97, 0x18, 0x0);
  420. else
  421. emu10k1_ac97_write(card->ac97, 0x18, 0x0808);
  422. break;
  423. default:
  424. ret = -EINVAL;
  425. break;
  426. }
  427. kfree(ctl);
  428. return ret;
  429. break;
  430. case SOUND_MIXER_PRIVATE4:
  431. if (copy_from_user(&size, argp, sizeof(size)))
  432. return -EFAULT;
  433. DPD(2, "External tram size %#x\n", size);
  434. if (size > 0x1fffff)
  435. return -EINVAL;
  436. size_reg = 0;
  437. if (size != 0) {
  438. size = (size - 1) >> 14;
  439. while (size) {
  440. size >>= 1;
  441. size_reg++;
  442. }
  443. size = 0x4000 << size_reg;
  444. }
  445. DPD(2, "External tram size %#x %#x\n", size, size_reg);
  446. if (size != card->tankmem.size) {
  447. if (card->tankmem.size > 0) {
  448. emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 1);
  449. sblive_writeptr_tag(card, 0, TCB, 0, TCBS, 0, TAGLIST_END);
  450. pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
  451. card->tankmem.size = 0;
  452. }
  453. if (size != 0) {
  454. card->tankmem.addr = pci_alloc_consistent(card->pci_dev, size, &card->tankmem.dma_handle);
  455. if (card->tankmem.addr == NULL)
  456. return -ENOMEM;
  457. card->tankmem.size = size;
  458. sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS,(u32) size_reg, TAGLIST_END);
  459. emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0);
  460. }
  461. }
  462. return 0;
  463. break;
  464. default:
  465. break;
  466. }
  467. return -EINVAL;
  468. }
  469. static int emu10k1_dsp_mixer(struct emu10k1_card *card, unsigned int oss_mixer, unsigned long arg)
  470. {
  471. unsigned int left, right;
  472. int val;
  473. int scale;
  474. card->ac97->modcnt++;
  475. if (get_user(val, (int __user *)arg))
  476. return -EFAULT;
  477. /* cleanse input a little */
  478. right = ((val >> 8) & 0xff);
  479. left = (val & 0xff);
  480. if (right > 100) right = 100;
  481. if (left > 100) left = 100;
  482. card->ac97->mixer_state[oss_mixer] = (right << 8) | left;
  483. if (oss_mixer == SOUND_MIXER_TREBLE) {
  484. set_treble(card, left, right);
  485. return 0;
  486. } if (oss_mixer == SOUND_MIXER_BASS) {
  487. set_bass(card, left, right);
  488. return 0;
  489. }
  490. if (oss_mixer == SOUND_MIXER_VOLUME)
  491. scale = 1 << card->ac97->bit_resolution;
  492. else
  493. scale = volume_params[oss_mixer];
  494. emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left, scale);
  495. emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][1], right, scale);
  496. if (card->ac97_supported_mixers & (1 << oss_mixer))
  497. card->ac97->write_mixer(card->ac97, oss_mixer, left, right);
  498. return 0;
  499. }
  500. static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  501. {
  502. int ret;
  503. struct emu10k1_card *card = file->private_data;
  504. unsigned int oss_mixer = _IOC_NR(cmd);
  505. ret = -EINVAL;
  506. if (!card->is_aps) {
  507. if (cmd == SOUND_MIXER_INFO) {
  508. mixer_info info;
  509. strlcpy(info.id, card->ac97->name, sizeof(info.id));
  510. if (card->is_audigy)
  511. strlcpy(info.name, "Audigy - Emu10k1", sizeof(info.name));
  512. else
  513. strlcpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name));
  514. info.modify_counter = card->ac97->modcnt;
  515. if (copy_to_user((void __user *)arg, &info, sizeof(info)))
  516. return -EFAULT;
  517. return 0;
  518. }
  519. if ((_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES)
  520. ret = emu10k1_dsp_mixer(card, oss_mixer, arg);
  521. else
  522. ret = card->ac97->mixer_ioctl(card->ac97, cmd, arg);
  523. }
  524. if (ret < 0)
  525. ret = emu10k1_private_mixer(card, cmd, arg);
  526. return ret;
  527. }
  528. static int emu10k1_mixer_open(struct inode *inode, struct file *file)
  529. {
  530. int minor = iminor(inode);
  531. struct emu10k1_card *card = NULL;
  532. struct list_head *entry;
  533. DPF(4, "emu10k1_mixer_open()\n");
  534. list_for_each(entry, &emu10k1_devs) {
  535. card = list_entry(entry, struct emu10k1_card, list);
  536. if (card->ac97->dev_mixer == minor)
  537. goto match;
  538. }
  539. return -ENODEV;
  540. match:
  541. file->private_data = card;
  542. return 0;
  543. }
  544. static int emu10k1_mixer_release(struct inode *inode, struct file *file)
  545. {
  546. DPF(4, "emu10k1_mixer_release()\n");
  547. return 0;
  548. }
  549. struct file_operations emu10k1_mixer_fops = {
  550. .owner = THIS_MODULE,
  551. .llseek = no_llseek,
  552. .ioctl = emu10k1_mixer_ioctl,
  553. .open = emu10k1_mixer_open,
  554. .release = emu10k1_mixer_release,
  555. };