cs4236_lib.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. /*
  2. * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  3. * Routines for control of CS4235/4236B/4237B/4238B/4239 chips
  4. *
  5. * Note:
  6. * -----
  7. *
  8. * Bugs:
  9. * -----
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. *
  25. */
  26. /*
  27. * Indirect control registers (CS4236B+)
  28. *
  29. * C0
  30. * D8: WSS reset (all chips)
  31. *
  32. * C1 (all chips except CS4236)
  33. * D7-D5: version
  34. * D4-D0: chip id
  35. * 11101 - CS4235
  36. * 01011 - CS4236B
  37. * 01000 - CS4237B
  38. * 01001 - CS4238B
  39. * 11110 - CS4239
  40. *
  41. * C2
  42. * D7-D4: 3D Space (CS4235,CS4237B,CS4238B,CS4239)
  43. * D3-D0: 3D Center (CS4237B); 3D Volume (CS4238B)
  44. *
  45. * C3
  46. * D7: 3D Enable (CS4237B)
  47. * D6: 3D Mono Enable (CS4237B)
  48. * D5: 3D Serial Output (CS4237B,CS4238B)
  49. * D4: 3D Enable (CS4235,CS4238B,CS4239)
  50. *
  51. * C4
  52. * D7: consumer serial port enable (CS4237B,CS4238B)
  53. * D6: channels status block reset (CS4237B,CS4238B)
  54. * D5: user bit in sub-frame of digital audio data (CS4237B,CS4238B)
  55. * D4: validity bit bit in sub-frame of digital audio data (CS4237B,CS4238B)
  56. *
  57. * C5 lower channel status (digital serial data description) (CS4237B,CS4238B)
  58. * D7-D6: first two bits of category code
  59. * D5: lock
  60. * D4-D3: pre-emphasis (0 = none, 1 = 50/15us)
  61. * D2: copy/copyright (0 = copy inhibited)
  62. * D1: 0 = digital audio / 1 = non-digital audio
  63. *
  64. * C6 upper channel status (digital serial data description) (CS4237B,CS4238B)
  65. * D7-D6: sample frequency (0 = 44.1kHz)
  66. * D5: generation status (0 = no indication, 1 = original/commercially precaptureed data)
  67. * D4-D0: category code (upper bits)
  68. *
  69. * C7 reserved (must write 0)
  70. *
  71. * C8 wavetable control
  72. * D7: volume control interrupt enable (CS4235,CS4239)
  73. * D6: hardware volume control format (CS4235,CS4239)
  74. * D3: wavetable serial port enable (all chips)
  75. * D2: DSP serial port switch (all chips)
  76. * D1: disable MCLK (all chips)
  77. * D0: force BRESET low (all chips)
  78. *
  79. */
  80. #include <linux/io.h>
  81. #include <linux/delay.h>
  82. #include <linux/init.h>
  83. #include <linux/time.h>
  84. #include <linux/wait.h>
  85. #include <sound/core.h>
  86. #include <sound/wss.h>
  87. #include <sound/asoundef.h>
  88. #include <sound/initval.h>
  89. #include <sound/tlv.h>
  90. /*
  91. *
  92. */
  93. static unsigned char snd_cs4236_ext_map[18] = {
  94. /* CS4236_LEFT_LINE */ 0xff,
  95. /* CS4236_RIGHT_LINE */ 0xff,
  96. /* CS4236_LEFT_MIC */ 0xdf,
  97. /* CS4236_RIGHT_MIC */ 0xdf,
  98. /* CS4236_LEFT_MIX_CTRL */ 0xe0 | 0x18,
  99. /* CS4236_RIGHT_MIX_CTRL */ 0xe0,
  100. /* CS4236_LEFT_FM */ 0xbf,
  101. /* CS4236_RIGHT_FM */ 0xbf,
  102. /* CS4236_LEFT_DSP */ 0xbf,
  103. /* CS4236_RIGHT_DSP */ 0xbf,
  104. /* CS4236_RIGHT_LOOPBACK */ 0xbf,
  105. /* CS4236_DAC_MUTE */ 0xe0,
  106. /* CS4236_ADC_RATE */ 0x01, /* 48kHz */
  107. /* CS4236_DAC_RATE */ 0x01, /* 48kHz */
  108. /* CS4236_LEFT_MASTER */ 0xbf,
  109. /* CS4236_RIGHT_MASTER */ 0xbf,
  110. /* CS4236_LEFT_WAVE */ 0xbf,
  111. /* CS4236_RIGHT_WAVE */ 0xbf
  112. };
  113. /*
  114. *
  115. */
  116. static void snd_cs4236_ctrl_out(struct snd_wss *chip,
  117. unsigned char reg, unsigned char val)
  118. {
  119. outb(reg, chip->cport + 3);
  120. outb(chip->cimage[reg] = val, chip->cport + 4);
  121. }
  122. static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg)
  123. {
  124. outb(reg, chip->cport + 3);
  125. return inb(chip->cport + 4);
  126. }
  127. /*
  128. * PCM
  129. */
  130. #define CLOCKS 8
  131. static struct snd_ratnum clocks[CLOCKS] = {
  132. { .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 },
  133. { .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 },
  134. { .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 },
  135. { .num = 16934400, .den_min = 1058, .den_max = 1058, .den_step = 1 },
  136. { .num = 16934400, .den_min = 1764, .den_max = 1764, .den_step = 1 },
  137. { .num = 16934400, .den_min = 2117, .den_max = 2117, .den_step = 1 },
  138. { .num = 16934400, .den_min = 2558, .den_max = 2558, .den_step = 1 },
  139. { .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 }
  140. };
  141. static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = {
  142. .nrats = CLOCKS,
  143. .rats = clocks,
  144. };
  145. static int snd_cs4236_xrate(struct snd_pcm_runtime *runtime)
  146. {
  147. return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
  148. &hw_constraints_clocks);
  149. }
  150. static unsigned char divisor_to_rate_register(unsigned int divisor)
  151. {
  152. switch (divisor) {
  153. case 353: return 1;
  154. case 529: return 2;
  155. case 617: return 3;
  156. case 1058: return 4;
  157. case 1764: return 5;
  158. case 2117: return 6;
  159. case 2558: return 7;
  160. default:
  161. if (divisor < 21 || divisor > 192) {
  162. snd_BUG();
  163. return 192;
  164. }
  165. return divisor;
  166. }
  167. }
  168. static void snd_cs4236_playback_format(struct snd_wss *chip,
  169. struct snd_pcm_hw_params *params,
  170. unsigned char pdfr)
  171. {
  172. unsigned long flags;
  173. unsigned char rate = divisor_to_rate_register(params->rate_den);
  174. spin_lock_irqsave(&chip->reg_lock, flags);
  175. /* set fast playback format change and clean playback FIFO */
  176. snd_wss_out(chip, CS4231_ALT_FEATURE_1,
  177. chip->image[CS4231_ALT_FEATURE_1] | 0x10);
  178. snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr & 0xf0);
  179. snd_wss_out(chip, CS4231_ALT_FEATURE_1,
  180. chip->image[CS4231_ALT_FEATURE_1] & ~0x10);
  181. snd_cs4236_ext_out(chip, CS4236_DAC_RATE, rate);
  182. spin_unlock_irqrestore(&chip->reg_lock, flags);
  183. }
  184. static void snd_cs4236_capture_format(struct snd_wss *chip,
  185. struct snd_pcm_hw_params *params,
  186. unsigned char cdfr)
  187. {
  188. unsigned long flags;
  189. unsigned char rate = divisor_to_rate_register(params->rate_den);
  190. spin_lock_irqsave(&chip->reg_lock, flags);
  191. /* set fast capture format change and clean capture FIFO */
  192. snd_wss_out(chip, CS4231_ALT_FEATURE_1,
  193. chip->image[CS4231_ALT_FEATURE_1] | 0x20);
  194. snd_wss_out(chip, CS4231_REC_FORMAT, cdfr & 0xf0);
  195. snd_wss_out(chip, CS4231_ALT_FEATURE_1,
  196. chip->image[CS4231_ALT_FEATURE_1] & ~0x20);
  197. snd_cs4236_ext_out(chip, CS4236_ADC_RATE, rate);
  198. spin_unlock_irqrestore(&chip->reg_lock, flags);
  199. }
  200. #ifdef CONFIG_PM
  201. static void snd_cs4236_suspend(struct snd_wss *chip)
  202. {
  203. int reg;
  204. unsigned long flags;
  205. spin_lock_irqsave(&chip->reg_lock, flags);
  206. for (reg = 0; reg < 32; reg++)
  207. chip->image[reg] = snd_wss_in(chip, reg);
  208. for (reg = 0; reg < 18; reg++)
  209. chip->eimage[reg] = snd_cs4236_ext_in(chip, CS4236_I23VAL(reg));
  210. for (reg = 2; reg < 9; reg++)
  211. chip->cimage[reg] = snd_cs4236_ctrl_in(chip, reg);
  212. spin_unlock_irqrestore(&chip->reg_lock, flags);
  213. }
  214. static void snd_cs4236_resume(struct snd_wss *chip)
  215. {
  216. int reg;
  217. unsigned long flags;
  218. snd_wss_mce_up(chip);
  219. spin_lock_irqsave(&chip->reg_lock, flags);
  220. for (reg = 0; reg < 32; reg++) {
  221. switch (reg) {
  222. case CS4236_EXT_REG:
  223. case CS4231_VERSION:
  224. case 27: /* why? CS4235 - master left */
  225. case 29: /* why? CS4235 - master right */
  226. break;
  227. default:
  228. snd_wss_out(chip, reg, chip->image[reg]);
  229. break;
  230. }
  231. }
  232. for (reg = 0; reg < 18; reg++)
  233. snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), chip->eimage[reg]);
  234. for (reg = 2; reg < 9; reg++) {
  235. switch (reg) {
  236. case 7:
  237. break;
  238. default:
  239. snd_cs4236_ctrl_out(chip, reg, chip->cimage[reg]);
  240. }
  241. }
  242. spin_unlock_irqrestore(&chip->reg_lock, flags);
  243. snd_wss_mce_down(chip);
  244. }
  245. #endif /* CONFIG_PM */
  246. /*
  247. * This function does no fail if the chip is not CS4236B or compatible.
  248. * It just an equivalent to the snd_wss_create() then.
  249. */
  250. int snd_cs4236_create(struct snd_card *card,
  251. unsigned long port,
  252. unsigned long cport,
  253. int irq, int dma1, int dma2,
  254. unsigned short hardware,
  255. unsigned short hwshare,
  256. struct snd_wss **rchip)
  257. {
  258. struct snd_wss *chip;
  259. unsigned char ver1, ver2;
  260. unsigned int reg;
  261. int err;
  262. *rchip = NULL;
  263. if (hardware == WSS_HW_DETECT)
  264. hardware = WSS_HW_DETECT3;
  265. err = snd_wss_create(card, port, cport,
  266. irq, dma1, dma2, hardware, hwshare, &chip);
  267. if (err < 0)
  268. return err;
  269. if ((chip->hardware & WSS_HW_CS4236B_MASK) == 0) {
  270. snd_printd("chip is not CS4236+, hardware=0x%x\n",
  271. chip->hardware);
  272. *rchip = chip;
  273. return 0;
  274. }
  275. #if 0
  276. {
  277. int idx;
  278. for (idx = 0; idx < 8; idx++)
  279. snd_printk(KERN_DEBUG "CD%i = 0x%x\n",
  280. idx, inb(chip->cport + idx));
  281. for (idx = 0; idx < 9; idx++)
  282. snd_printk(KERN_DEBUG "C%i = 0x%x\n",
  283. idx, snd_cs4236_ctrl_in(chip, idx));
  284. }
  285. #endif
  286. if (cport < 0x100 || cport == SNDRV_AUTO_PORT) {
  287. snd_printk(KERN_ERR "please, specify control port "
  288. "for CS4236+ chips\n");
  289. snd_device_free(card, chip);
  290. return -ENODEV;
  291. }
  292. ver1 = snd_cs4236_ctrl_in(chip, 1);
  293. ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION);
  294. snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n",
  295. cport, ver1, ver2);
  296. if (ver1 != ver2) {
  297. snd_printk(KERN_ERR "CS4236+ chip detected, but "
  298. "control port 0x%lx is not valid\n", cport);
  299. snd_device_free(card, chip);
  300. return -ENODEV;
  301. }
  302. snd_cs4236_ctrl_out(chip, 0, 0x00);
  303. snd_cs4236_ctrl_out(chip, 2, 0xff);
  304. snd_cs4236_ctrl_out(chip, 3, 0x00);
  305. snd_cs4236_ctrl_out(chip, 4, 0x80);
  306. reg = ((IEC958_AES1_CON_PCM_CODER & 3) << 6) |
  307. IEC958_AES0_CON_EMPHASIS_NONE;
  308. snd_cs4236_ctrl_out(chip, 5, reg);
  309. snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2);
  310. snd_cs4236_ctrl_out(chip, 7, 0x00);
  311. /*
  312. * 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958
  313. * output is working with this setup, other hardware should
  314. * have different signal paths and this value should be
  315. * selectable in the future
  316. */
  317. snd_cs4236_ctrl_out(chip, 8, 0x8c);
  318. chip->rate_constraint = snd_cs4236_xrate;
  319. chip->set_playback_format = snd_cs4236_playback_format;
  320. chip->set_capture_format = snd_cs4236_capture_format;
  321. #ifdef CONFIG_PM
  322. chip->suspend = snd_cs4236_suspend;
  323. chip->resume = snd_cs4236_resume;
  324. #endif
  325. /* initialize extended registers */
  326. for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++)
  327. snd_cs4236_ext_out(chip, CS4236_I23VAL(reg),
  328. snd_cs4236_ext_map[reg]);
  329. /* initialize compatible but more featured registers */
  330. snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40);
  331. snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40);
  332. snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
  333. snd_wss_out(chip, CS4231_AUX1_RIGHT_INPUT, 0xff);
  334. snd_wss_out(chip, CS4231_AUX2_LEFT_INPUT, 0xdf);
  335. snd_wss_out(chip, CS4231_AUX2_RIGHT_INPUT, 0xdf);
  336. snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
  337. snd_wss_out(chip, CS4231_LEFT_LINE_IN, 0xff);
  338. snd_wss_out(chip, CS4231_RIGHT_LINE_IN, 0xff);
  339. switch (chip->hardware) {
  340. case WSS_HW_CS4235:
  341. case WSS_HW_CS4239:
  342. snd_wss_out(chip, CS4235_LEFT_MASTER, 0xff);
  343. snd_wss_out(chip, CS4235_RIGHT_MASTER, 0xff);
  344. break;
  345. }
  346. *rchip = chip;
  347. return 0;
  348. }
  349. int snd_cs4236_pcm(struct snd_wss *chip, int device)
  350. {
  351. int err;
  352. err = snd_wss_pcm(chip, device);
  353. if (err < 0)
  354. return err;
  355. chip->pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX;
  356. return 0;
  357. }
  358. /*
  359. * MIXER
  360. */
  361. #define CS4236_SINGLE(xname, xindex, reg, shift, mask, invert) \
  362. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  363. .info = snd_cs4236_info_single, \
  364. .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
  365. .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
  366. #define CS4236_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
  367. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  368. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  369. .info = snd_cs4236_info_single, \
  370. .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
  371. .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
  372. .tlv = { .p = (xtlv) } }
  373. static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  374. {
  375. int mask = (kcontrol->private_value >> 16) & 0xff;
  376. uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
  377. uinfo->count = 1;
  378. uinfo->value.integer.min = 0;
  379. uinfo->value.integer.max = mask;
  380. return 0;
  381. }
  382. static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  383. {
  384. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  385. unsigned long flags;
  386. int reg = kcontrol->private_value & 0xff;
  387. int shift = (kcontrol->private_value >> 8) & 0xff;
  388. int mask = (kcontrol->private_value >> 16) & 0xff;
  389. int invert = (kcontrol->private_value >> 24) & 0xff;
  390. spin_lock_irqsave(&chip->reg_lock, flags);
  391. ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(reg)] >> shift) & mask;
  392. spin_unlock_irqrestore(&chip->reg_lock, flags);
  393. if (invert)
  394. ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
  395. return 0;
  396. }
  397. static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  398. {
  399. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  400. unsigned long flags;
  401. int reg = kcontrol->private_value & 0xff;
  402. int shift = (kcontrol->private_value >> 8) & 0xff;
  403. int mask = (kcontrol->private_value >> 16) & 0xff;
  404. int invert = (kcontrol->private_value >> 24) & 0xff;
  405. int change;
  406. unsigned short val;
  407. val = (ucontrol->value.integer.value[0] & mask);
  408. if (invert)
  409. val = mask - val;
  410. val <<= shift;
  411. spin_lock_irqsave(&chip->reg_lock, flags);
  412. val = (chip->eimage[CS4236_REG(reg)] & ~(mask << shift)) | val;
  413. change = val != chip->eimage[CS4236_REG(reg)];
  414. snd_cs4236_ext_out(chip, reg, val);
  415. spin_unlock_irqrestore(&chip->reg_lock, flags);
  416. return change;
  417. }
  418. #define CS4236_SINGLEC(xname, xindex, reg, shift, mask, invert) \
  419. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  420. .info = snd_cs4236_info_single, \
  421. .get = snd_cs4236_get_singlec, .put = snd_cs4236_put_singlec, \
  422. .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
  423. static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  424. {
  425. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  426. unsigned long flags;
  427. int reg = kcontrol->private_value & 0xff;
  428. int shift = (kcontrol->private_value >> 8) & 0xff;
  429. int mask = (kcontrol->private_value >> 16) & 0xff;
  430. int invert = (kcontrol->private_value >> 24) & 0xff;
  431. spin_lock_irqsave(&chip->reg_lock, flags);
  432. ucontrol->value.integer.value[0] = (chip->cimage[reg] >> shift) & mask;
  433. spin_unlock_irqrestore(&chip->reg_lock, flags);
  434. if (invert)
  435. ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
  436. return 0;
  437. }
  438. static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  439. {
  440. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  441. unsigned long flags;
  442. int reg = kcontrol->private_value & 0xff;
  443. int shift = (kcontrol->private_value >> 8) & 0xff;
  444. int mask = (kcontrol->private_value >> 16) & 0xff;
  445. int invert = (kcontrol->private_value >> 24) & 0xff;
  446. int change;
  447. unsigned short val;
  448. val = (ucontrol->value.integer.value[0] & mask);
  449. if (invert)
  450. val = mask - val;
  451. val <<= shift;
  452. spin_lock_irqsave(&chip->reg_lock, flags);
  453. val = (chip->cimage[reg] & ~(mask << shift)) | val;
  454. change = val != chip->cimage[reg];
  455. snd_cs4236_ctrl_out(chip, reg, val);
  456. spin_unlock_irqrestore(&chip->reg_lock, flags);
  457. return change;
  458. }
  459. #define CS4236_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
  460. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  461. .info = snd_cs4236_info_double, \
  462. .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
  463. .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
  464. #define CS4236_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, \
  465. shift_right, mask, invert, xtlv) \
  466. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  467. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  468. .info = snd_cs4236_info_double, \
  469. .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
  470. .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
  471. (shift_right << 19) | (mask << 24) | (invert << 22), \
  472. .tlv = { .p = (xtlv) } }
  473. static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  474. {
  475. int mask = (kcontrol->private_value >> 24) & 0xff;
  476. uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
  477. uinfo->count = 2;
  478. uinfo->value.integer.min = 0;
  479. uinfo->value.integer.max = mask;
  480. return 0;
  481. }
  482. static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  483. {
  484. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  485. unsigned long flags;
  486. int left_reg = kcontrol->private_value & 0xff;
  487. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  488. int shift_left = (kcontrol->private_value >> 16) & 0x07;
  489. int shift_right = (kcontrol->private_value >> 19) & 0x07;
  490. int mask = (kcontrol->private_value >> 24) & 0xff;
  491. int invert = (kcontrol->private_value >> 22) & 1;
  492. spin_lock_irqsave(&chip->reg_lock, flags);
  493. ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(left_reg)] >> shift_left) & mask;
  494. ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask;
  495. spin_unlock_irqrestore(&chip->reg_lock, flags);
  496. if (invert) {
  497. ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
  498. ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
  499. }
  500. return 0;
  501. }
  502. static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  503. {
  504. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  505. unsigned long flags;
  506. int left_reg = kcontrol->private_value & 0xff;
  507. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  508. int shift_left = (kcontrol->private_value >> 16) & 0x07;
  509. int shift_right = (kcontrol->private_value >> 19) & 0x07;
  510. int mask = (kcontrol->private_value >> 24) & 0xff;
  511. int invert = (kcontrol->private_value >> 22) & 1;
  512. int change;
  513. unsigned short val1, val2;
  514. val1 = ucontrol->value.integer.value[0] & mask;
  515. val2 = ucontrol->value.integer.value[1] & mask;
  516. if (invert) {
  517. val1 = mask - val1;
  518. val2 = mask - val2;
  519. }
  520. val1 <<= shift_left;
  521. val2 <<= shift_right;
  522. spin_lock_irqsave(&chip->reg_lock, flags);
  523. if (left_reg != right_reg) {
  524. val1 = (chip->eimage[CS4236_REG(left_reg)] & ~(mask << shift_left)) | val1;
  525. val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
  526. change = val1 != chip->eimage[CS4236_REG(left_reg)] || val2 != chip->eimage[CS4236_REG(right_reg)];
  527. snd_cs4236_ext_out(chip, left_reg, val1);
  528. snd_cs4236_ext_out(chip, right_reg, val2);
  529. } else {
  530. val1 = (chip->eimage[CS4236_REG(left_reg)] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
  531. change = val1 != chip->eimage[CS4236_REG(left_reg)];
  532. snd_cs4236_ext_out(chip, left_reg, val1);
  533. }
  534. spin_unlock_irqrestore(&chip->reg_lock, flags);
  535. return change;
  536. }
  537. #define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, \
  538. shift_right, mask, invert) \
  539. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  540. .info = snd_cs4236_info_double, \
  541. .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
  542. .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
  543. #define CS4236_DOUBLE1_TLV(xname, xindex, left_reg, right_reg, shift_left, \
  544. shift_right, mask, invert, xtlv) \
  545. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  546. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  547. .info = snd_cs4236_info_double, \
  548. .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
  549. .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
  550. (shift_right << 19) | (mask << 24) | (invert << 22), \
  551. .tlv = { .p = (xtlv) } }
  552. static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  553. {
  554. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  555. unsigned long flags;
  556. int left_reg = kcontrol->private_value & 0xff;
  557. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  558. int shift_left = (kcontrol->private_value >> 16) & 0x07;
  559. int shift_right = (kcontrol->private_value >> 19) & 0x07;
  560. int mask = (kcontrol->private_value >> 24) & 0xff;
  561. int invert = (kcontrol->private_value >> 22) & 1;
  562. spin_lock_irqsave(&chip->reg_lock, flags);
  563. ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
  564. ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask;
  565. spin_unlock_irqrestore(&chip->reg_lock, flags);
  566. if (invert) {
  567. ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
  568. ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
  569. }
  570. return 0;
  571. }
  572. static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  573. {
  574. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  575. unsigned long flags;
  576. int left_reg = kcontrol->private_value & 0xff;
  577. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  578. int shift_left = (kcontrol->private_value >> 16) & 0x07;
  579. int shift_right = (kcontrol->private_value >> 19) & 0x07;
  580. int mask = (kcontrol->private_value >> 24) & 0xff;
  581. int invert = (kcontrol->private_value >> 22) & 1;
  582. int change;
  583. unsigned short val1, val2;
  584. val1 = ucontrol->value.integer.value[0] & mask;
  585. val2 = ucontrol->value.integer.value[1] & mask;
  586. if (invert) {
  587. val1 = mask - val1;
  588. val2 = mask - val2;
  589. }
  590. val1 <<= shift_left;
  591. val2 <<= shift_right;
  592. spin_lock_irqsave(&chip->reg_lock, flags);
  593. val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
  594. val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
  595. change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)];
  596. snd_wss_out(chip, left_reg, val1);
  597. snd_cs4236_ext_out(chip, right_reg, val2);
  598. spin_unlock_irqrestore(&chip->reg_lock, flags);
  599. return change;
  600. }
  601. #define CS4236_MASTER_DIGITAL(xname, xindex, xtlv) \
  602. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  603. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  604. .info = snd_cs4236_info_double, \
  605. .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \
  606. .private_value = 71 << 24, \
  607. .tlv = { .p = (xtlv) } }
  608. static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
  609. {
  610. return (vol < 64) ? 63 - vol : 64 + (71 - vol);
  611. }
  612. static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  613. {
  614. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  615. unsigned long flags;
  616. spin_lock_irqsave(&chip->reg_lock, flags);
  617. ucontrol->value.integer.value[0] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & 0x7f);
  618. ucontrol->value.integer.value[1] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & 0x7f);
  619. spin_unlock_irqrestore(&chip->reg_lock, flags);
  620. return 0;
  621. }
  622. static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  623. {
  624. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  625. unsigned long flags;
  626. int change;
  627. unsigned short val1, val2;
  628. val1 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[0] & 0x7f);
  629. val2 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[1] & 0x7f);
  630. spin_lock_irqsave(&chip->reg_lock, flags);
  631. val1 = (chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & ~0x7f) | val1;
  632. val2 = (chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & ~0x7f) | val2;
  633. change = val1 != chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] || val2 != chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)];
  634. snd_cs4236_ext_out(chip, CS4236_LEFT_MASTER, val1);
  635. snd_cs4236_ext_out(chip, CS4236_RIGHT_MASTER, val2);
  636. spin_unlock_irqrestore(&chip->reg_lock, flags);
  637. return change;
  638. }
  639. #define CS4235_OUTPUT_ACCU(xname, xindex, xtlv) \
  640. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  641. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  642. .info = snd_cs4236_info_double, \
  643. .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \
  644. .private_value = 3 << 24, \
  645. .tlv = { .p = (xtlv) } }
  646. static inline int snd_cs4235_mixer_output_accu_get_volume(int vol)
  647. {
  648. switch ((vol >> 5) & 3) {
  649. case 0: return 1;
  650. case 1: return 3;
  651. case 2: return 2;
  652. case 3: return 0;
  653. }
  654. return 3;
  655. }
  656. static inline int snd_cs4235_mixer_output_accu_set_volume(int vol)
  657. {
  658. switch (vol & 3) {
  659. case 0: return 3 << 5;
  660. case 1: return 0 << 5;
  661. case 2: return 2 << 5;
  662. case 3: return 1 << 5;
  663. }
  664. return 1 << 5;
  665. }
  666. static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  667. {
  668. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  669. unsigned long flags;
  670. spin_lock_irqsave(&chip->reg_lock, flags);
  671. ucontrol->value.integer.value[0] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_LEFT_MASTER]);
  672. ucontrol->value.integer.value[1] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_RIGHT_MASTER]);
  673. spin_unlock_irqrestore(&chip->reg_lock, flags);
  674. return 0;
  675. }
  676. static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  677. {
  678. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  679. unsigned long flags;
  680. int change;
  681. unsigned short val1, val2;
  682. val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]);
  683. val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]);
  684. spin_lock_irqsave(&chip->reg_lock, flags);
  685. val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1;
  686. val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2;
  687. change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER];
  688. snd_wss_out(chip, CS4235_LEFT_MASTER, val1);
  689. snd_wss_out(chip, CS4235_RIGHT_MASTER, val2);
  690. spin_unlock_irqrestore(&chip->reg_lock, flags);
  691. return change;
  692. }
  693. static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -9450, 150, 0);
  694. static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
  695. static const DECLARE_TLV_DB_SCALE(db_scale_6bit_12db_max, -8250, 150, 0);
  696. static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
  697. static const DECLARE_TLV_DB_SCALE(db_scale_5bit_22db_max, -2400, 150, 0);
  698. static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
  699. static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0);
  700. static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
  701. static struct snd_kcontrol_new snd_cs4236_controls[] = {
  702. CS4236_DOUBLE("Master Digital Playback Switch", 0,
  703. CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
  704. CS4236_DOUBLE("Master Digital Capture Switch", 0,
  705. CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
  706. CS4236_MASTER_DIGITAL("Master Digital Volume", 0, db_scale_7bit),
  707. CS4236_DOUBLE_TLV("Capture Boost Volume", 0,
  708. CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
  709. db_scale_2bit),
  710. WSS_DOUBLE("PCM Playback Switch", 0,
  711. CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
  712. WSS_DOUBLE_TLV("PCM Playback Volume", 0,
  713. CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
  714. db_scale_6bit),
  715. CS4236_DOUBLE("DSP Playback Switch", 0,
  716. CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
  717. CS4236_DOUBLE_TLV("DSP Playback Volume", 0,
  718. CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1,
  719. db_scale_6bit),
  720. CS4236_DOUBLE("FM Playback Switch", 0,
  721. CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
  722. CS4236_DOUBLE_TLV("FM Playback Volume", 0,
  723. CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1,
  724. db_scale_6bit),
  725. CS4236_DOUBLE("Wavetable Playback Switch", 0,
  726. CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
  727. CS4236_DOUBLE_TLV("Wavetable Playback Volume", 0,
  728. CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1,
  729. db_scale_6bit_12db_max),
  730. WSS_DOUBLE("Synth Playback Switch", 0,
  731. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
  732. WSS_DOUBLE_TLV("Synth Volume", 0,
  733. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
  734. db_scale_5bit_12db_max),
  735. WSS_DOUBLE("Synth Capture Switch", 0,
  736. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
  737. WSS_DOUBLE("Synth Capture Bypass", 0,
  738. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1),
  739. CS4236_DOUBLE("Mic Playback Switch", 0,
  740. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
  741. CS4236_DOUBLE("Mic Capture Switch", 0,
  742. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
  743. CS4236_DOUBLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC,
  744. 0, 0, 31, 1, db_scale_5bit_22db_max),
  745. CS4236_DOUBLE("Mic Playback Boost (+20dB)", 0,
  746. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
  747. WSS_DOUBLE("Line Playback Switch", 0,
  748. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
  749. WSS_DOUBLE_TLV("Line Volume", 0,
  750. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
  751. db_scale_5bit_12db_max),
  752. WSS_DOUBLE("Line Capture Switch", 0,
  753. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
  754. WSS_DOUBLE("Line Capture Bypass", 0,
  755. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1),
  756. WSS_DOUBLE("CD Playback Switch", 0,
  757. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
  758. WSS_DOUBLE_TLV("CD Volume", 0,
  759. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
  760. db_scale_5bit_12db_max),
  761. WSS_DOUBLE("CD Capture Switch", 0,
  762. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
  763. CS4236_DOUBLE1("Mono Output Playback Switch", 0,
  764. CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
  765. CS4236_DOUBLE1("Beep Playback Switch", 0,
  766. CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
  767. WSS_SINGLE_TLV("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1,
  768. db_scale_4bit),
  769. WSS_SINGLE("Beep Bypass Playback Switch", 0, CS4231_MONO_CTRL, 5, 1, 0),
  770. WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
  771. 0, 0, 15, 0, db_scale_rec_gain),
  772. WSS_DOUBLE("Analog Loopback Capture Switch", 0,
  773. CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
  774. WSS_SINGLE("Loopback Digital Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
  775. CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0,
  776. CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1,
  777. db_scale_6bit),
  778. };
  779. static const DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0);
  780. static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0);
  781. static struct snd_kcontrol_new snd_cs4235_controls[] = {
  782. WSS_DOUBLE("Master Playback Switch", 0,
  783. CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
  784. WSS_DOUBLE_TLV("Master Playback Volume", 0,
  785. CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1,
  786. db_scale_5bit_6db_max),
  787. CS4235_OUTPUT_ACCU("Playback Volume", 0, db_scale_2bit_16db_max),
  788. WSS_DOUBLE("Synth Playback Switch", 1,
  789. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
  790. WSS_DOUBLE("Synth Capture Switch", 1,
  791. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
  792. WSS_DOUBLE_TLV("Synth Volume", 1,
  793. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
  794. db_scale_5bit_12db_max),
  795. CS4236_DOUBLE_TLV("Capture Volume", 0,
  796. CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
  797. db_scale_2bit),
  798. WSS_DOUBLE("PCM Playback Switch", 0,
  799. CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
  800. WSS_DOUBLE("PCM Capture Switch", 0,
  801. CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
  802. WSS_DOUBLE_TLV("PCM Volume", 0,
  803. CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
  804. db_scale_6bit),
  805. CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
  806. CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
  807. CS4236_DOUBLE("Wavetable Switch", 0,
  808. CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
  809. CS4236_DOUBLE("Mic Capture Switch", 0,
  810. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
  811. CS4236_DOUBLE("Mic Playback Switch", 0,
  812. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
  813. CS4236_SINGLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1,
  814. db_scale_5bit_22db_max),
  815. CS4236_SINGLE("Mic Boost (+20dB)", 0, CS4236_LEFT_MIC, 5, 1, 0),
  816. WSS_DOUBLE("Line Playback Switch", 0,
  817. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
  818. WSS_DOUBLE("Line Capture Switch", 0,
  819. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
  820. WSS_DOUBLE_TLV("Line Volume", 0,
  821. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
  822. db_scale_5bit_12db_max),
  823. WSS_DOUBLE("CD Playback Switch", 1,
  824. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
  825. WSS_DOUBLE("CD Capture Switch", 1,
  826. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
  827. WSS_DOUBLE_TLV("CD Volume", 1,
  828. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
  829. db_scale_5bit_12db_max),
  830. CS4236_DOUBLE1("Beep Playback Switch", 0,
  831. CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
  832. WSS_SINGLE("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
  833. WSS_DOUBLE("Analog Loopback Switch", 0,
  834. CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
  835. };
  836. #define CS4236_IEC958_ENABLE(xname, xindex) \
  837. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  838. .info = snd_cs4236_info_single, \
  839. .get = snd_cs4236_get_iec958_switch, .put = snd_cs4236_put_iec958_switch, \
  840. .private_value = 1 << 16 }
  841. static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  842. {
  843. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  844. unsigned long flags;
  845. spin_lock_irqsave(&chip->reg_lock, flags);
  846. ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0;
  847. #if 0
  848. printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, "
  849. "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
  850. snd_wss_in(chip, CS4231_ALT_FEATURE_1),
  851. snd_cs4236_ctrl_in(chip, 3),
  852. snd_cs4236_ctrl_in(chip, 4),
  853. snd_cs4236_ctrl_in(chip, 5),
  854. snd_cs4236_ctrl_in(chip, 6),
  855. snd_cs4236_ctrl_in(chip, 8));
  856. #endif
  857. spin_unlock_irqrestore(&chip->reg_lock, flags);
  858. return 0;
  859. }
  860. static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  861. {
  862. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  863. unsigned long flags;
  864. int change;
  865. unsigned short enable, val;
  866. enable = ucontrol->value.integer.value[0] & 1;
  867. mutex_lock(&chip->mce_mutex);
  868. snd_wss_mce_up(chip);
  869. spin_lock_irqsave(&chip->reg_lock, flags);
  870. val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1);
  871. change = val != chip->image[CS4231_ALT_FEATURE_1];
  872. snd_wss_out(chip, CS4231_ALT_FEATURE_1, val);
  873. val = snd_cs4236_ctrl_in(chip, 4) | 0xc0;
  874. snd_cs4236_ctrl_out(chip, 4, val);
  875. udelay(100);
  876. val &= ~0x40;
  877. snd_cs4236_ctrl_out(chip, 4, val);
  878. spin_unlock_irqrestore(&chip->reg_lock, flags);
  879. snd_wss_mce_down(chip);
  880. mutex_unlock(&chip->mce_mutex);
  881. #if 0
  882. printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, "
  883. "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
  884. snd_wss_in(chip, CS4231_ALT_FEATURE_1),
  885. snd_cs4236_ctrl_in(chip, 3),
  886. snd_cs4236_ctrl_in(chip, 4),
  887. snd_cs4236_ctrl_in(chip, 5),
  888. snd_cs4236_ctrl_in(chip, 6),
  889. snd_cs4236_ctrl_in(chip, 8));
  890. #endif
  891. return change;
  892. }
  893. static struct snd_kcontrol_new snd_cs4236_iec958_controls[] = {
  894. CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
  895. CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
  896. CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0),
  897. CS4236_SINGLEC("IEC958 Output CSBR", 0, 4, 6, 1, 0),
  898. CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),
  899. CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
  900. };
  901. static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4235[] = {
  902. CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
  903. CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
  904. };
  905. static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4237[] = {
  906. CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
  907. CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
  908. CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1),
  909. CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),
  910. CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
  911. };
  912. static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4238[] = {
  913. CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
  914. CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
  915. CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),
  916. CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
  917. };
  918. int snd_cs4236_mixer(struct snd_wss *chip)
  919. {
  920. struct snd_card *card;
  921. unsigned int idx, count;
  922. int err;
  923. struct snd_kcontrol_new *kcontrol;
  924. if (snd_BUG_ON(!chip || !chip->card))
  925. return -EINVAL;
  926. card = chip->card;
  927. strcpy(card->mixername, snd_wss_chip_id(chip));
  928. if (chip->hardware == WSS_HW_CS4235 ||
  929. chip->hardware == WSS_HW_CS4239) {
  930. for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
  931. if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
  932. return err;
  933. }
  934. } else {
  935. for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) {
  936. if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0)
  937. return err;
  938. }
  939. }
  940. switch (chip->hardware) {
  941. case WSS_HW_CS4235:
  942. case WSS_HW_CS4239:
  943. count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
  944. kcontrol = snd_cs4236_3d_controls_cs4235;
  945. break;
  946. case WSS_HW_CS4237B:
  947. count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
  948. kcontrol = snd_cs4236_3d_controls_cs4237;
  949. break;
  950. case WSS_HW_CS4238B:
  951. count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
  952. kcontrol = snd_cs4236_3d_controls_cs4238;
  953. break;
  954. default:
  955. count = 0;
  956. kcontrol = NULL;
  957. }
  958. for (idx = 0; idx < count; idx++, kcontrol++) {
  959. if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0)
  960. return err;
  961. }
  962. if (chip->hardware == WSS_HW_CS4237B ||
  963. chip->hardware == WSS_HW_CS4238B) {
  964. for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
  965. if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
  966. return err;
  967. }
  968. }
  969. return 0;
  970. }