aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/soc-topology.c113
1 files changed, 111 insertions, 2 deletions
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index ee7f15aa46fc..05a18f68bfd0 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -48,9 +48,10 @@
48#define SOC_TPLG_PASS_PCM_DAI 4 48#define SOC_TPLG_PASS_PCM_DAI 4
49#define SOC_TPLG_PASS_GRAPH 5 49#define SOC_TPLG_PASS_GRAPH 5
50#define SOC_TPLG_PASS_PINS 6 50#define SOC_TPLG_PASS_PINS 6
51#define SOC_TPLG_PASS_BE_DAI 7
51 52
52#define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST 53#define SOC_TPLG_PASS_START SOC_TPLG_PASS_MANIFEST
53#define SOC_TPLG_PASS_END SOC_TPLG_PASS_PINS 54#define SOC_TPLG_PASS_END SOC_TPLG_PASS_BE_DAI
54 55
55struct soc_tplg { 56struct soc_tplg {
56 const struct firmware *fw; 57 const struct firmware *fw;
@@ -1556,6 +1557,24 @@ static void set_stream_info(struct snd_soc_pcm_stream *stream,
1556 stream->formats = caps->formats; 1557 stream->formats = caps->formats;
1557} 1558}
1558 1559
1560static void set_dai_flags(struct snd_soc_dai_driver *dai_drv,
1561 unsigned int flag_mask, unsigned int flags)
1562{
1563 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES)
1564 dai_drv->symmetric_rates =
1565 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0;
1566
1567 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS)
1568 dai_drv->symmetric_channels =
1569 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS ?
1570 1 : 0;
1571
1572 if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS)
1573 dai_drv->symmetric_samplebits =
1574 flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ?
1575 1 : 0;
1576}
1577
1559static int soc_tplg_dai_create(struct soc_tplg *tplg, 1578static int soc_tplg_dai_create(struct soc_tplg *tplg,
1560 struct snd_soc_tplg_pcm *pcm) 1579 struct snd_soc_tplg_pcm *pcm)
1561{ 1580{
@@ -1690,8 +1709,96 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
1690 return 0; 1709 return 0;
1691} 1710}
1692 1711
1712/* *
1713 * soc_tplg_be_dai_config - Find and configure an existing BE DAI.
1714 * @tplg: topology context
1715 * @be: topology BE DAI configs.
1716 *
1717 * The BE dai should already be registered by the platform driver. The
1718 * platform driver should specify the BE DAI name and ID for matching.
1719 */
1720static int soc_tplg_be_dai_config(struct soc_tplg *tplg,
1721 struct snd_soc_tplg_be_dai *be)
1722{
1723 struct snd_soc_dai_link_component dai_component = {0};
1724 struct snd_soc_dai *dai;
1725 struct snd_soc_dai_driver *dai_drv;
1726 struct snd_soc_pcm_stream *stream;
1727 struct snd_soc_tplg_stream_caps *caps;
1728 int ret;
1729
1730 dai_component.dai_name = be->dai_name;
1731 dai = snd_soc_find_dai(&dai_component);
1732 if (!dai) {
1733 dev_err(tplg->dev, "ASoC: BE DAI %s not registered\n",
1734 be->dai_name);
1735 return -EINVAL;
1736 }
1737
1738 if (be->dai_id != dai->id) {
1739 dev_err(tplg->dev, "ASoC: BE DAI %s id mismatch\n",
1740 be->dai_name);
1741 return -EINVAL;
1742 }
1743
1744 dai_drv = dai->driver;
1745 if (!dai_drv)
1746 return -EINVAL;
1747
1748 if (be->playback) {
1749 stream = &dai_drv->playback;
1750 caps = &be->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
1751 set_stream_info(stream, caps);
1752 }
1753
1754 if (be->capture) {
1755 stream = &dai_drv->capture;
1756 caps = &be->caps[SND_SOC_TPLG_STREAM_CAPTURE];
1757 set_stream_info(stream, caps);
1758 }
1759
1760 if (be->flag_mask)
1761 set_dai_flags(dai_drv, be->flag_mask, be->flags);
1762
1763 /* pass control to component driver for optional further init */
1764 ret = soc_tplg_dai_load(tplg, dai_drv);
1765 if (ret < 0) {
1766 dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
1767 return ret;
1768 }
1769
1770 return 0;
1771}
1772
1773static int soc_tplg_be_dai_elems_load(struct soc_tplg *tplg,
1774 struct snd_soc_tplg_hdr *hdr)
1775{
1776 struct snd_soc_tplg_be_dai *be;
1777 int count = hdr->count;
1778 int i;
1779
1780 if (tplg->pass != SOC_TPLG_PASS_BE_DAI)
1781 return 0;
1782
1783 /* config the existing BE DAIs */
1784 for (i = 0; i < count; i++) {
1785 be = (struct snd_soc_tplg_be_dai *)tplg->pos;
1786 if (be->size != sizeof(*be)) {
1787 dev_err(tplg->dev, "ASoC: invalid BE DAI size\n");
1788 return -EINVAL;
1789 }
1790
1791 soc_tplg_be_dai_config(tplg, be);
1792 tplg->pos += (sizeof(*be) + be->priv.size);
1793 }
1794
1795 dev_dbg(tplg->dev, "ASoC: Configure %d BE DAIs\n", count);
1796 return 0;
1797}
1798
1799
1693static int soc_tplg_manifest_load(struct soc_tplg *tplg, 1800static int soc_tplg_manifest_load(struct soc_tplg *tplg,
1694 struct snd_soc_tplg_hdr *hdr) 1801 struct snd_soc_tplg_hdr *hdr)
1695{ 1802{
1696 struct snd_soc_tplg_manifest *manifest; 1803 struct snd_soc_tplg_manifest *manifest;
1697 1804
@@ -1793,6 +1900,8 @@ static int soc_tplg_load_header(struct soc_tplg *tplg,
1793 return soc_tplg_dapm_widget_elems_load(tplg, hdr); 1900 return soc_tplg_dapm_widget_elems_load(tplg, hdr);
1794 case SND_SOC_TPLG_TYPE_PCM: 1901 case SND_SOC_TPLG_TYPE_PCM:
1795 return soc_tplg_pcm_elems_load(tplg, hdr); 1902 return soc_tplg_pcm_elems_load(tplg, hdr);
1903 case SND_SOC_TPLG_TYPE_BE_DAI:
1904 return soc_tplg_be_dai_elems_load(tplg, hdr);
1796 case SND_SOC_TPLG_TYPE_MANIFEST: 1905 case SND_SOC_TPLG_TYPE_MANIFEST:
1797 return soc_tplg_manifest_load(tplg, hdr); 1906 return soc_tplg_manifest_load(tplg, hdr);
1798 default: 1907 default: