[alsa-devel] [PATCH v2 01/11] ASoC: topology: Able to create BE DAIs
mengdong.lin at linux.intel.com
mengdong.lin at linux.intel.com
Fri Sep 9 13:43:11 CEST 2016
From: Mengdong Lin <mengdong.lin at linux.intel.com>
Topology will check with ASoC if a BE DAI already exists by checking
its name. If the BE DAI doesn't exist, topology will create a new one
and the dai_load ops will be called for device specific init.
Here is why we need topology to create BE DAIs (and BE DAI links
in later patches): Intel platform supports too many different types of
DAIs based on the platform variant e.g. I2S, HDA, DMIC and Soundwire in
the future. Due to the SoC pin count limitation, not all the interface
pins are taken out of the SoC to connect various peripherals. So even
though technically hardware supports many physical interfaces but the
platform may have limited what can be connected on the platform. Our
attempt is to create BE DAIs based on what is actually supported on a
platform, e.g. if the platform does not support HDA then we will not
create the HDA DAIs. Ideally, the driver should query BIOS to get the
physical pin output types and connections to peripherals for a specific
platform, but unfortunately BIOS sometimes does not have accurate info,
so there is still hard code of BE DAI & DAI links in driver. To share a
common driver across Intel platforms and remove the hard code, we choose
topology to give us such info e.g. SKL Chrome topology does not use HDA
Codec and so there are only I2S and DMIC DAIs.
Signed-off-by: Guneshwor Singh <guneshwor.o.singh at intel.com>
Signed-off-by: Mengdong Lin <mengdong.lin at linux.intel.com>
diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h
index d318fe4..9ebb9f2 100644
--- a/include/sound/soc-topology.h
+++ b/include/sound/soc-topology.h
@@ -39,6 +39,7 @@ enum snd_soc_dobj_type {
SND_SOC_DOBJ_ENUM,
SND_SOC_DOBJ_BYTES,
SND_SOC_DOBJ_PCM,
+ SND_SOC_DOBJ_BE_DAI,
SND_SOC_DOBJ_DAI_LINK,
SND_SOC_DOBJ_CODEC_LINK,
SND_SOC_DOBJ_WIDGET,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c0bbcd9..810b1d7 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2871,7 +2871,8 @@ int snd_soc_register_dai(struct snd_soc_component *component,
struct snd_soc_dai *dai;
int ret;
- if (dai_drv->dobj.type != SND_SOC_DOBJ_PCM) {
+ if (!(dai_drv->dobj.type == SND_SOC_DOBJ_PCM ||
+ dai_drv->dobj.type == SND_SOC_DOBJ_BE_DAI)) {
dev_err(component->dev, "Invalid dai type %d\n",
dai_drv->dobj.type);
return -EINVAL;
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 6b05047..b271248 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1711,42 +1711,14 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg,
return 0;
}
-/* *
- * soc_tplg_be_dai_config - Find and configure an existing BE DAI.
- * @tplg: topology context
- * @be: topology BE DAI configs.
- *
- * The BE dai should already be registered by the platform driver. The
- * platform driver should specify the BE DAI name and ID for matching.
- */
-static int soc_tplg_be_dai_config(struct soc_tplg *tplg,
+static int config_be_dai(struct soc_tplg *tplg,
+ struct snd_soc_dai_driver *dai_drv,
struct snd_soc_tplg_be_dai *be)
{
- struct snd_soc_dai_link_component dai_component = {0};
- struct snd_soc_dai *dai;
- struct snd_soc_dai_driver *dai_drv;
struct snd_soc_pcm_stream *stream;
struct snd_soc_tplg_stream_caps *caps;
int ret;
- dai_component.dai_name = be->dai_name;
- dai = snd_soc_find_dai(&dai_component);
- if (!dai) {
- dev_err(tplg->dev, "ASoC: BE DAI %s not registered\n",
- be->dai_name);
- return -EINVAL;
- }
-
- if (be->dai_id != dai->id) {
- dev_err(tplg->dev, "ASoC: BE DAI %s id mismatch\n",
- be->dai_name);
- return -EINVAL;
- }
-
- dai_drv = dai->driver;
- if (!dai_drv)
- return -EINVAL;
-
if (be->playback) {
stream = &dai_drv->playback;
caps = &be->caps[SND_SOC_TPLG_STREAM_PLAYBACK];
@@ -1765,13 +1737,80 @@ static int soc_tplg_be_dai_config(struct soc_tplg *tplg,
/* pass control to component driver for optional further init */
ret = soc_tplg_dai_load(tplg, dai_drv);
if (ret < 0) {
- dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n");
+ dev_err(tplg->comp->dev, "ASoC: BE DAI loading failed\n");
return ret;
}
return 0;
}
+static int soc_tplg_be_dai_create(struct soc_tplg *tplg,
+ struct snd_soc_tplg_be_dai *be)
+{
+ struct snd_soc_dai_driver *dai_drv;
+ int ret;
+
+ dai_drv = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
+ if (dai_drv == NULL)
+ return -ENOMEM;
+
+ dai_drv->name = be->dai_name;
+ dai_drv->id = be->dai_id;
+
+ ret = config_be_dai(tplg, dai_drv, be);
+ if (ret < 0) {
+ kfree(dai_drv);
+ return ret;
+ }
+
+ dai_drv->dobj.index = tplg->index;
+ dai_drv->dobj.ops = tplg->ops;
+ dai_drv->dobj.type = SND_SOC_DOBJ_BE_DAI;
+ list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);
+
+ /* register the DAI to the component */
+ return snd_soc_register_dai(tplg->comp, dai_drv);
+}
+
+/* *
+ * soc_tplg_be_dai_config - Create a new BE DAI or configure an existing one.
+ * @tplg: topology context
+ * @be: topology BE DAI configs.
+ *
+ * The BE dai should already be registered by the platform driver. The
+ * platform driver should specify the BE DAI name and ID for matching.
+ */
+static int soc_tplg_be_dai_config(struct soc_tplg *tplg,
+ struct snd_soc_tplg_be_dai *be)
+{
+ struct snd_soc_dai_link_component dai_component = {0};
+ struct snd_soc_dai *dai;
+ struct snd_soc_dai_driver *dai_drv;
+
+ if (!strlen(be->dai_name)) {
+ dev_err(tplg->dev, "ASoC: Invalid BE DAI name\n");
+ return -EINVAL;
+ }
+
+ dai_component.dai_name = be->dai_name;
+ dai = snd_soc_find_dai(&dai_component);
+ if (!dai) /* BE DAI doesn't exist, create it */
+ return soc_tplg_be_dai_create(tplg, be);
+
+ /* configure an existing BE DAI */
+ if (be->dai_id != dai->id) {
+ dev_err(tplg->dev, "ASoC: BE DAI %s id mismatch\n",
+ be->dai_name);
+ return -EINVAL;
+ }
+
+ dai_drv = dai->driver;
+ if (!dai_drv)
+ return -EINVAL;
+
+ return config_be_dai(tplg, dai_drv, be);
+}
+
static int soc_tplg_be_dai_elems_load(struct soc_tplg *tplg,
struct snd_soc_tplg_hdr *hdr)
{
@@ -2063,6 +2102,9 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
case SND_SOC_DOBJ_PCM:
remove_dai(comp, dobj, pass);
break;
+ case SND_SOC_DOBJ_BE_DAI:
+ remove_dai(comp, dobj, pass);
+ break;
case SND_SOC_DOBJ_DAI_LINK:
remove_link(comp, dobj, pass);
break;
--
2.5.0
More information about the Alsa-devel
mailing list