diff options
author | PC Liao <pc.liao@mediatek.com> | 2015-12-10 22:33:51 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-12-12 17:58:32 -0500 |
commit | 906c7d690c3b80e4321178c083db8c14afb56bf8 (patch) | |
tree | 443e2cc9c0dced923178bdfac26de652801706ab | |
parent | 95f444dc9371a3910179a9621c8b94f0f60f5f04 (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.c | 57 |
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 | ||
1619 | static 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 | |||
1619 | static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) | 1669 | static 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 | ||