cs4236_lib.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  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 <asm/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, struct snd_pcm **rpcm)
  350. {
  351. struct snd_pcm *pcm;
  352. int err;
  353. err = snd_wss_pcm(chip, device, &pcm);
  354. if (err < 0)
  355. return err;
  356. pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX;
  357. if (rpcm)
  358. *rpcm = pcm;
  359. return 0;
  360. }
  361. /*
  362. * MIXER
  363. */
  364. #define CS4236_SINGLE(xname, xindex, reg, shift, mask, invert) \
  365. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  366. .info = snd_cs4236_info_single, \
  367. .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
  368. .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
  369. #define CS4236_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
  370. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  371. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  372. .info = snd_cs4236_info_single, \
  373. .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
  374. .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
  375. .tlv = { .p = (xtlv) } }
  376. static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  377. {
  378. int mask = (kcontrol->private_value >> 16) & 0xff;
  379. uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
  380. uinfo->count = 1;
  381. uinfo->value.integer.min = 0;
  382. uinfo->value.integer.max = mask;
  383. return 0;
  384. }
  385. static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  386. {
  387. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  388. unsigned long flags;
  389. int reg = kcontrol->private_value & 0xff;
  390. int shift = (kcontrol->private_value >> 8) & 0xff;
  391. int mask = (kcontrol->private_value >> 16) & 0xff;
  392. int invert = (kcontrol->private_value >> 24) & 0xff;
  393. spin_lock_irqsave(&chip->reg_lock, flags);
  394. ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(reg)] >> shift) & mask;
  395. spin_unlock_irqrestore(&chip->reg_lock, flags);
  396. if (invert)
  397. ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
  398. return 0;
  399. }
  400. static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  401. {
  402. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  403. unsigned long flags;
  404. int reg = kcontrol->private_value & 0xff;
  405. int shift = (kcontrol->private_value >> 8) & 0xff;
  406. int mask = (kcontrol->private_value >> 16) & 0xff;
  407. int invert = (kcontrol->private_value >> 24) & 0xff;
  408. int change;
  409. unsigned short val;
  410. val = (ucontrol->value.integer.value[0] & mask);
  411. if (invert)
  412. val = mask - val;
  413. val <<= shift;
  414. spin_lock_irqsave(&chip->reg_lock, flags);
  415. val = (chip->eimage[CS4236_REG(reg)] & ~(mask << shift)) | val;
  416. change = val != chip->eimage[CS4236_REG(reg)];
  417. snd_cs4236_ext_out(chip, reg, val);
  418. spin_unlock_irqrestore(&chip->reg_lock, flags);
  419. return change;
  420. }
  421. #define CS4236_SINGLEC(xname, xindex, reg, shift, mask, invert) \
  422. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  423. .info = snd_cs4236_info_single, \
  424. .get = snd_cs4236_get_singlec, .put = snd_cs4236_put_singlec, \
  425. .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
  426. static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  427. {
  428. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  429. unsigned long flags;
  430. int reg = kcontrol->private_value & 0xff;
  431. int shift = (kcontrol->private_value >> 8) & 0xff;
  432. int mask = (kcontrol->private_value >> 16) & 0xff;
  433. int invert = (kcontrol->private_value >> 24) & 0xff;
  434. spin_lock_irqsave(&chip->reg_lock, flags);
  435. ucontrol->value.integer.value[0] = (chip->cimage[reg] >> shift) & mask;
  436. spin_unlock_irqrestore(&chip->reg_lock, flags);
  437. if (invert)
  438. ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
  439. return 0;
  440. }
  441. static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  442. {
  443. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  444. unsigned long flags;
  445. int reg = kcontrol->private_value & 0xff;
  446. int shift = (kcontrol->private_value >> 8) & 0xff;
  447. int mask = (kcontrol->private_value >> 16) & 0xff;
  448. int invert = (kcontrol->private_value >> 24) & 0xff;
  449. int change;
  450. unsigned short val;
  451. val = (ucontrol->value.integer.value[0] & mask);
  452. if (invert)
  453. val = mask - val;
  454. val <<= shift;
  455. spin_lock_irqsave(&chip->reg_lock, flags);
  456. val = (chip->cimage[reg] & ~(mask << shift)) | val;
  457. change = val != chip->cimage[reg];
  458. snd_cs4236_ctrl_out(chip, reg, val);
  459. spin_unlock_irqrestore(&chip->reg_lock, flags);
  460. return change;
  461. }
  462. #define CS4236_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
  463. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  464. .info = snd_cs4236_info_double, \
  465. .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
  466. .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
  467. #define CS4236_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, \
  468. shift_right, mask, invert, xtlv) \
  469. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  470. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  471. .info = snd_cs4236_info_double, \
  472. .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
  473. .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
  474. (shift_right << 19) | (mask << 24) | (invert << 22), \
  475. .tlv = { .p = (xtlv) } }
  476. static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
  477. {
  478. int mask = (kcontrol->private_value >> 24) & 0xff;
  479. uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
  480. uinfo->count = 2;
  481. uinfo->value.integer.min = 0;
  482. uinfo->value.integer.max = mask;
  483. return 0;
  484. }
  485. static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  486. {
  487. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  488. unsigned long flags;
  489. int left_reg = kcontrol->private_value & 0xff;
  490. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  491. int shift_left = (kcontrol->private_value >> 16) & 0x07;
  492. int shift_right = (kcontrol->private_value >> 19) & 0x07;
  493. int mask = (kcontrol->private_value >> 24) & 0xff;
  494. int invert = (kcontrol->private_value >> 22) & 1;
  495. spin_lock_irqsave(&chip->reg_lock, flags);
  496. ucontrol->value.integer.value[0] = (chip->eimage[CS4236_REG(left_reg)] >> shift_left) & mask;
  497. ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask;
  498. spin_unlock_irqrestore(&chip->reg_lock, flags);
  499. if (invert) {
  500. ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
  501. ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
  502. }
  503. return 0;
  504. }
  505. static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  506. {
  507. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  508. unsigned long flags;
  509. int left_reg = kcontrol->private_value & 0xff;
  510. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  511. int shift_left = (kcontrol->private_value >> 16) & 0x07;
  512. int shift_right = (kcontrol->private_value >> 19) & 0x07;
  513. int mask = (kcontrol->private_value >> 24) & 0xff;
  514. int invert = (kcontrol->private_value >> 22) & 1;
  515. int change;
  516. unsigned short val1, val2;
  517. val1 = ucontrol->value.integer.value[0] & mask;
  518. val2 = ucontrol->value.integer.value[1] & mask;
  519. if (invert) {
  520. val1 = mask - val1;
  521. val2 = mask - val2;
  522. }
  523. val1 <<= shift_left;
  524. val2 <<= shift_right;
  525. spin_lock_irqsave(&chip->reg_lock, flags);
  526. if (left_reg != right_reg) {
  527. val1 = (chip->eimage[CS4236_REG(left_reg)] & ~(mask << shift_left)) | val1;
  528. val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
  529. change = val1 != chip->eimage[CS4236_REG(left_reg)] || val2 != chip->eimage[CS4236_REG(right_reg)];
  530. snd_cs4236_ext_out(chip, left_reg, val1);
  531. snd_cs4236_ext_out(chip, right_reg, val2);
  532. } else {
  533. val1 = (chip->eimage[CS4236_REG(left_reg)] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
  534. change = val1 != chip->eimage[CS4236_REG(left_reg)];
  535. snd_cs4236_ext_out(chip, left_reg, val1);
  536. }
  537. spin_unlock_irqrestore(&chip->reg_lock, flags);
  538. return change;
  539. }
  540. #define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, \
  541. shift_right, mask, invert) \
  542. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  543. .info = snd_cs4236_info_double, \
  544. .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
  545. .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
  546. #define CS4236_DOUBLE1_TLV(xname, xindex, left_reg, right_reg, shift_left, \
  547. shift_right, mask, invert, xtlv) \
  548. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  549. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  550. .info = snd_cs4236_info_double, \
  551. .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
  552. .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
  553. (shift_right << 19) | (mask << 24) | (invert << 22), \
  554. .tlv = { .p = (xtlv) } }
  555. static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  556. {
  557. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  558. unsigned long flags;
  559. int left_reg = kcontrol->private_value & 0xff;
  560. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  561. int shift_left = (kcontrol->private_value >> 16) & 0x07;
  562. int shift_right = (kcontrol->private_value >> 19) & 0x07;
  563. int mask = (kcontrol->private_value >> 24) & 0xff;
  564. int invert = (kcontrol->private_value >> 22) & 1;
  565. spin_lock_irqsave(&chip->reg_lock, flags);
  566. ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
  567. ucontrol->value.integer.value[1] = (chip->eimage[CS4236_REG(right_reg)] >> shift_right) & mask;
  568. spin_unlock_irqrestore(&chip->reg_lock, flags);
  569. if (invert) {
  570. ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
  571. ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
  572. }
  573. return 0;
  574. }
  575. static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  576. {
  577. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  578. unsigned long flags;
  579. int left_reg = kcontrol->private_value & 0xff;
  580. int right_reg = (kcontrol->private_value >> 8) & 0xff;
  581. int shift_left = (kcontrol->private_value >> 16) & 0x07;
  582. int shift_right = (kcontrol->private_value >> 19) & 0x07;
  583. int mask = (kcontrol->private_value >> 24) & 0xff;
  584. int invert = (kcontrol->private_value >> 22) & 1;
  585. int change;
  586. unsigned short val1, val2;
  587. val1 = ucontrol->value.integer.value[0] & mask;
  588. val2 = ucontrol->value.integer.value[1] & mask;
  589. if (invert) {
  590. val1 = mask - val1;
  591. val2 = mask - val2;
  592. }
  593. val1 <<= shift_left;
  594. val2 <<= shift_right;
  595. spin_lock_irqsave(&chip->reg_lock, flags);
  596. val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
  597. val2 = (chip->eimage[CS4236_REG(right_reg)] & ~(mask << shift_right)) | val2;
  598. change = val1 != chip->image[left_reg] || val2 != chip->eimage[CS4236_REG(right_reg)];
  599. snd_wss_out(chip, left_reg, val1);
  600. snd_cs4236_ext_out(chip, right_reg, val2);
  601. spin_unlock_irqrestore(&chip->reg_lock, flags);
  602. return change;
  603. }
  604. #define CS4236_MASTER_DIGITAL(xname, xindex, xtlv) \
  605. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  606. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  607. .info = snd_cs4236_info_double, \
  608. .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \
  609. .private_value = 71 << 24, \
  610. .tlv = { .p = (xtlv) } }
  611. static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
  612. {
  613. return (vol < 64) ? 63 - vol : 64 + (71 - vol);
  614. }
  615. static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  616. {
  617. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  618. unsigned long flags;
  619. spin_lock_irqsave(&chip->reg_lock, flags);
  620. ucontrol->value.integer.value[0] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & 0x7f);
  621. ucontrol->value.integer.value[1] = snd_cs4236_mixer_master_digital_invert_volume(chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & 0x7f);
  622. spin_unlock_irqrestore(&chip->reg_lock, flags);
  623. return 0;
  624. }
  625. static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  626. {
  627. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  628. unsigned long flags;
  629. int change;
  630. unsigned short val1, val2;
  631. val1 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[0] & 0x7f);
  632. val2 = snd_cs4236_mixer_master_digital_invert_volume(ucontrol->value.integer.value[1] & 0x7f);
  633. spin_lock_irqsave(&chip->reg_lock, flags);
  634. val1 = (chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] & ~0x7f) | val1;
  635. val2 = (chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)] & ~0x7f) | val2;
  636. change = val1 != chip->eimage[CS4236_REG(CS4236_LEFT_MASTER)] || val2 != chip->eimage[CS4236_REG(CS4236_RIGHT_MASTER)];
  637. snd_cs4236_ext_out(chip, CS4236_LEFT_MASTER, val1);
  638. snd_cs4236_ext_out(chip, CS4236_RIGHT_MASTER, val2);
  639. spin_unlock_irqrestore(&chip->reg_lock, flags);
  640. return change;
  641. }
  642. #define CS4235_OUTPUT_ACCU(xname, xindex, xtlv) \
  643. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  644. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  645. .info = snd_cs4236_info_double, \
  646. .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \
  647. .private_value = 3 << 24, \
  648. .tlv = { .p = (xtlv) } }
  649. static inline int snd_cs4235_mixer_output_accu_get_volume(int vol)
  650. {
  651. switch ((vol >> 5) & 3) {
  652. case 0: return 1;
  653. case 1: return 3;
  654. case 2: return 2;
  655. case 3: return 0;
  656. }
  657. return 3;
  658. }
  659. static inline int snd_cs4235_mixer_output_accu_set_volume(int vol)
  660. {
  661. switch (vol & 3) {
  662. case 0: return 3 << 5;
  663. case 1: return 0 << 5;
  664. case 2: return 2 << 5;
  665. case 3: return 1 << 5;
  666. }
  667. return 1 << 5;
  668. }
  669. static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  670. {
  671. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  672. unsigned long flags;
  673. spin_lock_irqsave(&chip->reg_lock, flags);
  674. ucontrol->value.integer.value[0] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_LEFT_MASTER]);
  675. ucontrol->value.integer.value[1] = snd_cs4235_mixer_output_accu_get_volume(chip->image[CS4235_RIGHT_MASTER]);
  676. spin_unlock_irqrestore(&chip->reg_lock, flags);
  677. return 0;
  678. }
  679. static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  680. {
  681. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  682. unsigned long flags;
  683. int change;
  684. unsigned short val1, val2;
  685. val1 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[0]);
  686. val2 = snd_cs4235_mixer_output_accu_set_volume(ucontrol->value.integer.value[1]);
  687. spin_lock_irqsave(&chip->reg_lock, flags);
  688. val1 = (chip->image[CS4235_LEFT_MASTER] & ~(3 << 5)) | val1;
  689. val2 = (chip->image[CS4235_RIGHT_MASTER] & ~(3 << 5)) | val2;
  690. change = val1 != chip->image[CS4235_LEFT_MASTER] || val2 != chip->image[CS4235_RIGHT_MASTER];
  691. snd_wss_out(chip, CS4235_LEFT_MASTER, val1);
  692. snd_wss_out(chip, CS4235_RIGHT_MASTER, val2);
  693. spin_unlock_irqrestore(&chip->reg_lock, flags);
  694. return change;
  695. }
  696. static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -9450, 150, 0);
  697. static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
  698. static const DECLARE_TLV_DB_SCALE(db_scale_6bit_12db_max, -8250, 150, 0);
  699. static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
  700. static const DECLARE_TLV_DB_SCALE(db_scale_5bit_22db_max, -2400, 150, 0);
  701. static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
  702. static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0);
  703. static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
  704. static struct snd_kcontrol_new snd_cs4236_controls[] = {
  705. CS4236_DOUBLE("Master Digital Playback Switch", 0,
  706. CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
  707. CS4236_DOUBLE("Master Digital Capture Switch", 0,
  708. CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
  709. CS4236_MASTER_DIGITAL("Master Digital Volume", 0, db_scale_7bit),
  710. CS4236_DOUBLE_TLV("Capture Boost Volume", 0,
  711. CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
  712. db_scale_2bit),
  713. WSS_DOUBLE("PCM Playback Switch", 0,
  714. CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
  715. WSS_DOUBLE_TLV("PCM Playback Volume", 0,
  716. CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
  717. db_scale_6bit),
  718. CS4236_DOUBLE("DSP Playback Switch", 0,
  719. CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
  720. CS4236_DOUBLE_TLV("DSP Playback Volume", 0,
  721. CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1,
  722. db_scale_6bit),
  723. CS4236_DOUBLE("FM Playback Switch", 0,
  724. CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
  725. CS4236_DOUBLE_TLV("FM Playback Volume", 0,
  726. CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1,
  727. db_scale_6bit),
  728. CS4236_DOUBLE("Wavetable Playback Switch", 0,
  729. CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
  730. CS4236_DOUBLE_TLV("Wavetable Playback Volume", 0,
  731. CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1,
  732. db_scale_6bit_12db_max),
  733. WSS_DOUBLE("Synth Playback Switch", 0,
  734. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
  735. WSS_DOUBLE_TLV("Synth Volume", 0,
  736. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
  737. db_scale_5bit_12db_max),
  738. WSS_DOUBLE("Synth Capture Switch", 0,
  739. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
  740. WSS_DOUBLE("Synth Capture Bypass", 0,
  741. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 5, 5, 1, 1),
  742. CS4236_DOUBLE("Mic Playback Switch", 0,
  743. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
  744. CS4236_DOUBLE("Mic Capture Switch", 0,
  745. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
  746. CS4236_DOUBLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC,
  747. 0, 0, 31, 1, db_scale_5bit_22db_max),
  748. CS4236_DOUBLE("Mic Playback Boost (+20dB)", 0,
  749. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
  750. WSS_DOUBLE("Line Playback Switch", 0,
  751. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
  752. WSS_DOUBLE_TLV("Line Volume", 0,
  753. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
  754. db_scale_5bit_12db_max),
  755. WSS_DOUBLE("Line Capture Switch", 0,
  756. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
  757. WSS_DOUBLE("Line Capture Bypass", 0,
  758. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 5, 5, 1, 1),
  759. WSS_DOUBLE("CD Playback Switch", 0,
  760. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
  761. WSS_DOUBLE_TLV("CD Volume", 0,
  762. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
  763. db_scale_5bit_12db_max),
  764. WSS_DOUBLE("CD Capture Switch", 0,
  765. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
  766. CS4236_DOUBLE1("Mono Output Playback Switch", 0,
  767. CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
  768. CS4236_DOUBLE1("Beep Playback Switch", 0,
  769. CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
  770. WSS_SINGLE_TLV("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1,
  771. db_scale_4bit),
  772. WSS_SINGLE("Beep Bypass Playback Switch", 0, CS4231_MONO_CTRL, 5, 1, 0),
  773. WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
  774. 0, 0, 15, 0, db_scale_rec_gain),
  775. WSS_DOUBLE("Analog Loopback Capture Switch", 0,
  776. CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
  777. WSS_SINGLE("Loopback Digital Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
  778. CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0,
  779. CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1,
  780. db_scale_6bit),
  781. };
  782. static const DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0);
  783. static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0);
  784. static struct snd_kcontrol_new snd_cs4235_controls[] = {
  785. WSS_DOUBLE("Master Playback Switch", 0,
  786. CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
  787. WSS_DOUBLE_TLV("Master Playback Volume", 0,
  788. CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1,
  789. db_scale_5bit_6db_max),
  790. CS4235_OUTPUT_ACCU("Playback Volume", 0, db_scale_2bit_16db_max),
  791. WSS_DOUBLE("Synth Playback Switch", 1,
  792. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
  793. WSS_DOUBLE("Synth Capture Switch", 1,
  794. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
  795. WSS_DOUBLE_TLV("Synth Volume", 1,
  796. CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
  797. db_scale_5bit_12db_max),
  798. CS4236_DOUBLE_TLV("Capture Volume", 0,
  799. CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
  800. db_scale_2bit),
  801. WSS_DOUBLE("PCM Playback Switch", 0,
  802. CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
  803. WSS_DOUBLE("PCM Capture Switch", 0,
  804. CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
  805. WSS_DOUBLE_TLV("PCM Volume", 0,
  806. CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
  807. db_scale_6bit),
  808. CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
  809. CS4236_DOUBLE("FM Switch", 0, CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
  810. CS4236_DOUBLE("Wavetable Switch", 0,
  811. CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
  812. CS4236_DOUBLE("Mic Capture Switch", 0,
  813. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
  814. CS4236_DOUBLE("Mic Playback Switch", 0,
  815. CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
  816. CS4236_SINGLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1,
  817. db_scale_5bit_22db_max),
  818. CS4236_SINGLE("Mic Boost (+20dB)", 0, CS4236_LEFT_MIC, 5, 1, 0),
  819. WSS_DOUBLE("Line Playback Switch", 0,
  820. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
  821. WSS_DOUBLE("Line Capture Switch", 0,
  822. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
  823. WSS_DOUBLE_TLV("Line Volume", 0,
  824. CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
  825. db_scale_5bit_12db_max),
  826. WSS_DOUBLE("CD Playback Switch", 1,
  827. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
  828. WSS_DOUBLE("CD Capture Switch", 1,
  829. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
  830. WSS_DOUBLE_TLV("CD Volume", 1,
  831. CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
  832. db_scale_5bit_12db_max),
  833. CS4236_DOUBLE1("Beep Playback Switch", 0,
  834. CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
  835. WSS_SINGLE("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
  836. WSS_DOUBLE("Analog Loopback Switch", 0,
  837. CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
  838. };
  839. #define CS4236_IEC958_ENABLE(xname, xindex) \
  840. { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
  841. .info = snd_cs4236_info_single, \
  842. .get = snd_cs4236_get_iec958_switch, .put = snd_cs4236_put_iec958_switch, \
  843. .private_value = 1 << 16 }
  844. static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  845. {
  846. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  847. unsigned long flags;
  848. spin_lock_irqsave(&chip->reg_lock, flags);
  849. ucontrol->value.integer.value[0] = chip->image[CS4231_ALT_FEATURE_1] & 0x02 ? 1 : 0;
  850. #if 0
  851. printk(KERN_DEBUG "get valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, "
  852. "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
  853. snd_wss_in(chip, CS4231_ALT_FEATURE_1),
  854. snd_cs4236_ctrl_in(chip, 3),
  855. snd_cs4236_ctrl_in(chip, 4),
  856. snd_cs4236_ctrl_in(chip, 5),
  857. snd_cs4236_ctrl_in(chip, 6),
  858. snd_cs4236_ctrl_in(chip, 8));
  859. #endif
  860. spin_unlock_irqrestore(&chip->reg_lock, flags);
  861. return 0;
  862. }
  863. static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
  864. {
  865. struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
  866. unsigned long flags;
  867. int change;
  868. unsigned short enable, val;
  869. enable = ucontrol->value.integer.value[0] & 1;
  870. mutex_lock(&chip->mce_mutex);
  871. snd_wss_mce_up(chip);
  872. spin_lock_irqsave(&chip->reg_lock, flags);
  873. val = (chip->image[CS4231_ALT_FEATURE_1] & ~0x0e) | (0<<2) | (enable << 1);
  874. change = val != chip->image[CS4231_ALT_FEATURE_1];
  875. snd_wss_out(chip, CS4231_ALT_FEATURE_1, val);
  876. val = snd_cs4236_ctrl_in(chip, 4) | 0xc0;
  877. snd_cs4236_ctrl_out(chip, 4, val);
  878. udelay(100);
  879. val &= ~0x40;
  880. snd_cs4236_ctrl_out(chip, 4, val);
  881. spin_unlock_irqrestore(&chip->reg_lock, flags);
  882. snd_wss_mce_down(chip);
  883. mutex_unlock(&chip->mce_mutex);
  884. #if 0
  885. printk(KERN_DEBUG "set valid: ALT = 0x%x, C3 = 0x%x, C4 = 0x%x, "
  886. "C5 = 0x%x, C6 = 0x%x, C8 = 0x%x\n",
  887. snd_wss_in(chip, CS4231_ALT_FEATURE_1),
  888. snd_cs4236_ctrl_in(chip, 3),
  889. snd_cs4236_ctrl_in(chip, 4),
  890. snd_cs4236_ctrl_in(chip, 5),
  891. snd_cs4236_ctrl_in(chip, 6),
  892. snd_cs4236_ctrl_in(chip, 8));
  893. #endif
  894. return change;
  895. }
  896. static struct snd_kcontrol_new snd_cs4236_iec958_controls[] = {
  897. CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
  898. CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
  899. CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0),
  900. CS4236_SINGLEC("IEC958 Output CSBR", 0, 4, 6, 1, 0),
  901. CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),
  902. CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
  903. };
  904. static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4235[] = {
  905. CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
  906. CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
  907. };
  908. static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4237[] = {
  909. CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
  910. CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
  911. CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1),
  912. CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),
  913. CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
  914. };
  915. static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4238[] = {
  916. CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
  917. CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
  918. CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),
  919. CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
  920. };
  921. int snd_cs4236_mixer(struct snd_wss *chip)
  922. {
  923. struct snd_card *card;
  924. unsigned int idx, count;
  925. int err;
  926. struct snd_kcontrol_new *kcontrol;
  927. if (snd_BUG_ON(!chip || !chip->card))
  928. return -EINVAL;
  929. card = chip->card;
  930. strcpy(card->mixername, snd_wss_chip_id(chip));
  931. if (chip->hardware == WSS_HW_CS4235 ||
  932. chip->hardware == WSS_HW_CS4239) {
  933. for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
  934. if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
  935. return err;
  936. }
  937. } else {
  938. for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) {
  939. if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0)
  940. return err;
  941. }
  942. }
  943. switch (chip->hardware) {
  944. case WSS_HW_CS4235:
  945. case WSS_HW_CS4239:
  946. count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
  947. kcontrol = snd_cs4236_3d_controls_cs4235;
  948. break;
  949. case WSS_HW_CS4237B:
  950. count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
  951. kcontrol = snd_cs4236_3d_controls_cs4237;
  952. break;
  953. case WSS_HW_CS4238B:
  954. count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
  955. kcontrol = snd_cs4236_3d_controls_cs4238;
  956. break;
  957. default:
  958. count = 0;
  959. kcontrol = NULL;
  960. }
  961. for (idx = 0; idx < count; idx++, kcontrol++) {
  962. if ((err = snd_ctl_add(card, snd_ctl_new1(kcontrol, chip))) < 0)
  963. return err;
  964. }
  965. if (chip->hardware == WSS_HW_CS4237B ||
  966. chip->hardware == WSS_HW_CS4238B) {
  967. for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
  968. if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
  969. return err;
  970. }
  971. }
  972. return 0;
  973. }