[PATCH v2 0/9] Audio graph card updates and usage with Tegra210 audio
This series proposes following enhancements to audio-graph card driver. * Support multiple instances of a component. * Support open platforms with empty Codec endpoint. * Identify no-pcm DPCM DAI links which can be used in BE<->BE connections. * Add new compatible to support DPCM based DAI chaining.
This pushes DT support for Tegra210 based platforms which uses audio-graph card and above enhancements.
The series is based on following references where DPCM usgae for Tegra Audio and simple-card driver proposal were discussed. * https://lkml.org/lkml/2020/4/30/519 (DPCM for Tegra) * https://lkml.org/lkml/2020/6/27/4 (simple-card driver)
Changelog =========
v1 -> v2 -------- * Re-organized ports/endpoints description for ADMAIF and XBAR. Updated DT patches accordingly. * After above change, multiple Codec endpoint support is not required and hence dropped for now. This will be considered separately if at all required in future. * Re-ordered patches in the series.
Sameer Pujar (9): ASoC: soc-core: Fix component name_prefix parsing ASoC: audio-graph: Use of_node and DAI for DPCM DAI link names ASoC: audio-graph: Identify 'no_pcm' DAI links for DPCM ASoC: soc-pcm: Get all BEs along DAPM path ASoC: dt-bindings: audio-graph-card: Support for component chaining ASoC: audio-graph: Add support for component chaining ASoC: audio-graph: Support empty Codec endpoint arm64: tegra: Audio graph header for Tegra210 arm64: tegra: Audio graph sound card for Jetson Nano and TX1
.../devicetree/bindings/sound/audio-graph-card.txt | 1 + .../boot/dts/nvidia/tegra210-audio-graph.dtsi | 141 +++++++++++++ arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts | 217 +++++++++++++++++++++ arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts | 122 ++++++++++++ include/sound/soc.h | 1 + sound/soc/generic/audio-graph-card.c | 69 ++++++- sound/soc/soc-core.c | 3 +- sound/soc/soc-pcm.c | 3 +- 8 files changed, 545 insertions(+), 12 deletions(-) create mode 100644 arch/arm64/boot/dts/nvidia/tegra210-audio-graph.dtsi
The "prefix" can be defined in DAI link node or it can be specified as part of the component node itself. Currently "sound-name-prefix" defined in a component is not taking effect. Actually the property is not getting parsed. It can be fixed by parsing "sound-name-prefix" property whenever "prefix" is missing in DAI link Codec node.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- sound/soc/soc-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2fe1b2ec..ec000fb 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1113,7 +1113,8 @@ static void soc_set_name_prefix(struct snd_soc_card *card, for (i = 0; i < card->num_configs; i++) { struct snd_soc_codec_conf *map = &card->codec_conf[i];
- if (snd_soc_is_matching_component(&map->dlc, component)) { + if (snd_soc_is_matching_component(&map->dlc, component) && + map->name_prefix) { component->name_prefix = map->name_prefix; return; }
For multiple instances of components, using DAI name alone for DAI links is causing conflicts. Components can define multiple DAIs and hence using just a device name won't help either. Thus DT device node reference and DAI names are used to uniquely represent DAI link names.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- sound/soc/generic/audio-graph-card.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 97b4f54..1e20562 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -253,7 +253,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, goto out_put_node;
ret = asoc_simple_set_dailink_name(dev, dai_link, - "fe.%s", + "fe.%pOFP.%s", + cpus->of_node, cpus->dai_name); if (ret < 0) goto out_put_node; @@ -287,7 +288,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, goto out_put_node;
ret = asoc_simple_set_dailink_name(dev, dai_link, - "be.%s", + "be.%pOFP.%s", + codecs->of_node, codecs->dai_name); if (ret < 0) goto out_put_node;
Hi
For multiple instances of components, using DAI name alone for DAI links is causing conflicts. Components can define multiple DAIs and hence using just a device name won't help either. Thus DT device node reference and DAI names are used to uniquely represent DAI link names.
Signed-off-by: Sameer Pujar spujar@nvidia.com
Acked-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Thank you for your help !!
Best regards --- Kuninori Morimoto
PCM devices are created for FE dai links with 'no-pcm' flag as '0'. Such DAI links have CPU component which implement either pcm_construct() or pcm_new() at component or dai level respectively. Based on this, current patch exposes a helper function to identify such components and populate 'no_pcm' flag for DPCM DAI link.
This helps to have BE<->BE component links where PCM devices need not be created for CPU component involved in such links.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- sound/soc/generic/audio-graph-card.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 1e20562..93bddf6 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -111,6 +111,17 @@ static int graph_get_dai_id(struct device_node *ep) return id; }
+static bool soc_component_is_pcm(struct snd_soc_dai_link_component *dlc) +{ + struct snd_soc_dai *dai = snd_soc_find_dai(dlc); + + if (dai && (dai->component->driver->pcm_construct || + dai->driver->pcm_new)) + return true; + + return false; +} + static int asoc_simple_parse_dai(struct device_node *ep, struct snd_soc_dai_link_component *dlc, int *is_single_link) @@ -259,6 +270,16 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node;
+ /* + * In BE<->BE connections it is not required to create + * PCM devices at CPU end of the dai link and thus 'no_pcm' + * flag needs to be set. It is useful when there are many + * BE components and some of these have to be connected to + * form a valid audio path. + */ + if (!soc_component_is_pcm(cpus)) + dai_link->no_pcm = 1; + /* card->num_links includes Codec */ asoc_simple_canonicalize_cpu(dai_link, is_single_links); } else {
Hi Sameer
PCM devices are created for FE dai links with 'no-pcm' flag as '0'. Such DAI links have CPU component which implement either pcm_construct() or pcm_new() at component or dai level respectively. Based on this, current patch exposes a helper function to identify such components and populate 'no_pcm' flag for DPCM DAI link.
This helps to have BE<->BE component links where PCM devices need not be created for CPU component involved in such links.
Signed-off-by: Sameer Pujar spujar@nvidia.com
(snip)
@@ -259,6 +270,16 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node;
/*
* In BE<->BE connections it is not required to create
* PCM devices at CPU end of the dai link and thus 'no_pcm'
* flag needs to be set. It is useful when there are many
* BE components and some of these have to be connected to
* form a valid audio path.
*/
if (!soc_component_is_pcm(cpus))
dai_link->no_pcm = 1;
For safety, I want to judge with data->component_chaining.
if (data->component_chaining && !soc_component_is_pcm(cpus)) dai_link->no_pcm = 1;
Thank you for your help !!
Best regards --- Kuninori Morimoto
Hi Kuninori,
On 8/18/2020 8:11 AM, Kuninori Morimoto wrote:
External email: Use caution opening links or attachments
Hi Sameer
PCM devices are created for FE dai links with 'no-pcm' flag as '0'. Such DAI links have CPU component which implement either pcm_construct() or pcm_new() at component or dai level respectively. Based on this, current patch exposes a helper function to identify such components and populate 'no_pcm' flag for DPCM DAI link.
This helps to have BE<->BE component links where PCM devices need not be created for CPU component involved in such links.
Signed-off-by: Sameer Pujar spujar@nvidia.com
(snip)
@@ -259,6 +270,16 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node;
/*
* In BE<->BE connections it is not required to create
* PCM devices at CPU end of the dai link and thus 'no_pcm'
* flag needs to be set. It is useful when there are many
* BE components and some of these have to be connected to
* form a valid audio path.
*/
if (!soc_component_is_pcm(cpus))
dai_link->no_pcm = 1;
For safety, I want to judge with data->component_chaining.
if (data->component_chaining && !soc_component_is_pcm(cpus)) dai_link->no_pcm = 1;
OK. I will keep the additional check. Thanks.
Thank you for your help !!
Best regards
Kuninori Morimoto
Hi again
PCM devices are created for FE dai links with 'no-pcm' flag as '0'. Such DAI links have CPU component which implement either pcm_construct() or pcm_new() at component or dai level respectively. Based on this, current patch exposes a helper function to identify such components and populate 'no_pcm' flag for DPCM DAI link.
This helps to have BE<->BE component links where PCM devices need not be created for CPU component involved in such links.
Signed-off-by: Sameer Pujar spujar@nvidia.com
(snip)
+static bool soc_component_is_pcm(struct snd_soc_dai_link_component *dlc) +{
- struct snd_soc_dai *dai = snd_soc_find_dai(dlc);
- if (dai && (dai->component->driver->pcm_construct ||
dai->driver->pcm_new))
return true;
- return false;
+}
This snd_soc_find_dai() will indicate WARNING if .config has CONFIG_LOCKDEP for me.
Maybe implement it at soc-core.c with client_mutex lock is needed.
Thank you for your help !!
Best regards --- Kuninori Morimoto
Hi Kuninori,
On 8/18/2020 10:53 AM, Kuninori Morimoto wrote:
External email: Use caution opening links or attachments
Hi again
PCM devices are created for FE dai links with 'no-pcm' flag as '0'. Such DAI links have CPU component which implement either pcm_construct() or pcm_new() at component or dai level respectively. Based on this, current patch exposes a helper function to identify such components and populate 'no_pcm' flag for DPCM DAI link.
This helps to have BE<->BE component links where PCM devices need not be created for CPU component involved in such links.
Signed-off-by: Sameer Pujar spujar@nvidia.com
(snip)
+static bool soc_component_is_pcm(struct snd_soc_dai_link_component *dlc) +{
struct snd_soc_dai *dai = snd_soc_find_dai(dlc);
if (dai && (dai->component->driver->pcm_construct ||
dai->driver->pcm_new))
return true;
return false;
+}
This snd_soc_find_dai() will indicate WARNING if .config has CONFIG_LOCKDEP for me.
Maybe implement it at soc-core.c with client_mutex lock is needed.
Thank you for testing this. I will update this in next revision.
Thank you for your help !!
Best regards
Kuninori Morimoto
Hi Morimoto-san,
(snip)
+static bool soc_component_is_pcm(struct snd_soc_dai_link_component *dlc) +{ + struct snd_soc_dai *dai = snd_soc_find_dai(dlc);
+ if (dai && (dai->component->driver->pcm_construct || + dai->driver->pcm_new)) + return true;
+ return false; +}
This snd_soc_find_dai() will indicate WARNING if .config has CONFIG_LOCKDEP for me.
Maybe implement it at soc-core.c with client_mutex lock is needed.
I tried testing this with LOCKDEP config enabled at my end. It seems I don't see warning originated from above function. Are you suggesting that, in general, snd_soc_find_dai() should be called with client_mutex held?
However I do see below warning and stack which is not related to above function call. dump_backtrace+0x0/0x1c0 show_stack+0x18/0x28 dump_stack+0xc8/0x128 __warn+0xa0/0x15c report_bug+0xc8/0x180 bug_handler+0x20/0x80 brk_handler+0x6c/0xc0 do_debug_exception+0xd8/0x1f0 el1_sync_handler+0x98/0x128 el1_sync+0x7c/0x100 snd_soc_find_dai+0x10c/0x120 [snd_soc_core] snd_soc_dai_link_set_capabilities+0xc0/0x168 [snd_soc_core] graph_dai_link_of_dpcm+0x3a4/0x410 [snd_soc_audio_graph_card] graph_for_each_link+0x174/0x220 [snd_soc_audio_graph_card] graph_probe+0x174/0x270 [snd_soc_audio_graph_card]
May be *snd_soc_dai_link_set_capabilities**()* requires similar fix?
Thanks, Sameer
Hi Sameer
+static bool soc_component_is_pcm(struct snd_soc_dai_link_component *dlc) +{ + struct snd_soc_dai *dai = snd_soc_find_dai(dlc); + + if (dai && (dai->component->driver->pcm_construct || + dai->driver->pcm_new)) + return true; + + return false; +}
(snip)
I tried testing this with LOCKDEP config enabled at my end. It seems I don't see warning originated from above function. Are you suggesting that, in general, snd_soc_find_dai() should be called with client_mutex held?
Hmm ? strange...
snd_soc_find_dai() is using lockdep_assert_held()
struct snd_soc_dai *snd_soc_find_dai(...) { ... => lockdep_assert_held(&client_mutex); ... }
and lockdep_assert_held() will indicate WARN_ON()
-- lockdep.h -- ... #ifdef CONFIG_LOCKDEP ... #define lockdep_assert_held(l) do { \ => WARN_ON(debug_locks && !lockdep_is_held(l)); \ } while (0)
May be snd_soc_dai_link_set_capabilities() requires similar fix?
Yes, I'm posting fixup patch.
https://patchwork.kernel.org/patch/11719919/
Thank you for your help !!
Best regards --- Kuninori Morimoto
Hi Morimoto-san,
(snip)
I tried testing this with LOCKDEP config enabled at my end. It seems I don't see warning originated from above function. Are you suggesting that, in general, snd_soc_find_dai() should be called with client_mutex held?
Hmm ? strange...
Yes indeed. For saftely I will follow the same as other callers are doing.
...
Yes, I'm posting fixup patch.
https://patchwork.kernel.org/patch/11719919/
Just curious that why snd_soc_find_dai() itself cannot be protected, instead of leaving this to callers.
Thanks, Sameer.
Hi Sameer
Yes, I'm posting fixup patch.
https://patchwork.kernel.org/patch/11719919/
Just curious that why snd_soc_find_dai() itself cannot be protected, instead of leaving this to callers.
Because, snd_soc_find_dai() is called both with/without client_mutex. (same/sof are calling it with mutex, simple-card/audio-graph are calling without mutex)
Other solution is create both snd_soc_find_dai_with_mutex()/without_mutex(). I'm not sure which style is best.
Thank you for your help !!
Best regards --- Kuninori Morimoto
Hi Morimoto-san,
Yes, I'm posting fixup patch.
https://patchwork.kernel.org/patch/11719919/
Just curious that why snd_soc_find_dai() itself cannot be protected, instead of leaving this to callers.
Because, snd_soc_find_dai() is called both with/without client_mutex. (same/sof are calling it with mutex, simple-card/audio-graph are calling without mutex)
Other solution is create both snd_soc_find_dai_with_mutex()/without_mutex(). I'm not sure which style is best.
I don't know how complex it is to have a unified solution. But if we can protect snd_soc_find_dai() itself, things would be simpler may be in long term. Right now there are separate source files for soc-core, soc-dai and soc-component, but because of two approaches looks like the function need to be moved around and need to be placed in soc-core. Also the issue might go unnoticed if LOCKDEP is not enabled.
May be start with a wrapper for now and eventually unify?
Thanks, Sameer.
Hi Sameer
Other solution is create both snd_soc_find_dai_with_mutex()/without_mutex(). I'm not sure which style is best.
I don't know how complex it is to have a unified solution. But if we can protect snd_soc_find_dai() itself, things would be simpler may be in long term. Right now there are separate source files for soc-core, soc-dai and soc-component, but because of two approaches looks like the function need to be moved around and need to be placed in soc-core. Also the issue might go unnoticed if LOCKDEP is not enabled.
May be start with a wrapper for now and eventually unify?
Yeah, it seems has _with_mutex() can be better idea. I'm posting patch, but I noticed that Mark's branch vs Linus branch have some mismatch (?), and now I'm asking it to him. I can post _with_mutex() version as v2 if I could get answer. After that I'm happy your next patch can re-use it.
Thank you for your help !!
Best regards --- Kuninori Morimoto
Hi Morimoto-san,
Other solution is create both snd_soc_find_dai_with_mutex()/without_mutex(). I'm not sure which style is best.
I don't know how complex it is to have a unified solution. But if we can protect snd_soc_find_dai() itself, things would be simpler may be in long term. Right now there are separate source files for soc-core, soc-dai and soc-component, but because of two approaches looks like the function need to be moved around and need to be placed in soc-core. Also the issue might go unnoticed if LOCKDEP is not enabled.
May be start with a wrapper for now and eventually unify?
Yeah, it seems has _with_mutex() can be better idea. I'm posting patch, but I noticed that Mark's branch vs Linus branch have some mismatch (?), and now I'm asking it to him. I can post _with_mutex() version as v2 if I could get answer. After that I'm happy your next patch can re-use it.
Sure. BTW, there are more such candidates which require 'lock' version of these helpers. For example: soc_find_component(), snd_soc_add/remove_pcm_runtime() and snd_soc_register_dai().
Thank you for the feedback.
Hi Sameer
Sure. BTW, there are more such candidates which require 'lock' version of these helpers. For example: soc_find_component(), snd_soc_add/remove_pcm_runtime() and snd_soc_register_dai().
soc_find_component() is static function, no need to care about mutex. other functions are indeed exported function, but is used from topology.c which is calling it under mutex.
Thank you for your help !!
Best regards --- Kuninori Morimoto
Hi Morimoto-san,
Sorry for the delayed reply as I was on sick leave.
Sure. BTW, there are more such candidates which require 'lock' version of these helpers. For example: soc_find_component(), snd_soc_add/remove_pcm_runtime() and snd_soc_register_dai().
soc_find_component() is static function, no need to care about mutex. other functions are indeed exported function, but is used from topology.c which is calling it under mutex.
I was just thinking if we need to future proof these functions. As you mentioned, currently these have limited usage (in topology.c) and should just be fine to address snd_soc_find_dai() for now.
Thanks, Sameer.
dpcm_end_walk_at_be() stops the graph walk when first BE is found for the given FE component. In a component model we may want to connect multiple DAIs from different components. A new flag is introduced in 'snd_soc_card', which when set allows DAI/component chaining. Later PCM operations can be called for all these listed components for a valid DAPM path.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- include/sound/soc.h | 1 + sound/soc/soc-pcm.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 5e3919f..e8531be 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1084,6 +1084,7 @@ struct snd_soc_card { unsigned int fully_routed:1; unsigned int disable_route_checks:1; unsigned int probed:1; + unsigned int component_chaining:1;
void *drvdata; }; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 00ac1cb..5f1d8d3 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1323,7 +1323,8 @@ int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
/* get number of valid DAI paths and their widgets */ paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, list, - dpcm_end_walk_at_be); + fe->card->component_chaining ? + NULL : dpcm_end_walk_at_be);
dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths, stream ? "capture" : "playback");
New compatible "audio-graph-cc-card" is exposed for audio-graph card driver which allows usage of DAI link chaining and thus connects multiple components together in a system.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- Documentation/devicetree/bindings/sound/audio-graph-card.txt | 1 + 1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sound/audio-graph-card.txt b/Documentation/devicetree/bindings/sound/audio-graph-card.txt index d5f6919..8bf2038 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-card.txt +++ b/Documentation/devicetree/bindings/sound/audio-graph-card.txt @@ -27,6 +27,7 @@ Below are same as Simple-Card. Required properties:
- compatible : "audio-graph-card"; + : "audio-graph-cc-card"; - dais : list of CPU DAI port{s}
Optional properties:
The audio-graph driver supports both normal and DPCM DAI links. The sound cards requiring DPCM DAI link support, use DPCM_SELECTABLE flag and DAI links are treated as DPCM links depending on the number of child nodes in a given DAI link.
There is another requirement where multiple ASoC components need to be connected together in a chained fashion in a component model. This patch sets 'component_chaining' flag for such sound cards where FE<->BE and multiple BE<->BE component connections are required. Hence support for such sound cards is added under 'audio-graph-cc-card' compatible. All DAI links under this are treated as DPCM links.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- sound/soc/generic/audio-graph-card.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 93bddf6..4a0a345 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -20,10 +20,13 @@ #include <linux/string.h> #include <sound/simple_card_utils.h>
-#define DPCM_SELECTABLE 1 - #define PREFIX "audio-graph-card,"
+struct asoc_simple_soc_data { + unsigned int dpcm_selectable:1; + unsigned int component_chaining:1; +}; + static int graph_outdrv_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -447,7 +450,7 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, struct device_node *codec_port; struct device_node *codec_port_old = NULL; struct asoc_simple_data adata; - uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev); + const struct asoc_simple_soc_data *data = of_device_get_match_data(dev); int rc, ret;
/* loop for all listed CPU port */ @@ -474,10 +477,12 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, * It is DPCM * if Codec port has many endpoints, * or has convert-xxx property + * or component chaining is used */ - if (dpcm_selectable && + if (data && data->dpcm_selectable && ((of_get_child_count(codec_port) > 1) || - adata.convert_rate || adata.convert_channels)) + adata.convert_rate || adata.convert_channels || + data->component_chaining)) ret = func_dpcm(priv, cpu_ep, codec_ep, li, (codec_port_old == codec_port)); /* else normal sound */ @@ -650,6 +655,7 @@ static int graph_probe(struct platform_device *pdev) { struct asoc_simple_priv *priv; struct device *dev = &pdev->dev; + const struct asoc_simple_soc_data *data = of_device_get_match_data(dev); struct snd_soc_card *card; struct link_info li; int ret; @@ -666,6 +672,9 @@ static int graph_probe(struct platform_device *pdev) card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets); card->probe = graph_card_probe;
+ if (data) + card->component_chaining = data->component_chaining; + memset(&li, 0, sizeof(li)); graph_get_dais_count(priv, &li); if (!li.link || !li.dais) @@ -711,10 +720,19 @@ static int graph_remove(struct platform_device *pdev) return asoc_simple_clean_reference(card); }
+static const struct asoc_simple_soc_data scu_card_data = { + .dpcm_selectable = 1, +}; + +static const struct asoc_simple_soc_data cc_card_data = { + .dpcm_selectable = 1, + .component_chaining = 1, +}; + static const struct of_device_id graph_of_match[] = { { .compatible = "audio-graph-card", }, - { .compatible = "audio-graph-scu-card", - .data = (void *)DPCM_SELECTABLE }, + { .compatible = "audio-graph-scu-card", .data = &scu_card_data, }, + { .compatible = "audio-graph-cc-card", .data = &cc_card_data, }, {}, }; MODULE_DEVICE_TABLE(of, graph_of_match);
For open platforms, which can support pluggable audio cards, Codec endpoint is not fixed always. It actually depends on the compatible HW module that is going to be connected. From SoC side the given I/O interface is always available. Hence such links have fixed CPU endpoint but no Codec endpoint. This patch helps to support such links where user can populate Codec endpoint only and its fields in Platform DT depending on the plugged HW.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- sound/soc/generic/audio-graph-card.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 4a0a345..b588be9 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -231,6 +231,14 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct snd_soc_dai_link_component *codecs = dai_link->codecs; int ret;
+ /* + * Codec endpoint can be NULL for pluggable audio HW. + * Platform DT can populate the Codec endpoint depending on the + * plugged HW. + */ + if (!li->cpu && !codec_ep) + return 0; + /* Do it all CPU endpoint, and 1st Codec endpoint */ if (!li->cpu && dup_codec) return 0; @@ -566,7 +574,7 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, li->link++; /* 1xCPU-dummy */ li->dais++; /* 1xCPU */
- if (!dup_codec) { + if (!dup_codec && codec_ep) { li->link++; /* 1xdummy-Codec */ li->conf++; /* 1xdummy-Codec */ li->dais++; /* 1xCodec */
Expose a header which describes DT bindings required to use audio-graph based sound card. All Tegra210 based platforms can include this header and add platform specific information. Currently, from SoC point of view, all links are exposed for ADMAIF, AHUB, I2S and DMIC components.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- .../boot/dts/nvidia/tegra210-audio-graph.dtsi | 141 +++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 arch/arm64/boot/dts/nvidia/tegra210-audio-graph.dtsi
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-audio-graph.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-audio-graph.dtsi new file mode 100644 index 0000000..23f524d --- /dev/null +++ b/arch/arm64/boot/dts/nvidia/tegra210-audio-graph.dtsi @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 + +/ { + tegra_sound { + status = "disabled"; + + compatible = "audio-graph-cc-card"; + + clocks = <&tegra_car TEGRA210_CLK_PLL_A>, + <&tegra_car TEGRA210_CLK_PLL_A_OUT0>, + <&tegra_car TEGRA210_CLK_EXTERN1>; + clock-names = "pll_a", "plla_out0", "aud_mclk"; + + assigned-clocks = <&tegra_car TEGRA210_CLK_PLL_A>, + <&tegra_car TEGRA210_CLK_PLL_A_OUT0>, + <&tegra_car TEGRA210_CLK_EXTERN1>; + assigned-clock-parents = <0>, <0>, <&tegra_car TEGRA210_CLK_PLL_A_OUT0>; + assigned-clock-rates = <368640000>, <49152000>, <12288000>; + }; +}; + +&tegra_admaif { + admaif1_port: port@0 { + admaif1_ep: endpoint { + remote-endpoint = <&xbar_admaif1_ep>; + }; + }; + admaif2_port: port@1 { + admaif2_ep: endpoint { + remote-endpoint = <&xbar_admaif2_ep>; + }; + }; + admaif3_port: port@2 { + admaif3_ep: endpoint { + remote-endpoint = <&xbar_admaif3_ep>; + }; + }; + admaif4_port: port@3 { + admaif4_ep: endpoint { + remote-endpoint = <&xbar_admaif4_ep>; + }; + }; + admaif5_port: port@4 { + admaif5_ep: endpoint { + remote-endpoint = <&xbar_admaif5_ep>; + }; + }; + admaif6_port: port@5 { + admaif6_ep: endpoint { + remote-endpoint = <&xbar_admaif6_ep>; + }; + }; + admaif7_port: port@6 { + admaif7_ep: endpoint { + remote-endpoint = <&xbar_admaif7_ep>; + }; + }; + admaif8_port: port@7 { + admaif8_ep: endpoint { + remote-endpoint = <&xbar_admaif8_ep>; + }; + }; + admaif9_port: port@8 { + admaif9_ep: endpoint { + remote-endpoint = <&xbar_admaif9_ep>; + }; + }; + admaif10_port: port@9 { + admaif10_ep: endpoint { + remote-endpoint = <&xbar_admaif10_ep>; + }; + }; +}; + +&tegra_ahub { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0x0>; + xbar_admaif1_ep: endpoint { + remote-endpoint = <&admaif1_ep>; + }; + }; + port@1 { + reg = <0x1>; + xbar_admaif2_ep: endpoint { + remote-endpoint = <&admaif2_ep>; + }; + }; + port@2 { + reg = <0x2>; + xbar_admaif3_ep: endpoint { + remote-endpoint = <&admaif3_ep>; + }; + }; + port@3 { + reg = <0x3>; + xbar_admaif4_ep: endpoint { + remote-endpoint = <&admaif4_ep>; + }; + }; + port@4 { + reg = <0x4>; + xbar_admaif5_ep: endpoint { + remote-endpoint = <&admaif5_ep>; + }; + }; + port@5 { + reg = <0x5>; + xbar_admaif6_ep: endpoint { + remote-endpoint = <&admaif6_ep>; + }; + }; + port@6 { + reg = <0x6>; + xbar_admaif7_ep: endpoint { + remote-endpoint = <&admaif7_ep>; + }; + }; + port@7 { + reg = <0x7>; + xbar_admaif8_ep: endpoint { + remote-endpoint = <&admaif8_ep>; + }; + }; + port@8 { + reg = <0x8>; + xbar_admaif9_ep: endpoint { + remote-endpoint = <&admaif9_ep>; + }; + }; + port@9 { + reg = <0x9>; + xbar_admaif10_ep: endpoint { + remote-endpoint = <&admaif10_ep>; + }; + }; + }; +};
Enable support for audio-graph based sound card on Jetson-Nano and Jetson-TX1. Depending on the platform, required I/O interfaces are enabled.
* Jetson-Nano: Enable I2S3, I2S4, DMIC1 and DMIC2. * Jetson-TX1: Enable all I2S and DMIC interfaces.
Signed-off-by: Sameer Pujar spujar@nvidia.com --- arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts | 217 +++++++++++++++++++++ arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts | 122 ++++++++++++ 2 files changed, 339 insertions(+)
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts b/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts index 56adf28..0eefad7 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts @@ -3,6 +3,7 @@
#include "tegra210-p2180.dtsi" #include "tegra210-p2597.dtsi" +#include "tegra210-audio-graph.dtsi"
/ { model = "NVIDIA Jetson TX1 Developer Kit"; @@ -126,4 +127,220 @@ status = "okay"; }; }; + + tegra_sound { + status = "okay"; + + dais = /* FE */ + <&admaif1_port>, <&admaif2_port>, <&admaif3_port>, + <&admaif4_port>, <&admaif5_port>, <&admaif6_port>, + <&admaif7_port>, <&admaif8_port>, <&admaif9_port>, + <&admaif10_port>, + /* Router */ + <&xbar_i2s1_port>, <&xbar_i2s2_port>, <&xbar_i2s3_port>, + <&xbar_i2s4_port>, <&xbar_i2s5_port>, <&xbar_dmic1_port>, + <&xbar_dmic2_port>, <&xbar_dmic3_port>, + /* I/O DAP Ports */ + <&i2s1_port>, <&i2s2_port>, <&i2s3_port>, <&i2s4_port>, + <&i2s5_port>, <&dmic1_port>, <&dmic2_port>, <&dmic3_port>; + + label = "jetson-tx1-ape"; + }; +}; + +&tegra_admaif { + status = "okay"; +}; + +&tegra_ahub { + status = "okay"; + + ports { + xbar_i2s1_port: port@a { + reg = <0xa>; + xbar_i2s1_ep: endpoint { + remote-endpoint = <&i2s1_cif_ep>; + }; + }; + xbar_i2s2_port: port@b { + reg = <0xb>; + xbar_i2s2_ep: endpoint { + remote-endpoint = <&i2s2_cif_ep>; + }; + }; + xbar_i2s3_port: port@c { + reg = <0xc>; + xbar_i2s3_ep: endpoint { + remote-endpoint = <&i2s3_cif_ep>; + }; + }; + xbar_i2s4_port: port@d { + reg = <0xd>; + xbar_i2s4_ep: endpoint { + remote-endpoint = <&i2s4_cif_ep>; + }; + }; + xbar_i2s5_port: port@e { + reg = <0xe>; + xbar_i2s5_ep: endpoint { + remote-endpoint = <&i2s5_cif_ep>; + }; + }; + xbar_dmic1_port: port@f { + reg = <0xf>; + xbar_dmic1_ep: endpoint { + remote-endpoint = <&dmic1_cif_ep>; + }; + }; + xbar_dmic2_port: port@10 { + reg = <0x10>; + xbar_dmic2_ep: endpoint { + remote-endpoint = <&dmic2_cif_ep>; + }; + }; + xbar_dmic3_port: port@11 { + reg = <0x11>; + xbar_dmic3_ep: endpoint { + remote-endpoint = <&dmic3_cif_ep>; + }; + }; + }; +}; + +&tegra_i2s1 { + status = "okay"; + + port@0 { + i2s1_cif_ep: endpoint { + remote-endpoint = <&xbar_i2s1_ep>; + }; + }; + + i2s1_port: port@1 { + i2s1_dap: endpoint { + dai-format = "i2s"; + + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_i2s2 { + status = "okay"; + + port@0 { + i2s2_cif_ep: endpoint { + remote-endpoint = <&xbar_i2s2_ep>; + }; + }; + + i2s2_port: port@1 { + i2s2_dap: endpoint { + dai-format = "i2s"; + + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_i2s3 { + status = "okay"; + + port@0 { + i2s3_cif_ep: endpoint { + remote-endpoint = <&xbar_i2s3_ep>; + }; + }; + + i2s3_port: port@1 { + i2s3_dap_ep: endpoint { + dai-format = "i2s"; + + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_i2s4 { + status = "okay"; + + port@0 { + i2s4_cif_ep: endpoint { + remote-endpoint = <&xbar_i2s4_ep>; + }; + }; + + i2s4_port: port@1 { + i2s4_dap: endpoint { + dai-format = "i2s"; + + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_i2s5 { + status = "okay"; + + port@0 { + i2s5_cif_ep: endpoint { + remote-endpoint = <&xbar_i2s5_ep>; + }; + }; + + i2s5_port: port@1 { + i2s5_dap: endpoint { + dai-format = "i2s"; + + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_dmic1 { + status = "okay"; + + port@0 { + dmic1_cif_ep: endpoint { + remote-endpoint = <&xbar_dmic1_ep>; + }; + }; + + dmic1_port: port@1 { + dmic1_dap: endpoint { + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_dmic2 { + status = "okay"; + + port@0 { + dmic2_cif_ep: endpoint { + remote-endpoint = <&xbar_dmic2_ep>; + }; + }; + + dmic2_port: port@1 { + dmic2_dap: endpoint { + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_dmic3 { + status = "okay"; + + port@0 { + dmic3_cif_ep: endpoint { + remote-endpoint = <&xbar_dmic3_ep>; + }; + }; + + dmic3_port: port@1 { + dmic3_dap: endpoint { + /* Placeholder for external Codec */ + }; + }; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts index 0dd3d02..dc6a1d8 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts +++ b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts @@ -6,6 +6,7 @@ #include <dt-bindings/mfd/max77620.h>
#include "tegra210.dtsi" +#include "tegra210-audio-graph.dtsi"
/ { model = "NVIDIA Jetson Nano Developer Kit"; @@ -855,4 +856,125 @@ status = "okay"; }; }; + + tegra_sound { + status = "okay"; + + dais = /* FE */ + <&admaif1_port>, <&admaif2_port>, <&admaif3_port>, + <&admaif4_port>, <&admaif5_port>, <&admaif6_port>, + <&admaif7_port>, <&admaif8_port>, <&admaif9_port>, + <&admaif10_port>, + /* Router */ + <&xbar_i2s3_port>, <&xbar_i2s4_port>, + <&xbar_dmic1_port>, <&xbar_dmic2_port>, + /* I/O DAP Ports */ + <&i2s3_port>, <&i2s4_port>, + <&dmic1_port>, <&dmic2_port>; + + label = "jetson-nano-ape"; + }; +}; + +&tegra_admaif { + status = "okay"; +}; + +&tegra_ahub { + status = "okay"; + + ports { + xbar_i2s3_port: port@c { + reg = <0xc>; + xbar_i2s3_ep: endpoint { + remote-endpoint = <&i2s3_cif_ep>; + }; + }; + xbar_i2s4_port: port@d { + reg = <0xd>; + xbar_i2s4_ep: endpoint { + remote-endpoint = <&i2s4_cif_ep>; + }; + }; + xbar_dmic1_port: port@f { + reg = <0xf>; + xbar_dmic1_ep: endpoint { + remote-endpoint = <&dmic1_cif_ep>; + }; + }; + xbar_dmic2_port: port@10 { + reg = <0x10>; + xbar_dmic2_ep: endpoint { + remote-endpoint = <&dmic2_cif_ep>; + }; + }; + }; +}; + +&tegra_i2s3 { + status = "okay"; + + port@0 { + i2s3_cif_ep: endpoint { + remote-endpoint = <&xbar_i2s3_ep>; + }; + }; + + i2s3_port: port@1 { + i2s3_dap_ep: endpoint { + dai-format = "i2s"; + + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_i2s4 { + status = "okay"; + + port@0 { + i2s4_cif_ep: endpoint { + remote-endpoint = <&xbar_i2s4_ep>; + }; + }; + + i2s4_port: port@1 { + i2s4_dap: endpoint@0 { + dai-format = "i2s"; + + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_dmic1 { + status = "okay"; + + port@0 { + dmic1_cif_ep: endpoint@0 { + remote-endpoint = <&xbar_dmic1_ep>; + }; + }; + + dmic1_port: port@1 { + dmic1_dap: endpoint@0 { + /* Placeholder for external Codec */ + }; + }; +}; + +&tegra_dmic2 { + status = "okay"; + + port@0 { + dmic2_cif_ep: endpoint@0 { + remote-endpoint = <&xbar_dmic2_ep>; + }; + }; + + dmic2_port: port@1 { + dmic2_dap: endpoint@0 { + /* Placeholder for external Codec */ + }; + }; };
Hi Sameer Cc Mark
This series proposes following enhancements to audio-graph card driver.
- Support multiple instances of a component.
- Support open platforms with empty Codec endpoint.
- Identify no-pcm DPCM DAI links which can be used in BE<->BE connections.
- Add new compatible to support DPCM based DAI chaining.
This pushes DT support for Tegra210 based platforms which uses audio-graph card and above enhancements.
The series is based on following references where DPCM usgae for Tegra Audio and simple-card driver proposal were discussed.
- https://lkml.org/lkml/2020/4/30/519 (DPCM for Tegra)
- https://lkml.org/lkml/2020/6/27/4 (simple-card driver)
I will try to test this patch-set this week, and report/review it.
Thank you for your help !!
Best regards --- Kuninori Morimoto
Hi Kuninori,
On 8/17/2020 7:23 AM, Kuninori Morimoto wrote:
External email: Use caution opening links or attachments
Hi Sameer Cc Mark
This series proposes following enhancements to audio-graph card driver.
- Support multiple instances of a component.
- Support open platforms with empty Codec endpoint.
- Identify no-pcm DPCM DAI links which can be used in BE<->BE connections.
- Add new compatible to support DPCM based DAI chaining.
This pushes DT support for Tegra210 based platforms which uses audio-graph card and above enhancements.
The series is based on following references where DPCM usgae for Tegra Audio and simple-card driver proposal were discussed.
- https://lkml.org/lkml/2020/4/30/519 (DPCM for Tegra)
- https://lkml.org/lkml/2020/6/27/4 (simple-card driver)
I will try to test this patch-set this week, and report/review it.
Thank you for review so far. Have you also got a chance to review remaining commits in the series?
Thank you for your help !!
Best regards
Kuninori Morimoto
Hi Sameer
This series proposes following enhancements to audio-graph card driver.
- Support multiple instances of a component.
- Support open platforms with empty Codec endpoint.
- Identify no-pcm DPCM DAI links which can be used in BE<->BE connections.
- Add new compatible to support DPCM based DAI chaining.
This pushes DT support for Tegra210 based platforms which uses audio-graph card and above enhancements.
The series is based on following references where DPCM usgae for Tegra Audio and simple-card driver proposal were discussed.
- https://lkml.org/lkml/2020/4/30/519 (DPCM for Tegra)
- https://lkml.org/lkml/2020/6/27/4 (simple-card driver)
I will try to test this patch-set this week, and report/review it.
Thank you for review so far. Have you also got a chance to review remaining commits in the series?
I have no comment/opinion for other patches. Thanks
Thank you for your help !!
Best regards --- Kuninori Morimoto
participants (2)
-
Kuninori Morimoto
-
Sameer Pujar