diff options
Diffstat (limited to 'sound/pci/ca0106/ca0106_mixer.c')
-rw-r--r-- | sound/pci/ca0106/ca0106_mixer.c | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index a135b9c4c3c8..7fbfe17438b4 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.17 | 4 | * Version: 0.0.18 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -39,6 +39,8 @@ | |||
39 | * Modified Copyright message. | 39 | * Modified Copyright message. |
40 | * 0.0.17 | 40 | * 0.0.17 |
41 | * Implement Mic and Line in Capture. | 41 | * Implement Mic and Line in Capture. |
42 | * 0.0.18 | ||
43 | * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) | ||
42 | * | 44 | * |
43 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 45 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
44 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | 46 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
@@ -462,6 +464,42 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, | |||
462 | return change; | 464 | return change; |
463 | } | 465 | } |
464 | 466 | ||
467 | #define spi_mute_info snd_ctl_boolean_mono_info | ||
468 | |||
469 | static int spi_mute_get(struct snd_kcontrol *kcontrol, | ||
470 | struct snd_ctl_elem_value *ucontrol) | ||
471 | { | ||
472 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
473 | unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; | ||
474 | unsigned int bit = kcontrol->private_value & SPI_REG_MASK; | ||
475 | |||
476 | ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit); | ||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int spi_mute_put(struct snd_kcontrol *kcontrol, | ||
481 | struct snd_ctl_elem_value *ucontrol) | ||
482 | { | ||
483 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
484 | unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT; | ||
485 | unsigned int bit = kcontrol->private_value & SPI_REG_MASK; | ||
486 | int ret; | ||
487 | |||
488 | ret = emu->spi_dac_reg[reg] & bit; | ||
489 | if (ucontrol->value.integer.value[0]) { | ||
490 | if (!ret) /* bit already cleared, do nothing */ | ||
491 | return 0; | ||
492 | emu->spi_dac_reg[reg] &= ~bit; | ||
493 | } else { | ||
494 | if (ret) /* bit already set, do nothing */ | ||
495 | return 0; | ||
496 | emu->spi_dac_reg[reg] |= bit; | ||
497 | } | ||
498 | |||
499 | ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); | ||
500 | return ret ? -1 : 1; | ||
501 | } | ||
502 | |||
465 | #define CA_VOLUME(xname,chid,reg) \ | 503 | #define CA_VOLUME(xname,chid,reg) \ |
466 | { \ | 504 | { \ |
467 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 505 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
@@ -554,6 +592,28 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = | |||
554 | I2C_VOLUME("Aux Capture Volume", 3), | 592 | I2C_VOLUME("Aux Capture Volume", 3), |
555 | }; | 593 | }; |
556 | 594 | ||
595 | #define SPI_SWITCH(xname,reg,bit) \ | ||
596 | { \ | ||
597 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
598 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
599 | .info = spi_mute_info, \ | ||
600 | .get = spi_mute_get, \ | ||
601 | .put = spi_mute_put, \ | ||
602 | .private_value = (reg<<SPI_REG_SHIFT) | (1<<bit) \ | ||
603 | } | ||
604 | |||
605 | static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[] | ||
606 | __devinitdata = { | ||
607 | SPI_SWITCH("Analog Front Playback Switch", | ||
608 | SPI_DMUTE4_REG, SPI_DMUTE4_BIT), | ||
609 | SPI_SWITCH("Analog Rear Playback Switch", | ||
610 | SPI_DMUTE0_REG, SPI_DMUTE0_BIT), | ||
611 | SPI_SWITCH("Analog Center/LFE Playback Switch", | ||
612 | SPI_DMUTE2_REG, SPI_DMUTE2_BIT), | ||
613 | SPI_SWITCH("Analog Side Playback Switch", | ||
614 | SPI_DMUTE1_REG, SPI_DMUTE1_BIT), | ||
615 | }; | ||
616 | |||
557 | static int __devinit remove_ctl(struct snd_card *card, const char *name) | 617 | static int __devinit remove_ctl(struct snd_card *card, const char *name) |
558 | { | 618 | { |
559 | struct snd_ctl_elem_id id; | 619 | struct snd_ctl_elem_id id; |
@@ -650,6 +710,13 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
650 | if (err < 0) | 710 | if (err < 0) |
651 | return err; | 711 | return err; |
652 | } | 712 | } |
713 | if (emu->details->spi_dac == 1) { | ||
714 | for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_spi_dac_ctls); i++) { | ||
715 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_spi_dac_ctls[i], emu)); | ||
716 | if (err < 0) | ||
717 | return err; | ||
718 | } | ||
719 | } | ||
653 | return 0; | 720 | return 0; |
654 | } | 721 | } |
655 | 722 | ||