Commit 6a0d3607 authored by Mark Brown's avatar Mark Brown

ASoC: simple-card / audio-graph:

Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

Introduce the ability for sound cards to manually order the startup of
the various components in the card.
parents 936abb09 e64343fa
......@@ -25,6 +25,15 @@ definitions:
capture-only:
description: port connection used only for capture
$ref: /schemas/types.yaml#/definitions/flag
link-trigger-order:
description: trigger order for both start/stop
$ref: /schemas/types.yaml#/definitions/uint32-array
link-trigger-order-start:
description: trigger order for start
$ref: /schemas/types.yaml#/definitions/uint32-array
link-trigger-order-stop:
description: trigger order for stop
$ref: /schemas/types.yaml#/definitions/uint32-array
endpoint-base:
allOf:
......
/* SPDX-License-Identifier: GPL-2.0
*
* audio-graph.h
*
* Copyright (c) 2024 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*/
#ifndef __AUDIO_GRAPH_H
#define __AUDIO_GRAPH_H
/*
* used in
* link-trigger-order
* link-trigger-order-start
* link-trigger-order-stop
*
* default is
* link-trigger-order = <SND_SOC_TRIGGER_LINK
* SND_SOC_TRIGGER_COMPONENT
* SND_SOC_TRIGGER_DAI>;
*/
#define SND_SOC_TRIGGER_LINK 0
#define SND_SOC_TRIGGER_COMPONENT 1
#define SND_SOC_TRIGGER_DAI 2
#define SND_SOC_TRIGGER_SIZE 3 /* shoud be last */
#endif /* __AUDIO_GRAPH_H */
......@@ -199,6 +199,10 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep,
void graph_util_parse_link_direction(struct device_node *np,
bool *is_playback_only, bool *is_capture_only);
void graph_util_parse_trigger_order(struct simple_util_priv *priv,
struct device_node *np,
enum snd_soc_trigger_order *trigger_start,
enum snd_soc_trigger_order *trigger_stop);
#ifdef DEBUG
static inline void simple_util_debug_dai(struct simple_util_priv *priv,
......
......@@ -143,6 +143,8 @@ static int graph_link_init(struct simple_util_priv *priv,
struct device_node *port_codec = ep_to_port(ep_codec);
struct device_node *ports_cpu = port_to_ports(port_cpu);
struct device_node *ports_codec = port_to_ports(port_codec);
enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT;
enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT;
bool playback_only = 0, capture_only = 0;
int ret;
......@@ -165,9 +167,20 @@ static int graph_link_init(struct simple_util_priv *priv,
of_property_read_u32(ep_cpu, "mclk-fs", &dai_props->mclk_fs);
of_property_read_u32(ep_codec, "mclk-fs", &dai_props->mclk_fs);
graph_util_parse_trigger_order(priv, top, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, ports_cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, ports_codec, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, ep_cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, ep_codec, &trigger_start, &trigger_stop);
dai_link->playback_only = playback_only;
dai_link->capture_only = capture_only;
dai_link->trigger_start = trigger_start;
dai_link->trigger_stop = trigger_stop;
dai_link->init = simple_util_dai_init;
dai_link->ops = &graph_ops;
if (priv->ops)
......
......@@ -759,6 +759,8 @@ static void graph_link_init(struct simple_util_priv *priv,
struct device_node *ports_cpu, *ports_codec;
unsigned int daifmt = 0, daiclk = 0;
bool playback_only = 0, capture_only = 0;
enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT;
enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT;
unsigned int bit_frame = 0;
of_node_get(port_cpu);
......@@ -806,6 +808,14 @@ static void graph_link_init(struct simple_util_priv *priv,
of_property_read_u32(ep_cpu, "mclk-fs", &dai_props->mclk_fs);
of_property_read_u32(ep_codec, "mclk-fs", &dai_props->mclk_fs);
graph_util_parse_trigger_order(priv, lnk, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, ports_cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, ports_codec, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, port_cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, ep_cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, ep_codec, &trigger_start, &trigger_stop);
/*
* convert bit_frame
* We need to flip clock_provider if it was CPU node,
......@@ -818,6 +828,9 @@ static void graph_link_init(struct simple_util_priv *priv,
dai_link->playback_only = playback_only;
dai_link->capture_only = capture_only;
dai_link->trigger_start = trigger_start;
dai_link->trigger_stop = trigger_stop;
dai_link->dai_fmt = daifmt | daiclk;
dai_link->init = simple_util_dai_init;
dai_link->ops = &graph_ops;
......
......@@ -4,6 +4,7 @@
//
// Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
#include <dt-bindings/sound/audio-graph.h>
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
......@@ -1156,6 +1157,76 @@ void graph_util_parse_link_direction(struct device_node *np,
}
EXPORT_SYMBOL_GPL(graph_util_parse_link_direction);
static enum snd_soc_trigger_order
__graph_util_parse_trigger_order(struct simple_util_priv *priv,
struct device_node *np,
const char *prop)
{
u32 val[SND_SOC_TRIGGER_SIZE];
int ret;
ret = of_property_read_u32_array(np, prop, val, SND_SOC_TRIGGER_SIZE);
if (ret == 0) {
struct device *dev = simple_priv_to_dev(priv);
u32 order = (val[0] << 8) +
(val[1] << 4) +
(val[2]);
switch (order) {
case (SND_SOC_TRIGGER_LINK << 8) +
(SND_SOC_TRIGGER_COMPONENT << 4) +
(SND_SOC_TRIGGER_DAI):
return SND_SOC_TRIGGER_ORDER_DEFAULT;
case (SND_SOC_TRIGGER_LINK << 8) +
(SND_SOC_TRIGGER_DAI << 4) +
(SND_SOC_TRIGGER_COMPONENT):
return SND_SOC_TRIGGER_ORDER_LDC;
default:
dev_err(dev, "unsupported trigger order [0x%x]\n", order);
}
}
/* SND_SOC_TRIGGER_ORDER_MAX means error */
return SND_SOC_TRIGGER_ORDER_MAX;
}
void graph_util_parse_trigger_order(struct simple_util_priv *priv,
struct device_node *np,
enum snd_soc_trigger_order *trigger_start,
enum snd_soc_trigger_order *trigger_stop)
{
static enum snd_soc_trigger_order order;
/*
* We can use it like below
*
* #include <dt-bindings/sound/audio-graph.h>
*
* link-trigger-order = <SND_SOC_TRIGGER_LINK
* SND_SOC_TRIGGER_COMPONENT
* SND_SOC_TRIGGER_DAI>;
*/
order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order");
if (order < SND_SOC_TRIGGER_ORDER_MAX) {
*trigger_start = order;
*trigger_stop = order;
}
order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order-start");
if (order < SND_SOC_TRIGGER_ORDER_MAX)
*trigger_start = order;
order = __graph_util_parse_trigger_order(priv, np, "link-trigger-order-stop");
if (order < SND_SOC_TRIGGER_ORDER_MAX)
*trigger_stop = order;
return;
}
EXPORT_SYMBOL_GPL(graph_util_parse_trigger_order);
/* Module information */
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
......
......@@ -176,6 +176,8 @@ static int simple_link_init(struct simple_util_priv *priv,
struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
struct device_node *node = of_get_parent(cpu);
enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT;
enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT;
bool playback_only = 0, capture_only = 0;
int ret;
......@@ -198,9 +200,17 @@ static int simple_link_init(struct simple_util_priv *priv,
of_property_read_u32(codec, "mclk-fs", &dai_props->mclk_fs);
of_property_read_u32(codec, PREFIX "mclk-fs", &dai_props->mclk_fs);
graph_util_parse_trigger_order(priv, top, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, node, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, cpu, &trigger_start, &trigger_stop);
graph_util_parse_trigger_order(priv, codec, &trigger_start, &trigger_stop);
dai_link->playback_only = playback_only;
dai_link->capture_only = capture_only;
dai_link->trigger_start = trigger_start;
dai_link->trigger_stop = trigger_stop;
dai_link->init = simple_util_dai_init;
dai_link->ops = &simple_ops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment