summaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorLiam Girdwood <liam.r.girdwood@linux.intel.com>2018-03-27 09:30:40 -0400
committerMark Brown <broonie@kernel.org>2018-04-17 13:07:20 -0400
commit45f8cb57da0d7a9ead4b39d7f5def333a5b0c08b (patch)
treedbccf8956339890ce71070e5799daceb1b29232e /sound/soc
parent7b0037fa2d6048284e90de4131fc53c0ac1d4430 (diff)
ASoC: core: Allow topology to override machine driver FE DAI link config.
Machine drivers statically define a number of DAI links that currently cannot be changed or removed by topology. This means PCMs and platform components cannot be changed by topology at runtime AND machine drivers are tightly coupled to topology. This patch allows topology to override the machine driver DAI link config in order to reuse machine drivers with different topologies and platform components. The patch supports :- 1) create new FE PCMs with a topology defined PCM ID. 2) destroy existing static FE PCMs 3) change the platform component driver. 4) assign any new HW params fixups. The patch requires no changes to the machine drivers, but does add some platform component flags that the platform component driver can assign before loading topologies. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/soc-core.c79
-rw-r--r--sound/soc/soc-pcm.c12
2 files changed, 88 insertions, 3 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index bf7ca32ab31f..8f01fe8296ff 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1050,6 +1050,9 @@ static int soc_bind_dai_link(struct snd_soc_card *card,
1050 const char *platform_name; 1050 const char *platform_name;
1051 int i; 1051 int i;
1052 1052
1053 if (dai_link->ignore)
1054 return 0;
1055
1053 dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name); 1056 dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name);
1054 1057
1055 if (soc_is_dai_link_bound(card, dai_link)) { 1058 if (soc_is_dai_link_bound(card, dai_link)) {
@@ -1672,7 +1675,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
1672{ 1675{
1673 struct snd_soc_dai_link *dai_link = rtd->dai_link; 1676 struct snd_soc_dai_link *dai_link = rtd->dai_link;
1674 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 1677 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1675 int i, ret; 1678 int i, ret, num;
1676 1679
1677 dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", 1680 dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
1678 card->name, rtd->num, order); 1681 card->name, rtd->num, order);
@@ -1718,9 +1721,23 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
1718 soc_dpcm_debugfs_add(rtd); 1721 soc_dpcm_debugfs_add(rtd);
1719#endif 1722#endif
1720 1723
1724 /*
1725 * most drivers will register their PCMs using DAI link ordering but
1726 * topology based drivers can use the DAI link id field to set PCM
1727 * device number and then use rtd + a base offset of the BEs.
1728 */
1729 if (rtd->platform->driver->use_dai_pcm_id) {
1730 if (rtd->dai_link->no_pcm)
1731 num = rtd->platform->driver->be_pcm_base + rtd->num;
1732 else
1733 num = rtd->dai_link->id;
1734 } else {
1735 num = rtd->num;
1736 }
1737
1721 if (cpu_dai->driver->compress_new) { 1738 if (cpu_dai->driver->compress_new) {
1722 /*create compress_device"*/ 1739 /*create compress_device"*/
1723 ret = cpu_dai->driver->compress_new(rtd, rtd->num); 1740 ret = cpu_dai->driver->compress_new(rtd, num);
1724 if (ret < 0) { 1741 if (ret < 0) {
1725 dev_err(card->dev, "ASoC: can't create compress %s\n", 1742 dev_err(card->dev, "ASoC: can't create compress %s\n",
1726 dai_link->stream_name); 1743 dai_link->stream_name);
@@ -1730,7 +1747,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
1730 1747
1731 if (!dai_link->params) { 1748 if (!dai_link->params) {
1732 /* create the pcm */ 1749 /* create the pcm */
1733 ret = soc_new_pcm(rtd, rtd->num); 1750 ret = soc_new_pcm(rtd, num);
1734 if (ret < 0) { 1751 if (ret < 0) {
1735 dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", 1752 dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
1736 dai_link->stream_name, ret); 1753 dai_link->stream_name, ret);
@@ -2076,6 +2093,59 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
2076EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name); 2093EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
2077#endif /* CONFIG_DMI */ 2094#endif /* CONFIG_DMI */
2078 2095
2096static void soc_check_tplg_fes(struct snd_soc_card *card)
2097{
2098 struct snd_soc_platform *platform;
2099 struct snd_soc_dai_link *dai_link;
2100 int i;
2101
2102 list_for_each_entry(platform, &platform_list, list) {
2103
2104 /* does this platform override FEs ? */
2105 if (!platform->driver->ignore_machine)
2106 continue;
2107
2108 /* for this machine ? */
2109 if (strcmp(platform->driver->ignore_machine,
2110 card->dev->driver->name))
2111 continue;
2112
2113 /* machine matches, so override the rtd data */
2114 for (i = 0; i < card->num_links; i++) {
2115
2116 dai_link = &card->dai_link[i];
2117
2118 /* ignore this FE */
2119 if (dai_link->dynamic) {
2120 dai_link->ignore = true;
2121 continue;
2122 }
2123
2124 dev_info(card->dev, "info: override FE DAI link %s\n",
2125 card->dai_link[i].name);
2126
2127 /* override platform */
2128 dai_link->platform_name = platform->component.name;
2129 dai_link->cpu_dai_name = platform->component.name;
2130
2131 /* convert non BE into BE */
2132 dai_link->no_pcm = 1;
2133 dai_link->dpcm_playback = 1;
2134 dai_link->dpcm_capture = 1;
2135
2136 /* override any BE fixups */
2137 dai_link->be_hw_params_fixup =
2138 platform->driver->be_hw_params_fixup;
2139
2140 /* most BE links dont set stream name, so set it to
2141 * dai link name if it's NULL to help bind widgets.
2142 */
2143 if (!dai_link->stream_name)
2144 dai_link->stream_name = dai_link->name;
2145 }
2146 }
2147}
2148
2079static int snd_soc_instantiate_card(struct snd_soc_card *card) 2149static int snd_soc_instantiate_card(struct snd_soc_card *card)
2080{ 2150{
2081 struct snd_soc_codec *codec; 2151 struct snd_soc_codec *codec;
@@ -2086,6 +2156,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
2086 mutex_lock(&client_mutex); 2156 mutex_lock(&client_mutex);
2087 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); 2157 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
2088 2158
2159 /* check whether any platform is ignore machine FE and using topology */
2160 soc_check_tplg_fes(card);
2161
2089 /* bind DAIs */ 2162 /* bind DAIs */
2090 for (i = 0; i < card->num_links; i++) { 2163 for (i = 0; i < card->num_links; i++) {
2091 ret = soc_bind_dai_link(card, &card->dai_link[i]); 2164 ret = soc_bind_dai_link(card, &card->dai_link[i]);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 68d9dc930096..4ce489165a6d 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -909,8 +909,20 @@ int soc_dai_hw_params(struct snd_pcm_substream *substream,
909 struct snd_pcm_hw_params *params, 909 struct snd_pcm_hw_params *params,
910 struct snd_soc_dai *dai) 910 struct snd_soc_dai *dai)
911{ 911{
912 struct snd_soc_pcm_runtime *rtd = substream->private_data;
912 int ret; 913 int ret;
913 914
915 /* perform any topology hw_params fixups before DAI */
916 if (rtd->dai_link->be_hw_params_fixup) {
917 ret = rtd->dai_link->be_hw_params_fixup(rtd, params);
918 if (ret < 0) {
919 dev_err(rtd->dev,
920 "ASoC: hw_params topology fixup failed %d\n",
921 ret);
922 return ret;
923 }
924 }
925
914 if (dai->driver->ops->hw_params) { 926 if (dai->driver->ops->hw_params) {
915 ret = dai->driver->ops->hw_params(substream, params, dai); 927 ret = dai->driver->ops->hw_params(substream, params, dai);
916 if (ret < 0) { 928 if (ret < 0) {