aboutsummaryrefslogtreecommitdiff
path: root/sound/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/i2c')
-rw-r--r--sound/i2c/other/ak4xxx-adda.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 7d562f08420..d76d8b078a8 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -472,6 +472,57 @@ static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol,
return change;
}
+static int ak4xxx_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
+ int shift = AK_GET_SHIFT(kcontrol->private_value);
+ int invert = AK_GET_INVERT(kcontrol->private_value);
+ unsigned char val = snd_akm4xxx_get(ak, chip, addr);
+
+ if (invert)
+ val = ! val;
+ ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0;
+ return 0;
+}
+
+static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
+ int chip = AK_GET_CHIP(kcontrol->private_value);
+ int addr = AK_GET_ADDR(kcontrol->private_value);
+ int shift = AK_GET_SHIFT(kcontrol->private_value);
+ int invert = AK_GET_INVERT(kcontrol->private_value);
+ long flag = ucontrol->value.integer.value[0];
+ unsigned char val, oval;
+ int change;
+
+ if (invert)
+ flag = ! flag;
+ oval = snd_akm4xxx_get(ak, chip, addr);
+ if (flag)
+ val = oval | (1<<shift);
+ else
+ val = oval & ~(1<<shift);
+ change = (oval != val);
+ if (change)
+ snd_akm4xxx_write(ak, chip, addr, val);
+ return change;
+}
+
/*
* build AK4xxx controls
*/
@@ -621,6 +672,27 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
SNDRV_CTL_ELEM_ACCESS_WRITE));
if (err < 0)
goto __error;
+
+ memset(ctl, 0, sizeof(*ctl));
+ if (ak->channel_names == NULL)
+ strcpy(ctl->id.name, "Capture Switch");
+ else
+ strcpy(ctl->id.name, ak->channel_names[1]);
+ ctl->id.index = ak->idx_offset * 2;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = ak4xxx_switch_info;
+ ctl->get = ak4xxx_switch_get;
+ ctl->put = ak4xxx_switch_put;
+ /* register 2, bit 0 (SMUTE): 0 = normal operation, 1 = mute */
+ ctl->private_value =
+ AK_COMPOSE(0, 2, 0, 0) | AK_INVERT;
+ ctl->private_data = ak;
+ err = snd_ctl_add(ak->card,
+ snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|
+ SNDRV_CTL_ELEM_ACCESS_WRITE));
+ if (err < 0)
+ goto __error;
}
if (ak->type == SND_AK4355 || ak->type == SND_AK4358)