Some of TWL4030's input selection are in bitfield, which needs special helper function to deal with. For example: PREDL_CTL register: bit 0 (0x1): voice_en bit 1 (0x2): Audio L1 enable (DACL1) bit 2 (0x4): Audio L2 enable (DACL2) bit 3 (0x8): Audio R2 enable (DACR2)
Signed-off-by: Peter Ujfalusi peter.ujfalusi@nokia.com --- sound/soc/codecs/twl4030.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 91effd3..17f2b51 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -191,6 +191,57 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) }
/* + * Some of TWL's input selection are in bitfield. + * Dealing with those need special function + * For example: PREDL_CTL register: + * bit 0 (0x1): voice_en + * bit 1 (0x2): Audio L1 enable (DACL1) + * bit 2 (0x4): Audio L2 enable (DACL2) + * bit 3 (0x8): Audio R2 enable (DACR2) + */ +static int snd_soc_get_enum_twl4030(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int val_mask = 0; + int i; + int val = twl4030_read_reg_cache(codec, e->reg); + + for (i = 0; i < e->max - 1; i++) + val_mask |= (1 << i); + + val = (val >> e->shift_l) & val_mask; + i = 0; + while (val && i++ < e->max) + val >>= 1; + + ucontrol->value.integer.value[0] = i; + return 0; +} + +static int snd_soc_put_enum_twl4030(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int val_mask = 0; + int val = 0; + int i; + + for (i = 0; i < e->max - 1; i++) + val_mask |= (1 << i); + val_mask <<= e->shift_l; + + if (ucontrol->value.integer.value[0]) { + val = (1 << (ucontrol->value.integer.value[0] - 1)); + val <<= e->shift_l; + } + + return snd_soc_update_bits(codec, e->reg, val_mask, val); +} + +/* * FGAIN volume control: * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB) */