* [PATCH] ASoC: ti: davinci-mcasp: Add audio-graph-card2 and DPCM support
@ 2026-06-03 21:18 Sen Wang
2026-06-11 19:48 ` Mark Brown
0 siblings, 1 reply; 2+ messages in thread
From: Sen Wang @ 2026-06-03 21:18 UTC (permalink / raw)
To: linux-sound; +Cc: broonie, lgirdwood, perex, tiwai, linux-kernel, Sen Wang
Extend the McASP driver to support audio-graph-card2 of-graph topology,
while maintaining backwards compatibility for existing simple-audio-card
phandles and machine drivers, which now uses the default MCASP_GRAPH_NONE
code path.
Signed-off-by: Sen Wang <sen@ti.com>
---
sound/soc/ti/davinci-mcasp.c | 183 ++++++++++++++++++++++++++++++++++-
1 file changed, 180 insertions(+), 3 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index f229f847eaf4..79239131b659 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <linux/platform_data/davinci_asp.h>
#include <linux/math64.h>
#include <linux/bitmap.h>
@@ -74,6 +75,14 @@ struct davinci_mcasp_ruledata {
int stream;
};
+enum mcasp_graph_mode {
+ MCASP_GRAPH_NONE, /* 1:1, simple-audio-card, no of-graph endpoints */
+ MCASP_GRAPH_PORT, /* 1:1, audio-graph-card: port { endpoint } */
+ MCASP_GRAPH_PORTS, /* 1:N, audio-graph-card2 non-DPCM: ports { port@0; ... } */
+ MCASP_GRAPH_DPCM, /* N:M, audio-graph-card2 DPCM: N FE DAIs, detected via */
+ /* remote "dpcm" node in the sound card DT */
+};
+
struct davinci_mcasp {
struct snd_dmaengine_dai_dma_data dma_data[2];
struct davinci_mcasp_pdata *pdata;
@@ -124,6 +133,10 @@ struct davinci_mcasp {
int max_format_width;
u8 active_serializers[2];
+ /* Audio graph support */
+ enum mcasp_graph_mode graph_mode;
+ int num_dais;
+
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
#endif
@@ -1486,7 +1499,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt);
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ unsigned int cpu_fmt;
+
+ if (mcasp->graph_mode != MCASP_GRAPH_NONE && rtd->dai_link->dai_fmt)
+ /* clock provider bits stored separately in ext_fmt */
+ cpu_fmt = snd_soc_daifmt_clock_provider_flipped(
+ rtd->dai_link->dai_fmt) |
+ rtd->dai_link->cpus[0].ext_fmt;
+ else
+ cpu_fmt = mcasp->dai_fmt;
+
+ ret = davinci_mcasp_set_dai_fmt(cpu_dai, cpu_fmt);
if (ret)
return ret;
@@ -2029,8 +2053,31 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
};
+/* Translate of-graph endpoint to DAI ID (DPCM: port reg; else 0). */
+static int davinci_mcasp_of_xlate_dai_id(struct snd_soc_component *component,
+ struct device_node *endpoint)
+{
+ struct davinci_mcasp *mcasp = snd_soc_component_get_drvdata(component);
+ struct device_node *port;
+ u32 port_reg = 0;
+
+ if (mcasp->graph_mode != MCASP_GRAPH_DPCM)
+ return 0;
+
+ /* endpoint is inside mcasp/ports/port@N — read port's reg */
+ port = of_get_parent(endpoint);
+ if (!port)
+ return -EINVAL;
+
+ of_property_read_u32(port, "reg", &port_reg);
+ of_node_put(port);
+
+ return port_reg;
+}
+
static const struct snd_soc_component_driver davinci_mcasp_component = {
.name = "davinci-mcasp",
+ .of_xlate_dai_id = davinci_mcasp_of_xlate_dai_id,
.legacy_dai_naming = 1,
};
@@ -2138,6 +2185,88 @@ static bool davinci_mcasp_have_gpiochip(struct davinci_mcasp *mcasp)
return device_property_present(mcasp->dev, "gpio-controller");
}
+/* Return true if the remote sound card uses a "dpcm" container. */
+static bool mcasp_detect_dpcm(struct device_node *np)
+{
+ struct device_node *ep, *remote_ep;
+ struct device_node *port, *container, *parent;
+ bool is_dpcm = false;
+
+ /* Grab the first endpoint under this McASP node */
+ ep = of_graph_get_next_endpoint(np, NULL);
+ if (!ep)
+ return false;
+
+ /* Follow remote-endpoint phandle into the card node */
+ remote_ep = of_graph_get_remote_endpoint(ep);
+ of_node_put(ep);
+ if (!remote_ep)
+ return false;
+
+ /* Traverse the remote: remote_ep -> port -> ports@N -> dpcm */
+ port = of_get_parent(remote_ep);
+ of_node_put(remote_ep);
+ if (!port)
+ return false;
+
+ container = of_get_parent(port);
+ of_node_put(port);
+ if (!container)
+ return false;
+
+ if (of_node_name_eq(container, "ports")) {
+ parent = of_get_parent(container);
+ of_node_put(container);
+ if (parent) {
+ is_dpcm = of_node_name_eq(parent, "dpcm");
+ of_node_put(parent);
+ }
+ } else {
+ of_node_put(container);
+ }
+
+ return is_dpcm;
+}
+
+/* Detect audio-graph topology and return the number of DAIs to register. */
+static int davinci_mcasp_parse_of_graph(struct davinci_mcasp *mcasp,
+ struct device_node *np)
+{
+ struct device_node *port, *ports;
+ int num_dais = 0;
+
+ mcasp->graph_mode = MCASP_GRAPH_NONE;
+
+ /* audio-graph-card2: ports { port@0 ... }; DPCM -> N DAIs, else 1 */
+ ports = of_get_child_by_name(np, "ports");
+ if (ports) {
+ int port_count = of_get_child_count(ports);
+
+ of_node_put(ports);
+
+ if (mcasp_detect_dpcm(np)) {
+ num_dais = port_count;
+ mcasp->graph_mode = MCASP_GRAPH_DPCM;
+ } else {
+ num_dais = 1;
+ mcasp->graph_mode = MCASP_GRAPH_PORTS;
+ }
+
+ return num_dais;
+ }
+
+ /* audio-graph-card: single port { endpoint } */
+ port = of_get_child_by_name(np, "port");
+ if (port) {
+ num_dais = of_graph_get_endpoint_count(port);
+ if (num_dais > 0)
+ mcasp->graph_mode = MCASP_GRAPH_PORT;
+ of_node_put(port);
+ }
+
+ return num_dais ? num_dais : 1;
+}
+
static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
struct platform_device *pdev)
{
@@ -2555,6 +2684,53 @@ static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp)
}
#endif /* CONFIG_GPIOLIB */
+static int davinci_mcasp_register_component(struct davinci_mcasp *mcasp,
+ struct platform_device *pdev)
+{
+ struct snd_soc_dai_driver *dais;
+ int i;
+
+ if (mcasp->graph_mode == MCASP_GRAPH_NONE || mcasp->num_dais <= 1)
+ return devm_snd_soc_register_component(&pdev->dev,
+ &davinci_mcasp_component,
+ &davinci_mcasp_dai[mcasp->op_mode], 1);
+
+ dais = devm_kcalloc(&pdev->dev, mcasp->num_dais, sizeof(*dais),
+ GFP_KERNEL);
+ if (!dais)
+ return -ENOMEM;
+
+ for (i = 0; i < mcasp->num_dais; i++) {
+ memcpy(&dais[i], &davinci_mcasp_dai[mcasp->op_mode],
+ sizeof(*dais));
+ dais[i].id = i;
+ dais[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "davinci-mcasp.%d", i);
+ if (!dais[i].name)
+ return -ENOMEM;
+
+ /* Unique stream names per DAI */
+ if (dais[i].playback.channels_min) {
+ dais[i].playback.stream_name =
+ devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "Playback Port %d", i);
+ if (!dais[i].playback.stream_name)
+ return -ENOMEM;
+ }
+ if (dais[i].capture.channels_min) {
+ dais[i].capture.stream_name =
+ devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "Capture Port %d", i);
+ if (!dais[i].capture.stream_name)
+ return -ENOMEM;
+ }
+ }
+
+ return devm_snd_soc_register_component(&pdev->dev,
+ &davinci_mcasp_component,
+ dais, mcasp->num_dais);
+}
+
static int davinci_mcasp_probe(struct platform_device *pdev)
{
struct snd_dmaengine_dai_dma_data *dma_data;
@@ -2760,9 +2936,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
goto err;
}
- ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
- &davinci_mcasp_dai[mcasp->op_mode], 1);
+ /* Parse audio-graph structure and register DAIs */
+ mcasp->num_dais = davinci_mcasp_parse_of_graph(mcasp, pdev->dev.of_node);
+ ret = davinci_mcasp_register_component(mcasp, pdev);
if (ret != 0)
goto err;
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] ASoC: ti: davinci-mcasp: Add audio-graph-card2 and DPCM support
2026-06-03 21:18 [PATCH] ASoC: ti: davinci-mcasp: Add audio-graph-card2 and DPCM support Sen Wang
@ 2026-06-11 19:48 ` Mark Brown
0 siblings, 0 replies; 2+ messages in thread
From: Mark Brown @ 2026-06-11 19:48 UTC (permalink / raw)
To: linux-sound, Sen Wang; +Cc: lgirdwood, perex, tiwai, linux-kernel
On Wed, 03 Jun 2026 16:18:30 -0500, Sen Wang wrote:
> ASoC: ti: davinci-mcasp: Add audio-graph-card2 and DPCM support
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.2
Thanks!
[1/1] ASoC: ti: davinci-mcasp: Add audio-graph-card2 and DPCM support
https://git.kernel.org/broonie/sound/c/216f7452a68e
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-12 22:18 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-03 21:18 [PATCH] ASoC: ti: davinci-mcasp: Add audio-graph-card2 and DPCM support Sen Wang
2026-06-11 19:48 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®