Skip to content

Commit a008c00

Browse files
lrgirdwoplbossart
authored andcommitted
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>
1 parent 284250b commit a008c00

3 files changed

Lines changed: 98 additions & 3 deletions

File tree

include/sound/soc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,13 @@ struct snd_soc_platform_driver {
10051005

10061006
/* platform stream compress ops */
10071007
const struct snd_compr_ops *compr_ops;
1008+
1009+
/* this platform uses topology and ignore machine driver FEs */
1010+
const char *ignore_machine;
1011+
int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
1012+
struct snd_pcm_hw_params *params);
1013+
bool use_dai_pcm_id; /* use the DAI link PCM ID as PCM device number */
1014+
int be_pcm_base; /* base device ID for all BE PCMs */
10081015
};
10091016

10101017
struct snd_soc_dai_link_component {
@@ -1111,6 +1118,9 @@ struct snd_soc_dai_link {
11111118
/* pmdown_time is ignored at stop */
11121119
unsigned int ignore_pmdown_time:1;
11131120

1121+
/* Do not create a PCM for this DAI link (Backend link) */
1122+
unsigned int ignore:1;
1123+
11141124
struct list_head list; /* DAI link list of the soc card */
11151125
struct snd_soc_dobj dobj; /* For topology */
11161126
};

sound/soc/soc-core.c

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,9 @@ static int soc_bind_dai_link(struct snd_soc_card *card,
11121112
const char *platform_name;
11131113
int i;
11141114

1115+
if (dai_link->ignore)
1116+
return 0;
1117+
11151118
dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name);
11161119

11171120
if (soc_is_dai_link_bound(card, dai_link)) {
@@ -1729,7 +1732,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
17291732
{
17301733
struct snd_soc_dai_link *dai_link = rtd->dai_link;
17311734
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1732-
int i, ret;
1735+
int i, ret, num;
17331736

17341737
dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
17351738
card->name, rtd->num, order);
@@ -1775,9 +1778,23 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
17751778
soc_dpcm_debugfs_add(rtd);
17761779
#endif
17771780

1781+
/*
1782+
* most drivers will register their PCMs using DAI link ordering but
1783+
* topology based drivers can use the DAI link id field to set PCM
1784+
* device number and then use rtd + a base offset of the BEs.
1785+
*/
1786+
if (rtd->platform->driver->use_dai_pcm_id) {
1787+
if (rtd->dai_link->no_pcm)
1788+
num = rtd->platform->driver->be_pcm_base + rtd->num;
1789+
else
1790+
num = rtd->dai_link->id;
1791+
} else {
1792+
num = rtd->num;
1793+
}
1794+
17781795
if (cpu_dai->driver->compress_new) {
17791796
/*create compress_device"*/
1780-
ret = cpu_dai->driver->compress_new(rtd, rtd->num);
1797+
ret = cpu_dai->driver->compress_new(rtd, num);
17811798
if (ret < 0) {
17821799
dev_err(card->dev, "ASoC: can't create compress %s\n",
17831800
dai_link->stream_name);
@@ -1787,7 +1804,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
17871804

17881805
if (!dai_link->params) {
17891806
/* create the pcm */
1790-
ret = soc_new_pcm(rtd, rtd->num);
1807+
ret = soc_new_pcm(rtd, num);
17911808
if (ret < 0) {
17921809
dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
17931810
dai_link->stream_name, ret);
@@ -2131,6 +2148,59 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
21312148
EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
21322149
#endif /* CONFIG_DMI */
21332150

2151+
static void soc_check_tplg_fes(struct snd_soc_card *card)
2152+
{
2153+
struct snd_soc_platform *platform;
2154+
struct snd_soc_dai_link *dai_link;
2155+
int i;
2156+
2157+
list_for_each_entry(platform, &platform_list, list) {
2158+
2159+
/* does this platform override FEs ? */
2160+
if (!platform->driver->ignore_machine)
2161+
continue;
2162+
2163+
/* for this machine ? */
2164+
if (strcmp(platform->driver->ignore_machine,
2165+
card->dev->driver->name))
2166+
continue;
2167+
2168+
/* machine matches, so override the rtd data */
2169+
for (i = 0; i < card->num_links; i++) {
2170+
2171+
dai_link = &card->dai_link[i];
2172+
2173+
/* ignore this FE */
2174+
if (dai_link->dynamic) {
2175+
dai_link->ignore = true;
2176+
continue;
2177+
}
2178+
2179+
dev_info(card->dev, "info: override FE DAI link %s\n",
2180+
card->dai_link[i].name);
2181+
2182+
/* override platform */
2183+
dai_link->platform_name = platform->component.name;
2184+
dai_link->cpu_dai_name = platform->component.name;
2185+
2186+
/* convert non BE into BE */
2187+
dai_link->no_pcm = 1;
2188+
dai_link->dpcm_playback = 1;
2189+
dai_link->dpcm_capture = 1;
2190+
2191+
/* override any BE fixups */
2192+
dai_link->be_hw_params_fixup =
2193+
platform->driver->be_hw_params_fixup;
2194+
2195+
/* most BE links don't set stream name, so set it to
2196+
* dai link name if it's NULL to help bind widgets.
2197+
*/
2198+
if (!dai_link->stream_name)
2199+
dai_link->stream_name = dai_link->name;
2200+
}
2201+
}
2202+
}
2203+
21342204
static int snd_soc_instantiate_card(struct snd_soc_card *card)
21352205
{
21362206
struct snd_soc_codec *codec;
@@ -2141,6 +2211,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
21412211
mutex_lock(&client_mutex);
21422212
mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
21432213

2214+
/* check whether any platform is ignore machine FE and using topology */
2215+
soc_check_tplg_fes(card);
2216+
21442217
/* bind DAIs */
21452218
for (i = 0; i < card->num_links; i++) {
21462219
ret = soc_bind_dai_link(card, &card->dai_link[i]);

sound/soc/soc-pcm.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,20 @@ int soc_dai_hw_params(struct snd_pcm_substream *substream,
909909
struct snd_pcm_hw_params *params,
910910
struct snd_soc_dai *dai)
911911
{
912+
struct snd_soc_pcm_runtime *rtd = substream->private_data;
912913
int ret;
913914

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+
914926
if (dai->driver->ops->hw_params) {
915927
ret = dai->driver->ops->hw_params(substream, params, dai);
916928
if (ret < 0) {

0 commit comments

Comments
 (0)