aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/twl6040.c
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2011-10-12 04:57:57 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-10-12 06:48:52 -0400
commit67c341302f5a401a405be758250bada39746c96b (patch)
tree181f7fedaadaa32f4df3ad7b9118b3bab0a8b542 /sound/soc/codecs/twl6040.c
parent5f07c32e289d159be3fc1e4f257e8cad5336f83a (diff)
ASoC: twl6040: Support for vibra output paths
twl6040 have two vibra output drivers. They can be operated with audio stream coming through the PDM interface (fifth channel). The vibra outputs can be controlled via the input/FF driver as well. Selection between the two mode is implemented within the codec driver, the input/FF driver can only operate if the routing is set to "Input FF". Changing from "Input FF" to "Audio PDM" mode is protected as well: The switchin can only be done, if there is no running effect from the input/FF. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/twl6040.c')
-rw-r--r--sound/soc/codecs/twl6040.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 93f8a59a086d..864849838f4d 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -803,6 +803,23 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
803 return 0; 803 return 0;
804} 804}
805 805
806static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
807 struct snd_ctl_elem_value *ucontrol)
808{
809 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
810 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
811 struct snd_soc_codec *codec = widget->codec;
812 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
813 unsigned int val;
814
815 /* Do not allow changes while Input/FF efect is running */
816 val = twl6040_read_reg_volatile(codec, e->reg);
817 if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL))
818 return -EBUSY;
819
820 return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
821}
822
806/* 823/*
807 * MICATT volume control: 824 * MICATT volume control:
808 * from -6 to 0 dB in 6 dB steps 825 * from -6 to 0 dB in 6 dB steps
@@ -874,6 +891,19 @@ static const struct soc_enum twl6040_hf_enum[] = {
874 twl6040_hf_texts), 891 twl6040_hf_texts),
875}; 892};
876 893
894static const char *twl6040_vibrapath_texts[] = {
895 "Input FF", "Audio PDM"
896};
897
898static const struct soc_enum twl6040_vibra_enum[] = {
899 SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1,
900 ARRAY_SIZE(twl6040_vibrapath_texts),
901 twl6040_vibrapath_texts),
902 SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1,
903 ARRAY_SIZE(twl6040_vibrapath_texts),
904 twl6040_vibrapath_texts),
905};
906
877static const struct snd_kcontrol_new amicl_control = 907static const struct snd_kcontrol_new amicl_control =
878 SOC_DAPM_ENUM("Route", twl6040_enum[0]); 908 SOC_DAPM_ENUM("Route", twl6040_enum[0]);
879 909
@@ -903,6 +933,17 @@ static const struct snd_kcontrol_new auxl_switch_control =
903static const struct snd_kcontrol_new auxr_switch_control = 933static const struct snd_kcontrol_new auxr_switch_control =
904 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0); 934 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0);
905 935
936/* Vibra playback switches */
937static const struct snd_kcontrol_new vibral_mux_controls =
938 SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0],
939 snd_soc_dapm_get_enum_double,
940 twl6040_soc_dapm_put_vibra_enum);
941
942static const struct snd_kcontrol_new vibrar_mux_controls =
943 SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1],
944 snd_soc_dapm_get_enum_double,
945 twl6040_soc_dapm_put_vibra_enum);
946
906/* Headset power mode */ 947/* Headset power mode */
907static const char *twl6040_power_mode_texts[] = { 948static const char *twl6040_power_mode_texts[] = {
908 "Low-Power", "High-Perfomance", 949 "Low-Power", "High-Perfomance",
@@ -1024,6 +1065,8 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
1024 SND_SOC_DAPM_OUTPUT("EP"), 1065 SND_SOC_DAPM_OUTPUT("EP"),
1025 SND_SOC_DAPM_OUTPUT("AUXL"), 1066 SND_SOC_DAPM_OUTPUT("AUXL"),
1026 SND_SOC_DAPM_OUTPUT("AUXR"), 1067 SND_SOC_DAPM_OUTPUT("AUXR"),
1068 SND_SOC_DAPM_OUTPUT("VIBRAL"),
1069 SND_SOC_DAPM_OUTPUT("VIBRAR"),
1027 1070
1028 /* Analog input muxes for the capture amplifiers */ 1071 /* Analog input muxes for the capture amplifiers */
1029 SND_SOC_DAPM_MUX("Analog Left Capture Route", 1072 SND_SOC_DAPM_MUX("Analog Left Capture Route",
@@ -1076,6 +1119,9 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
1076 TWL6040_REG_HFRCTL, 0, 0, 1119 TWL6040_REG_HFRCTL, 0, 0,
1077 twl6040_power_mode_event, 1120 twl6040_power_mode_event,
1078 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1121 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1122 /* Virtual DAC for vibra path (DL4 channel) */
1123 SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback",
1124 SND_SOC_NOPM, 0, 0),
1079 1125
1080 SND_SOC_DAPM_MUX("Handsfree Left Playback", 1126 SND_SOC_DAPM_MUX("Handsfree Left Playback",
1081 SND_SOC_NOPM, 0, 0, &hfl_mux_controls), 1127 SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
@@ -1087,6 +1133,11 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
1087 SND_SOC_DAPM_MUX("Headset Right Playback", 1133 SND_SOC_DAPM_MUX("Headset Right Playback",
1088 SND_SOC_NOPM, 0, 0, &hsr_mux_controls), 1134 SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
1089 1135
1136 SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0,
1137 &vibral_mux_controls),
1138 SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0,
1139 &vibrar_mux_controls),
1140
1090 SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0, 1141 SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
1091 &ep_path_enable_control), 1142 &ep_path_enable_control),
1092 SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0, 1143 SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0,
@@ -1115,6 +1166,15 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
1115 TWL6040_REG_EARCTL, 0, 0, NULL, 0, 1166 TWL6040_REG_EARCTL, 0, 0, NULL, 0,
1116 twl6040_power_mode_event, 1167 twl6040_power_mode_event,
1117 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 1168 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1169 SND_SOC_DAPM_OUT_DRV("Vibra Left Driver",
1170 TWL6040_REG_VIBCTLL, 0, 0, NULL, 0),
1171 SND_SOC_DAPM_OUT_DRV("Vibra Right Driver",
1172 TWL6040_REG_VIBCTLR, 0, 0, NULL, 0),
1173
1174 SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0,
1175 NULL, 0),
1176 SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0,
1177 NULL, 0),
1118 1178
1119 /* Analog playback PGAs */ 1179 /* Analog playback PGAs */
1120 SND_SOC_DAPM_PGA("HF Left PGA", 1180 SND_SOC_DAPM_PGA("HF Left PGA",
@@ -1181,6 +1241,18 @@ static const struct snd_soc_dapm_route intercon[] = {
1181 1241
1182 {"AUXL", NULL, "AUXL Playback"}, 1242 {"AUXL", NULL, "AUXL Playback"},
1183 {"AUXR", NULL, "AUXR Playback"}, 1243 {"AUXR", NULL, "AUXR Playback"},
1244
1245 /* Vibrator paths */
1246 {"Vibra Left Playback", "Audio PDM", "VIBRA DAC"},
1247 {"Vibra Right Playback", "Audio PDM", "VIBRA DAC"},
1248
1249 {"Vibra Left Driver", NULL, "Vibra Left Playback"},
1250 {"Vibra Right Driver", NULL, "Vibra Right Playback"},
1251 {"Vibra Left Driver", NULL, "Vibra Left Control"},
1252 {"Vibra Right Driver", NULL, "Vibra Right Control"},
1253
1254 {"VIBRAL", NULL, "Vibra Left Driver"},
1255 {"VIBRAR", NULL, "Vibra Right Driver"},
1184}; 1256};
1185 1257
1186static int twl6040_set_bias_level(struct snd_soc_codec *codec, 1258static int twl6040_set_bias_level(struct snd_soc_codec *codec,