aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
authorLiam Girdwood <liam.r.girdwood@linux.intel.com>2018-07-02 16:59:54 +0100
committerMark Brown <broonie@kernel.org>2018-07-03 16:38:29 +0100
commita655de808cbde6c58b3298e704d786b53f59fb5d (patch)
treef096c0994bbebf6ea7fbdc1660bf09949ccb38dd /sound/soc/soc-core.c
parentASoC: atmel-i2s: dt-bindings: Remove unnecessary phandle to aclk (diff)
downloadlinux-dev-a655de808cbde6c58b3298e704d786b53f59fb5d.tar.xz
linux-dev-a655de808cbde6c58b3298e704d786b53f59fb5d.zip
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. 5) assign a new card name prefix to differentiate this topology to userspace. 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/soc-core.c')
-rw-r--r--sound/soc/soc-core.c101
1 files changed, 98 insertions, 3 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 68b08781c832..00bd58d167dd 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -847,6 +847,9 @@ static int soc_bind_dai_link(struct snd_soc_card *card,
const char *platform_name;
int i;
+ if (dai_link->ignore)
+ return 0;
+
dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name);
if (soc_is_dai_link_bound(card, dai_link)) {
@@ -1456,7 +1459,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int i, ret;
+ struct snd_soc_rtdcom_list *rtdcom;
+ struct snd_soc_component *component;
+ int i, ret, num;
dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n",
card->name, rtd->num, order);
@@ -1502,9 +1507,28 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
soc_dpcm_debugfs_add(rtd);
#endif
+ num = rtd->num;
+
+ /*
+ * most drivers will register their PCMs using DAI link ordering but
+ * topology based drivers can use the DAI link id field to set PCM
+ * device number and then use rtd + a base offset of the BEs.
+ */
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ if (!component->driver->use_dai_pcm_id)
+ continue;
+
+ if (rtd->dai_link->no_pcm)
+ num += component->driver->be_pcm_base;
+ else
+ num = rtd->dai_link->id;
+ }
+
if (cpu_dai->driver->compress_new) {
/*create compress_device"*/
- ret = cpu_dai->driver->compress_new(rtd, rtd->num);
+ ret = cpu_dai->driver->compress_new(rtd, num);
if (ret < 0) {
dev_err(card->dev, "ASoC: can't create compress %s\n",
dai_link->stream_name);
@@ -1514,7 +1538,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card,
if (!dai_link->params) {
/* create the pcm */
- ret = soc_new_pcm(rtd, rtd->num);
+ ret = soc_new_pcm(rtd, num);
if (ret < 0) {
dev_err(card->dev, "ASoC: can't create pcm %s :%d\n",
dai_link->stream_name, ret);
@@ -1841,6 +1865,74 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
#endif /* CONFIG_DMI */
+static void soc_check_tplg_fes(struct snd_soc_card *card)
+{
+ struct snd_soc_component *component;
+ const struct snd_soc_component_driver *comp_drv;
+ struct snd_soc_dai_link *dai_link;
+ int i;
+
+ list_for_each_entry(component, &component_list, list) {
+
+ /* does this component override FEs ? */
+ if (!component->driver->ignore_machine)
+ continue;
+
+ /* for this machine ? */
+ if (strcmp(component->driver->ignore_machine,
+ card->dev->driver->name))
+ continue;
+
+ /* machine matches, so override the rtd data */
+ for (i = 0; i < card->num_links; i++) {
+
+ dai_link = &card->dai_link[i];
+
+ /* ignore this FE */
+ if (dai_link->dynamic) {
+ dai_link->ignore = true;
+ continue;
+ }
+
+ dev_info(card->dev, "info: override FE DAI link %s\n",
+ card->dai_link[i].name);
+
+ /* override platform component */
+ dai_link->platform_name = component->name;
+
+ /* convert non BE into BE */
+ dai_link->no_pcm = 1;
+
+ /* override any BE fixups */
+ dai_link->be_hw_params_fixup =
+ component->driver->be_hw_params_fixup;
+
+ /* most BE links don't set stream name, so set it to
+ * dai link name if it's NULL to help bind widgets.
+ */
+ if (!dai_link->stream_name)
+ dai_link->stream_name = dai_link->name;
+ }
+
+ /* Inform userspace we are using alternate topology */
+ if (component->driver->topology_name_prefix) {
+
+ /* topology shortname created ? */
+ if (!card->topology_shortname_created) {
+ comp_drv = component->driver;
+
+ snprintf(card->topology_shortname, 32, "%s-%s",
+ comp_drv->topology_name_prefix,
+ card->name);
+ card->topology_shortname_created = true;
+ }
+
+ /* use topology shortname */
+ card->name = card->topology_shortname;
+ }
+ }
+}
+
static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd;
@@ -1850,6 +1942,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
mutex_lock(&client_mutex);
mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
+ /* check whether any platform is ignore machine FE and using topology */
+ soc_check_tplg_fes(card);
+
/* bind DAIs */
for (i = 0; i < card->num_links; i++) {
ret = soc_bind_dai_link(card, &card->dai_link[i]);