ASoC: audio-graph-card2.c: make Codec2Codec settings optional

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

Audio Graph Card2 has Codec2Codec support, but I noticed
 - Current Codec2Codec setting value is not correct
   because it is using of_get_property().
 - simple-card-utils has default Codec2Codec settings
   and it is overwriting Card2 settings
 - This default settings works for non Codec2Codec case
   (= DPCM::BE case) too.

This patch-set solve these issues.
This commit is contained in:
Mark Brown 2022-07-08 21:46:29 +01:00
commit 7d596d9bb2
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
4 changed files with 126 additions and 43 deletions

View file

@ -51,7 +51,6 @@ struct prop_nums {
int cpus;
int codecs;
int platforms;
int c2c;
};
struct asoc_simple_priv {
@ -64,7 +63,6 @@ struct asoc_simple_priv {
struct snd_soc_dai_link_component *platforms;
struct asoc_simple_data adata;
struct snd_soc_codec_conf *codec_conf;
struct snd_soc_pcm_stream *c2c_conf;
struct prop_nums num;
unsigned int mclk_fs;
} *dai_props;
@ -75,7 +73,6 @@ struct asoc_simple_priv {
struct snd_soc_dai_link_component *dlcs;
struct snd_soc_dai_link_component dummy;
struct snd_soc_codec_conf *codec_conf;
struct snd_soc_pcm_stream *c2c_conf;
struct gpio_desc *pa_gpio;
const struct snd_soc_ops *ops;
unsigned int dpcm_selectable:1;

View file

@ -17,6 +17,23 @@
* CONFIG_SND_AUDIO_GRAPH_CARD2
* CONFIG_SND_AUDIO_GRAPH_CARD2_CUSTOM_SAMPLE
* CONFIG_SND_TEST_COMPONENT
*
*
* You can indicate more detail each device behavior as debug if you modify
* "compatible" on each test-component. see below
*
* test_cpu {
* - compatible = "test-cpu";
* + compatible = "test-cpu-verbose";
* ...
* };
*
* test_codec {
* - compatible = "test-codec";
* + compatible = "test-codec-verbose";
* ...
* };
*
*/
/ {
/*
@ -101,35 +118,74 @@ audio-graph-card2-custom-sample {
"TC OUT", "TC DAI11 Playback",
"TC DAI9 Capture", "TC IN";
links = <&cpu0 /* normal: cpu side only */
&mcpu0 /* multi: cpu side only */
&fe00 &fe01 &be0 /* dpcm: both FE / BE */
&fe10 &fe11 &be1 /* dpcm-m: both FE / BE */
&c2c /* c2c: cpu side only */
&c2c_m /* c2c: cpu side only */
links = <
/*
* [Normal]: cpu side only
* cpu0/codec0
*/
&cpu0
/*
* [Multi-CPU/Codec]: cpu side only
* cpu1/cpu2/codec1/codec2
*/
&mcpu0
/*
* [DPCM]: both FE / BE
* cpu3/cpu4/codec3
*/
&fe00 &fe01 &be0
/*
* [DPCM-Multi]: both FE / BE
* cpu5/cpu6/codec4/codec5
*/
&fe10 &fe11 &be1
/*
* [Codec2Codec]: cpu side only
* codec6/codec7
*/
&c2c
/*
* [Codec2Codec-Multi]: cpu side only
* codec8/codec9/codec10/codec11
*/
&c2c_m
>;
multi {
ports@0 {
/* [Multi-CPU] */
mcpu0: port@0 { mcpu0_ep: endpoint { remote-endpoint = <&mcodec0_ep>; }; };
port@1 { mcpu1_ep: endpoint { remote-endpoint = <&cpu1_ep>; }; };
port@2 { mcpu2_ep: endpoint { remote-endpoint = <&cpu2_ep>; }; };
};
/* [Multi-Codec] */
ports@1 {
port@0 { mcodec0_ep: endpoint { remote-endpoint = <&mcpu0_ep>; }; };
port@1 { mcodec1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; };
port@2 { mcodec2_ep: endpoint { remote-endpoint = <&codec2_ep>; }; };
};
/* [DPCM-Multi]::BE */
ports@2 {
port@0 { mbe_ep: endpoint { remote-endpoint = <&be10_ep>; }; };
port@1 { mbe1_ep: endpoint { remote-endpoint = <&codec4_ep>; }; };
port@2 { mbe2_ep: endpoint { remote-endpoint = <&codec5_ep>; }; };
};
/* [Codec2Codec-Multi]::CPU */
ports@3 {
port@0 { mc2c0_ep: endpoint { remote-endpoint = <&c2cmf_ep>; }; };
port@1 { mc2c00_ep: endpoint { remote-endpoint = <&codec8_ep>; }; };
port@2 { mc2c01_ep: endpoint { remote-endpoint = <&codec9_ep>; }; };
};
/* [Codec2Codec-Multi]::Codec */
ports@4 {
port@0 { mc2c1_ep: endpoint { remote-endpoint = <&c2cmb_ep>; }; };
port@1 { mc2c10_ep: endpoint { remote-endpoint = <&codec10_ep>; }; };
@ -138,27 +194,36 @@ ports@4 {
};
dpcm {
/* FE */
ports@0 {
/* [DPCM]::FE */
fe00: port@0 { fe00_ep: endpoint { remote-endpoint = <&cpu3_ep>; }; };
fe01: port@1 { fe01_ep: endpoint { remote-endpoint = <&cpu4_ep>; }; };
/* [DPCM-Multi]::FE */
fe10: port@2 { fe10_ep: endpoint { remote-endpoint = <&cpu5_ep>; }; };
fe11: port@3 { fe11_ep: endpoint { remote-endpoint = <&cpu6_ep>; }; };
};
/* BE */
ports@1 {
/* [DPCM]::BE */
be0: port@0 { be00_ep: endpoint { remote-endpoint = <&codec3_ep>; }; };
/* [DPCM-Multi]::BE */
be1: port@1 { be10_ep: endpoint { remote-endpoint = <&mbe_ep>; }; };
};
};
codec2codec {
/* [Codec2Codec] */
ports@0 {
rate = <48000>;
/* use default settings */
c2c: port@0 { c2cf_ep: endpoint { remote-endpoint = <&codec6_ep>; }; };
port@1 { c2cb_ep: endpoint { remote-endpoint = <&codec7_ep>; }; };
};
/* [Codec2Codec-Multi] */
ports@1 {
/* use original settings */
rate = <48000>;
c2c_m: port@0 { c2cmf_ep: endpoint { remote-endpoint = <&mc2c0_ep>; }; };
port@1 { c2cmb_ep: endpoint { remote-endpoint = <&mc2c1_ep>; }; };
@ -179,11 +244,18 @@ test_cpu {
ports {
bitclock-master;
frame-master;
/* [Normal] */
cpu0: port@0 { cpu0_ep: endpoint { remote-endpoint = <&codec0_ep>; }; };
/* [Multi-CPU] */
port@1 { cpu1_ep: endpoint { remote-endpoint = <&mcpu1_ep>; }; };
port@2 { cpu2_ep: endpoint { remote-endpoint = <&mcpu2_ep>; }; };
/* [DPCM]::FE */
port@3 { cpu3_ep: endpoint { remote-endpoint = <&fe00_ep>; }; };
port@4 { cpu4_ep: endpoint { remote-endpoint = <&fe01_ep>; }; };
/* [DPCM-Multi]::FE */
port@5 { cpu5_ep: endpoint { remote-endpoint = <&fe10_ep>; }; };
port@6 { cpu6_ep: endpoint { remote-endpoint = <&fe11_ep>; }; };
};
@ -206,16 +278,27 @@ ports {
*/
prefix = "TC";
/* [Normal] */
port@0 { codec0_ep: endpoint { remote-endpoint = <&cpu0_ep>; }; };
/* [Multi-Codec] */
port@1 { codec1_ep: endpoint { remote-endpoint = <&mcodec1_ep>; }; };
port@2 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; };
/* [DPCM]::BE */
port@3 { codec3_ep: endpoint { remote-endpoint = <&be00_ep>; }; };
/* [DPCM-Multi]::BE */
port@4 { codec4_ep: endpoint { remote-endpoint = <&mbe1_ep>; }; };
port@5 { codec5_ep: endpoint { remote-endpoint = <&mbe2_ep>; }; };
/* [Codec2Codec] */
port@6 { bitclock-master;
frame-master;
codec6_ep: endpoint { remote-endpoint = <&c2cf_ep>; }; };
port@7 { codec7_ep: endpoint { remote-endpoint = <&c2cb_ep>; }; };
/* [Codec2Codec-Multi] */
port@8 { bitclock-master;
frame-master;
codec8_ep: endpoint { remote-endpoint = <&mc2c00_ep>; }; };

View file

@ -851,12 +851,10 @@ int audio_graph2_link_c2c(struct asoc_simple_priv *priv,
struct link_info *li)
{
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 snd_soc_pcm_stream *c2c_conf = dai_props->c2c_conf;
struct device_node *port0, *port1, *ports;
struct device_node *codec0_port, *codec1_port;
struct device_node *ep0, *ep1;
u32 val;
u32 val = 0;
int ret = -EINVAL;
/*
@ -880,20 +878,34 @@ int audio_graph2_link_c2c(struct asoc_simple_priv *priv,
ports = of_get_parent(port0);
port1 = of_get_next_child(ports, lnk);
if (!of_get_property(ports, "rate", &val)) {
/*
* Card2 can use original Codec2Codec settings if DT has.
* It will use default settings if no settings on DT.
* see
* asoc_simple_init_for_codec2codec()
*
* Add more settings here if needed
*/
of_property_read_u32(ports, "rate", &val);
if (val) {
struct device *dev = simple_priv_to_dev(priv);
struct snd_soc_pcm_stream *c2c_conf;
dev_err(dev, "Codec2Codec needs rate settings\n");
goto err1;
c2c_conf = devm_kzalloc(dev, sizeof(*c2c_conf), GFP_KERNEL);
if (!c2c_conf)
goto err1;
c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */
c2c_conf->rates = SNDRV_PCM_RATE_8000_384000;
c2c_conf->rate_min =
c2c_conf->rate_max = val;
c2c_conf->channels_min =
c2c_conf->channels_max = 2; /* update ME */
dai_link->params = c2c_conf;
dai_link->num_params = 1;
}
c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */
c2c_conf->rate_min =
c2c_conf->rate_max = val;
c2c_conf->channels_min =
c2c_conf->channels_max = 2; /* update ME */
dai_link->params = c2c_conf;
ep0 = port_to_endpoint(port0);
ep1 = port_to_endpoint(port1);
@ -1086,7 +1098,6 @@ static int graph_count_c2c(struct asoc_simple_priv *priv,
li->num[li->link].cpus =
li->num[li->link].platforms = graph_counter(codec0);
li->num[li->link].codecs = graph_counter(codec1);
li->num[li->link].c2c = 1;
of_node_put(ports);
of_node_put(port1);

View file

@ -527,6 +527,14 @@ static int asoc_simple_init_for_codec2codec(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hardware hw;
int i, ret, stream;
/* Do nothing if it already has Codec2Codec settings */
if (dai_link->params)
return 0;
/* Do nothing if it was DPCM :: BE */
if (dai_link->no_pcm)
return 0;
/* Only Codecs */
for_each_rtd_components(rtd, i, component) {
if (!asoc_simple_component_is_codec(component))
@ -746,8 +754,7 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
struct asoc_simple_dai *dais;
struct snd_soc_dai_link_component *dlcs;
struct snd_soc_codec_conf *cconf = NULL;
struct snd_soc_pcm_stream *c2c_conf = NULL;
int i, dai_num = 0, dlc_num = 0, cnf_num = 0, c2c_num = 0;
int i, dai_num = 0, dlc_num = 0, cnf_num = 0;
dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL);
dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL);
@ -766,8 +773,6 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
if (!li->num[i].cpus)
cnf_num += li->num[i].codecs;
c2c_num += li->num[i].c2c;
}
dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL);
@ -781,12 +786,6 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
return -ENOMEM;
}
if (c2c_num) {
c2c_conf = devm_kcalloc(dev, c2c_num, sizeof(*c2c_conf), GFP_KERNEL);
if (!c2c_conf)
return -ENOMEM;
}
dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
li->link, dai_num, cnf_num);
@ -800,7 +799,6 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
priv->dais = dais;
priv->dlcs = dlcs;
priv->codec_conf = cconf;
priv->c2c_conf = c2c_conf;
card->dai_link = priv->dai_link;
card->num_links = li->link;
@ -818,12 +816,6 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv,
dlcs += li->num[i].cpus;
dais += li->num[i].cpus;
if (li->num[i].c2c) {
/* Codec2Codec */
dai_props[i].c2c_conf = c2c_conf;
c2c_conf += li->num[i].c2c;
}
} else {
/* DPCM Be's CPU = dummy */
dai_props[i].cpus =