diff options
-rw-r--r-- | sound/soc/codecs/twl4030.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index abf691493f43..731534c19b7f 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -814,6 +814,48 @@ static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, | |||
814 | return err; | 814 | return err; |
815 | } | 815 | } |
816 | 816 | ||
817 | /* Codec operation modes */ | ||
818 | static const char *twl4030_op_modes_texts[] = { | ||
819 | "Option 2 (voice/audio)", "Option 1 (audio)" | ||
820 | }; | ||
821 | |||
822 | static const struct soc_enum twl4030_op_modes_enum = | ||
823 | SOC_ENUM_SINGLE(TWL4030_REG_CODEC_MODE, 0, | ||
824 | ARRAY_SIZE(twl4030_op_modes_texts), | ||
825 | twl4030_op_modes_texts); | ||
826 | |||
827 | int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, | ||
828 | struct snd_ctl_elem_value *ucontrol) | ||
829 | { | ||
830 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
831 | struct twl4030_priv *twl4030 = codec->private_data; | ||
832 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
833 | unsigned short val; | ||
834 | unsigned short mask, bitmask; | ||
835 | |||
836 | if (twl4030->configured) { | ||
837 | printk(KERN_ERR "twl4030 operation mode cannot be " | ||
838 | "changed on-the-fly\n"); | ||
839 | return -EBUSY; | ||
840 | } | ||
841 | |||
842 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
843 | ; | ||
844 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | ||
845 | return -EINVAL; | ||
846 | |||
847 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | ||
848 | mask = (bitmask - 1) << e->shift_l; | ||
849 | if (e->shift_l != e->shift_r) { | ||
850 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | ||
851 | return -EINVAL; | ||
852 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | ||
853 | mask |= (bitmask - 1) << e->shift_r; | ||
854 | } | ||
855 | |||
856 | return snd_soc_update_bits(codec, e->reg, mask, val); | ||
857 | } | ||
858 | |||
817 | /* | 859 | /* |
818 | * FGAIN volume control: | 860 | * FGAIN volume control: |
819 | * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB) | 861 | * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB) |
@@ -895,6 +937,11 @@ static const struct soc_enum twl4030_vibradir_enum = | |||
895 | twl4030_vibradir_texts); | 937 | twl4030_vibradir_texts); |
896 | 938 | ||
897 | static const struct snd_kcontrol_new twl4030_snd_controls[] = { | 939 | static const struct snd_kcontrol_new twl4030_snd_controls[] = { |
940 | /* Codec operation mode control */ | ||
941 | SOC_ENUM_EXT("Codec Operation Mode", twl4030_op_modes_enum, | ||
942 | snd_soc_get_enum_double, | ||
943 | snd_soc_put_twl4030_opmode_enum_double), | ||
944 | |||
898 | /* Common playback gain controls */ | 945 | /* Common playback gain controls */ |
899 | SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", | 946 | SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", |
900 | TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, | 947 | TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, |