cs4236_lib.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. /*
  2. * Copyright (c) by Jaroslav Kysela <[email protected]>
  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. }