summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorOla Lilja <ola.o.lilja@stericsson.com>2011-07-06 10:25:47 +0200
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 16:07:35 +0200
commit215bc4eaad28cf2bf85ebb5ff9df31a89bcf31e0 (patch)
tree3bad3a1d95b4dc98209a1377d929ce532fc74425 /sound
parent511982bc8298e65b13acec3b3b980bb8263efcda (diff)
Ux500 ASoC: Move mic-regulators into DAPM-paths
Race-conditions could occur when mic-regulators were turned on/off outside DAPM-paths. They are now moved into machine-driver DAPM-paths. ST-Ericsson Linux next: NA ST-Ericsson ID: 348272 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I27b7225326db9c0ccaaabf5aec5bbc9c3cfbd573 Signed-off-by: Ola Lilja <ola.o.lilja@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/26679 Reviewed-by: Roger NILSSON1 <roger.xr.nilsson@stericsson.com> Tested-by: Roger NILSSON1 <roger.xr.nilsson@stericsson.com> Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com> Conflicts: sound/soc/codecs/ab8500_audio.c sound/soc/ux500/ux500_ab8500.c Change-Id: Ic32c44f335a54a7a52fb395503af860ba2aae94d Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30844 Reviewed-by: Roger NILSSON1 <roger.xr.nilsson@stericsson.com> Tested-by: Roger NILSSON1 <roger.xr.nilsson@stericsson.com> Reviewed-by: Avinash A <avinash.a@stericsson.com> Tested-by: Avinash A <avinash.a@stericsson.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/ab8500_audio.c38
-rw-r--r--sound/soc/ux500/ux500_ab8500.c209
2 files changed, 156 insertions, 91 deletions
diff --git a/sound/soc/codecs/ab8500_audio.c b/sound/soc/codecs/ab8500_audio.c
index f7a90b6e80c..a20eb3f7618 100644
--- a/sound/soc/codecs/ab8500_audio.c
+++ b/sound/soc/codecs/ab8500_audio.c
@@ -643,7 +643,7 @@ static const struct snd_kcontrol_new dapm_pwm2vib2[] = {
SOC_DAPM_ENUM("Vibra 2 Controller", dapm_enum_pwm2vib2),
};
-/* DAPM Widgets */
+/* DAPM-widgets */
static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = {
/* Headset path */
@@ -769,7 +769,7 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("LINL"),
SND_SOC_DAPM_INPUT("LINR"),
- SND_SOC_DAPM_INPUT("MIC2"),
+ SND_SOC_DAPM_INPUT("MIC2 Input"),
SND_SOC_DAPM_SWITCH("LineIn Left", SND_SOC_NOPM, 0, 0, dapm_linl_mute),
SND_SOC_DAPM_SWITCH("LineIn Right", SND_SOC_NOPM, 0, 0, dapm_linr_mute),
@@ -806,8 +806,7 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = {
/* Microphone 1 path */
- SND_SOC_DAPM_INPUT("MIC1A"),
- SND_SOC_DAPM_INPUT("MIC1B"),
+ SND_SOC_DAPM_INPUT("MIC1 Input"),
SND_SOC_DAPM_MUX("Mic 1A or 1B Select Capture Route",
SND_SOC_NOPM, 0, 0, dapm_mic1ab_select),
@@ -850,12 +849,7 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = {
/* Digital Microphone path */
- SND_SOC_DAPM_INPUT("DMIC1"),
- SND_SOC_DAPM_INPUT("DMIC2"),
- SND_SOC_DAPM_INPUT("DMIC3"),
- SND_SOC_DAPM_INPUT("DMIC4"),
- SND_SOC_DAPM_INPUT("DMIC5"),
- SND_SOC_DAPM_INPUT("DMIC6"),
+ SND_SOC_DAPM_INPUT("DMIC Input"),
SND_SOC_DAPM_SWITCH("DMic 1", SND_SOC_NOPM, 0, 0, dapm_dmic1_mute),
SND_SOC_DAPM_SWITCH("DMic 2", SND_SOC_NOPM, 0, 0, dapm_dmic2_mute),
@@ -901,9 +895,9 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("STFIR2 Gain", SND_SOC_NOPM, 0, 0, NULL, 0),
};
-/* DAPM interconnection */
+/* DAPM-routes */
-static const struct snd_soc_dapm_route intercon[] = {
+static const struct snd_soc_dapm_route dapm_routes[] = {
/* Headset path */
{"DA1 Channel Gain", NULL, "DA_IN1"},
@@ -989,7 +983,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"LineIn Left", "Capture Switch", "LINL"},
{"LineIn Right", "Capture Switch", "LINR"},
- {"Mic 2", "Capture Switch", "MIC2"},
+ {"Mic 2", "Capture Switch", "MIC2 Input"},
{"LINL Enable", NULL, "LineIn Left"},
{"LINR Enable", NULL, "LineIn Right"},
@@ -1015,8 +1009,8 @@ static const struct snd_soc_dapm_route intercon[] = {
/* Microphone 1 path */
- {"Mic 1A or 1B Select Capture Route", "Mic 1A", "MIC1A"},
- {"Mic 1A or 1B Select Capture Route", "Mic 1B", "MIC1B"},
+ {"Mic 1A or 1B Select Capture Route", "Mic 1A", "MIC1 Input"},
+ {"Mic 1A or 1B Select Capture Route", "Mic 1B", "MIC1 Input"},
{"Mic 1", "Capture Switch", "Mic 1A or 1B Select Capture Route"},
@@ -1048,12 +1042,12 @@ static const struct snd_soc_dapm_route intercon[] = {
/* Digital Microphone path */
- {"DMic 1", "Capture Switch", "DMIC1"},
- {"DMic 2", "Capture Switch", "DMIC2"},
- {"DMic 3", "Capture Switch", "DMIC3"},
- {"DMic 4", "Capture Switch", "DMIC4"},
- {"DMic 5", "Capture Switch", "DMIC5"},
- {"DMic 6", "Capture Switch", "DMIC6"},
+ {"DMic 1", "Capture Switch", "DMIC Input"},
+ {"DMic 2", "Capture Switch", "DMIC Input"},
+ {"DMic 3", "Capture Switch", "DMIC Input"},
+ {"DMic 4", "Capture Switch", "DMIC Input"},
+ {"DMic 5", "Capture Switch", "DMIC Input"},
+ {"DMic 6", "Capture Switch", "DMIC Input"},
{"AD 1 Select Capture Route", "DMic 1", "DMic 1"},
{"AD 2 Select Capture Route", "DMic 2", "DMic 2"},
@@ -2008,7 +2002,7 @@ static int ab8500_codec_add_widgets(struct snd_soc_codec *codec)
return ret;
}
- ret = snd_soc_dapm_add_routes(&codec->dapm, intercon, ARRAY_SIZE(intercon));
+ ret = snd_soc_dapm_add_routes(&codec->dapm, dapm_routes, ARRAY_SIZE(dapm_routes));
if (ret < 0) {
pr_err("%s: Failed to add DAPM routes (%d).\n",
__func__, ret);
diff --git a/sound/soc/ux500/ux500_ab8500.c b/sound/soc/ux500/ux500_ab8500.c
index a58bb7ea62f..c7799c3415b 100644
--- a/sound/soc/ux500/ux500_ab8500.c
+++ b/sound/soc/ux500/ux500_ab8500.c
@@ -19,8 +19,9 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/io.h>
-#include <sound/soc.h>
#include <linux/regulator/consumer.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include <sound/jack.h>
#include <sound/pcm_params.h>
@@ -82,55 +83,6 @@ static bool reg_enabled[4] = {
static unsigned int tx_slots = DEF_TX_SLOTS;
static unsigned int rx_slots = DEF_RX_SLOTS;
-/* Machine-driver ALSA-controls */
-
-static int mclk_input_control_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item) {
- uinfo->value.enumerated.item = 1;
- strcpy(uinfo->value.enumerated.name, "ULPCLK");
- } else {
- strcpy(uinfo->value.enumerated.name, "SYSCLK");
- }
- return 0;
-}
-
-static int mclk_input_control_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.enumerated.item[0] = master_clock_sel;
- return 0;
-}
-
-static int mclk_input_control_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- unsigned int val;
-
- val = (ucontrol->value.enumerated.item[0] != 0);
- if (master_clock_sel == val)
- return 0;
-
- master_clock_sel = val;
-
- return 1;
-}
-
-static const struct snd_kcontrol_new mclk_input_control = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Clock Select",
- .index = 0,
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = mclk_input_control_info,
- .get = mclk_input_control_get,
- .put = mclk_input_control_put,
- .private_value = 1 /* ULPCLK */
-};
-
/* Regulators */
static int enable_regulator(enum regulator_idx idx)
@@ -209,6 +161,137 @@ err_get:
return status;
}
+/* Controls - Non-DAPM Non-ASoC */
+
+static int mclk_input_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item) {
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name, "ULPCLK");
+ } else {
+ strcpy(uinfo->value.enumerated.name, "SYSCLK");
+ }
+ return 0;
+}
+
+static int mclk_input_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] = master_clock_sel;
+ return 0;
+}
+
+static int mclk_input_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ unsigned int val;
+
+ val = (ucontrol->value.enumerated.item[0] != 0);
+ if (master_clock_sel == val)
+ return 0;
+
+ master_clock_sel = val;
+
+ return 1;
+}
+
+static const struct snd_kcontrol_new mclk_input_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Clock Select",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = mclk_input_control_info,
+ .get = mclk_input_control_get,
+ .put = mclk_input_control_put,
+ .private_value = 1 /* ULPCLK */
+};
+
+/* DAPM-events */
+
+static int dapm_mic1reg_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ int ret = 0;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ ret = enable_regulator(REGULATOR_AMIC1);
+ else
+ disable_regulator(REGULATOR_AMIC1);
+
+ return ret;
+}
+
+static int dapm_mic2reg_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ int ret = 0;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ ret = enable_regulator(REGULATOR_AMIC2);
+ else
+ disable_regulator(REGULATOR_AMIC2);
+
+ return ret;
+}
+
+static int dapm_dmicreg_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ int ret = 0;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ ret = enable_regulator(REGULATOR_DMIC);
+ else
+ disable_regulator(REGULATOR_DMIC);
+
+ return ret;
+}
+
+/* DAPM-widgets */
+
+static const struct snd_soc_dapm_widget ux500_ab8500_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("MIC1 Regulator", dapm_mic1reg_event),
+ SND_SOC_DAPM_MIC("MIC2 Regulator", dapm_mic2reg_event),
+ SND_SOC_DAPM_MIC("DMIC Regulator", dapm_dmicreg_event),
+};
+
+/* DAPM-routes */
+
+static const struct snd_soc_dapm_route ux500_ab8500_dapm_intercon[] = {
+ {"MIC1 Input", NULL, "MIC1 Regulator"},
+ {"MIC2 Input", NULL, "MIC2 Regulator"},
+ {"DMIC Input", NULL, "DMIC Regulator"},
+};
+
+static int add_widgets(struct snd_soc_codec *codec)
+{
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(&codec->dapm,
+ ux500_ab8500_dapm_widgets,
+ ARRAY_SIZE(ux500_ab8500_dapm_widgets));
+ if (ret < 0) {
+ pr_err("%s: Failed to create DAPM controls (%d).\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_add_routes(&codec->dapm,
+ ux500_ab8500_dapm_intercon,
+ ARRAY_SIZE(ux500_ab8500_dapm_intercon));
+ if (ret < 0) {
+ pr_err("%s: Failed to add DAPM routes (%d).\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/* Power/clock control */
static int ux500_ab8500_power_control_inc(void)
@@ -295,18 +378,6 @@ int ux500_ab8500_startup(struct snd_pcm_substream *substream)
pr_debug("%s: Enter\n", __func__);
- /* If we start recording we better enable the needed mic-regulators */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- if (ab8500_audio_dapm_path_active(AB8500_AUDIO_DAPM_PATH_DMIC))
- ret += enable_regulator(REGULATOR_DMIC);
- if (ab8500_audio_dapm_path_active(AB8500_AUDIO_DAPM_PATH_AMIC1))
- ret += enable_regulator(REGULATOR_AMIC1);
- if (ab8500_audio_dapm_path_active(AB8500_AUDIO_DAPM_PATH_AMIC2))
- ret += enable_regulator(REGULATOR_AMIC2);
- if (ret != 0)
- return ret;
- }
-
/* Enable gpio.1-clock (needed by DSP in burst mode) */
ret = clk_enable(clk_ptr_gpio1);
if (ret) {
@@ -327,13 +398,6 @@ void ux500_ab8500_shutdown(struct snd_pcm_substream *substream)
else
rx_slots = DEF_RX_SLOTS;
- /* Disable all mic-regulators that were enabled when we stop recording */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- disable_regulator(REGULATOR_DMIC);
- disable_regulator(REGULATOR_AMIC1);
- disable_regulator(REGULATOR_AMIC2);
- }
-
clk_disable(clk_ptr_gpio1);
ux500_ab8500_power_control_dec();
}
@@ -528,6 +592,13 @@ int ux500_ab8500_machine_codec_init(struct snd_soc_pcm_runtime *rtd)
ab8500_power_count = 0;
+ /* Add DAPM-widgets */
+ ret = add_widgets(codec);
+ if (ret < 0) {
+ pr_err("%s: Failed add widgets (%d).\n", __func__, ret);
+ return ret;
+ }
+
return 0;
}