diff options
author | Simon Wilson <simonwilson@google.com> | 2011-07-29 15:20:57 -0700 |
---|---|---|
committer | Simon Wilson <simonwilson@google.com> | 2011-07-29 15:25:53 -0700 |
commit | 2bcce7cdfb73536c20b70b067d46e9cd3fea7c85 (patch) | |
tree | bd1926ed99282020701686c915f03893a0c2b260 /sound | |
parent | bc6bcb13746e0b2dd74422fb544f4e330a5789b5 (diff) | |
parent | 42fe5ffe2507ab7c9283d704ce21d0911e32667c (diff) | |
download | kernel_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.c | 157 | ||||
-rw-r--r-- | sound/soc/omap/omap-abe.c | 100 | ||||
-rw-r--r-- | sound/soc/omap/omap-abe.h | 4 | ||||
-rw-r--r-- | sound/soc/omap/sdp4430.c | 2 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 6 | ||||
-rw-r--r-- | sound/soc/soc-dsp.c | 42 |
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) { |