sb_mixer.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. /*
  2. * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  3. * Routines for Sound Blaster mixer control
  4. *
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. */
  21. #include <sound/driver.h>
  22. #include <asm/io.h>
  23. #include <linux/delay.h>
  24. #include <linux/time.h>
  25. #include <sound/core.h>
  26. #include <sound/sb.h>
  27. #include <sound/control.h>
  28. #undef IO_DEBUG
  29. void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data)
  30. {
  31. outb(reg, SBP(chip, MIXER_ADDR));
  32. udelay(10);
  33. outb(data, SBP(chip, MIXER_DATA));
  34. udelay(10);
  35. #ifdef IO_DEBUG
  36. snd_printk("mixer_write 0x%x 0x%x\n", reg, data);
  37. #endif
  38. }
  39. unsigned char snd_sbmixer_read(sb_t *chip, unsigned char reg)
  40. {
  41. unsigned char result;
  42. outb(reg, SBP(chip, MIXER_ADDR));
  43. udelay(10);
  44. result = inb(SBP(chip, MIXER_DATA));
  45. udelay(10);
  46. #ifdef IO_DEBUG
  47. snd_printk("mixer_read 0x%x 0x%x\n", reg, result);
  48. #endif
  49. return result;
  50. }
  51. /*
  52. * Single channel mixer element
  53. */
  54. static int snd_sbmixer_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  55. {
  56. int mask = (kcontrol->private_value >> 24) & 0xff;
  57. uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
  58. uinfo->count = 1;
  59. uinfo->value.integer.min = 0;
  60. uinfo->value.integer.max = mask;
  61. return 0;
  62. }
  63. static int snd_sbmixer_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  64. {
  65. sb_t *sb = snd_kcontrol_chip(kcontrol);
  66. unsigned long flags;
  67. int reg = kcontrol->private_value & 0xff;
  68. int shift = (kcontrol->private_value >> 16) & 0xff;
  69. int mask = (kcontrol->private_value >> 24) & 0xff;
  70. unsigned char val;
  71. spin_lock_irqsave(&sb->mixer_lock, flags);
  72. val = (snd_sbmixer_read(sb, reg) >> shift) & mask;
  73. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  74. ucontrol->value.integer.value[0] = val;
  75. return 0;
  76. }
  77. static int snd_sbmixer_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  78. {
  79. sb_t *sb = snd_kcontrol_chip(kcontrol);
  80. unsigned long flags;
  81. int reg = kcontrol->private_value & 0xff;
  82. int shift = (kcontrol->private_value >> 16) & 0x07;
  83. int mask = (kcontrol->private_value >> 24) & 0xff;
  84. int change;
  85. unsigned char val, oval;
  86. val = (ucontrol->value.integer.value[0] & mask) << shift;
  87. spin_lock_irqsave(&sb->mixer_lock, flags);
  88. oval = snd_sbmixer_read(sb, reg);
  89. val = (oval & ~(mask << shift)) | val;
  90. change = val != oval;
  91. if (change)
  92. snd_sbmixer_write(sb, reg, val);
  93. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  94. return change;
  95. }
  96. /*
  97. * Double channel mixer element
  98. */
  99. static int snd_sbmixer_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  100. {
  101. int mask = (kcontrol->private_value >> 24) & 0xff;
  102. uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
  103. uinfo->count = 2;
  104. uinfo->value.integer.min = 0;
  105. uinfo->value.integer.max = mask;
  106. return 0;
  107. }
  108. static int snd_sbmixer_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  109. {
  110. sb_t *sb = snd_kcontrol_chip(kcontrol);
  111. unsigned long flags;
  112. int left_reg = kcontrol->private_value & 0xff;
  113. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  114. int left_shift = (kcontrol->private_value >> 16) & 0x07;
  115. int right_shift = (kcontrol->private_value >> 19) & 0x07;
  116. int mask = (kcontrol->private_value >> 24) & 0xff;
  117. unsigned char left, right;
  118. spin_lock_irqsave(&sb->mixer_lock, flags);
  119. left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask;
  120. right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask;
  121. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  122. ucontrol->value.integer.value[0] = left;
  123. ucontrol->value.integer.value[1] = right;
  124. return 0;
  125. }
  126. static int snd_sbmixer_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  127. {
  128. sb_t *sb = snd_kcontrol_chip(kcontrol);
  129. unsigned long flags;
  130. int left_reg = kcontrol->private_value & 0xff;
  131. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  132. int left_shift = (kcontrol->private_value >> 16) & 0x07;
  133. int right_shift = (kcontrol->private_value >> 19) & 0x07;
  134. int mask = (kcontrol->private_value >> 24) & 0xff;
  135. int change;
  136. unsigned char left, right, oleft, oright;
  137. left = (ucontrol->value.integer.value[0] & mask) << left_shift;
  138. right = (ucontrol->value.integer.value[1] & mask) << right_shift;
  139. spin_lock_irqsave(&sb->mixer_lock, flags);
  140. if (left_reg == right_reg) {
  141. oleft = snd_sbmixer_read(sb, left_reg);
  142. left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right;
  143. change = left != oleft;
  144. if (change)
  145. snd_sbmixer_write(sb, left_reg, left);
  146. } else {
  147. oleft = snd_sbmixer_read(sb, left_reg);
  148. oright = snd_sbmixer_read(sb, right_reg);
  149. left = (oleft & ~(mask << left_shift)) | left;
  150. right = (oright & ~(mask << right_shift)) | right;
  151. change = left != oleft || right != oright;
  152. if (change) {
  153. snd_sbmixer_write(sb, left_reg, left);
  154. snd_sbmixer_write(sb, right_reg, right);
  155. }
  156. }
  157. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  158. return change;
  159. }
  160. /*
  161. * DT-019x / ALS-007 capture/input switch
  162. */
  163. static int snd_dt019x_input_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  164. {
  165. static char *texts[5] = {
  166. "CD", "Mic", "Line", "Synth", "Master"
  167. };
  168. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  169. uinfo->count = 1;
  170. uinfo->value.enumerated.items = 5;
  171. if (uinfo->value.enumerated.item > 4)
  172. uinfo->value.enumerated.item = 4;
  173. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  174. return 0;
  175. }
  176. static int snd_dt019x_input_sw_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  177. {
  178. sb_t *sb = snd_kcontrol_chip(kcontrol);
  179. unsigned long flags;
  180. unsigned char oval;
  181. spin_lock_irqsave(&sb->mixer_lock, flags);
  182. oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
  183. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  184. switch (oval & 0x07) {
  185. case SB_DT019X_CAP_CD:
  186. ucontrol->value.enumerated.item[0] = 0;
  187. break;
  188. case SB_DT019X_CAP_MIC:
  189. ucontrol->value.enumerated.item[0] = 1;
  190. break;
  191. case SB_DT019X_CAP_LINE:
  192. ucontrol->value.enumerated.item[0] = 2;
  193. break;
  194. case SB_DT019X_CAP_MAIN:
  195. ucontrol->value.enumerated.item[0] = 4;
  196. break;
  197. /* To record the synth on these cards you must record the main. */
  198. /* Thus SB_DT019X_CAP_SYNTH == SB_DT019X_CAP_MAIN and would cause */
  199. /* duplicate case labels if left uncommented. */
  200. /* case SB_DT019X_CAP_SYNTH:
  201. * ucontrol->value.enumerated.item[0] = 3;
  202. * break;
  203. */
  204. default:
  205. ucontrol->value.enumerated.item[0] = 4;
  206. break;
  207. }
  208. return 0;
  209. }
  210. static int snd_dt019x_input_sw_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  211. {
  212. sb_t *sb = snd_kcontrol_chip(kcontrol);
  213. unsigned long flags;
  214. int change;
  215. unsigned char nval, oval;
  216. if (ucontrol->value.enumerated.item[0] > 4)
  217. return -EINVAL;
  218. switch (ucontrol->value.enumerated.item[0]) {
  219. case 0:
  220. nval = SB_DT019X_CAP_CD;
  221. break;
  222. case 1:
  223. nval = SB_DT019X_CAP_MIC;
  224. break;
  225. case 2:
  226. nval = SB_DT019X_CAP_LINE;
  227. break;
  228. case 3:
  229. nval = SB_DT019X_CAP_SYNTH;
  230. break;
  231. case 4:
  232. nval = SB_DT019X_CAP_MAIN;
  233. break;
  234. default:
  235. nval = SB_DT019X_CAP_MAIN;
  236. }
  237. spin_lock_irqsave(&sb->mixer_lock, flags);
  238. oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
  239. change = nval != oval;
  240. if (change)
  241. snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval);
  242. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  243. return change;
  244. }
  245. /*
  246. * SBPRO input multiplexer
  247. */
  248. static int snd_sb8mixer_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  249. {
  250. static char *texts[3] = {
  251. "Mic", "CD", "Line"
  252. };
  253. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  254. uinfo->count = 1;
  255. uinfo->value.enumerated.items = 3;
  256. if (uinfo->value.enumerated.item > 2)
  257. uinfo->value.enumerated.item = 2;
  258. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  259. return 0;
  260. }
  261. static int snd_sb8mixer_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  262. {
  263. sb_t *sb = snd_kcontrol_chip(kcontrol);
  264. unsigned long flags;
  265. unsigned char oval;
  266. spin_lock_irqsave(&sb->mixer_lock, flags);
  267. oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
  268. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  269. switch ((oval >> 0x01) & 0x03) {
  270. case SB_DSP_MIXS_CD:
  271. ucontrol->value.enumerated.item[0] = 1;
  272. break;
  273. case SB_DSP_MIXS_LINE:
  274. ucontrol->value.enumerated.item[0] = 2;
  275. break;
  276. default:
  277. ucontrol->value.enumerated.item[0] = 0;
  278. break;
  279. }
  280. return 0;
  281. }
  282. static int snd_sb8mixer_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  283. {
  284. sb_t *sb = snd_kcontrol_chip(kcontrol);
  285. unsigned long flags;
  286. int change;
  287. unsigned char nval, oval;
  288. if (ucontrol->value.enumerated.item[0] > 2)
  289. return -EINVAL;
  290. switch (ucontrol->value.enumerated.item[0]) {
  291. case 1:
  292. nval = SB_DSP_MIXS_CD;
  293. break;
  294. case 2:
  295. nval = SB_DSP_MIXS_LINE;
  296. break;
  297. default:
  298. nval = SB_DSP_MIXS_MIC;
  299. }
  300. nval <<= 1;
  301. spin_lock_irqsave(&sb->mixer_lock, flags);
  302. oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
  303. nval |= oval & ~0x06;
  304. change = nval != oval;
  305. if (change)
  306. snd_sbmixer_write(sb, SB_DSP_CAPTURE_SOURCE, nval);
  307. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  308. return change;
  309. }
  310. /*
  311. * SB16 input switch
  312. */
  313. static int snd_sb16mixer_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
  314. {
  315. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  316. uinfo->count = 4;
  317. uinfo->value.integer.min = 0;
  318. uinfo->value.integer.max = 1;
  319. return 0;
  320. }
  321. static int snd_sb16mixer_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  322. {
  323. sb_t *sb = snd_kcontrol_chip(kcontrol);
  324. unsigned long flags;
  325. int reg1 = kcontrol->private_value & 0xff;
  326. int reg2 = (kcontrol->private_value >> 8) & 0xff;
  327. int left_shift = (kcontrol->private_value >> 16) & 0x0f;
  328. int right_shift = (kcontrol->private_value >> 24) & 0x0f;
  329. unsigned char val1, val2;
  330. spin_lock_irqsave(&sb->mixer_lock, flags);
  331. val1 = snd_sbmixer_read(sb, reg1);
  332. val2 = snd_sbmixer_read(sb, reg2);
  333. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  334. ucontrol->value.integer.value[0] = (val1 >> left_shift) & 0x01;
  335. ucontrol->value.integer.value[1] = (val2 >> left_shift) & 0x01;
  336. ucontrol->value.integer.value[2] = (val1 >> right_shift) & 0x01;
  337. ucontrol->value.integer.value[3] = (val2 >> right_shift) & 0x01;
  338. return 0;
  339. }
  340. static int snd_sb16mixer_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
  341. {
  342. sb_t *sb = snd_kcontrol_chip(kcontrol);
  343. unsigned long flags;
  344. int reg1 = kcontrol->private_value & 0xff;
  345. int reg2 = (kcontrol->private_value >> 8) & 0xff;
  346. int left_shift = (kcontrol->private_value >> 16) & 0x0f;
  347. int right_shift = (kcontrol->private_value >> 24) & 0x0f;
  348. int change;
  349. unsigned char val1, val2, oval1, oval2;
  350. spin_lock_irqsave(&sb->mixer_lock, flags);
  351. oval1 = snd_sbmixer_read(sb, reg1);
  352. oval2 = snd_sbmixer_read(sb, reg2);
  353. val1 = oval1 & ~((1 << left_shift) | (1 << right_shift));
  354. val2 = oval2 & ~((1 << left_shift) | (1 << right_shift));
  355. val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
  356. val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
  357. val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
  358. val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
  359. change = val1 != oval1 || val2 != oval2;
  360. if (change) {
  361. snd_sbmixer_write(sb, reg1, val1);
  362. snd_sbmixer_write(sb, reg2, val2);
  363. }
  364. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  365. return change;
  366. }
  367. /*
  368. */
  369. /*
  370. */
  371. int snd_sbmixer_add_ctl(sb_t *chip, const char *name, int index, int type, unsigned long value)
  372. {
  373. static snd_kcontrol_new_t newctls[] = {
  374. [SB_MIX_SINGLE] = {
  375. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  376. .info = snd_sbmixer_info_single,
  377. .get = snd_sbmixer_get_single,
  378. .put = snd_sbmixer_put_single,
  379. },
  380. [SB_MIX_DOUBLE] = {
  381. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  382. .info = snd_sbmixer_info_double,
  383. .get = snd_sbmixer_get_double,
  384. .put = snd_sbmixer_put_double,
  385. },
  386. [SB_MIX_INPUT_SW] = {
  387. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  388. .info = snd_sb16mixer_info_input_sw,
  389. .get = snd_sb16mixer_get_input_sw,
  390. .put = snd_sb16mixer_put_input_sw,
  391. },
  392. [SB_MIX_CAPTURE_PRO] = {
  393. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  394. .info = snd_sb8mixer_info_mux,
  395. .get = snd_sb8mixer_get_mux,
  396. .put = snd_sb8mixer_put_mux,
  397. },
  398. [SB_MIX_CAPTURE_DT019X] = {
  399. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  400. .info = snd_dt019x_input_sw_info,
  401. .get = snd_dt019x_input_sw_get,
  402. .put = snd_dt019x_input_sw_put,
  403. },
  404. };
  405. snd_kcontrol_t *ctl;
  406. int err;
  407. ctl = snd_ctl_new1(&newctls[type], chip);
  408. if (! ctl)
  409. return -ENOMEM;
  410. strlcpy(ctl->id.name, name, sizeof(ctl->id.name));
  411. ctl->id.index = index;
  412. ctl->private_value = value;
  413. if ((err = snd_ctl_add(chip->card, ctl)) < 0) {
  414. snd_ctl_free_one(ctl);
  415. return err;
  416. }
  417. return 0;
  418. }
  419. /*
  420. * SB 2.0 specific mixer elements
  421. */
  422. static struct sbmix_elem snd_sb20_ctl_master_play_vol =
  423. SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7);
  424. static struct sbmix_elem snd_sb20_ctl_pcm_play_vol =
  425. SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3);
  426. static struct sbmix_elem snd_sb20_ctl_synth_play_vol =
  427. SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7);
  428. static struct sbmix_elem snd_sb20_ctl_cd_play_vol =
  429. SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7);
  430. static struct sbmix_elem *snd_sb20_controls[] = {
  431. &snd_sb20_ctl_master_play_vol,
  432. &snd_sb20_ctl_pcm_play_vol,
  433. &snd_sb20_ctl_synth_play_vol,
  434. &snd_sb20_ctl_cd_play_vol
  435. };
  436. static unsigned char snd_sb20_init_values[][2] = {
  437. { SB_DSP20_MASTER_DEV, 0 },
  438. { SB_DSP20_FM_DEV, 0 },
  439. };
  440. /*
  441. * SB Pro specific mixer elements
  442. */
  443. static struct sbmix_elem snd_sbpro_ctl_master_play_vol =
  444. SB_DOUBLE("Master Playback Volume", SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7);
  445. static struct sbmix_elem snd_sbpro_ctl_pcm_play_vol =
  446. SB_DOUBLE("PCM Playback Volume", SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7);
  447. static struct sbmix_elem snd_sbpro_ctl_pcm_play_filter =
  448. SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1);
  449. static struct sbmix_elem snd_sbpro_ctl_synth_play_vol =
  450. SB_DOUBLE("Synth Playback Volume", SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7);
  451. static struct sbmix_elem snd_sbpro_ctl_cd_play_vol =
  452. SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7);
  453. static struct sbmix_elem snd_sbpro_ctl_line_play_vol =
  454. SB_DOUBLE("Line Playback Volume", SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7);
  455. static struct sbmix_elem snd_sbpro_ctl_mic_play_vol =
  456. SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3);
  457. static struct sbmix_elem snd_sbpro_ctl_capture_source =
  458. {
  459. .name = "Capture Source",
  460. .type = SB_MIX_CAPTURE_PRO
  461. };
  462. static struct sbmix_elem snd_sbpro_ctl_capture_filter =
  463. SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1);
  464. static struct sbmix_elem snd_sbpro_ctl_capture_low_filter =
  465. SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1);
  466. static struct sbmix_elem *snd_sbpro_controls[] = {
  467. &snd_sbpro_ctl_master_play_vol,
  468. &snd_sbpro_ctl_pcm_play_vol,
  469. &snd_sbpro_ctl_pcm_play_filter,
  470. &snd_sbpro_ctl_synth_play_vol,
  471. &snd_sbpro_ctl_cd_play_vol,
  472. &snd_sbpro_ctl_line_play_vol,
  473. &snd_sbpro_ctl_mic_play_vol,
  474. &snd_sbpro_ctl_capture_source,
  475. &snd_sbpro_ctl_capture_filter,
  476. &snd_sbpro_ctl_capture_low_filter
  477. };
  478. static unsigned char snd_sbpro_init_values[][2] = {
  479. { SB_DSP_MASTER_DEV, 0 },
  480. { SB_DSP_PCM_DEV, 0 },
  481. { SB_DSP_FM_DEV, 0 },
  482. };
  483. /*
  484. * SB16 specific mixer elements
  485. */
  486. static struct sbmix_elem snd_sb16_ctl_master_play_vol =
  487. SB_DOUBLE("Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31);
  488. static struct sbmix_elem snd_sb16_ctl_3d_enhance_switch =
  489. SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1);
  490. static struct sbmix_elem snd_sb16_ctl_tone_bass =
  491. SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15);
  492. static struct sbmix_elem snd_sb16_ctl_tone_treble =
  493. SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15);
  494. static struct sbmix_elem snd_sb16_ctl_pcm_play_vol =
  495. SB_DOUBLE("PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31);
  496. static struct sbmix_elem snd_sb16_ctl_synth_capture_route =
  497. SB16_INPUT_SW("Synth Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 6, 5);
  498. static struct sbmix_elem snd_sb16_ctl_synth_play_vol =
  499. SB_DOUBLE("Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31);
  500. static struct sbmix_elem snd_sb16_ctl_cd_capture_route =
  501. SB16_INPUT_SW("CD Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, 1);
  502. static struct sbmix_elem snd_sb16_ctl_cd_play_switch =
  503. SB_DOUBLE("CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1);
  504. static struct sbmix_elem snd_sb16_ctl_cd_play_vol =
  505. SB_DOUBLE("CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31);
  506. static struct sbmix_elem snd_sb16_ctl_line_capture_route =
  507. SB16_INPUT_SW("Line Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3);
  508. static struct sbmix_elem snd_sb16_ctl_line_play_switch =
  509. SB_DOUBLE("Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1);
  510. static struct sbmix_elem snd_sb16_ctl_line_play_vol =
  511. SB_DOUBLE("Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31);
  512. static struct sbmix_elem snd_sb16_ctl_mic_capture_route =
  513. SB16_INPUT_SW("Mic Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0);
  514. static struct sbmix_elem snd_sb16_ctl_mic_play_switch =
  515. SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1);
  516. static struct sbmix_elem snd_sb16_ctl_mic_play_vol =
  517. SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31);
  518. static struct sbmix_elem snd_sb16_ctl_pc_speaker_vol =
  519. SB_SINGLE("PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3);
  520. static struct sbmix_elem snd_sb16_ctl_capture_vol =
  521. SB_DOUBLE("Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3);
  522. static struct sbmix_elem snd_sb16_ctl_play_vol =
  523. SB_DOUBLE("Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3);
  524. static struct sbmix_elem snd_sb16_ctl_auto_mic_gain =
  525. SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1);
  526. static struct sbmix_elem *snd_sb16_controls[] = {
  527. &snd_sb16_ctl_master_play_vol,
  528. &snd_sb16_ctl_3d_enhance_switch,
  529. &snd_sb16_ctl_tone_bass,
  530. &snd_sb16_ctl_tone_treble,
  531. &snd_sb16_ctl_pcm_play_vol,
  532. &snd_sb16_ctl_synth_capture_route,
  533. &snd_sb16_ctl_synth_play_vol,
  534. &snd_sb16_ctl_cd_capture_route,
  535. &snd_sb16_ctl_cd_play_switch,
  536. &snd_sb16_ctl_cd_play_vol,
  537. &snd_sb16_ctl_line_capture_route,
  538. &snd_sb16_ctl_line_play_switch,
  539. &snd_sb16_ctl_line_play_vol,
  540. &snd_sb16_ctl_mic_capture_route,
  541. &snd_sb16_ctl_mic_play_switch,
  542. &snd_sb16_ctl_mic_play_vol,
  543. &snd_sb16_ctl_pc_speaker_vol,
  544. &snd_sb16_ctl_capture_vol,
  545. &snd_sb16_ctl_play_vol,
  546. &snd_sb16_ctl_auto_mic_gain
  547. };
  548. static unsigned char snd_sb16_init_values[][2] = {
  549. { SB_DSP4_MASTER_DEV + 0, 0 },
  550. { SB_DSP4_MASTER_DEV + 1, 0 },
  551. { SB_DSP4_PCM_DEV + 0, 0 },
  552. { SB_DSP4_PCM_DEV + 1, 0 },
  553. { SB_DSP4_SYNTH_DEV + 0, 0 },
  554. { SB_DSP4_SYNTH_DEV + 1, 0 },
  555. { SB_DSP4_INPUT_LEFT, 0 },
  556. { SB_DSP4_INPUT_RIGHT, 0 },
  557. { SB_DSP4_OUTPUT_SW, 0 },
  558. { SB_DSP4_SPEAKER_DEV, 0 },
  559. };
  560. /*
  561. * DT019x specific mixer elements
  562. */
  563. static struct sbmix_elem snd_dt019x_ctl_master_play_vol =
  564. SB_DOUBLE("Master Playback Volume", SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4,0, 15);
  565. static struct sbmix_elem snd_dt019x_ctl_pcm_play_vol =
  566. SB_DOUBLE("PCM Playback Volume", SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4,0, 15);
  567. static struct sbmix_elem snd_dt019x_ctl_synth_play_vol =
  568. SB_DOUBLE("Synth Playback Volume", SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4,0, 15);
  569. static struct sbmix_elem snd_dt019x_ctl_cd_play_vol =
  570. SB_DOUBLE("CD Playback Volume", SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4,0, 15);
  571. static struct sbmix_elem snd_dt019x_ctl_mic_play_vol =
  572. SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7);
  573. static struct sbmix_elem snd_dt019x_ctl_pc_speaker_vol =
  574. SB_SINGLE("PC Speaker Volume", SB_DT019X_SPKR_DEV, 0, 7);
  575. static struct sbmix_elem snd_dt019x_ctl_line_play_vol =
  576. SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, 15);
  577. static struct sbmix_elem snd_dt019x_ctl_pcm_play_switch =
  578. SB_DOUBLE("PCM Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2,1, 1);
  579. static struct sbmix_elem snd_dt019x_ctl_synth_play_switch =
  580. SB_DOUBLE("Synth Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4,3, 1);
  581. static struct sbmix_elem snd_dt019x_ctl_capture_source =
  582. {
  583. .name = "Capture Source",
  584. .type = SB_MIX_CAPTURE_DT019X
  585. };
  586. static struct sbmix_elem *snd_dt019x_controls[] = {
  587. &snd_dt019x_ctl_master_play_vol,
  588. &snd_dt019x_ctl_pcm_play_vol,
  589. &snd_dt019x_ctl_synth_play_vol,
  590. &snd_dt019x_ctl_cd_play_vol,
  591. &snd_dt019x_ctl_mic_play_vol,
  592. &snd_dt019x_ctl_pc_speaker_vol,
  593. &snd_dt019x_ctl_line_play_vol,
  594. &snd_sb16_ctl_mic_play_switch,
  595. &snd_sb16_ctl_cd_play_switch,
  596. &snd_sb16_ctl_line_play_switch,
  597. &snd_dt019x_ctl_pcm_play_switch,
  598. &snd_dt019x_ctl_synth_play_switch,
  599. &snd_dt019x_ctl_capture_source
  600. };
  601. static unsigned char snd_dt019x_init_values[][2] = {
  602. { SB_DT019X_MASTER_DEV, 0 },
  603. { SB_DT019X_PCM_DEV, 0 },
  604. { SB_DT019X_SYNTH_DEV, 0 },
  605. { SB_DT019X_CD_DEV, 0 },
  606. { SB_DT019X_MIC_DEV, 0 }, /* Includes PC-speaker in high nibble */
  607. { SB_DT019X_LINE_DEV, 0 },
  608. { SB_DSP4_OUTPUT_SW, 0 },
  609. { SB_DT019X_OUTPUT_SW2, 0 },
  610. { SB_DT019X_CAPTURE_SW, 0x06 },
  611. };
  612. /*
  613. * ALS4000 specific mixer elements
  614. */
  615. /* FIXME: SB_ALS4000_MONO_IO_CTRL needs output select ctrl ! */
  616. static struct sbmix_elem snd_als4000_ctl_mono_output_switch =
  617. SB_SINGLE("Mono Output Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1);
  618. /* FIXME: mono input switch also available on DT019X ? */
  619. static struct sbmix_elem snd_als4000_ctl_mono_input_switch =
  620. SB_SINGLE("Mono Input Switch", SB_DT019X_OUTPUT_SW2, 0, 1);
  621. static struct sbmix_elem snd_als4000_ctl_mic_20db_boost =
  622. SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03);
  623. static struct sbmix_elem snd_als4000_ctl_mixer_out_to_in =
  624. SB_SINGLE("Mixer Out To In", SB_ALS4000_MIC_IN_GAIN, 7, 0x01);
  625. /* FIXME: 3D needs much more sophisticated controls, many more features ! */
  626. static struct sbmix_elem snd_als4000_ctl_3d_output_switch =
  627. SB_SINGLE("3D Output Switch", SB_ALS4000_3D_SND_FX, 6, 0x01);
  628. static struct sbmix_elem snd_als4000_ctl_3d_output_ratio =
  629. SB_SINGLE("3D Output Ratio", SB_ALS4000_3D_SND_FX, 0, 0x07);
  630. static struct sbmix_elem snd_als4000_ctl_3d_poweroff_switch =
  631. SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01);
  632. static struct sbmix_elem snd_als4000_ctl_3d_delay =
  633. SB_SINGLE("3D Delay", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f);
  634. #if NOT_AVAILABLE
  635. static struct sbmix_elem snd_als4000_ctl_fmdac =
  636. SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01);
  637. static struct sbmix_elem snd_als4000_ctl_qsound =
  638. SB_SINGLE("QSound Mode", SB_ALS4000_QSOUND, 1, 0x1f);
  639. #endif
  640. static struct sbmix_elem *snd_als4000_controls[] = {
  641. &snd_sb16_ctl_master_play_vol,
  642. &snd_dt019x_ctl_pcm_play_switch,
  643. &snd_sb16_ctl_pcm_play_vol,
  644. &snd_sb16_ctl_synth_capture_route,
  645. &snd_dt019x_ctl_synth_play_switch,
  646. &snd_sb16_ctl_synth_play_vol,
  647. &snd_sb16_ctl_cd_capture_route,
  648. &snd_sb16_ctl_cd_play_switch,
  649. &snd_sb16_ctl_cd_play_vol,
  650. &snd_sb16_ctl_line_capture_route,
  651. &snd_sb16_ctl_line_play_switch,
  652. &snd_sb16_ctl_line_play_vol,
  653. &snd_sb16_ctl_mic_capture_route,
  654. &snd_als4000_ctl_mic_20db_boost,
  655. &snd_sb16_ctl_auto_mic_gain,
  656. &snd_sb16_ctl_mic_play_switch,
  657. &snd_sb16_ctl_mic_play_vol,
  658. &snd_sb16_ctl_pc_speaker_vol,
  659. &snd_sb16_ctl_capture_vol,
  660. &snd_sb16_ctl_play_vol,
  661. &snd_als4000_ctl_mono_output_switch,
  662. &snd_als4000_ctl_mono_input_switch,
  663. &snd_als4000_ctl_mixer_out_to_in,
  664. &snd_als4000_ctl_3d_output_switch,
  665. &snd_als4000_ctl_3d_output_ratio,
  666. &snd_als4000_ctl_3d_delay,
  667. &snd_als4000_ctl_3d_poweroff_switch,
  668. #if NOT_AVAILABLE
  669. &snd_als4000_ctl_fmdac,
  670. &snd_als4000_ctl_qsound,
  671. #endif
  672. };
  673. static unsigned char snd_als4000_init_values[][2] = {
  674. { SB_DSP4_MASTER_DEV + 0, 0 },
  675. { SB_DSP4_MASTER_DEV + 1, 0 },
  676. { SB_DSP4_PCM_DEV + 0, 0 },
  677. { SB_DSP4_PCM_DEV + 1, 0 },
  678. { SB_DSP4_SYNTH_DEV + 0, 0 },
  679. { SB_DSP4_SYNTH_DEV + 1, 0 },
  680. { SB_DSP4_SPEAKER_DEV, 0 },
  681. { SB_DSP4_OUTPUT_SW, 0 },
  682. { SB_DSP4_INPUT_LEFT, 0 },
  683. { SB_DSP4_INPUT_RIGHT, 0 },
  684. { SB_DT019X_OUTPUT_SW2, 0 },
  685. { SB_ALS4000_MIC_IN_GAIN, 0 },
  686. };
  687. /*
  688. */
  689. static int snd_sbmixer_init(sb_t *chip,
  690. struct sbmix_elem **controls,
  691. int controls_count,
  692. unsigned char map[][2],
  693. int map_count,
  694. char *name)
  695. {
  696. unsigned long flags;
  697. snd_card_t *card = chip->card;
  698. int idx, err;
  699. /* mixer reset */
  700. spin_lock_irqsave(&chip->mixer_lock, flags);
  701. snd_sbmixer_write(chip, 0x00, 0x00);
  702. spin_unlock_irqrestore(&chip->mixer_lock, flags);
  703. /* mute and zero volume channels */
  704. for (idx = 0; idx < map_count; idx++) {
  705. spin_lock_irqsave(&chip->mixer_lock, flags);
  706. snd_sbmixer_write(chip, map[idx][0], map[idx][1]);
  707. spin_unlock_irqrestore(&chip->mixer_lock, flags);
  708. }
  709. for (idx = 0; idx < controls_count; idx++) {
  710. if ((err = snd_sbmixer_add_ctl_elem(chip, controls[idx])) < 0)
  711. return err;
  712. }
  713. snd_component_add(card, name);
  714. strcpy(card->mixername, name);
  715. return 0;
  716. }
  717. int snd_sbmixer_new(sb_t *chip)
  718. {
  719. snd_card_t * card;
  720. int err;
  721. snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
  722. card = chip->card;
  723. switch (chip->hardware) {
  724. case SB_HW_10:
  725. return 0; /* no mixer chip on SB1.x */
  726. case SB_HW_20:
  727. case SB_HW_201:
  728. if ((err = snd_sbmixer_init(chip,
  729. snd_sb20_controls,
  730. ARRAY_SIZE(snd_sb20_controls),
  731. snd_sb20_init_values,
  732. ARRAY_SIZE(snd_sb20_init_values),
  733. "CTL1335")) < 0)
  734. return err;
  735. break;
  736. case SB_HW_PRO:
  737. if ((err = snd_sbmixer_init(chip,
  738. snd_sbpro_controls,
  739. ARRAY_SIZE(snd_sbpro_controls),
  740. snd_sbpro_init_values,
  741. ARRAY_SIZE(snd_sbpro_init_values),
  742. "CTL1345")) < 0)
  743. return err;
  744. break;
  745. case SB_HW_16:
  746. case SB_HW_ALS100:
  747. if ((err = snd_sbmixer_init(chip,
  748. snd_sb16_controls,
  749. ARRAY_SIZE(snd_sb16_controls),
  750. snd_sb16_init_values,
  751. ARRAY_SIZE(snd_sb16_init_values),
  752. "CTL1745")) < 0)
  753. return err;
  754. break;
  755. case SB_HW_ALS4000:
  756. if ((err = snd_sbmixer_init(chip,
  757. snd_als4000_controls,
  758. ARRAY_SIZE(snd_als4000_controls),
  759. snd_als4000_init_values,
  760. ARRAY_SIZE(snd_als4000_init_values),
  761. "ALS4000")) < 0)
  762. return err;
  763. break;
  764. case SB_HW_DT019X:
  765. if ((err = snd_sbmixer_init(chip,
  766. snd_dt019x_controls,
  767. ARRAY_SIZE(snd_dt019x_controls),
  768. snd_dt019x_init_values,
  769. ARRAY_SIZE(snd_dt019x_init_values),
  770. "DT019X")) < 0)
  771. break;
  772. default:
  773. strcpy(card->mixername, "???");
  774. }
  775. return 0;
  776. }