aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/cs423x/cs4236_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa/cs423x/cs4236_lib.c')
-rw-r--r--sound/isa/cs423x/cs4236_lib.c241
1 files changed, 155 insertions, 86 deletions
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 38835f31298b..c5adca300632 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -87,6 +87,8 @@
87#include <sound/core.h> 87#include <sound/core.h>
88#include <sound/wss.h> 88#include <sound/wss.h>
89#include <sound/asoundef.h> 89#include <sound/asoundef.h>
90#include <sound/initval.h>
91#include <sound/tlv.h>
90 92
91/* 93/*
92 * 94 *
@@ -264,7 +266,10 @@ static void snd_cs4236_resume(struct snd_wss *chip)
264} 266}
265 267
266#endif /* CONFIG_PM */ 268#endif /* CONFIG_PM */
267 269/*
270 * This function does no fail if the chip is not CS4236B or compatible.
271 * It just an equivalent to the snd_wss_create() then.
272 */
268int snd_cs4236_create(struct snd_card *card, 273int snd_cs4236_create(struct snd_card *card,
269 unsigned long port, 274 unsigned long port,
270 unsigned long cport, 275 unsigned long cport,
@@ -281,21 +286,17 @@ int snd_cs4236_create(struct snd_card *card,
281 *rchip = NULL; 286 *rchip = NULL;
282 if (hardware == WSS_HW_DETECT) 287 if (hardware == WSS_HW_DETECT)
283 hardware = WSS_HW_DETECT3; 288 hardware = WSS_HW_DETECT3;
284 if (cport < 0x100) { 289
285 snd_printk(KERN_ERR "please, specify control port "
286 "for CS4236+ chips\n");
287 return -ENODEV;
288 }
289 err = snd_wss_create(card, port, cport, 290 err = snd_wss_create(card, port, cport,
290 irq, dma1, dma2, hardware, hwshare, &chip); 291 irq, dma1, dma2, hardware, hwshare, &chip);
291 if (err < 0) 292 if (err < 0)
292 return err; 293 return err;
293 294
294 if (!(chip->hardware & WSS_HW_CS4236B_MASK)) { 295 if ((chip->hardware & WSS_HW_CS4236B_MASK) == 0) {
295 snd_printk(KERN_ERR "CS4236+: MODE3 and extended registers " 296 snd_printd("chip is not CS4236+, hardware=0x%x\n",
296 "not available, hardware=0x%x\n", chip->hardware); 297 chip->hardware);
297 snd_device_free(card, chip); 298 *rchip = chip;
298 return -ENODEV; 299 return 0;
299 } 300 }
300#if 0 301#if 0
301 { 302 {
@@ -308,9 +309,16 @@ int snd_cs4236_create(struct snd_card *card,
308 idx, snd_cs4236_ctrl_in(chip, idx)); 309 idx, snd_cs4236_ctrl_in(chip, idx));
309 } 310 }
310#endif 311#endif
312 if (cport < 0x100 || cport == SNDRV_AUTO_PORT) {
313 snd_printk(KERN_ERR "please, specify control port "
314 "for CS4236+ chips\n");
315 snd_device_free(card, chip);
316 return -ENODEV;
317 }
311 ver1 = snd_cs4236_ctrl_in(chip, 1); 318 ver1 = snd_cs4236_ctrl_in(chip, 1);
312 ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION); 319 ver2 = snd_cs4236_ext_in(chip, CS4236_VERSION);
313 snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n", cport, ver1, ver2); 320 snd_printdd("CS4236: [0x%lx] C1 (version) = 0x%x, ext = 0x%x\n",
321 cport, ver1, ver2);
314 if (ver1 != ver2) { 322 if (ver1 != ver2) {
315 snd_printk(KERN_ERR "CS4236+ chip detected, but " 323 snd_printk(KERN_ERR "CS4236+ chip detected, but "
316 "control port 0x%lx is not valid\n", cport); 324 "control port 0x%lx is not valid\n", cport);
@@ -321,13 +329,17 @@ int snd_cs4236_create(struct snd_card *card,
321 snd_cs4236_ctrl_out(chip, 2, 0xff); 329 snd_cs4236_ctrl_out(chip, 2, 0xff);
322 snd_cs4236_ctrl_out(chip, 3, 0x00); 330 snd_cs4236_ctrl_out(chip, 3, 0x00);
323 snd_cs4236_ctrl_out(chip, 4, 0x80); 331 snd_cs4236_ctrl_out(chip, 4, 0x80);
324 snd_cs4236_ctrl_out(chip, 5, ((IEC958_AES1_CON_PCM_CODER & 3) << 6) | IEC958_AES0_CON_EMPHASIS_NONE); 332 reg = ((IEC958_AES1_CON_PCM_CODER & 3) << 6) |
333 IEC958_AES0_CON_EMPHASIS_NONE;
334 snd_cs4236_ctrl_out(chip, 5, reg);
325 snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2); 335 snd_cs4236_ctrl_out(chip, 6, IEC958_AES1_CON_PCM_CODER >> 2);
326 snd_cs4236_ctrl_out(chip, 7, 0x00); 336 snd_cs4236_ctrl_out(chip, 7, 0x00);
327 /* 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958 output */ 337 /*
328 /* is working with this setup, other hardware should have */ 338 * 0x8c for C8 is valid for Turtle Beach Malibu - the IEC-958
329 /* different signal paths and this value should be selectable */ 339 * output is working with this setup, other hardware should
330 /* in the future */ 340 * have different signal paths and this value should be
341 * selectable in the future
342 */
331 snd_cs4236_ctrl_out(chip, 8, 0x8c); 343 snd_cs4236_ctrl_out(chip, 8, 0x8c);
332 chip->rate_constraint = snd_cs4236_xrate; 344 chip->rate_constraint = snd_cs4236_xrate;
333 chip->set_playback_format = snd_cs4236_playback_format; 345 chip->set_playback_format = snd_cs4236_playback_format;
@@ -339,9 +351,10 @@ int snd_cs4236_create(struct snd_card *card,
339 351
340 /* initialize extended registers */ 352 /* initialize extended registers */
341 for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++) 353 for (reg = 0; reg < sizeof(snd_cs4236_ext_map); reg++)
342 snd_cs4236_ext_out(chip, CS4236_I23VAL(reg), snd_cs4236_ext_map[reg]); 354 snd_cs4236_ext_out(chip, CS4236_I23VAL(reg),
355 snd_cs4236_ext_map[reg]);
343 356
344 /* initialize compatible but more featured registers */ 357 /* initialize compatible but more featured registers */
345 snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40); 358 snd_wss_out(chip, CS4231_LEFT_INPUT, 0x40);
346 snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40); 359 snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x40);
347 snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff); 360 snd_wss_out(chip, CS4231_AUX1_LEFT_INPUT, 0xff);
@@ -387,6 +400,14 @@ int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
387 .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \ 400 .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
388 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } 401 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
389 402
403#define CS4236_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
404{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
405 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
406 .info = snd_cs4236_info_single, \
407 .get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
408 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
409 .tlv = { .p = (xtlv) } }
410
390static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 411static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
391{ 412{
392 int mask = (kcontrol->private_value >> 16) & 0xff; 413 int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -490,6 +511,16 @@ static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_
490 .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \ 511 .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
491 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } 512 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
492 513
514#define CS4236_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, \
515 shift_right, mask, invert, xtlv) \
516{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
517 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
518 .info = snd_cs4236_info_double, \
519 .get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
520 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
521 (shift_right << 19) | (mask << 24) | (invert << 22), \
522 .tlv = { .p = (xtlv) } }
523
493static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 524static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
494{ 525{
495 int mask = (kcontrol->private_value >> 24) & 0xff; 526 int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -560,12 +591,23 @@ static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
560 return change; 591 return change;
561} 592}
562 593
563#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ 594#define CS4236_DOUBLE1(xname, xindex, left_reg, right_reg, shift_left, \
595 shift_right, mask, invert) \
564{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 596{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
565 .info = snd_cs4236_info_double, \ 597 .info = snd_cs4236_info_double, \
566 .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \ 598 .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
567 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } 599 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
568 600
601#define CS4236_DOUBLE1_TLV(xname, xindex, left_reg, right_reg, shift_left, \
602 shift_right, mask, invert, xtlv) \
603{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
604 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
605 .info = snd_cs4236_info_double, \
606 .get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
607 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
608 (shift_right << 19) | (mask << 24) | (invert << 22), \
609 .tlv = { .p = (xtlv) } }
610
569static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 611static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
570{ 612{
571 struct snd_wss *chip = snd_kcontrol_chip(kcontrol); 613 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
@@ -619,16 +661,18 @@ static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_
619 return change; 661 return change;
620} 662}
621 663
622#define CS4236_MASTER_DIGITAL(xname, xindex) \ 664#define CS4236_MASTER_DIGITAL(xname, xindex, xtlv) \
623{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 665{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
666 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
624 .info = snd_cs4236_info_double, \ 667 .info = snd_cs4236_info_double, \
625 .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \ 668 .get = snd_cs4236_get_master_digital, .put = snd_cs4236_put_master_digital, \
626 .private_value = 71 << 24 } 669 .private_value = 71 << 24, \
670 .tlv = { .p = (xtlv) } }
627 671
628static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol) 672static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
629{ 673{
630 return (vol < 64) ? 63 - vol : 64 + (71 - vol); 674 return (vol < 64) ? 63 - vol : 64 + (71 - vol);
631} 675}
632 676
633static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 677static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
634{ 678{
@@ -661,11 +705,13 @@ static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct s
661 return change; 705 return change;
662} 706}
663 707
664#define CS4235_OUTPUT_ACCU(xname, xindex) \ 708#define CS4235_OUTPUT_ACCU(xname, xindex, xtlv) \
665{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 709{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
710 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
666 .info = snd_cs4236_info_double, \ 711 .info = snd_cs4236_info_double, \
667 .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \ 712 .get = snd_cs4235_get_output_accu, .put = snd_cs4235_put_output_accu, \
668 .private_value = 3 << 24 } 713 .private_value = 3 << 24, \
714 .tlv = { .p = (xtlv) } }
669 715
670static inline int snd_cs4235_mixer_output_accu_get_volume(int vol) 716static inline int snd_cs4235_mixer_output_accu_get_volume(int vol)
671{ 717{
@@ -720,41 +766,56 @@ static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_
720 return change; 766 return change;
721} 767}
722 768
769static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -9450, 150, 0);
770static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
771static const DECLARE_TLV_DB_SCALE(db_scale_6bit_12db_max, -8250, 150, 0);
772static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
773static const DECLARE_TLV_DB_SCALE(db_scale_5bit_22db_max, -2400, 150, 0);
774static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
775static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0);
776static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
777
723static struct snd_kcontrol_new snd_cs4236_controls[] = { 778static struct snd_kcontrol_new snd_cs4236_controls[] = {
724 779
725CS4236_DOUBLE("Master Digital Playback Switch", 0, 780CS4236_DOUBLE("Master Digital Playback Switch", 0,
726 CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1), 781 CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
727CS4236_DOUBLE("Master Digital Capture Switch", 0, 782CS4236_DOUBLE("Master Digital Capture Switch", 0,
728 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1), 783 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
729CS4236_MASTER_DIGITAL("Master Digital Volume", 0), 784CS4236_MASTER_DIGITAL("Master Digital Volume", 0, db_scale_7bit),
730 785
731CS4236_DOUBLE("Capture Boost Volume", 0, 786CS4236_DOUBLE_TLV("Capture Boost Volume", 0,
732 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), 787 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
788 db_scale_2bit),
733 789
734WSS_DOUBLE("PCM Playback Switch", 0, 790WSS_DOUBLE("PCM Playback Switch", 0,
735 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), 791 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
736WSS_DOUBLE("PCM Playback Volume", 0, 792WSS_DOUBLE_TLV("PCM Playback Volume", 0,
737 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), 793 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
794 db_scale_6bit),
738 795
739CS4236_DOUBLE("DSP Playback Switch", 0, 796CS4236_DOUBLE("DSP Playback Switch", 0,
740 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), 797 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
741CS4236_DOUBLE("DSP Playback Volume", 0, 798CS4236_DOUBLE_TLV("DSP Playback Volume", 0,
742 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1), 799 CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 0, 0, 63, 1,
800 db_scale_6bit),
743 801
744CS4236_DOUBLE("FM Playback Switch", 0, 802CS4236_DOUBLE("FM Playback Switch", 0,
745 CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1), 803 CS4236_LEFT_FM, CS4236_RIGHT_FM, 7, 7, 1, 1),
746CS4236_DOUBLE("FM Playback Volume", 0, 804CS4236_DOUBLE_TLV("FM Playback Volume", 0,
747 CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1), 805 CS4236_LEFT_FM, CS4236_RIGHT_FM, 0, 0, 63, 1,
806 db_scale_6bit),
748 807
749CS4236_DOUBLE("Wavetable Playback Switch", 0, 808CS4236_DOUBLE("Wavetable Playback Switch", 0,
750 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1), 809 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 7, 7, 1, 1),
751CS4236_DOUBLE("Wavetable Playback Volume", 0, 810CS4236_DOUBLE_TLV("Wavetable Playback Volume", 0,
752 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1), 811 CS4236_LEFT_WAVE, CS4236_RIGHT_WAVE, 0, 0, 63, 1,
812 db_scale_6bit_12db_max),
753 813
754WSS_DOUBLE("Synth Playback Switch", 0, 814WSS_DOUBLE("Synth Playback Switch", 0,
755 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), 815 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
756WSS_DOUBLE("Synth Volume", 0, 816WSS_DOUBLE_TLV("Synth Volume", 0,
757 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), 817 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
818 db_scale_5bit_12db_max),
758WSS_DOUBLE("Synth Capture Switch", 0, 819WSS_DOUBLE("Synth Capture Switch", 0,
759 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), 820 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
760WSS_DOUBLE("Synth Capture Bypass", 0, 821WSS_DOUBLE("Synth Capture Bypass", 0,
@@ -764,14 +825,16 @@ CS4236_DOUBLE("Mic Playback Switch", 0,
764 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), 825 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
765CS4236_DOUBLE("Mic Capture Switch", 0, 826CS4236_DOUBLE("Mic Capture Switch", 0,
766 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), 827 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
767CS4236_DOUBLE("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 0, 0, 31, 1), 828CS4236_DOUBLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, CS4236_RIGHT_MIC,
768CS4236_DOUBLE("Mic Playback Boost", 0, 829 0, 0, 31, 1, db_scale_5bit_22db_max),
830CS4236_DOUBLE("Mic Playback Boost (+20dB)", 0,
769 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0), 831 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 5, 5, 1, 0),
770 832
771WSS_DOUBLE("Line Playback Switch", 0, 833WSS_DOUBLE("Line Playback Switch", 0,
772 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), 834 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
773WSS_DOUBLE("Line Volume", 0, 835WSS_DOUBLE_TLV("Line Volume", 0,
774 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), 836 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
837 db_scale_5bit_12db_max),
775WSS_DOUBLE("Line Capture Switch", 0, 838WSS_DOUBLE("Line Capture Switch", 0,
776 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), 839 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
777WSS_DOUBLE("Line Capture Bypass", 0, 840WSS_DOUBLE("Line Capture Bypass", 0,
@@ -779,57 +842,63 @@ WSS_DOUBLE("Line Capture Bypass", 0,
779 842
780WSS_DOUBLE("CD Playback Switch", 0, 843WSS_DOUBLE("CD Playback Switch", 0,
781 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), 844 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
782WSS_DOUBLE("CD Volume", 0, 845WSS_DOUBLE_TLV("CD Volume", 0,
783 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), 846 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
847 db_scale_5bit_12db_max),
784WSS_DOUBLE("CD Capture Switch", 0, 848WSS_DOUBLE("CD Capture Switch", 0,
785 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), 849 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
786 850
787CS4236_DOUBLE1("Mono Output Playback Switch", 0, 851CS4236_DOUBLE1("Mono Output Playback Switch", 0,
788 CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1), 852 CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
789CS4236_DOUBLE1("Mono Playback Switch", 0, 853CS4236_DOUBLE1("Beep Playback Switch", 0,
790 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), 854 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
791WSS_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), 855WSS_SINGLE_TLV("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1,
792WSS_SINGLE("Mono Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), 856 db_scale_4bit),
857WSS_SINGLE("Beep Bypass Playback Switch", 0, CS4231_MONO_CTRL, 5, 1, 0),
793 858
794WSS_DOUBLE("Capture Volume", 0, 859WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
795 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), 860 0, 0, 15, 0, db_scale_rec_gain),
796WSS_DOUBLE("Analog Loopback Capture Switch", 0, 861WSS_DOUBLE("Analog Loopback Capture Switch", 0,
797 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), 862 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),
798 863
799WSS_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0), 864WSS_SINGLE("Loopback Digital Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
800CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, 865CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0,
801 CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1) 866 CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1,
867 db_scale_6bit),
802}; 868};
803 869
870static const DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0);
871static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0);
872
804static struct snd_kcontrol_new snd_cs4235_controls[] = { 873static struct snd_kcontrol_new snd_cs4235_controls[] = {
805 874
806WSS_DOUBLE("Master Switch", 0, 875WSS_DOUBLE("Master Playback Switch", 0,
807 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1), 876 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
808WSS_DOUBLE("Master Volume", 0, 877WSS_DOUBLE_TLV("Master Playback Volume", 0,
809 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1), 878 CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1,
810 879 db_scale_5bit_6db_max),
811CS4235_OUTPUT_ACCU("Playback Volume", 0),
812 880
813CS4236_DOUBLE("Master Digital Playback Switch", 0, 881CS4235_OUTPUT_ACCU("Playback Volume", 0, db_scale_2bit_16db_max),
814 CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
815CS4236_DOUBLE("Master Digital Capture Switch", 0,
816 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
817CS4236_MASTER_DIGITAL("Master Digital Volume", 0),
818 882
819WSS_DOUBLE("Master Digital Playback Switch", 1, 883WSS_DOUBLE("Synth Playback Switch", 1,
820 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), 884 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
821WSS_DOUBLE("Master Digital Capture Switch", 1, 885WSS_DOUBLE("Synth Capture Switch", 1,
822 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1), 886 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 6, 6, 1, 1),
823WSS_DOUBLE("Master Digital Volume", 1, 887WSS_DOUBLE_TLV("Synth Volume", 1,
824 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), 888 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
889 db_scale_5bit_12db_max),
825 890
826CS4236_DOUBLE("Capture Volume", 0, 891CS4236_DOUBLE_TLV("Capture Volume", 0,
827 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1), 892 CS4236_LEFT_MIX_CTRL, CS4236_RIGHT_MIX_CTRL, 5, 5, 3, 1,
893 db_scale_2bit),
828 894
829WSS_DOUBLE("PCM Switch", 0, 895WSS_DOUBLE("PCM Playback Switch", 0,
830 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), 896 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
831WSS_DOUBLE("PCM Volume", 0, 897WSS_DOUBLE("PCM Capture Switch", 0,
832 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), 898 CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
899WSS_DOUBLE_TLV("PCM Volume", 0,
900 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
901 db_scale_6bit),
833 902
834CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1), 903CS4236_DOUBLE("DSP Switch", 0, CS4236_LEFT_DSP, CS4236_RIGHT_DSP, 7, 7, 1, 1),
835 904
@@ -842,29 +911,29 @@ CS4236_DOUBLE("Mic Capture Switch", 0,
842 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1), 911 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 7, 7, 1, 1),
843CS4236_DOUBLE("Mic Playback Switch", 0, 912CS4236_DOUBLE("Mic Playback Switch", 0,
844 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1), 913 CS4236_LEFT_MIC, CS4236_RIGHT_MIC, 6, 6, 1, 1),
845CS4236_SINGLE("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1), 914CS4236_SINGLE_TLV("Mic Volume", 0, CS4236_LEFT_MIC, 0, 31, 1,
846CS4236_SINGLE("Mic Playback Boost", 0, CS4236_LEFT_MIC, 5, 1, 0), 915 db_scale_5bit_22db_max),
916CS4236_SINGLE("Mic Boost (+20dB)", 0, CS4236_LEFT_MIC, 5, 1, 0),
847 917
848WSS_DOUBLE("Aux Playback Switch", 0, 918WSS_DOUBLE("Line Playback Switch", 0,
849 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), 919 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
850WSS_DOUBLE("Aux Capture Switch", 0, 920WSS_DOUBLE("Line Capture Switch", 0,
851 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1), 921 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 6, 6, 1, 1),
852WSS_DOUBLE("Aux Volume", 0, 922WSS_DOUBLE_TLV("Line Volume", 0,
853 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), 923 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
924 db_scale_5bit_12db_max),
854 925
855WSS_DOUBLE("Aux Playback Switch", 1, 926WSS_DOUBLE("CD Playback Switch", 1,
856 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), 927 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
857WSS_DOUBLE("Aux Capture Switch", 1, 928WSS_DOUBLE("CD Capture Switch", 1,
858 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1), 929 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 6, 6, 1, 1),
859WSS_DOUBLE("Aux Volume", 1, 930WSS_DOUBLE_TLV("CD Volume", 1,
860 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), 931 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
861 932 db_scale_5bit_12db_max),
862CS4236_DOUBLE1("Master Mono Switch", 0,
863 CS4231_MONO_CTRL, CS4236_RIGHT_MIX_CTRL, 6, 7, 1, 1),
864 933
865CS4236_DOUBLE1("Mono Switch", 0, 934CS4236_DOUBLE1("Beep Playback Switch", 0,
866 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1), 935 CS4231_MONO_CTRL, CS4236_LEFT_MIX_CTRL, 7, 7, 1, 1),
867WSS_SINGLE("Mono Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), 936WSS_SINGLE("Beep Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
868 937
869WSS_DOUBLE("Analog Loopback Switch", 0, 938WSS_DOUBLE("Analog Loopback Switch", 0,
870 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0), 939 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 7, 7, 1, 0),