sb_mixer.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  1. /*
  2. * Copyright (c) by Jaroslav Kysela <perex@perex.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 <asm/io.h>
  22. #include <linux/delay.h>
  23. #include <linux/time.h>
  24. #include <sound/core.h>
  25. #include <sound/sb.h>
  26. #include <sound/control.h>
  27. #undef IO_DEBUG
  28. void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data)
  29. {
  30. outb(reg, SBP(chip, MIXER_ADDR));
  31. udelay(10);
  32. outb(data, SBP(chip, MIXER_DATA));
  33. udelay(10);
  34. #ifdef IO_DEBUG
  35. snd_printk(KERN_DEBUG "mixer_write 0x%x 0x%x\n", reg, data);
  36. #endif
  37. }
  38. unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg)
  39. {
  40. unsigned char result;
  41. outb(reg, SBP(chip, MIXER_ADDR));
  42. udelay(10);
  43. result = inb(SBP(chip, MIXER_DATA));
  44. udelay(10);
  45. #ifdef IO_DEBUG
  46. snd_printk(KERN_DEBUG "mixer_read 0x%x 0x%x\n", reg, result);
  47. #endif
  48. return result;
  49. }
  50. /*
  51. * Single channel mixer element
  52. */
  53. static int snd_sbmixer_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  54. {
  55. int mask = (kcontrol->private_value >> 24) & 0xff;
  56. uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
  57. uinfo->count = 1;
  58. uinfo->value.integer.min = 0;
  59. uinfo->value.integer.max = mask;
  60. return 0;
  61. }
  62. static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  63. {
  64. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  65. unsigned long flags;
  66. int reg = kcontrol->private_value & 0xff;
  67. int shift = (kcontrol->private_value >> 16) & 0xff;
  68. int mask = (kcontrol->private_value >> 24) & 0xff;
  69. unsigned char val;
  70. spin_lock_irqsave(&sb->mixer_lock, flags);
  71. val = (snd_sbmixer_read(sb, reg) >> shift) & mask;
  72. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  73. ucontrol->value.integer.value[0] = val;
  74. return 0;
  75. }
  76. static int snd_sbmixer_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  77. {
  78. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  79. unsigned long flags;
  80. int reg = kcontrol->private_value & 0xff;
  81. int shift = (kcontrol->private_value >> 16) & 0x07;
  82. int mask = (kcontrol->private_value >> 24) & 0xff;
  83. int change;
  84. unsigned char val, oval;
  85. val = (ucontrol->value.integer.value[0] & mask) << shift;
  86. spin_lock_irqsave(&sb->mixer_lock, flags);
  87. oval = snd_sbmixer_read(sb, reg);
  88. val = (oval & ~(mask << shift)) | val;
  89. change = val != oval;
  90. if (change)
  91. snd_sbmixer_write(sb, reg, val);
  92. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  93. return change;
  94. }
  95. /*
  96. * Double channel mixer element
  97. */
  98. static int snd_sbmixer_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  99. {
  100. int mask = (kcontrol->private_value >> 24) & 0xff;
  101. uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
  102. uinfo->count = 2;
  103. uinfo->value.integer.min = 0;
  104. uinfo->value.integer.max = mask;
  105. return 0;
  106. }
  107. static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  108. {
  109. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  110. unsigned long flags;
  111. int left_reg = kcontrol->private_value & 0xff;
  112. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  113. int left_shift = (kcontrol->private_value >> 16) & 0x07;
  114. int right_shift = (kcontrol->private_value >> 19) & 0x07;
  115. int mask = (kcontrol->private_value >> 24) & 0xff;
  116. unsigned char left, right;
  117. spin_lock_irqsave(&sb->mixer_lock, flags);
  118. left = (snd_sbmixer_read(sb, left_reg) >> left_shift) & mask;
  119. right = (snd_sbmixer_read(sb, right_reg) >> right_shift) & mask;
  120. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  121. ucontrol->value.integer.value[0] = left;
  122. ucontrol->value.integer.value[1] = right;
  123. return 0;
  124. }
  125. static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  126. {
  127. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  128. unsigned long flags;
  129. int left_reg = kcontrol->private_value & 0xff;
  130. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  131. int left_shift = (kcontrol->private_value >> 16) & 0x07;
  132. int right_shift = (kcontrol->private_value >> 19) & 0x07;
  133. int mask = (kcontrol->private_value >> 24) & 0xff;
  134. int change;
  135. unsigned char left, right, oleft, oright;
  136. left = (ucontrol->value.integer.value[0] & mask) << left_shift;
  137. right = (ucontrol->value.integer.value[1] & mask) << right_shift;
  138. spin_lock_irqsave(&sb->mixer_lock, flags);
  139. if (left_reg == right_reg) {
  140. oleft = snd_sbmixer_read(sb, left_reg);
  141. left = (oleft & ~((mask << left_shift) | (mask << right_shift))) | left | right;
  142. change = left != oleft;
  143. if (change)
  144. snd_sbmixer_write(sb, left_reg, left);
  145. } else {
  146. oleft = snd_sbmixer_read(sb, left_reg);
  147. oright = snd_sbmixer_read(sb, right_reg);
  148. left = (oleft & ~(mask << left_shift)) | left;
  149. right = (oright & ~(mask << right_shift)) | right;
  150. change = left != oleft || right != oright;
  151. if (change) {
  152. snd_sbmixer_write(sb, left_reg, left);
  153. snd_sbmixer_write(sb, right_reg, right);
  154. }
  155. }
  156. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  157. return change;
  158. }
  159. /*
  160. * DT-019x / ALS-007 capture/input switch
  161. */
  162. static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  163. {
  164. static const char *texts[5] = {
  165. "CD", "Mic", "Line", "Synth", "Master"
  166. };
  167. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  168. uinfo->count = 1;
  169. uinfo->value.enumerated.items = 5;
  170. if (uinfo->value.enumerated.item > 4)
  171. uinfo->value.enumerated.item = 4;
  172. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  173. return 0;
  174. }
  175. static int snd_dt019x_input_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  176. {
  177. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  178. unsigned long flags;
  179. unsigned char oval;
  180. spin_lock_irqsave(&sb->mixer_lock, flags);
  181. oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
  182. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  183. switch (oval & 0x07) {
  184. case SB_DT019X_CAP_CD:
  185. ucontrol->value.enumerated.item[0] = 0;
  186. break;
  187. case SB_DT019X_CAP_MIC:
  188. ucontrol->value.enumerated.item[0] = 1;
  189. break;
  190. case SB_DT019X_CAP_LINE:
  191. ucontrol->value.enumerated.item[0] = 2;
  192. break;
  193. case SB_DT019X_CAP_MAIN:
  194. ucontrol->value.enumerated.item[0] = 4;
  195. break;
  196. /* To record the synth on these cards you must record the main. */
  197. /* Thus SB_DT019X_CAP_SYNTH == SB_DT019X_CAP_MAIN and would cause */
  198. /* duplicate case labels if left uncommented. */
  199. /* case SB_DT019X_CAP_SYNTH:
  200. * ucontrol->value.enumerated.item[0] = 3;
  201. * break;
  202. */
  203. default:
  204. ucontrol->value.enumerated.item[0] = 4;
  205. break;
  206. }
  207. return 0;
  208. }
  209. static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  210. {
  211. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  212. unsigned long flags;
  213. int change;
  214. unsigned char nval, oval;
  215. if (ucontrol->value.enumerated.item[0] > 4)
  216. return -EINVAL;
  217. switch (ucontrol->value.enumerated.item[0]) {
  218. case 0:
  219. nval = SB_DT019X_CAP_CD;
  220. break;
  221. case 1:
  222. nval = SB_DT019X_CAP_MIC;
  223. break;
  224. case 2:
  225. nval = SB_DT019X_CAP_LINE;
  226. break;
  227. case 3:
  228. nval = SB_DT019X_CAP_SYNTH;
  229. break;
  230. case 4:
  231. nval = SB_DT019X_CAP_MAIN;
  232. break;
  233. default:
  234. nval = SB_DT019X_CAP_MAIN;
  235. }
  236. spin_lock_irqsave(&sb->mixer_lock, flags);
  237. oval = snd_sbmixer_read(sb, SB_DT019X_CAPTURE_SW);
  238. change = nval != oval;
  239. if (change)
  240. snd_sbmixer_write(sb, SB_DT019X_CAPTURE_SW, nval);
  241. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  242. return change;
  243. }
  244. /*
  245. * ALS4000 mono recording control switch
  246. */
  247. static int snd_als4k_mono_capture_route_info(struct snd_kcontrol *kcontrol,
  248. struct snd_ctl_elem_info *uinfo)
  249. {
  250. static const char *texts[3] = {
  251. "L chan only", "R chan only", "L ch/2 + R ch/2"
  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,
  259. texts[uinfo->value.enumerated.item]);
  260. return 0;
  261. }
  262. static int snd_als4k_mono_capture_route_get(struct snd_kcontrol *kcontrol,
  263. struct snd_ctl_elem_value *ucontrol)
  264. {
  265. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  266. unsigned long flags;
  267. unsigned char oval;
  268. spin_lock_irqsave(&sb->mixer_lock, flags);
  269. oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL);
  270. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  271. oval >>= 6;
  272. if (oval > 2)
  273. oval = 2;
  274. ucontrol->value.enumerated.item[0] = oval;
  275. return 0;
  276. }
  277. static int snd_als4k_mono_capture_route_put(struct snd_kcontrol *kcontrol,
  278. struct snd_ctl_elem_value *ucontrol)
  279. {
  280. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  281. unsigned long flags;
  282. int change;
  283. unsigned char nval, oval;
  284. if (ucontrol->value.enumerated.item[0] > 2)
  285. return -EINVAL;
  286. spin_lock_irqsave(&sb->mixer_lock, flags);
  287. oval = snd_sbmixer_read(sb, SB_ALS4000_MONO_IO_CTRL);
  288. nval = (oval & ~(3 << 6))
  289. | (ucontrol->value.enumerated.item[0] << 6);
  290. change = nval != oval;
  291. if (change)
  292. snd_sbmixer_write(sb, SB_ALS4000_MONO_IO_CTRL, nval);
  293. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  294. return change;
  295. }
  296. /*
  297. * SBPRO input multiplexer
  298. */
  299. static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  300. {
  301. static const char *texts[3] = {
  302. "Mic", "CD", "Line"
  303. };
  304. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  305. uinfo->count = 1;
  306. uinfo->value.enumerated.items = 3;
  307. if (uinfo->value.enumerated.item > 2)
  308. uinfo->value.enumerated.item = 2;
  309. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  310. return 0;
  311. }
  312. static int snd_sb8mixer_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  313. {
  314. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  315. unsigned long flags;
  316. unsigned char oval;
  317. spin_lock_irqsave(&sb->mixer_lock, flags);
  318. oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
  319. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  320. switch ((oval >> 0x01) & 0x03) {
  321. case SB_DSP_MIXS_CD:
  322. ucontrol->value.enumerated.item[0] = 1;
  323. break;
  324. case SB_DSP_MIXS_LINE:
  325. ucontrol->value.enumerated.item[0] = 2;
  326. break;
  327. default:
  328. ucontrol->value.enumerated.item[0] = 0;
  329. break;
  330. }
  331. return 0;
  332. }
  333. static int snd_sb8mixer_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  334. {
  335. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  336. unsigned long flags;
  337. int change;
  338. unsigned char nval, oval;
  339. if (ucontrol->value.enumerated.item[0] > 2)
  340. return -EINVAL;
  341. switch (ucontrol->value.enumerated.item[0]) {
  342. case 1:
  343. nval = SB_DSP_MIXS_CD;
  344. break;
  345. case 2:
  346. nval = SB_DSP_MIXS_LINE;
  347. break;
  348. default:
  349. nval = SB_DSP_MIXS_MIC;
  350. }
  351. nval <<= 1;
  352. spin_lock_irqsave(&sb->mixer_lock, flags);
  353. oval = snd_sbmixer_read(sb, SB_DSP_CAPTURE_SOURCE);
  354. nval |= oval & ~0x06;
  355. change = nval != oval;
  356. if (change)
  357. snd_sbmixer_write(sb, SB_DSP_CAPTURE_SOURCE, nval);
  358. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  359. return change;
  360. }
  361. /*
  362. * SB16 input switch
  363. */
  364. static int snd_sb16mixer_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  365. {
  366. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  367. uinfo->count = 4;
  368. uinfo->value.integer.min = 0;
  369. uinfo->value.integer.max = 1;
  370. return 0;
  371. }
  372. static int snd_sb16mixer_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  373. {
  374. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  375. unsigned long flags;
  376. int reg1 = kcontrol->private_value & 0xff;
  377. int reg2 = (kcontrol->private_value >> 8) & 0xff;
  378. int left_shift = (kcontrol->private_value >> 16) & 0x0f;
  379. int right_shift = (kcontrol->private_value >> 24) & 0x0f;
  380. unsigned char val1, val2;
  381. spin_lock_irqsave(&sb->mixer_lock, flags);
  382. val1 = snd_sbmixer_read(sb, reg1);
  383. val2 = snd_sbmixer_read(sb, reg2);
  384. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  385. ucontrol->value.integer.value[0] = (val1 >> left_shift) & 0x01;
  386. ucontrol->value.integer.value[1] = (val2 >> left_shift) & 0x01;
  387. ucontrol->value.integer.value[2] = (val1 >> right_shift) & 0x01;
  388. ucontrol->value.integer.value[3] = (val2 >> right_shift) & 0x01;
  389. return 0;
  390. }
  391. static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  392. {
  393. struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
  394. unsigned long flags;
  395. int reg1 = kcontrol->private_value & 0xff;
  396. int reg2 = (kcontrol->private_value >> 8) & 0xff;
  397. int left_shift = (kcontrol->private_value >> 16) & 0x0f;
  398. int right_shift = (kcontrol->private_value >> 24) & 0x0f;
  399. int change;
  400. unsigned char val1, val2, oval1, oval2;
  401. spin_lock_irqsave(&sb->mixer_lock, flags);
  402. oval1 = snd_sbmixer_read(sb, reg1);
  403. oval2 = snd_sbmixer_read(sb, reg2);
  404. val1 = oval1 & ~((1 << left_shift) | (1 << right_shift));
  405. val2 = oval2 & ~((1 << left_shift) | (1 << right_shift));
  406. val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
  407. val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
  408. val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
  409. val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
  410. change = val1 != oval1 || val2 != oval2;
  411. if (change) {
  412. snd_sbmixer_write(sb, reg1, val1);
  413. snd_sbmixer_write(sb, reg2, val2);
  414. }
  415. spin_unlock_irqrestore(&sb->mixer_lock, flags);
  416. return change;
  417. }
  418. /*
  419. */
  420. /*
  421. */
  422. int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int type, unsigned long value)
  423. {
  424. static struct snd_kcontrol_new newctls[] = {
  425. [SB_MIX_SINGLE] = {
  426. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  427. .info = snd_sbmixer_info_single,
  428. .get = snd_sbmixer_get_single,
  429. .put = snd_sbmixer_put_single,
  430. },
  431. [SB_MIX_DOUBLE] = {
  432. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  433. .info = snd_sbmixer_info_double,
  434. .get = snd_sbmixer_get_double,
  435. .put = snd_sbmixer_put_double,
  436. },
  437. [SB_MIX_INPUT_SW] = {
  438. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  439. .info = snd_sb16mixer_info_input_sw,
  440. .get = snd_sb16mixer_get_input_sw,
  441. .put = snd_sb16mixer_put_input_sw,
  442. },
  443. [SB_MIX_CAPTURE_PRO] = {
  444. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  445. .info = snd_sb8mixer_info_mux,
  446. .get = snd_sb8mixer_get_mux,
  447. .put = snd_sb8mixer_put_mux,
  448. },
  449. [SB_MIX_CAPTURE_DT019X] = {
  450. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  451. .info = snd_dt019x_input_sw_info,
  452. .get = snd_dt019x_input_sw_get,
  453. .put = snd_dt019x_input_sw_put,
  454. },
  455. [SB_MIX_MONO_CAPTURE_ALS4K] = {
  456. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  457. .info = snd_als4k_mono_capture_route_info,
  458. .get = snd_als4k_mono_capture_route_get,
  459. .put = snd_als4k_mono_capture_route_put,
  460. },
  461. };
  462. struct snd_kcontrol *ctl;
  463. int err;
  464. ctl = snd_ctl_new1(&newctls[type], chip);
  465. if (! ctl)
  466. return -ENOMEM;
  467. strlcpy(ctl->id.name, name, sizeof(ctl->id.name));
  468. ctl->id.index = index;
  469. ctl->private_value = value;
  470. if ((err = snd_ctl_add(chip->card, ctl)) < 0)
  471. return err;
  472. return 0;
  473. }
  474. /*
  475. * SB 2.0 specific mixer elements
  476. */
  477. static struct sbmix_elem snd_sb20_ctl_master_play_vol =
  478. SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7);
  479. static struct sbmix_elem snd_sb20_ctl_pcm_play_vol =
  480. SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3);
  481. static struct sbmix_elem snd_sb20_ctl_synth_play_vol =
  482. SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7);
  483. static struct sbmix_elem snd_sb20_ctl_cd_play_vol =
  484. SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7);
  485. static struct sbmix_elem *snd_sb20_controls[] = {
  486. &snd_sb20_ctl_master_play_vol,
  487. &snd_sb20_ctl_pcm_play_vol,
  488. &snd_sb20_ctl_synth_play_vol,
  489. &snd_sb20_ctl_cd_play_vol
  490. };
  491. static unsigned char snd_sb20_init_values[][2] = {
  492. { SB_DSP20_MASTER_DEV, 0 },
  493. { SB_DSP20_FM_DEV, 0 },
  494. };
  495. /*
  496. * SB Pro specific mixer elements
  497. */
  498. static struct sbmix_elem snd_sbpro_ctl_master_play_vol =
  499. SB_DOUBLE("Master Playback Volume", SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7);
  500. static struct sbmix_elem snd_sbpro_ctl_pcm_play_vol =
  501. SB_DOUBLE("PCM Playback Volume", SB_DSP_PCM_DEV, SB_DSP_PCM_DEV, 5, 1, 7);
  502. static struct sbmix_elem snd_sbpro_ctl_pcm_play_filter =
  503. SB_SINGLE("PCM Playback Filter", SB_DSP_PLAYBACK_FILT, 5, 1);
  504. static struct sbmix_elem snd_sbpro_ctl_synth_play_vol =
  505. SB_DOUBLE("Synth Playback Volume", SB_DSP_FM_DEV, SB_DSP_FM_DEV, 5, 1, 7);
  506. static struct sbmix_elem snd_sbpro_ctl_cd_play_vol =
  507. SB_DOUBLE("CD Playback Volume", SB_DSP_CD_DEV, SB_DSP_CD_DEV, 5, 1, 7);
  508. static struct sbmix_elem snd_sbpro_ctl_line_play_vol =
  509. SB_DOUBLE("Line Playback Volume", SB_DSP_LINE_DEV, SB_DSP_LINE_DEV, 5, 1, 7);
  510. static struct sbmix_elem snd_sbpro_ctl_mic_play_vol =
  511. SB_SINGLE("Mic Playback Volume", SB_DSP_MIC_DEV, 1, 3);
  512. static struct sbmix_elem snd_sbpro_ctl_capture_source =
  513. {
  514. .name = "Capture Source",
  515. .type = SB_MIX_CAPTURE_PRO
  516. };
  517. static struct sbmix_elem snd_sbpro_ctl_capture_filter =
  518. SB_SINGLE("Capture Filter", SB_DSP_CAPTURE_FILT, 5, 1);
  519. static struct sbmix_elem snd_sbpro_ctl_capture_low_filter =
  520. SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1);
  521. static struct sbmix_elem *snd_sbpro_controls[] = {
  522. &snd_sbpro_ctl_master_play_vol,
  523. &snd_sbpro_ctl_pcm_play_vol,
  524. &snd_sbpro_ctl_pcm_play_filter,
  525. &snd_sbpro_ctl_synth_play_vol,
  526. &snd_sbpro_ctl_cd_play_vol,
  527. &snd_sbpro_ctl_line_play_vol,
  528. &snd_sbpro_ctl_mic_play_vol,
  529. &snd_sbpro_ctl_capture_source,
  530. &snd_sbpro_ctl_capture_filter,
  531. &snd_sbpro_ctl_capture_low_filter
  532. };
  533. static unsigned char snd_sbpro_init_values[][2] = {
  534. { SB_DSP_MASTER_DEV, 0 },
  535. { SB_DSP_PCM_DEV, 0 },
  536. { SB_DSP_FM_DEV, 0 },
  537. };
  538. /*
  539. * SB16 specific mixer elements
  540. */
  541. static struct sbmix_elem snd_sb16_ctl_master_play_vol =
  542. SB_DOUBLE("Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31);
  543. static struct sbmix_elem snd_sb16_ctl_3d_enhance_switch =
  544. SB_SINGLE("3D Enhancement Switch", SB_DSP4_3DSE, 0, 1);
  545. static struct sbmix_elem snd_sb16_ctl_tone_bass =
  546. SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15);
  547. static struct sbmix_elem snd_sb16_ctl_tone_treble =
  548. SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15);
  549. static struct sbmix_elem snd_sb16_ctl_pcm_play_vol =
  550. SB_DOUBLE("PCM Playback Volume", SB_DSP4_PCM_DEV, (SB_DSP4_PCM_DEV + 1), 3, 3, 31);
  551. static struct sbmix_elem snd_sb16_ctl_synth_capture_route =
  552. SB16_INPUT_SW("Synth Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 6, 5);
  553. static struct sbmix_elem snd_sb16_ctl_synth_play_vol =
  554. SB_DOUBLE("Synth Playback Volume", SB_DSP4_SYNTH_DEV, (SB_DSP4_SYNTH_DEV + 1), 3, 3, 31);
  555. static struct sbmix_elem snd_sb16_ctl_cd_capture_route =
  556. SB16_INPUT_SW("CD Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 2, 1);
  557. static struct sbmix_elem snd_sb16_ctl_cd_play_switch =
  558. SB_DOUBLE("CD Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 2, 1, 1);
  559. static struct sbmix_elem snd_sb16_ctl_cd_play_vol =
  560. SB_DOUBLE("CD Playback Volume", SB_DSP4_CD_DEV, (SB_DSP4_CD_DEV + 1), 3, 3, 31);
  561. static struct sbmix_elem snd_sb16_ctl_line_capture_route =
  562. SB16_INPUT_SW("Line Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 4, 3);
  563. static struct sbmix_elem snd_sb16_ctl_line_play_switch =
  564. SB_DOUBLE("Line Playback Switch", SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, 4, 3, 1);
  565. static struct sbmix_elem snd_sb16_ctl_line_play_vol =
  566. SB_DOUBLE("Line Playback Volume", SB_DSP4_LINE_DEV, (SB_DSP4_LINE_DEV + 1), 3, 3, 31);
  567. static struct sbmix_elem snd_sb16_ctl_mic_capture_route =
  568. SB16_INPUT_SW("Mic Capture Route", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0);
  569. static struct sbmix_elem snd_sb16_ctl_mic_play_switch =
  570. SB_SINGLE("Mic Playback Switch", SB_DSP4_OUTPUT_SW, 0, 1);
  571. static struct sbmix_elem snd_sb16_ctl_mic_play_vol =
  572. SB_SINGLE("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31);
  573. static struct sbmix_elem snd_sb16_ctl_pc_speaker_vol =
  574. SB_SINGLE("PC Speaker Volume", SB_DSP4_SPEAKER_DEV, 6, 3);
  575. static struct sbmix_elem snd_sb16_ctl_capture_vol =
  576. SB_DOUBLE("Capture Volume", SB_DSP4_IGAIN_DEV, (SB_DSP4_IGAIN_DEV + 1), 6, 6, 3);
  577. static struct sbmix_elem snd_sb16_ctl_play_vol =
  578. SB_DOUBLE("Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6, 3);
  579. static struct sbmix_elem snd_sb16_ctl_auto_mic_gain =
  580. SB_SINGLE("Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1);
  581. static struct sbmix_elem *snd_sb16_controls[] = {
  582. &snd_sb16_ctl_master_play_vol,
  583. &snd_sb16_ctl_3d_enhance_switch,
  584. &snd_sb16_ctl_tone_bass,
  585. &snd_sb16_ctl_tone_treble,
  586. &snd_sb16_ctl_pcm_play_vol,
  587. &snd_sb16_ctl_synth_capture_route,
  588. &snd_sb16_ctl_synth_play_vol,
  589. &snd_sb16_ctl_cd_capture_route,
  590. &snd_sb16_ctl_cd_play_switch,
  591. &snd_sb16_ctl_cd_play_vol,
  592. &snd_sb16_ctl_line_capture_route,
  593. &snd_sb16_ctl_line_play_switch,
  594. &snd_sb16_ctl_line_play_vol,
  595. &snd_sb16_ctl_mic_capture_route,
  596. &snd_sb16_ctl_mic_play_switch,
  597. &snd_sb16_ctl_mic_play_vol,
  598. &snd_sb16_ctl_pc_speaker_vol,
  599. &snd_sb16_ctl_capture_vol,
  600. &snd_sb16_ctl_play_vol,
  601. &snd_sb16_ctl_auto_mic_gain
  602. };
  603. static unsigned char snd_sb16_init_values[][2] = {
  604. { SB_DSP4_MASTER_DEV + 0, 0 },
  605. { SB_DSP4_MASTER_DEV + 1, 0 },
  606. { SB_DSP4_PCM_DEV + 0, 0 },
  607. { SB_DSP4_PCM_DEV + 1, 0 },
  608. { SB_DSP4_SYNTH_DEV + 0, 0 },
  609. { SB_DSP4_SYNTH_DEV + 1, 0 },
  610. { SB_DSP4_INPUT_LEFT, 0 },
  611. { SB_DSP4_INPUT_RIGHT, 0 },
  612. { SB_DSP4_OUTPUT_SW, 0 },
  613. { SB_DSP4_SPEAKER_DEV, 0 },
  614. };
  615. /*
  616. * DT019x specific mixer elements
  617. */
  618. static struct sbmix_elem snd_dt019x_ctl_master_play_vol =
  619. SB_DOUBLE("Master Playback Volume", SB_DT019X_MASTER_DEV, SB_DT019X_MASTER_DEV, 4,0, 15);
  620. static struct sbmix_elem snd_dt019x_ctl_pcm_play_vol =
  621. SB_DOUBLE("PCM Playback Volume", SB_DT019X_PCM_DEV, SB_DT019X_PCM_DEV, 4,0, 15);
  622. static struct sbmix_elem snd_dt019x_ctl_synth_play_vol =
  623. SB_DOUBLE("Synth Playback Volume", SB_DT019X_SYNTH_DEV, SB_DT019X_SYNTH_DEV, 4,0, 15);
  624. static struct sbmix_elem snd_dt019x_ctl_cd_play_vol =
  625. SB_DOUBLE("CD Playback Volume", SB_DT019X_CD_DEV, SB_DT019X_CD_DEV, 4,0, 15);
  626. static struct sbmix_elem snd_dt019x_ctl_mic_play_vol =
  627. SB_SINGLE("Mic Playback Volume", SB_DT019X_MIC_DEV, 4, 7);
  628. static struct sbmix_elem snd_dt019x_ctl_pc_speaker_vol =
  629. SB_SINGLE("PC Speaker Volume", SB_DT019X_SPKR_DEV, 0, 7);
  630. static struct sbmix_elem snd_dt019x_ctl_line_play_vol =
  631. SB_DOUBLE("Line Playback Volume", SB_DT019X_LINE_DEV, SB_DT019X_LINE_DEV, 4,0, 15);
  632. static struct sbmix_elem snd_dt019x_ctl_pcm_play_switch =
  633. SB_DOUBLE("PCM Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2,1, 1);
  634. static struct sbmix_elem snd_dt019x_ctl_synth_play_switch =
  635. SB_DOUBLE("Synth Playback Switch", SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 4,3, 1);
  636. static struct sbmix_elem snd_dt019x_ctl_capture_source =
  637. {
  638. .name = "Capture Source",
  639. .type = SB_MIX_CAPTURE_DT019X
  640. };
  641. static struct sbmix_elem *snd_dt019x_controls[] = {
  642. /* ALS4000 below has some parts which we might be lacking,
  643. * e.g. snd_als4000_ctl_mono_playback_switch - check it! */
  644. &snd_dt019x_ctl_master_play_vol,
  645. &snd_dt019x_ctl_pcm_play_vol,
  646. &snd_dt019x_ctl_synth_play_vol,
  647. &snd_dt019x_ctl_cd_play_vol,
  648. &snd_dt019x_ctl_mic_play_vol,
  649. &snd_dt019x_ctl_pc_speaker_vol,
  650. &snd_dt019x_ctl_line_play_vol,
  651. &snd_sb16_ctl_mic_play_switch,
  652. &snd_sb16_ctl_cd_play_switch,
  653. &snd_sb16_ctl_line_play_switch,
  654. &snd_dt019x_ctl_pcm_play_switch,
  655. &snd_dt019x_ctl_synth_play_switch,
  656. &snd_dt019x_ctl_capture_source
  657. };
  658. static unsigned char snd_dt019x_init_values[][2] = {
  659. { SB_DT019X_MASTER_DEV, 0 },
  660. { SB_DT019X_PCM_DEV, 0 },
  661. { SB_DT019X_SYNTH_DEV, 0 },
  662. { SB_DT019X_CD_DEV, 0 },
  663. { SB_DT019X_MIC_DEV, 0 }, /* Includes PC-speaker in high nibble */
  664. { SB_DT019X_LINE_DEV, 0 },
  665. { SB_DSP4_OUTPUT_SW, 0 },
  666. { SB_DT019X_OUTPUT_SW2, 0 },
  667. { SB_DT019X_CAPTURE_SW, 0x06 },
  668. };
  669. /*
  670. * ALS4000 specific mixer elements
  671. */
  672. static struct sbmix_elem snd_als4000_ctl_master_mono_playback_switch =
  673. SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1);
  674. static struct sbmix_elem snd_als4k_ctl_master_mono_capture_route = {
  675. .name = "Master Mono Capture Route",
  676. .type = SB_MIX_MONO_CAPTURE_ALS4K
  677. };
  678. static struct sbmix_elem snd_als4000_ctl_mono_playback_switch =
  679. SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1);
  680. static struct sbmix_elem snd_als4000_ctl_mic_20db_boost =
  681. SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03);
  682. static struct sbmix_elem snd_als4000_ctl_mixer_analog_loopback =
  683. SB_SINGLE("Analog Loopback Switch", SB_ALS4000_MIC_IN_GAIN, 7, 0x01);
  684. static struct sbmix_elem snd_als4000_ctl_mixer_digital_loopback =
  685. SB_SINGLE("Digital Loopback Switch",
  686. SB_ALS4000_CR3_CONFIGURATION, 7, 0x01);
  687. /* FIXME: functionality of 3D controls might be swapped, I didn't find
  688. * a description of how to identify what is supposed to be what */
  689. static struct sbmix_elem snd_als4000_3d_control_switch =
  690. SB_SINGLE("3D Control - Switch", SB_ALS4000_3D_SND_FX, 6, 0x01);
  691. static struct sbmix_elem snd_als4000_3d_control_ratio =
  692. SB_SINGLE("3D Control - Level", SB_ALS4000_3D_SND_FX, 0, 0x07);
  693. static struct sbmix_elem snd_als4000_3d_control_freq =
  694. /* FIXME: maybe there's actually some standard 3D ctrl name for it?? */
  695. SB_SINGLE("3D Control - Freq", SB_ALS4000_3D_SND_FX, 4, 0x03);
  696. static struct sbmix_elem snd_als4000_3d_control_delay =
  697. /* FIXME: ALS4000a.pdf mentions BBD (Bucket Brigade Device) time delay,
  698. * but what ALSA 3D attribute is that actually? "Center", "Depth",
  699. * "Wide" or "Space" or even "Level"? Assuming "Wide" for now... */
  700. SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f);
  701. static struct sbmix_elem snd_als4000_3d_control_poweroff_switch =
  702. SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01);
  703. static struct sbmix_elem snd_als4000_ctl_3db_freq_control_switch =
  704. SB_SINGLE("Master Playback 8kHz / 20kHz LPF Switch",
  705. SB_ALS4000_FMDAC, 5, 0x01);
  706. #ifdef NOT_AVAILABLE
  707. static struct sbmix_elem snd_als4000_ctl_fmdac =
  708. SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01);
  709. static struct sbmix_elem snd_als4000_ctl_qsound =
  710. SB_SINGLE("QSound Mode", SB_ALS4000_QSOUND, 1, 0x1f);
  711. #endif
  712. static struct sbmix_elem *snd_als4000_controls[] = {
  713. /* ALS4000a.PDF regs page */
  714. &snd_sb16_ctl_master_play_vol, /* MX30/31 12 */
  715. &snd_dt019x_ctl_pcm_play_switch, /* MX4C 16 */
  716. &snd_sb16_ctl_pcm_play_vol, /* MX32/33 12 */
  717. &snd_sb16_ctl_synth_capture_route, /* MX3D/3E 14 */
  718. &snd_dt019x_ctl_synth_play_switch, /* MX4C 16 */
  719. &snd_sb16_ctl_synth_play_vol, /* MX34/35 12/13 */
  720. &snd_sb16_ctl_cd_capture_route, /* MX3D/3E 14 */
  721. &snd_sb16_ctl_cd_play_switch, /* MX3C 14 */
  722. &snd_sb16_ctl_cd_play_vol, /* MX36/37 13 */
  723. &snd_sb16_ctl_line_capture_route, /* MX3D/3E 14 */
  724. &snd_sb16_ctl_line_play_switch, /* MX3C 14 */
  725. &snd_sb16_ctl_line_play_vol, /* MX38/39 13 */
  726. &snd_sb16_ctl_mic_capture_route, /* MX3D/3E 14 */
  727. &snd_als4000_ctl_mic_20db_boost, /* MX4D 16 */
  728. &snd_sb16_ctl_mic_play_switch, /* MX3C 14 */
  729. &snd_sb16_ctl_mic_play_vol, /* MX3A 13 */
  730. &snd_sb16_ctl_pc_speaker_vol, /* MX3B 14 */
  731. &snd_sb16_ctl_capture_vol, /* MX3F/40 15 */
  732. &snd_sb16_ctl_play_vol, /* MX41/42 15 */
  733. &snd_als4000_ctl_master_mono_playback_switch, /* MX4C 16 */
  734. &snd_als4k_ctl_master_mono_capture_route, /* MX4B 16 */
  735. &snd_als4000_ctl_mono_playback_switch, /* MX4C 16 */
  736. &snd_als4000_ctl_mixer_analog_loopback, /* MX4D 16 */
  737. &snd_als4000_ctl_mixer_digital_loopback, /* CR3 21 */
  738. &snd_als4000_3d_control_switch, /* MX50 17 */
  739. &snd_als4000_3d_control_ratio, /* MX50 17 */
  740. &snd_als4000_3d_control_freq, /* MX50 17 */
  741. &snd_als4000_3d_control_delay, /* MX51 18 */
  742. &snd_als4000_3d_control_poweroff_switch, /* MX51 18 */
  743. &snd_als4000_ctl_3db_freq_control_switch, /* MX4F 17 */
  744. #ifdef NOT_AVAILABLE
  745. &snd_als4000_ctl_fmdac,
  746. &snd_als4000_ctl_qsound,
  747. #endif
  748. };
  749. static unsigned char snd_als4000_init_values[][2] = {
  750. { SB_DSP4_MASTER_DEV + 0, 0 },
  751. { SB_DSP4_MASTER_DEV + 1, 0 },
  752. { SB_DSP4_PCM_DEV + 0, 0 },
  753. { SB_DSP4_PCM_DEV + 1, 0 },
  754. { SB_DSP4_SYNTH_DEV + 0, 0 },
  755. { SB_DSP4_SYNTH_DEV + 1, 0 },
  756. { SB_DSP4_SPEAKER_DEV, 0 },
  757. { SB_DSP4_OUTPUT_SW, 0 },
  758. { SB_DSP4_INPUT_LEFT, 0 },
  759. { SB_DSP4_INPUT_RIGHT, 0 },
  760. { SB_DT019X_OUTPUT_SW2, 0 },
  761. { SB_ALS4000_MIC_IN_GAIN, 0 },
  762. };
  763. /*
  764. */
  765. static int snd_sbmixer_init(struct snd_sb *chip,
  766. struct sbmix_elem **controls,
  767. int controls_count,
  768. unsigned char map[][2],
  769. int map_count,
  770. char *name)
  771. {
  772. unsigned long flags;
  773. struct snd_card *card = chip->card;
  774. int idx, err;
  775. /* mixer reset */
  776. spin_lock_irqsave(&chip->mixer_lock, flags);
  777. snd_sbmixer_write(chip, 0x00, 0x00);
  778. spin_unlock_irqrestore(&chip->mixer_lock, flags);
  779. /* mute and zero volume channels */
  780. for (idx = 0; idx < map_count; idx++) {
  781. spin_lock_irqsave(&chip->mixer_lock, flags);
  782. snd_sbmixer_write(chip, map[idx][0], map[idx][1]);
  783. spin_unlock_irqrestore(&chip->mixer_lock, flags);
  784. }
  785. for (idx = 0; idx < controls_count; idx++) {
  786. if ((err = snd_sbmixer_add_ctl_elem(chip, controls[idx])) < 0)
  787. return err;
  788. }
  789. snd_component_add(card, name);
  790. strcpy(card->mixername, name);
  791. return 0;
  792. }
  793. int snd_sbmixer_new(struct snd_sb *chip)
  794. {
  795. struct snd_card *card;
  796. int err;
  797. if (snd_BUG_ON(!chip || !chip->card))
  798. return -EINVAL;
  799. card = chip->card;
  800. switch (chip->hardware) {
  801. case SB_HW_10:
  802. return 0; /* no mixer chip on SB1.x */
  803. case SB_HW_20:
  804. case SB_HW_201:
  805. if ((err = snd_sbmixer_init(chip,
  806. snd_sb20_controls,
  807. ARRAY_SIZE(snd_sb20_controls),
  808. snd_sb20_init_values,
  809. ARRAY_SIZE(snd_sb20_init_values),
  810. "CTL1335")) < 0)
  811. return err;
  812. break;
  813. case SB_HW_PRO:
  814. if ((err = snd_sbmixer_init(chip,
  815. snd_sbpro_controls,
  816. ARRAY_SIZE(snd_sbpro_controls),
  817. snd_sbpro_init_values,
  818. ARRAY_SIZE(snd_sbpro_init_values),
  819. "CTL1345")) < 0)
  820. return err;
  821. break;
  822. case SB_HW_16:
  823. case SB_HW_ALS100:
  824. case SB_HW_CS5530:
  825. if ((err = snd_sbmixer_init(chip,
  826. snd_sb16_controls,
  827. ARRAY_SIZE(snd_sb16_controls),
  828. snd_sb16_init_values,
  829. ARRAY_SIZE(snd_sb16_init_values),
  830. "CTL1745")) < 0)
  831. return err;
  832. break;
  833. case SB_HW_ALS4000:
  834. if ((err = snd_sbmixer_init(chip,
  835. snd_als4000_controls,
  836. ARRAY_SIZE(snd_als4000_controls),
  837. snd_als4000_init_values,
  838. ARRAY_SIZE(snd_als4000_init_values),
  839. "ALS4000")) < 0)
  840. return err;
  841. break;
  842. case SB_HW_DT019X:
  843. if ((err = snd_sbmixer_init(chip,
  844. snd_dt019x_controls,
  845. ARRAY_SIZE(snd_dt019x_controls),
  846. snd_dt019x_init_values,
  847. ARRAY_SIZE(snd_dt019x_init_values),
  848. "DT019X")) < 0)
  849. break;
  850. default:
  851. strcpy(card->mixername, "???");
  852. }
  853. return 0;
  854. }
  855. #ifdef CONFIG_PM
  856. static unsigned char sb20_saved_regs[] = {
  857. SB_DSP20_MASTER_DEV,
  858. SB_DSP20_PCM_DEV,
  859. SB_DSP20_FM_DEV,
  860. SB_DSP20_CD_DEV,
  861. };
  862. static unsigned char sbpro_saved_regs[] = {
  863. SB_DSP_MASTER_DEV,
  864. SB_DSP_PCM_DEV,
  865. SB_DSP_PLAYBACK_FILT,
  866. SB_DSP_FM_DEV,
  867. SB_DSP_CD_DEV,
  868. SB_DSP_LINE_DEV,
  869. SB_DSP_MIC_DEV,
  870. SB_DSP_CAPTURE_SOURCE,
  871. SB_DSP_CAPTURE_FILT,
  872. };
  873. static unsigned char sb16_saved_regs[] = {
  874. SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
  875. SB_DSP4_3DSE,
  876. SB_DSP4_BASS_DEV, SB_DSP4_BASS_DEV + 1,
  877. SB_DSP4_TREBLE_DEV, SB_DSP4_TREBLE_DEV + 1,
  878. SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
  879. SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
  880. SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
  881. SB_DSP4_OUTPUT_SW,
  882. SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
  883. SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1,
  884. SB_DSP4_MIC_DEV,
  885. SB_DSP4_SPEAKER_DEV,
  886. SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
  887. SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1,
  888. SB_DSP4_MIC_AGC
  889. };
  890. static unsigned char dt019x_saved_regs[] = {
  891. SB_DT019X_MASTER_DEV,
  892. SB_DT019X_PCM_DEV,
  893. SB_DT019X_SYNTH_DEV,
  894. SB_DT019X_CD_DEV,
  895. SB_DT019X_MIC_DEV,
  896. SB_DT019X_SPKR_DEV,
  897. SB_DT019X_LINE_DEV,
  898. SB_DSP4_OUTPUT_SW,
  899. SB_DT019X_OUTPUT_SW2,
  900. SB_DT019X_CAPTURE_SW,
  901. };
  902. static unsigned char als4000_saved_regs[] = {
  903. /* please verify in dsheet whether regs to be added
  904. are actually real H/W or just dummy */
  905. SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
  906. SB_DSP4_OUTPUT_SW,
  907. SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
  908. SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
  909. SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
  910. SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
  911. SB_DSP4_MIC_DEV,
  912. SB_DSP4_SPEAKER_DEV,
  913. SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
  914. SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1,
  915. SB_DT019X_OUTPUT_SW2,
  916. SB_ALS4000_MONO_IO_CTRL,
  917. SB_ALS4000_MIC_IN_GAIN,
  918. SB_ALS4000_FMDAC,
  919. SB_ALS4000_3D_SND_FX,
  920. SB_ALS4000_3D_TIME_DELAY,
  921. SB_ALS4000_CR3_CONFIGURATION,
  922. };
  923. static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
  924. {
  925. unsigned char *val = chip->saved_regs;
  926. if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
  927. return;
  928. for (; num_regs; num_regs--)
  929. *val++ = snd_sbmixer_read(chip, *regs++);
  930. }
  931. static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
  932. {
  933. unsigned char *val = chip->saved_regs;
  934. if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
  935. return;
  936. for (; num_regs; num_regs--)
  937. snd_sbmixer_write(chip, *regs++, *val++);
  938. }
  939. void snd_sbmixer_suspend(struct snd_sb *chip)
  940. {
  941. switch (chip->hardware) {
  942. case SB_HW_20:
  943. case SB_HW_201:
  944. save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
  945. break;
  946. case SB_HW_PRO:
  947. save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
  948. break;
  949. case SB_HW_16:
  950. case SB_HW_ALS100:
  951. case SB_HW_CS5530:
  952. save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
  953. break;
  954. case SB_HW_ALS4000:
  955. save_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs));
  956. break;
  957. case SB_HW_DT019X:
  958. save_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs));
  959. break;
  960. default:
  961. break;
  962. }
  963. }
  964. void snd_sbmixer_resume(struct snd_sb *chip)
  965. {
  966. switch (chip->hardware) {
  967. case SB_HW_20:
  968. case SB_HW_201:
  969. restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
  970. break;
  971. case SB_HW_PRO:
  972. restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
  973. break;
  974. case SB_HW_16:
  975. case SB_HW_ALS100:
  976. case SB_HW_CS5530:
  977. restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
  978. break;
  979. case SB_HW_ALS4000:
  980. restore_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs));
  981. break;
  982. case SB_HW_DT019X:
  983. restore_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs));
  984. break;
  985. default:
  986. break;
  987. }
  988. }
  989. #endif