From 627305eeba0851a7c1012193378fad27eb03c5e8 Mon Sep 17 00:00:00 2001 From: Jorge Eduardo Candelaria Date: Thu, 8 Apr 2010 13:14:59 -0500 Subject: ASoC: ABE-TWL6040: Correct widget handling for drivers In order to reduce pop-noise at powering up/down of the DACs and Drivers, these components have to be handled in a specific sequence. Headset, Handsfree, and Earphone drivers are now registered as PGA components to ensure DACs are enabled first. Also, add a pop_time of 1 ms to leave time for DACs to settle before continuing power up/down sequence. Signed-off-by: Jorge Eduardo Candelaria --- sound/soc/codecs/abe-twl6040.c | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/sound/soc/codecs/abe-twl6040.c b/sound/soc/codecs/abe-twl6040.c index 06a84207675a..af0e5fb0dcef 100644 --- a/sound/soc/codecs/abe-twl6040.c +++ b/sound/soc/codecs/abe-twl6040.c @@ -636,20 +636,6 @@ static const struct snd_kcontrol_new hfdacl_switch_controls = static const struct snd_kcontrol_new hfdacr_switch_controls = SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 2, 1, 0); -/* Headset driver switches */ -static const struct snd_kcontrol_new hsl_driver_switch_controls = - SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSLCTL, 2, 1, 0); - -static const struct snd_kcontrol_new hsr_driver_switch_controls = - SOC_DAPM_SINGLE("Switch", TWL6040_REG_HSRCTL, 2, 1, 0); - -/* Handsfree driver switches */ -static const struct snd_kcontrol_new hfl_driver_switch_controls = - SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 4, 1, 0); - -static const struct snd_kcontrol_new hfr_driver_switch_controls = - SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 4, 1, 0); - static const struct snd_kcontrol_new ep_driver_switch_controls = SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0); @@ -721,11 +707,11 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("AIFIN Tones", "Playback", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_IN("AIFIN Voice", "Playback", 1, + SND_SOC_DAPM_AIF_IN("AIFIN Voice", "Playback", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_IN("AIFIN Multimedia Uplink", "Playback", 2, + SND_SOC_DAPM_AIF_IN("AIFIN Multimedia Uplink", "Playback", 0, SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_AIF_IN("AIFIN Multimedia", "Playback", 3, + SND_SOC_DAPM_AIF_IN("AIFIN Multimedia", "Playback", 0, SND_SOC_NOPM, 0, 0), /* DACs */ @@ -752,18 +738,19 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("HFDAC Right Playback", SND_SOC_NOPM, 0, 0, &hfdacr_switch_controls), - SND_SOC_DAPM_SWITCH("Headset Left Driver", - SND_SOC_NOPM, 0, 0, &hsl_driver_switch_controls), - SND_SOC_DAPM_SWITCH("Headset Right Driver", - SND_SOC_NOPM, 0, 0, &hsr_driver_switch_controls), - SND_SOC_DAPM_SWITCH_E("Handsfree Left Driver", - SND_SOC_NOPM, 0, 0, &hfl_driver_switch_controls, + /* Analog playback drivers */ + SND_SOC_DAPM_PGA_E("Handsfree Left Driver", + TWL6040_REG_HFLCTL, 4, 0, NULL, 0, twl6040_power_mode_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_SWITCH_E("Handsfree Right Driver", - SND_SOC_NOPM, 0, 0, &hfr_driver_switch_controls, + SND_SOC_DAPM_PGA_E("Handsfree Right Driver", + TWL6040_REG_HFRCTL, 4, 0, NULL, 0, twl6040_power_mode_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA("Headset Left Driver", + TWL6040_REG_HSLCTL, 2, 0, NULL, 0), + SND_SOC_DAPM_PGA("Headset Right Driver", + TWL6040_REG_HSRCTL, 2, 0, NULL, 0), SND_SOC_DAPM_SWITCH_E("Earphone Driver", SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls, twl6040_power_mode_event, @@ -805,8 +792,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"HSDAC Left Playback", "Switch", "HSDAC Left"}, {"HSDAC Right Playback", "Switch", "HSDAC Right"}, - {"Headset Left Driver", "Switch", "HSDAC Left Playback"}, - {"Headset Right Driver", "Switch", "HSDAC Right Playback"}, + {"Headset Left Driver", NULL, "HSDAC Left Playback"}, + {"Headset Right Driver", NULL, "HSDAC Right Playback"}, {"HSOL", NULL, "Headset Left Driver"}, {"HSOR", NULL, "Headset Right Driver"}, @@ -1578,6 +1565,7 @@ static int __devinit abe_twl6040_codec_probe(struct platform_device *pdev) priv->naudint = naudint; codec = &priv->codec; + codec->pop_time = 1; codec->dev = &pdev->dev; codec->name = "twl6040"; codec->owner = THIS_MODULE; -- cgit v1.2.3 From a60000ef173ddce2fd265f795959738fd49b800b Mon Sep 17 00:00:00 2001 From: Jorge Eduardo Candelaria Date: Thu, 8 Apr 2010 13:29:13 -0500 Subject: ASoC: OMAP4: Move trigger handling to ABE A loud pop-noise was heard when pausing/releasing a stream, caused by incorrect handling of of trigger callback. To correct this, McPDM enables its channels before DAPM powers up codec components, leaving ABE in charge of starting/stopping the data transfer when triggered. Signed-off-by: Jorge Eduardo Candelaria --- sound/soc/codecs/abe-twl6040.c | 2 ++ sound/soc/omap/omap-abe.c | 35 ++++------------------------------- sound/soc/omap/omap-mcpdm.c | 35 ++++------------------------------- 3 files changed, 10 insertions(+), 62 deletions(-) diff --git a/sound/soc/codecs/abe-twl6040.c b/sound/soc/codecs/abe-twl6040.c index af0e5fb0dcef..022a49a0b6ca 100644 --- a/sound/soc/codecs/abe-twl6040.c +++ b/sound/soc/codecs/abe-twl6040.c @@ -1179,12 +1179,14 @@ static int abe_mm_trigger(struct snd_pcm_substream *substream, priv->sysclk); return -EPERM; } + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (!substream->stream) abe_enable_data_transfer(MM_DL_PORT); else abe_enable_data_transfer(MM_UL_PORT); break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (!substream->stream) abe_disable_data_transfer(MM_DL_PORT); else diff --git a/sound/soc/omap/omap-abe.c b/sound/soc/omap/omap-abe.c index a7ee806675c2..9c1b9bc4e317 100644 --- a/sound/soc/omap/omap-abe.c +++ b/sound/soc/omap/omap-abe.c @@ -112,36 +112,6 @@ static void omap_abe_dai_shutdown(struct snd_pcm_substream *substream, omap_mcpdm_free(); } -static int omap_abe_dai_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; - int stream = substream->stream; - int err = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!mcpdm_priv->active[stream]++) - omap_mcpdm_start(stream); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (!--mcpdm_priv->active[stream]) - omap_mcpdm_stop(stream); - break; - default: - err = -EINVAL; - } - - return err; -} - static int omap_abe_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -213,6 +183,8 @@ static int omap_abe_dai_hw_params(struct snd_pcm_substream *substream, else err = omap_mcpdm_capture_open(&mcpdm_links[stream]); + omap_mcpdm_start(stream); + return err; } @@ -231,13 +203,14 @@ static int omap_abe_dai_hw_free(struct snd_pcm_substream *substream, else err = omap_mcpdm_capture_close(&mcpdm_links[stream]); + omap_mcpdm_stop(stream); + return err; } static struct snd_soc_dai_ops omap_abe_dai_ops = { .startup = omap_abe_dai_startup, .shutdown = omap_abe_dai_shutdown, - .trigger = omap_abe_dai_trigger, .hw_params = omap_abe_dai_hw_params, .hw_free = omap_abe_dai_hw_free, }; diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 25f19e4728bf..9fe0dea89756 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -109,36 +109,6 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, omap_mcpdm_free(); } -static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data; - int stream = substream->stream; - int err = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!mcpdm_priv->active++) - omap_mcpdm_start(stream); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (!--mcpdm_priv->active) - omap_mcpdm_stop(stream); - break; - default: - err = -EINVAL; - } - - return err; -} - static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -182,6 +152,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, err = omap_mcpdm_capture_open(&mcpdm_links[stream]); } + omap_mcpdm_start(stream); + return err; } @@ -200,13 +172,14 @@ static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream, else err = omap_mcpdm_capture_close(&mcpdm_links[stream]); + omap_mcpdm_stop(stream); + return err; } static struct snd_soc_dai_ops omap_mcpdm_dai_ops = { .startup = omap_mcpdm_dai_startup, .shutdown = omap_mcpdm_dai_shutdown, - .trigger = omap_mcpdm_dai_trigger, .hw_params = omap_mcpdm_dai_hw_params, .hw_free = omap_mcpdm_dai_hw_free, }; -- cgit v1.2.3