mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 02:47:31 -04:00
ASoC: audio-graph-card2: Use extra format on each DAI
Current ASoC is using dai_link->dai_fmt to set DAI format for both CPU/Codec. But because it is using same settings, and SND_SOC_DAIFMT_CLOCK_PROVIDER is flipped for CPU, we can't set both CPU/Codec as clock consumer, for example. To solve this issue, this patch uses extra format for each DAI which can keep compatibility with legacy system, 1. SND_SOC_DAIFMT_FORMAT_MASK 2. SND_SOC_DAIFMT_CLOCK 3. SND_SOC_DAIFMT_INV 4. SND_SOC_DAIFMT_CLOCK_PROVIDER Legacy dai_fmt includes 1, 2, 3, 4 New idea dai_fmt includes 1, 2, 3 ext_fmt includes 4 Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Stephen Gordon <gordoste@iinet.net.au> Link: https://patch.msgid.link/87pll0o5j6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
committed by
Mark Brown
parent
24410f499e
commit
365865b7d7
@@ -667,8 +667,7 @@ static int graph_parse_node(struct simple_util_priv *priv,
|
||||
return graph_parse_node_single(priv, gtype, port, li, is_cpu);
|
||||
}
|
||||
|
||||
static void graph_parse_daifmt(struct device_node *node,
|
||||
unsigned int *daifmt, unsigned int *bit_frame)
|
||||
static void graph_parse_daifmt(struct device_node *node, unsigned int *daifmt)
|
||||
{
|
||||
unsigned int fmt;
|
||||
|
||||
@@ -693,16 +692,6 @@ static void graph_parse_daifmt(struct device_node *node,
|
||||
* };
|
||||
*/
|
||||
|
||||
/*
|
||||
* clock_provider:
|
||||
*
|
||||
* It can be judged it is provider
|
||||
* if (A) or (B) or (C) has bitclock-master / frame-master flag.
|
||||
*
|
||||
* use "or"
|
||||
*/
|
||||
*bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL);
|
||||
|
||||
#define update_daifmt(name) \
|
||||
if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \
|
||||
(fmt & SND_SOC_DAIFMT_##name##_MASK)) \
|
||||
@@ -720,6 +709,17 @@ static void graph_parse_daifmt(struct device_node *node,
|
||||
update_daifmt(INV);
|
||||
}
|
||||
|
||||
static unsigned int graph_parse_bitframe(struct device_node *ep)
|
||||
{
|
||||
struct device_node *port __free(device_node) = ep_to_port(ep);
|
||||
struct device_node *ports __free(device_node) = port_to_ports(port);
|
||||
|
||||
return snd_soc_daifmt_clock_provider_from_bitmap(
|
||||
snd_soc_daifmt_parse_clock_provider_as_bitmap(ep, NULL) |
|
||||
snd_soc_daifmt_parse_clock_provider_as_bitmap(port, NULL) |
|
||||
snd_soc_daifmt_parse_clock_provider_as_bitmap(ports, NULL));
|
||||
}
|
||||
|
||||
static void graph_link_init(struct simple_util_priv *priv,
|
||||
struct device_node *lnk,
|
||||
struct device_node *port_cpu,
|
||||
@@ -730,15 +730,19 @@ static void graph_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 *ep_cpu, *ep_codec;
|
||||
unsigned int daifmt = 0, daiclk = 0;
|
||||
struct device_node *multi_cpu_port = NULL, *multi_codec_port = NULL;
|
||||
struct snd_soc_dai_link_component *dlc;
|
||||
unsigned int daifmt = 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;
|
||||
int multi_cpu_port_idx = 1, multi_codec_port_idx = 1;
|
||||
int i;
|
||||
|
||||
of_node_get(port_cpu);
|
||||
if (graph_lnk_is_multi(port_cpu)) {
|
||||
ep_cpu = graph_get_next_multi_ep(&port_cpu, 1);
|
||||
multi_cpu_port = port_cpu;
|
||||
ep_cpu = graph_get_next_multi_ep(&multi_cpu_port, multi_cpu_port_idx++);
|
||||
of_node_put(port_cpu);
|
||||
port_cpu = ep_to_port(ep_cpu);
|
||||
} else {
|
||||
@@ -748,7 +752,8 @@ static void graph_link_init(struct simple_util_priv *priv,
|
||||
|
||||
of_node_get(port_codec);
|
||||
if (graph_lnk_is_multi(port_codec)) {
|
||||
ep_codec = graph_get_next_multi_ep(&port_codec, 1);
|
||||
multi_codec_port = port_codec;
|
||||
ep_codec = graph_get_next_multi_ep(&multi_codec_port, multi_codec_port_idx++);
|
||||
of_node_put(port_codec);
|
||||
port_codec = ep_to_port(ep_codec);
|
||||
} else {
|
||||
@@ -756,13 +761,13 @@ static void graph_link_init(struct simple_util_priv *priv,
|
||||
}
|
||||
struct device_node *ports_codec __free(device_node) = port_to_ports(port_codec);
|
||||
|
||||
graph_parse_daifmt(ep_cpu, &daifmt, &bit_frame);
|
||||
graph_parse_daifmt(ep_codec, &daifmt, &bit_frame);
|
||||
graph_parse_daifmt(port_cpu, &daifmt, &bit_frame);
|
||||
graph_parse_daifmt(port_codec, &daifmt, &bit_frame);
|
||||
graph_parse_daifmt(ports_cpu, &daifmt, &bit_frame);
|
||||
graph_parse_daifmt(ports_codec, &daifmt, &bit_frame);
|
||||
graph_parse_daifmt(lnk, &daifmt, &bit_frame);
|
||||
graph_parse_daifmt(ep_cpu, &daifmt);
|
||||
graph_parse_daifmt(ep_codec, &daifmt);
|
||||
graph_parse_daifmt(port_cpu, &daifmt);
|
||||
graph_parse_daifmt(port_codec, &daifmt);
|
||||
graph_parse_daifmt(ports_cpu, &daifmt);
|
||||
graph_parse_daifmt(ports_codec, &daifmt);
|
||||
graph_parse_daifmt(lnk, &daifmt);
|
||||
|
||||
graph_util_parse_link_direction(lnk, &playback_only, &capture_only);
|
||||
graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only);
|
||||
@@ -788,14 +793,21 @@ static void graph_link_init(struct simple_util_priv *priv,
|
||||
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,
|
||||
* because it is Codec base.
|
||||
*/
|
||||
daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame);
|
||||
if (is_cpu_node)
|
||||
daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk);
|
||||
for_each_link_cpus(dai_link, i, dlc) {
|
||||
dlc->ext_fmt = graph_parse_bitframe(ep_cpu);
|
||||
|
||||
if (multi_cpu_port)
|
||||
ep_cpu = graph_get_next_multi_ep(&multi_cpu_port, multi_cpu_port_idx++);
|
||||
}
|
||||
|
||||
for_each_link_codecs(dai_link, i, dlc) {
|
||||
dlc->ext_fmt = graph_parse_bitframe(ep_codec);
|
||||
|
||||
if (multi_codec_port)
|
||||
ep_codec = graph_get_next_multi_ep(&multi_codec_port, multi_codec_port_idx++);
|
||||
}
|
||||
|
||||
/*** Don't use port_cpu / port_codec after here ***/
|
||||
|
||||
dai_link->playback_only = playback_only;
|
||||
dai_link->capture_only = capture_only;
|
||||
@@ -803,7 +815,7 @@ static void graph_link_init(struct simple_util_priv *priv,
|
||||
dai_link->trigger_start = trigger_start;
|
||||
dai_link->trigger_stop = trigger_stop;
|
||||
|
||||
dai_link->dai_fmt = daifmt | daiclk;
|
||||
dai_link->dai_fmt = daifmt;
|
||||
dai_link->init = simple_util_dai_init;
|
||||
dai_link->ops = &graph_ops;
|
||||
if (priv->ops)
|
||||
|
||||
Reference in New Issue
Block a user