Commit ca39fab8 authored by Mark Brown's avatar Mark Brown

ASoC: grace time for DPCM cleanup

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

As we discussed in [1], we don't need to use dpcm_playback/capture flag,
so we remove it. But we have been using it for 10 years, some driver might
get damage. The most likely case is that the device/driver can use both
playback/capture, but have only one flag, and not using xxx_only flag.
[1/3] patch indicates warning in such case.

These adds grace time for DPCM cleanup.
I'm not sure when dpcm_xxx will be removed, and Codec check bypass will be
error, but maybe v6.12 or v6.13 ?
Please check each driver by that time.

Previous patch-set try to check both CPU and Codec in DPCM, but we noticed
that there are some special DAI which we can't handle today [2]. So I will
escape it in this patch-set.

[1] https://lore.kernel.org/r/87edaym2cg.wl-kuninori.morimoto.gx@renesas.com
[2] https://lore.kernel.org/all/3e67d62d-fe08-4f55-ab5b-ece8a57154f9@linux.intel.com/

Link: https://lore.kernel.org/r/87edaym2cg.wl-kuninori.morimoto.gx@renesas.com
Link: https://lore.kernel.org/r/87wmo6dyxg.wl-kuninori.morimoto.gx@renesas.com
Link: https://lore.kernel.org/r/87msole5wc.wl-kuninori.morimoto.gx@renesas.com
Link: https://lore.kernel.org/r/871q5tnuok.wl-kuninori.morimoto.gx@renesas.com
Link: https://lore.kernel.org/r/87bk4oqerx.wl-kuninori.morimoto.gx@renesas.com
Link: https://lore.kernel.org/r/8734pctmte.wl-kuninori.morimoto.gx@renesas.com
Link: https://lore.kernel.org/r/87r0ctwzr4.wl-kuninori.morimoto.gx@renesas.com
Link: https://lore.kernel.org/r/87cymvlmki.wl-kuninori.morimoto.gx@renesas.com
parents 90dc34da 61e1f74f
......@@ -219,7 +219,6 @@ void snd_soc_dai_resume(struct snd_soc_dai *dai);
int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
struct snd_soc_pcm_runtime *rtd, int num);
bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int stream);
void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link);
void snd_soc_dai_action(struct snd_soc_dai *dai,
int stream, int action);
static inline void snd_soc_dai_activate(struct snd_soc_dai *dai,
......
......@@ -815,6 +815,7 @@ struct snd_soc_dai_link {
/* This DAI link can route to other DAI links at runtime (Frontend)*/
unsigned int dynamic:1;
/* REMOVE ME */
/* DPCM capture and Playback support */
unsigned int dpcm_capture:1;
unsigned int dpcm_playback:1;
......
......@@ -650,9 +650,6 @@ static int imx_card_parse_of(struct imx_card_data *data)
link->ops = &imx_aif_ops;
}
if (link->no_pcm || link->dynamic)
snd_soc_dai_link_set_capabilities(link);
/* Get dai fmt */
ret = simple_util_parse_daifmt(dev, np, codec,
NULL, &link->dai_fmt);
......
......@@ -279,8 +279,6 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv,
graph_parse_convert(dev, ep, &dai_props->adata);
snd_soc_dai_link_set_capabilities(dai_link);
ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name);
li->link++;
......
......@@ -966,8 +966,6 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv,
graph_parse_convert(ep, dai_props); /* at node of <dpcm> */
graph_parse_convert(rep, dai_props); /* at node of <CPU/Codec> */
snd_soc_dai_link_set_capabilities(dai_link);
graph_link_init(priv, lnk, cpu_port, codec_port, li, is_cpu);
err:
of_node_put(ep);
......
......@@ -291,8 +291,6 @@ static int simple_dai_link_of_dpcm(struct simple_util_priv *priv,
simple_parse_convert(dev, np, &dai_props->adata);
snd_soc_dai_link_set_capabilities(dai_link);
ret = simple_link_init(priv, np, codec, li, prefix, dai_name);
out_put_node:
......
......@@ -132,7 +132,7 @@ static int axg_card_add_tdm_loopback(struct snd_soc_card *card,
lb->stream_name = lb->name;
lb->cpus->of_node = pad->cpus->of_node;
lb->cpus->dai_name = "TDM Loopback";
lb->dpcm_capture = 1;
lb->capture_only = 1;
lb->no_pcm = 1;
lb->ops = &axg_card_tdm_be_ops;
lb->init = axg_card_tdm_dai_lb_init;
......@@ -176,7 +176,7 @@ static int axg_card_parse_cpu_tdm_slots(struct snd_soc_card *card,
/* Disable playback is the interface has no tx slots */
if (!tx)
link->dpcm_playback = 0;
link->capture_only = 1;
for (i = 0, rx = 0; i < AXG_TDM_NUM_LANES; i++) {
snprintf(propname, 32, "dai-tdm-slot-rx-mask-%d", i);
......@@ -186,9 +186,9 @@ static int axg_card_parse_cpu_tdm_slots(struct snd_soc_card *card,
/* Disable capture is the interface has no rx slots */
if (!rx)
link->dpcm_capture = 0;
link->playback_only = 1;
/* ... but the interface should at least have one of them */
/* ... but the interface should at least have one direction */
if (!tx && !rx) {
dev_err(card->dev, "tdm link has no cpu slots\n");
return -EINVAL;
......@@ -275,7 +275,7 @@ static int axg_card_parse_tdm(struct snd_soc_card *card,
return ret;
/* Add loopback if the pad dai has playback */
if (link->dpcm_playback) {
if (!link->capture_only) {
ret = axg_card_add_tdm_loopback(card, index);
if (ret)
return ret;
......@@ -339,7 +339,6 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np,
dai_link->num_c2c_params = 1;
} else {
dai_link->no_pcm = 1;
snd_soc_dai_link_set_capabilities(dai_link);
if (axg_card_cpu_is_tdm_iface(dai_link->cpus->of_node))
ret = axg_card_parse_tdm(card, np, index);
}
......
......@@ -107,7 +107,6 @@ static int gx_card_add_link(struct snd_soc_card *card, struct device_node *np,
dai_link->num_c2c_params = 1;
} else {
dai_link->no_pcm = 1;
snd_soc_dai_link_set_capabilities(dai_link);
/* Check if the cpu is the i2s encoder and parse i2s data */
if (gx_card_cpu_identify(dai_link->cpus, "I2S Encoder"))
ret = gx_card_parse_i2s(card, np, index);
......
......@@ -186,9 +186,9 @@ int meson_card_set_fe_link(struct snd_soc_card *card,
link->dpcm_merged_rate = 1;
if (is_playback)
link->dpcm_playback = 1;
link->playback_only = 1;
else
link->dpcm_capture = 1;
link->capture_only = 1;
return meson_card_set_link_name(card, link, node, "fe");
}
......
......@@ -155,7 +155,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
if (platform || !codec) {
/* DPCM */
snd_soc_dai_link_set_capabilities(link);
link->ignore_suspend = 1;
link->nonatomic = 1;
}
......
......@@ -950,8 +950,8 @@ void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_lin
dai_links->num_cpus = cpus_num;
dai_links->codecs = codecs;
dai_links->num_codecs = codecs_num;
dai_links->dpcm_playback = playback;
dai_links->dpcm_capture = capture;
dai_links->playback_only = playback && !capture;
dai_links->capture_only = !playback && capture;
dai_links->init = init;
dai_links->ops = ops;
}
......
......@@ -479,44 +479,6 @@ bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir)
return stream->channels_min;
}
/*
* snd_soc_dai_link_set_capabilities() - set dai_link properties based on its DAIs
*/
void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
{
bool supported[SNDRV_PCM_STREAM_LAST + 1];
int direction;
for_each_pcm_streams(direction) {
struct snd_soc_dai_link_component *cpu;
struct snd_soc_dai_link_component *codec;
struct snd_soc_dai *dai;
bool supported_cpu = false;
bool supported_codec = false;
int i;
for_each_link_cpus(dai_link, i, cpu) {
dai = snd_soc_find_dai_with_mutex(cpu);
if (dai && snd_soc_dai_stream_valid(dai, direction)) {
supported_cpu = true;
break;
}
}
for_each_link_codecs(dai_link, i, codec) {
dai = snd_soc_find_dai_with_mutex(codec);
if (dai && snd_soc_dai_stream_valid(dai, direction)) {
supported_codec = true;
break;
}
}
supported[direction] = supported_cpu && supported_codec;
}
dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK];
dai_link->dpcm_capture = supported[SNDRV_PCM_STREAM_CAPTURE];
}
EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities);
void snd_soc_dai_action(struct snd_soc_dai *dai,
int stream, int action)
{
......
......@@ -2739,6 +2739,7 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_dai *cpu_dai;
struct snd_soc_dai_link_ch_map *ch_maps;
int has_playback = 0;
int has_capture = 0;
int i;
......@@ -2749,43 +2750,51 @@ static int soc_get_playback_capture(struct snd_soc_pcm_runtime *rtd,
}
if (dai_link->dynamic || dai_link->no_pcm) {
int stream;
if (dai_link->dpcm_playback) {
stream = SNDRV_PCM_STREAM_PLAYBACK;
for_each_rtd_ch_maps(rtd, i, ch_maps) {
cpu_dai = snd_soc_rtd_to_cpu(rtd, ch_maps->cpu);
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
if (snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
has_playback = 1;
break;
}
}
if (!has_playback) {
dev_err(rtd->card->dev,
"No CPU DAIs support playback for stream %s\n",
dai_link->stream_name);
return -EINVAL;
}
}
if (dai_link->dpcm_capture) {
stream = SNDRV_PCM_STREAM_CAPTURE;
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
if (snd_soc_dai_stream_valid(cpu_dai, stream)) {
if (snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
has_capture = 1;
break;
}
/*
* REMOVE ME
*
* dpcm_xxx flag will be removed soon, Indicates warning if dpcm_xxx flag was used
* as availability limitation
*/
if (has_playback && has_capture) {
if ( dai_link->dpcm_playback &&
!dai_link->dpcm_capture &&
!dai_link->playback_only) {
dev_warn(rtd->card->dev,
"both playback/capture are available,"
" but not using playback_only flag (%s)\n",
dai_link->stream_name);
dev_warn(rtd->card->dev,
"dpcm_playback/capture are no longer needed,"
" please use playback/capture_only instead\n");
has_capture = 0;
}
if (!has_capture) {
dev_err(rtd->card->dev,
"No CPU DAIs support capture for stream %s\n",
if (!dai_link->dpcm_playback &&
dai_link->dpcm_capture &&
!dai_link->capture_only) {
dev_warn(rtd->card->dev,
"both playback/capture are available,"
" but not using capture_only flag (%s)\n",
dai_link->stream_name);
return -EINVAL;
dev_warn(rtd->card->dev,
"dpcm_playback/capture are no longer needed,"
" please use playback/capture_only instead\n");
has_playback = 0;
}
}
} else {
struct snd_soc_dai_link_ch_map *ch_maps;
struct snd_soc_dai *codec_dai;
/* Adapt stream for codec2codec links */
......
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