aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorSimon Wilson <simonwilson@google.com>2011-07-29 15:20:57 -0700
committerSimon Wilson <simonwilson@google.com>2011-07-29 15:25:53 -0700
commit2bcce7cdfb73536c20b70b067d46e9cd3fea7c85 (patch)
treebd1926ed99282020701686c915f03893a0c2b260 /sound
parentbc6bcb13746e0b2dd74422fb544f4e330a5789b5 (diff)
parent42fe5ffe2507ab7c9283d704ce21d0911e32667c (diff)
downloadkernel_samsung_tuna-2bcce7cdfb73536c20b70b067d46e9cd3fea7c85.zip
kernel_samsung_tuna-2bcce7cdfb73536c20b70b067d46e9cd3fea7c85.tar.gz
kernel_samsung_tuna-2bcce7cdfb73536c20b70b067d46e9cd3fea7c85.tar.bz2
Merge branch 'linux-omap-audio-3.0' into linux-omap-3.0
Signed-off-by: Simon Wilson <simonwilson@google.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/omap/omap-abe-dsp.c157
-rw-r--r--sound/soc/omap/omap-abe.c100
-rw-r--r--sound/soc/omap/omap-abe.h4
-rw-r--r--sound/soc/omap/sdp4430.c2
-rw-r--r--sound/soc/soc-core.c6
-rw-r--r--sound/soc/soc-dsp.c42
6 files changed, 268 insertions, 43 deletions
diff --git a/sound/soc/omap/omap-abe-dsp.c b/sound/soc/omap/omap-abe-dsp.c
index 8d69458..a4c7fc0 100644
--- a/sound/soc/omap/omap-abe-dsp.c
+++ b/sound/soc/omap/omap-abe-dsp.c
@@ -2058,43 +2058,6 @@ static struct snd_pcm_ops omap_aess_pcm_ops = {
.mmap = aess_mmap,
};
-#if CONFIG_PM
-static int aess_suspend(struct device *dev)
-{
- struct abe_data *abe = dev_get_drvdata(dev);
-
- pm_runtime_get_sync(abe->dev);
-
- aess_save_context(abe);
-
- pm_runtime_put_sync(abe->dev);
-
- return 0;
-}
-
-static int aess_resume(struct device *dev)
-{
- struct abe_data *abe = dev_get_drvdata(dev);
-
- pm_runtime_get_sync(abe->dev);
-
- aess_restore_context(abe);
-
- pm_runtime_put_sync(abe->dev);
-
- return 0;
-}
-
-#else
-#define aess_suspend NULL
-#define aess_resume NULL
-#endif
-
-static const struct dev_pm_ops aess_pm_ops = {
- .suspend = aess_suspend,
- .resume = aess_resume,
-};
-
static int aess_stream_event(struct snd_soc_dapm_context *dapm)
{
struct snd_soc_platform *platform = dapm->platform;
@@ -2159,6 +2122,123 @@ static int abe_add_widgets(struct snd_soc_platform *platform)
return 0;
}
+#ifdef CONFIG_PM
+static int abe_suspend(struct snd_soc_dai *dai)
+{
+ struct abe_data *abe = the_abe;
+ struct omap4_abe_dsp_pdata *pdata = abe->abe_pdata;
+ int ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s active %d\n",
+ __func__, dai->name, dai->active);
+
+ if (!dai->active)
+ return 0;
+
+ pm_runtime_get_sync(abe->dev);
+
+ switch (dai->id) {
+ case OMAP_ABE_DAI_PDM_UL:
+ abe_mute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_PDM_DL2:
+ case OMAP_ABE_DAI_PDM_VIB:
+ case OMAP_ABE_DAI_BT_VX:
+ case OMAP_ABE_DAI_MM_FM:
+ case OMAP_ABE_DAI_MODEM:
+ break;
+ case OMAP_ABE_DAI_DMIC0:
+ abe_mute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC1:
+ abe_mute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC2:
+ abe_mute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
+ abe_mute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
+ break;
+ default:
+ dev_err(dai->dev, "%s: invalid DAI id %d\n",
+ __func__, dai->id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (pdata->get_context_loss_count)
+ abe->loss_count = pdata->get_context_loss_count(abe->dev);
+
+out:
+ pm_runtime_put_sync(abe->dev);
+ return ret;
+}
+
+static int abe_resume(struct snd_soc_dai *dai)
+{
+ struct abe_data *abe = the_abe;
+ struct omap4_abe_dsp_pdata *pdata = abe->abe_pdata;
+ int loss_count = 0, ret = 0;
+
+ dev_dbg(dai->dev, "%s: %s active %d\n",
+ __func__, dai->name, dai->active);
+
+ if (!dai->active)
+ return 0;
+
+ if (pdata->get_context_loss_count)
+ loss_count = pdata->get_context_loss_count(abe->dev);
+
+ pm_runtime_get_sync(abe->dev);
+ omap_device_set_rate(&abe->dev, &abe->dev, 98000000);
+
+ if (loss_count != abe->loss_count)
+ abe_reload_fw();
+
+ switch (dai->id) {
+ case OMAP_ABE_DAI_PDM_UL:
+ abe_unmute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_PDM_DL1:
+ case OMAP_ABE_DAI_PDM_DL2:
+ case OMAP_ABE_DAI_PDM_VIB:
+ case OMAP_ABE_DAI_BT_VX:
+ case OMAP_ABE_DAI_MM_FM:
+ case OMAP_ABE_DAI_MODEM:
+ break;
+ case OMAP_ABE_DAI_DMIC0:
+ abe_unmute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC1:
+ abe_unmute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
+ break;
+ case OMAP_ABE_DAI_DMIC2:
+ abe_unmute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
+ abe_unmute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
+ break;
+ default:
+ dev_err(dai->dev, "%s: invalid DAI id %d\n",
+ __func__, dai->id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ abe_set_router_configuration(UPROUTE, 0, (u32 *)abe->router);
+
+out:
+ pm_runtime_put_sync(abe->dev);
+ return ret;
+}
+#else
+#define abe_suspend NULL
+#define abe_resume NULL
+#endif
+
static int abe_probe(struct snd_soc_platform *platform)
{
struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
@@ -2324,6 +2404,8 @@ static struct snd_soc_platform_driver omap_aess_platform = {
.ops = &omap_aess_pcm_ops,
.probe = abe_probe,
.remove = abe_remove,
+ .suspend = abe_suspend,
+ .resume = abe_resume,
.read = abe_dsp_read,
.write = abe_dsp_write,
.stream_event = aess_stream_event,
@@ -2404,7 +2486,6 @@ static struct platform_driver omap_aess_driver = {
.driver = {
.name = "aess",
.owner = THIS_MODULE,
- .pm = &aess_pm_ops,
},
.probe = abe_engine_probe,
.remove = __devexit_p(abe_engine_remove),
diff --git a/sound/soc/omap/omap-abe.c b/sound/soc/omap/omap-abe.c
index 6555a82..0c48828 100644
--- a/sound/soc/omap/omap-abe.c
+++ b/sound/soc/omap/omap-abe.c
@@ -56,6 +56,9 @@ struct omap_abe_data {
/* BE & FE Ports */
struct omap_abe_port *port[OMAP_ABE_MAX_PORT_ID + 1];
+
+ int active_dais;
+ int suspended_dais;
};
/*
@@ -782,6 +785,8 @@ static int omap_abe_dai_startup(struct snd_pcm_substream *substream,
dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
+ abe_priv->active_dais++;
+
if (dai->id == ABE_FRONTEND_DAI_MODEM) {
ret = modem_get_dai(substream, dai);
@@ -1065,7 +1070,88 @@ static void omap_abe_dai_shutdown(struct snd_pcm_substream *substream,
snd_soc_dai_shutdown(abe_priv->modem_substream[substream->stream],
abe_priv->modem_dai);
}
+
+ abe_priv->active_dais--;
+}
+
+#ifdef CONFIG_PM
+static int omap_abe_dai_suspend(struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(dai->dev, "%s: %s active %d\n",
+ __func__, dai->name, dai->active);
+
+ if (!dai->active)
+ return 0;
+
+ if (++abe_priv->suspended_dais < abe_priv->active_dais)
+ return 0;
+
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_mute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
+ abe_mute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
+ abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_mute_gain(MIXECHO, MIX_ECHO_DL2);
+
+ return 0;
+}
+
+static int omap_abe_dai_resume(struct snd_soc_dai *dai)
+{
+ struct omap_abe_data *abe_priv = snd_soc_dai_get_drvdata(dai);
+
+ dev_dbg(dai->dev, "%s: %s active %d\n",
+ __func__, dai->name, dai->active);
+
+ if (!dai->active)
+ return 0;
+
+ if (abe_priv->suspended_dais-- < abe_priv->active_dais)
+ return 0;
+
+ abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
+ abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
+ abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
+ abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
+ abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
+ abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
+ abe_unmute_gain(MIXECHO, MIX_ECHO_DL1);
+ abe_unmute_gain(MIXECHO, MIX_ECHO_DL2);
+
+ return 0;
}
+#else
+#define omap_abe_dai_suspend NULL
+#define omap_abe_dai_resume NULL
+#endif
static int omap_abe_dai_probe(struct snd_soc_dai *dai)
{
@@ -1125,6 +1211,8 @@ static struct snd_soc_dai_driver omap_abe_dai[] = {
.name = "MultiMedia1",
.probe = omap_abe_dai_probe,
.remove = omap_abe_dai_remove,
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
.playback = {
.stream_name = "MultiMedia1 Playback",
.channels_min = 1,
@@ -1143,6 +1231,8 @@ static struct snd_soc_dai_driver omap_abe_dai[] = {
},
{ /* Multimedia Capture */
.name = "MultiMedia2",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
.capture = {
.stream_name = "MultiMedia2 Capture",
.channels_min = 1,
@@ -1154,6 +1244,8 @@ static struct snd_soc_dai_driver omap_abe_dai[] = {
},
{ /* Voice Playback and Capture */
.name = "Voice",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
.playback = {
.stream_name = "Voice Playback",
.channels_min = 1,
@@ -1172,6 +1264,8 @@ static struct snd_soc_dai_driver omap_abe_dai[] = {
},
{ /* Tones Playback */
.name = "Tones",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
.playback = {
.stream_name = "Tones Playback",
.channels_min = 1,
@@ -1183,6 +1277,8 @@ static struct snd_soc_dai_driver omap_abe_dai[] = {
},
{ /* Vibra */
.name = "Vibra",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
.playback = {
.stream_name = "Vibra Playback",
.channels_min = 2,
@@ -1194,6 +1290,8 @@ static struct snd_soc_dai_driver omap_abe_dai[] = {
},
{ /* MODEM Voice Playback and Capture */
.name = "MODEM",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
.playback = {
.stream_name = "Voice Playback",
.channels_min = 1,
@@ -1212,6 +1310,8 @@ static struct snd_soc_dai_driver omap_abe_dai[] = {
},
{ /* Low Power HiFi Playback */
.name = "MultiMedia1 LP",
+ .suspend = omap_abe_dai_suspend,
+ .resume = omap_abe_dai_resume,
.playback = {
.stream_name = "MultiMedia1 LP Playback",
.channels_min = 2,
diff --git a/sound/soc/omap/omap-abe.h b/sound/soc/omap/omap-abe.h
index 7aca33e..5bdab50 100644
--- a/sound/soc/omap/omap-abe.h
+++ b/sound/soc/omap/omap-abe.h
@@ -30,7 +30,8 @@
#define ABE_FRONTEND_DAI_TONES 3
#define ABE_FRONTEND_DAI_VIBRA 4
#define ABE_FRONTEND_DAI_MODEM 5
-#define ABE_FRONTEND_DAI_LP_MEDIA 6
+#define ABE_FRONTEND_DAI_LP_MEDIA 6
+#define ABE_FRONTEND_DAI_NUM 7
/* This must currently match the BE order in DSP */
#define OMAP_ABE_DAI_PDM_UL 0
@@ -43,6 +44,7 @@
#define OMAP_ABE_DAI_DMIC0 7
#define OMAP_ABE_DAI_DMIC1 8
#define OMAP_ABE_DAI_DMIC2 9
+#define OMAP_ABE_DAI_NUM 10
#define OMAP_ABE_BE_PDM_DL1 "PDM-DL1"
#define OMAP_ABE_BE_PDM_UL1 "PDM-UL1"
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index b84399a..f9cc8cd 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -580,6 +580,7 @@ static struct snd_soc_dai_link sdp4430_dai[] = {
.no_codec = 1, /* TODO: have a dummy CODEC */
.ops = &sdp4430_mcbsp_ops,
+ .ignore_suspend = 1,
},
{
.name = "Legacy McPDM",
@@ -594,6 +595,7 @@ static struct snd_soc_dai_link sdp4430_dai[] = {
.codec_name = "twl6040-codec",
.ops = &sdp4430_mcpdm_ops,
+ .ignore_suspend = 1,
},
/*
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 70d3a22..845c9f6 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1192,8 +1192,7 @@ int snd_soc_suspend(struct device *dev)
continue;
if (card->rtd[i].dai_link->dynamic) {
- soc_dsp_be_cpu_dai_suspend(&card->rtd[i]);
- soc_dsp_be_platform_suspend(&card->rtd[i]);
+ soc_dsp_fe_suspend(&card->rtd[i]);
} else {
if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control)
cpu_dai->driver->suspend(cpu_dai);
@@ -1363,8 +1362,7 @@ static void soc_resume_deferred(struct work_struct *work)
continue;
if (card->rtd[i].dai_link->dynamic) {
- soc_dsp_be_cpu_dai_resume(&card->rtd[i]);
- soc_dsp_be_platform_resume(&card->rtd[i]);
+ soc_dsp_fe_resume(&card->rtd[i]);
} else {
if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control)
cpu_dai->driver->resume(cpu_dai);
diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c
index 1770ee8..50e5e17 100644
--- a/sound/soc/soc-dsp.c
+++ b/sound/soc/soc-dsp.c
@@ -1318,6 +1318,27 @@ int soc_dsp_be_platform_suspend(struct snd_soc_pcm_runtime *fe)
return 0;
}
+int soc_dsp_fe_suspend(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dai *dai = fe->cpu_dai;
+ struct snd_soc_dai_driver *dai_drv = dai->driver;
+ struct snd_soc_platform *platform = fe->platform;
+ struct snd_soc_platform_driver *plat_drv = platform->driver;
+
+ if (dai_drv->suspend && !dai_drv->ac97_control)
+ dai_drv->suspend(dai);
+
+ if (plat_drv->suspend && !platform->suspended) {
+ plat_drv->suspend(dai);
+ platform->suspended = 1;
+ }
+
+ soc_dsp_be_cpu_dai_suspend(fe);
+ soc_dsp_be_platform_suspend(fe);
+
+ return 0;
+}
+
int soc_dsp_be_cpu_dai_resume(struct snd_soc_pcm_runtime *fe)
{
struct snd_soc_dsp_params *dsp_params;
@@ -1453,6 +1474,27 @@ int soc_dsp_be_platform_resume(struct snd_soc_pcm_runtime *fe)
return 0;
}
+int soc_dsp_fe_resume(struct snd_soc_pcm_runtime *fe)
+{
+ struct snd_soc_dai *dai = fe->cpu_dai;
+ struct snd_soc_dai_driver *dai_drv = dai->driver;
+ struct snd_soc_platform *platform = fe->platform;
+ struct snd_soc_platform_driver *plat_drv = platform->driver;
+
+ soc_dsp_be_cpu_dai_resume(fe);
+ soc_dsp_be_platform_resume(fe);
+
+ if (dai_drv->resume && !dai_drv->ac97_control)
+ dai_drv->resume(dai);
+
+ if (plat_drv->resume && platform->suspended) {
+ plat_drv->resume(dai);
+ platform->suspended = 0;
+ }
+
+ return 0;
+}
+
/* called when opening FE stream */
int soc_dsp_fe_dai_open(struct snd_pcm_substream *fe_substream)
{