diff options
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r-- | sound/soc/soc-pcm.c | 99 |
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 | ||
635 | int 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 | ||
1611 | static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) | 1650 | static 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 | ||
1636 | static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) | 1691 | static 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 | } |
2121 | EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); | 2191 | EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params); |
2122 | 2192 | ||
2193 | int 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 | } | ||
2200 | EXPORT_SYMBOL_GPL(snd_soc_platform_trigger); | ||
2201 | |||
2123 | #ifdef CONFIG_DEBUG_FS | 2202 | #ifdef CONFIG_DEBUG_FS |
2124 | static char *dpcm_state_string(enum snd_soc_dpcm_state state) | 2203 | static char *dpcm_state_string(enum snd_soc_dpcm_state state) |
2125 | { | 2204 | { |