aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-pcm.c
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@ti.com>2012-04-25 07:12:52 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-26 12:48:42 -0400
commit07bf84aaf736781a283b1bd36eaa911453b14574 (patch)
treedc20d6d15dd5e90e25ec93146e87e3272e597395 /sound/soc/soc-pcm.c
parent47c88ffff73d27425be59b34a6d5a91518b5ebed (diff)
ASoC: dpcm: Add bespoke trigger()
Some on SoC DSP HW is very tightly coupled with DMA and DAI drivers. It's necessary to allow some flexability wrt to PCM operations here so that we can define a bespoke DPCM trigger() PCM operation for such HW. A bespoke DPCM trigger() allows exact ordering and timing of component triggering by allowing a component driver to manage the final enable and disable configurations without adding extra complexity to other component drivers. e.g. The McPDM DAI and ABE are tightly coupled on OMAP4 so we have a bespoke trigger to manage the trigger to improve performance and reduce complexity when triggering new McPDM BEs. Signed-off-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r--sound/soc/soc-pcm.c99
1 files changed, 89 insertions, 10 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ca36fd6746fc..5bd8270beea4 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -632,6 +632,33 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
632 return 0; 632 return 0;
633} 633}
634 634
635int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, int cmd)
636{
637 struct snd_soc_pcm_runtime *rtd = substream->private_data;
638 struct snd_soc_platform *platform = rtd->platform;
639 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
640 struct snd_soc_dai *codec_dai = rtd->codec_dai;
641 int ret;
642
643 if (codec_dai->driver->ops->bespoke_trigger) {
644 ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
645 if (ret < 0)
646 return ret;
647 }
648
649 if (platform->driver->bespoke_trigger) {
650 ret = platform->driver->bespoke_trigger(substream, cmd);
651 if (ret < 0)
652 return ret;
653 }
654
655 if (cpu_dai->driver->ops->bespoke_trigger) {
656 ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
657 if (ret < 0)
658 return ret;
659 }
660 return 0;
661}
635/* 662/*
636 * soc level wrapper for pointer callback 663 * soc level wrapper for pointer callback
637 * If cpu_dai, codec_dai, platform driver has the delay callback, than 664 * If cpu_dai, codec_dai, platform driver has the delay callback, than
@@ -1507,6 +1534,18 @@ int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
1507 1534
1508 ret = soc_pcm_trigger(substream, cmd); 1535 ret = soc_pcm_trigger(substream, cmd);
1509 break; 1536 break;
1537 case SND_SOC_DPCM_TRIGGER_BESPOKE:
1538 /* bespoke trigger() - handles both FE and BEs */
1539
1540 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd %d\n",
1541 fe->dai_link->name, cmd);
1542
1543 ret = soc_pcm_bespoke_trigger(substream, cmd);
1544 if (ret < 0) {
1545 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1546 goto out;
1547 }
1548 break;
1510 default: 1549 default:
1511 dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd, 1550 dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
1512 fe->dai_link->name); 1551 fe->dai_link->name);
@@ -1610,14 +1649,30 @@ out:
1610 1649
1611static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) 1650static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1612{ 1651{
1652 struct snd_pcm_substream *substream =
1653 snd_soc_dpcm_get_substream(fe, stream);
1654 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1613 int err; 1655 int err;
1614 1656
1615 dev_dbg(fe->dev, "runtime %s close on FE %s\n", 1657 dev_dbg(fe->dev, "runtime %s close on FE %s\n",
1616 stream ? "capture" : "playback", fe->dai_link->name); 1658 stream ? "capture" : "playback", fe->dai_link->name);
1617 1659
1618 err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP); 1660 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1619 if (err < 0) 1661 /* call bespoke trigger - FE takes care of all BE triggers */
1620 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err); 1662 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd stop\n",
1663 fe->dai_link->name);
1664
1665 err = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP);
1666 if (err < 0)
1667 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1668 } else {
1669 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd stop\n",
1670 fe->dai_link->name);
1671
1672 err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP);
1673 if (err < 0)
1674 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", err);
1675 }
1621 1676
1622 err = dpcm_be_dai_hw_free(fe, stream); 1677 err = dpcm_be_dai_hw_free(fe, stream);
1623 if (err < 0) 1678 if (err < 0)
@@ -1635,7 +1690,10 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1635 1690
1636static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) 1691static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
1637{ 1692{
1693 struct snd_pcm_substream *substream =
1694 snd_soc_dpcm_get_substream(fe, stream);
1638 struct snd_soc_dpcm *dpcm; 1695 struct snd_soc_dpcm *dpcm;
1696 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1639 int ret; 1697 int ret;
1640 1698
1641 dev_dbg(fe->dev, "runtime %s open on FE %s\n", 1699 dev_dbg(fe->dev, "runtime %s open on FE %s\n",
@@ -1682,14 +1740,26 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
1682 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP) 1740 fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP)
1683 return 0; 1741 return 0;
1684 1742
1685 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n", 1743 if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) {
1686 fe->dai_link->name); 1744 /* call trigger on the frontend - FE takes care of all BE triggers */
1745 dev_dbg(fe->dev, "dpcm: bespoke trigger FE %s cmd start\n",
1746 fe->dai_link->name);
1687 1747
1688 ret = dpcm_be_dai_trigger(fe, stream, 1748 ret = soc_pcm_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START);
1689 SNDRV_PCM_TRIGGER_START); 1749 if (ret < 0) {
1690 if (ret < 0) { 1750 dev_err(fe->dev,"dpcm: bespoke trigger FE failed %d\n", ret);
1691 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret); 1751 goto hw_free;
1692 goto hw_free; 1752 }
1753 } else {
1754 dev_dbg(fe->dev, "dpcm: trigger FE %s cmd start\n",
1755 fe->dai_link->name);
1756
1757 ret = dpcm_be_dai_trigger(fe, stream,
1758 SNDRV_PCM_TRIGGER_START);
1759 if (ret < 0) {
1760 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1761 goto hw_free;
1762 }
1693 } 1763 }
1694 1764
1695 return 0; 1765 return 0;
@@ -2120,6 +2190,15 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
2120} 2190}
2121EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); 2191EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
2122 2192
2193int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
2194 int cmd, struct snd_soc_platform *platform)
2195{
2196 if (platform->driver->ops->trigger)
2197 return platform->driver->ops->trigger(substream, cmd);
2198 return 0;
2199}
2200EXPORT_SYMBOL_GPL(snd_soc_platform_trigger);
2201
2123#ifdef CONFIG_DEBUG_FS 2202#ifdef CONFIG_DEBUG_FS
2124static char *dpcm_state_string(enum snd_soc_dpcm_state state) 2203static char *dpcm_state_string(enum snd_soc_dpcm_state state)
2125{ 2204{