aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPC Liao <pc.liao@mediatek.com>2015-12-10 22:33:51 -0500
committerMark Brown <broonie@kernel.org>2015-12-12 17:58:32 -0500
commit906c7d690c3b80e4321178c083db8c14afb56bf8 (patch)
tree443e2cc9c0dced923178bdfac26de652801706ab
parent95f444dc9371a3910179a9621c8b94f0f60f5f04 (diff)
ASoC: dpcm: Apply symmetry for DPCM
DPCM does not fully support symmetry attributes. soc_pcm_apply_symmetry() is skipped in soc_pcm_open() for DPCM, without being applied elsewhere. So HW parameters cannot be correctly limited, and user space can do playback/capture at different rates while HW actually does not support it. soc_pcm_params_symmetry() will return error and the second stream stops. This patch adds soc_pcm_apply_symmetry() for FE, BE, and codec DAIs in DPCM path that was skipped in soc_pcm_open(). Signed-off-by: PC Liao <pc.liao@mediatek.com> Signed-off-by: Koro Chen <koro.chen@mediatek.com> Acked-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/soc-pcm.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index c48232211c56..37de8af91f13 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1616,6 +1616,56 @@ static void dpcm_set_fe_update_state(struct snd_soc_pcm_runtime *fe,
1616 snd_pcm_stream_unlock_irq(substream); 1616 snd_pcm_stream_unlock_irq(substream);
1617} 1617}
1618 1618
1619static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
1620 int stream)
1621{
1622 struct snd_soc_dpcm *dpcm;
1623 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1624 struct snd_soc_dai *fe_cpu_dai = fe->cpu_dai;
1625 int err;
1626
1627 /* apply symmetry for FE */
1628 if (soc_pcm_has_symmetry(fe_substream))
1629 fe_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1630
1631 /* Symmetry only applies if we've got an active stream. */
1632 if (fe_cpu_dai->active) {
1633 err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai);
1634 if (err < 0)
1635 return err;
1636 }
1637
1638 /* apply symmetry for BE */
1639 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1640 struct snd_soc_pcm_runtime *be = dpcm->be;
1641 struct snd_pcm_substream *be_substream =
1642 snd_soc_dpcm_get_substream(be, stream);
1643 struct snd_soc_pcm_runtime *rtd = be_substream->private_data;
1644 int i;
1645
1646 if (soc_pcm_has_symmetry(be_substream))
1647 be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1648
1649 /* Symmetry only applies if we've got an active stream. */
1650 if (rtd->cpu_dai->active) {
1651 err = soc_pcm_apply_symmetry(be_substream, rtd->cpu_dai);
1652 if (err < 0)
1653 return err;
1654 }
1655
1656 for (i = 0; i < rtd->num_codecs; i++) {
1657 if (rtd->codec_dais[i]->active) {
1658 err = soc_pcm_apply_symmetry(be_substream,
1659 rtd->codec_dais[i]);
1660 if (err < 0)
1661 return err;
1662 }
1663 }
1664 }
1665
1666 return 0;
1667}
1668
1619static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) 1669static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
1620{ 1670{
1621 struct snd_soc_pcm_runtime *fe = fe_substream->private_data; 1671 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
@@ -1644,6 +1694,13 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
1644 dpcm_set_fe_runtime(fe_substream); 1694 dpcm_set_fe_runtime(fe_substream);
1645 snd_pcm_limit_hw_rates(runtime); 1695 snd_pcm_limit_hw_rates(runtime);
1646 1696
1697 ret = dpcm_apply_symmetry(fe_substream, stream);
1698 if (ret < 0) {
1699 dev_err(fe->dev, "ASoC: failed to apply dpcm symmetry %d\n",
1700 ret);
1701 goto unwind;
1702 }
1703
1647 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); 1704 dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO);
1648 return 0; 1705 return 0;
1649 1706