X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=sound%2Fpci%2Fca0106%2Fca0106_mixer.c;h=3025ed1b6e1efd1444ccf5d3403d4ca7ab36627c;hb=b17b3d479c4c43c3a980ee553c3be3ca456523de;hp=be519a17dfa513eb22eb610f98c2c0fbfaaf6d87;hpb=0b776eb5426752d4e53354ac89e3710d857e09a7;p=linux-2.6 diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index be519a17df..3025ed1b6e 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -60,7 +60,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#include #include #include #include @@ -86,7 +85,7 @@ static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol, { struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = emu->spdif_enable; + ucontrol->value.integer.value[0] = emu->spdif_enable; return 0; } @@ -98,11 +97,11 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol, int change = 0; u32 mask; - val = ucontrol->value.enumerated.item[0] ; + val = !!ucontrol->value.integer.value[0]; change = (emu->spdif_enable != val); if (change) { emu->spdif_enable = val; - if (val == 1) { + if (val) { /* Digital */ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); @@ -159,6 +158,8 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, u32 source; val = ucontrol->value.enumerated.item[0] ; + if (val >= 6) + return -EINVAL; change = (emu->capture_source != val); if (change) { emu->capture_source = val; @@ -207,6 +208,8 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, * for the particular source. */ source_id = ucontrol->value.enumerated.item[0] ; + if (source_id >= 4) + return -EINVAL; change = (emu->i2c_capture_source != source_id); if (change) { snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ @@ -271,6 +274,8 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, u32 tmp; val = ucontrol->value.enumerated.item[0] ; + if (val > 1) + return -EINVAL; change = (emu->capture_mic_line_in != val); if (change) { emu->capture_mic_line_in = val; @@ -443,7 +448,7 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ ngain = ucontrol->value.integer.value[0]; if (ngain > 0xff) - return 0; + return -EINVAL; if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); @@ -453,7 +458,7 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ ngain = ucontrol->value.integer.value[1]; if (ngain > 0xff) - return 0; + return -EINVAL; if (ogain != ngain) { if (emu->i2c_capture_source == source_id) snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); @@ -497,7 +502,7 @@ static int spi_mute_put(struct snd_kcontrol *kcontrol, } ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]); - return ret ? -1 : 1; + return ret ? -EINVAL : 1; } #define CA_VOLUME(xname,chid,reg) \ @@ -645,19 +650,55 @@ static int __devinit rename_ctl(struct snd_card *card, const char *src, const ch #define ADD_CTLS(emu, ctls) \ do { \ - int i, err; \ + int i, _err; \ for (i = 0; i < ARRAY_SIZE(ctls); i++) { \ - err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \ - if (err < 0) \ - return err; \ + _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \ + if (_err < 0) \ + return _err; \ } \ } while (0) +static __devinitdata +DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 50, 1); + +static char *slave_vols[] __devinitdata = { + "Analog Front Playback Volume", + "Analog Rear Playback Volume", + "Analog Center/LFE Playback Volume", + "Analog Side Playback Volume", + "IEC958 Front Playback Volume", + "IEC958 Rear Playback Volume", + "IEC958 Center/LFE Playback Volume", + "IEC958 Unknown Playback Volume", + "CAPTURE feedback Playback Volume", + NULL +}; + +static char *slave_sws[] __devinitdata = { + "Analog Front Playback Switch", + "Analog Rear Playback Switch", + "Analog Center/LFE Playback Switch", + "Analog Side Playback Switch", + "IEC958 Playback Switch", + NULL +}; + +static void __devinit add_slaves(struct snd_card *card, + struct snd_kcontrol *master, char **list) +{ + for (; *list; list++) { + struct snd_kcontrol *slave = ctl_find(card, *list); + if (slave) + snd_ctl_add_slave(master, slave); + } +} + int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) { int err; struct snd_card *card = emu->card; char **c; + struct snd_kcontrol *vmaster; static char *ca0106_remove_ctls[] = { "Master Mono Playback Switch", "Master Mono Playback Volume", @@ -714,6 +755,21 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) } if (emu->details->spi_dac == 1) ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls); + + /* Create virtual master controls */ + vmaster = snd_ctl_make_virtual_master("Master Playback Volume", + snd_ca0106_master_db_scale); + if (!vmaster) + return -ENOMEM; + add_slaves(card, vmaster, slave_vols); + + if (emu->details->spi_dac == 1) { + vmaster = snd_ctl_make_virtual_master("Master Playback Switch", + NULL); + if (!vmaster) + return -ENOMEM; + add_slaves(card, vmaster, slave_sws); + } return 0; }