Commit 04700027 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown

ASoC: rsrc-card: cleanup for DPCM

rsrc-card driver is based on simple-card driver which is caring about
CPU / Codec connection. OTOH, rsrc-card is used for DPCM system.
FE portion is constituted by CPU and dummy Codec, and BE is constituted
by dummy CPU and Codec in DPCM system.
Because of this, current rsrc-card is doing pointless method. It works well
if FE/BE was 1:1, but not good for multi FE/BE.
This patch cleanups rsrc-card driver for DPCM. and this is prepare for
MIX support for Renesas sound driver.
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: default avatarKeita Kobayashi <keita.kobayashi.ym@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 061015f7
...@@ -45,23 +45,20 @@ static const struct of_device_id rsrc_card_of_match[] = { ...@@ -45,23 +45,20 @@ static const struct of_device_id rsrc_card_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, rsrc_card_of_match); MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
#define DAI_NAME_NUM 32
struct rsrc_card_dai { struct rsrc_card_dai {
unsigned int fmt; unsigned int fmt;
unsigned int sysclk; unsigned int sysclk;
struct clk *clk; struct clk *clk;
char dai_name[DAI_NAME_NUM];
}; };
#define IDX_CPU 0 #define IDX_CPU 0
#define IDX_CODEC 1 #define IDX_CODEC 1
#define DAI_NAME_NUM 32
struct rsrc_card_priv { struct rsrc_card_priv {
struct snd_soc_card snd_card; struct snd_soc_card snd_card;
struct rsrc_card_dai_props {
struct rsrc_card_dai cpu_dai;
struct rsrc_card_dai codec_dai;
char dai_name[DAI_NAME_NUM];
} *dai_props;
struct snd_soc_codec_conf codec_conf; struct snd_soc_codec_conf codec_conf;
struct rsrc_card_dai *dai_props;
struct snd_soc_dai_link *dai_link; struct snd_soc_dai_link *dai_link;
int dai_num; int dai_num;
u32 convert_rate; u32 convert_rate;
...@@ -76,31 +73,22 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream) ...@@ -76,31 +73,22 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct rsrc_card_dai_props *dai_props = struct rsrc_card_dai *dai_props =
rsrc_priv_to_props(priv, rtd - rtd->card->rtd); rsrc_priv_to_props(priv, rtd - rtd->card->rtd);
int ret; int ret;
ret = clk_prepare_enable(dai_props->cpu_dai.clk);
if (ret)
return ret;
ret = clk_prepare_enable(dai_props->codec_dai.clk);
if (ret)
clk_disable_unprepare(dai_props->cpu_dai.clk);
return ret; return clk_prepare_enable(dai_props->clk);
} }
static void rsrc_card_shutdown(struct snd_pcm_substream *substream) static void rsrc_card_shutdown(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct rsrc_card_dai_props *dai_props = struct rsrc_card_dai *dai_props =
rsrc_priv_to_props(priv, rtd - rtd->card->rtd); rsrc_priv_to_props(priv, rtd - rtd->card->rtd);
clk_disable_unprepare(dai_props->cpu_dai.clk); clk_disable_unprepare(dai_props->clk);
clk_disable_unprepare(dai_props->codec_dai.clk);
} }
static struct snd_soc_ops rsrc_card_ops = { static struct snd_soc_ops rsrc_card_ops = {
...@@ -108,21 +96,31 @@ static struct snd_soc_ops rsrc_card_ops = { ...@@ -108,21 +96,31 @@ static struct snd_soc_ops rsrc_card_ops = {
.shutdown = rsrc_card_shutdown, .shutdown = rsrc_card_shutdown,
}; };
static int __rsrc_card_dai_init(struct snd_soc_dai *dai, static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
struct rsrc_card_dai *set)
{ {
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *dai;
struct snd_soc_dai_link *dai_link;
struct rsrc_card_dai *dai_props;
int num = rtd - rtd->card->rtd;
int ret; int ret;
if (set->fmt) { dai_link = rsrc_priv_to_link(priv, num);
ret = snd_soc_dai_set_fmt(dai, set->fmt); dai_props = rsrc_priv_to_props(priv, num);
dai = dai_link->dynamic ?
rtd->cpu_dai :
rtd->codec_dai;
if (dai_props->fmt) {
ret = snd_soc_dai_set_fmt(dai, dai_props->fmt);
if (ret && ret != -ENOTSUPP) { if (ret && ret != -ENOTSUPP) {
dev_err(dai->dev, "set_fmt error\n"); dev_err(dai->dev, "set_fmt error\n");
goto err; goto err;
} }
} }
if (set->sysclk) { if (dai_props->sysclk) {
ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0); ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0);
if (ret && ret != -ENOTSUPP) { if (ret && ret != -ENOTSUPP) {
dev_err(dai->dev, "set_sysclk error\n"); dev_err(dai->dev, "set_sysclk error\n");
goto err; goto err;
...@@ -135,27 +133,6 @@ static int __rsrc_card_dai_init(struct snd_soc_dai *dai, ...@@ -135,27 +133,6 @@ static int __rsrc_card_dai_init(struct snd_soc_dai *dai,
return ret; return ret;
} }
static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
{
struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *codec = rtd->codec_dai;
struct snd_soc_dai *cpu = rtd->cpu_dai;
struct rsrc_card_dai_props *dai_props;
int num, ret;
num = rtd - rtd->card->rtd;
dai_props = &priv->dai_props[num];
ret = __rsrc_card_dai_init(codec, &dai_props->codec_dai);
if (ret < 0)
return ret;
ret = __rsrc_card_dai_init(cpu, &dai_props->cpu_dai);
if (ret < 0)
return ret;
return 0;
}
static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params)
{ {
...@@ -172,15 +149,14 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, ...@@ -172,15 +149,14 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
} }
static int rsrc_card_parse_daifmt(struct device_node *node, static int rsrc_card_parse_daifmt(struct device_node *node,
struct device_node *np,
struct rsrc_card_priv *priv, struct rsrc_card_priv *priv,
struct device_node *codec, int idx, bool is_fe)
int idx)
{ {
struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
struct device_node *bitclkmaster = NULL; struct device_node *bitclkmaster = NULL;
struct device_node *framemaster = NULL; struct device_node *framemaster = NULL;
struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); struct device_node *codec = is_fe ? NULL : np;
struct rsrc_card_dai *cpu_dai = &dai_props->cpu_dai;
struct rsrc_card_dai *codec_dai = &dai_props->codec_dai;
unsigned int daifmt; unsigned int daifmt;
daifmt = snd_soc_of_parse_daifmt(node, NULL, daifmt = snd_soc_of_parse_daifmt(node, NULL,
...@@ -197,8 +173,7 @@ static int rsrc_card_parse_daifmt(struct device_node *node, ...@@ -197,8 +173,7 @@ static int rsrc_card_parse_daifmt(struct device_node *node,
daifmt |= (codec == framemaster) ? daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS; SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
cpu_dai->fmt = daifmt; dai_props->fmt = daifmt;
codec_dai->fmt = daifmt;
of_node_put(bitclkmaster); of_node_put(bitclkmaster);
of_node_put(framemaster); of_node_put(framemaster);
...@@ -206,41 +181,15 @@ static int rsrc_card_parse_daifmt(struct device_node *node, ...@@ -206,41 +181,15 @@ static int rsrc_card_parse_daifmt(struct device_node *node,
return 0; return 0;
} }
static int static int rsrc_card_parse_links(struct device_node *np,
rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, struct rsrc_card_priv *priv,
struct device_node *np, int idx, bool is_fe)
struct rsrc_card_dai *dai,
struct snd_soc_dai_link *dai_link,
int *args_count)
{ {
struct device *dev = rsrc_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
struct of_phandle_args args; struct of_phandle_args args;
struct device_node **p_node;
struct clk *clk;
const char **dai_name;
const char **name;
u32 val;
int ret; int ret;
if (args_count) {
p_node = &dai_link->cpu_of_node;
dai_name = &dai_link->cpu_dai_name;
name = &dai_link->cpu_name;
} else {
p_node = &dai_link->codec_of_node;
dai_name = &dai_link->codec_dai_name;
name = &dai_link->codec_name;
}
if (!np) {
/* use snd-soc-dummy */
*p_node = NULL;
*dai_name = "snd-soc-dummy-dai";
*name = "snd-soc-dummy";
return 0;
}
/* /*
* Get node via "sound-dai = <&phandle port>" * Get node via "sound-dai = <&phandle port>"
* it will be used as xxx_of_node on soc_bind_dai_link() * it will be used as xxx_of_node on soc_bind_dai_link()
...@@ -250,31 +199,82 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, ...@@ -250,31 +199,82 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv,
if (ret) if (ret)
return ret; return ret;
*p_node = args.np; if (is_fe) {
/* BE is dummy */
dai_link->codec_of_node = NULL;
dai_link->codec_dai_name = "snd-soc-dummy-dai";
dai_link->codec_name = "snd-soc-dummy";
/* Get dai->name */ /* FE settings */
ret = snd_soc_of_get_dai_name(np, dai_name); dai_link->dynamic = 1;
if (ret < 0) dai_link->dpcm_merged_format = 1;
return ret; dai_link->cpu_of_node = args.np;
snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name);
/* set dai_name */
snprintf(dai_props->dai_name, DAI_NAME_NUM, "fe.%s",
dai_link->cpu_dai_name);
/* /*
* FIXME * In soc_bind_dai_link() will check cpu name after
* * of_node matching if dai_link has cpu_dai_name.
* rsrc assumes DPCM playback/capture * but, it will never match if name was created by
* fmt_single_name() remove cpu_dai_name if cpu_args
* was 0. See:
* fmt_single_name()
* fmt_multiple_name()
*/ */
dai_link->dpcm_playback = 1; if (!args.args_count)
dai_link->dpcm_capture = 1; dai_link->cpu_dai_name = NULL;
if (args_count) {
*args_count = args.args_count;
dai_link->dynamic = 1;
dai_link->dpcm_merged_format = 1;
} else { } else {
struct device *dev = rsrc_priv_to_dev(priv);
const struct rsrc_card_of_data *of_data;
of_data = rsrc_dev_to_of_data(dev);
/* FE is dummy */
dai_link->cpu_of_node = NULL;
dai_link->cpu_dai_name = "snd-soc-dummy-dai";
dai_link->cpu_name = "snd-soc-dummy";
/* BE settings */
dai_link->no_pcm = 1; dai_link->no_pcm = 1;
priv->codec_conf.of_node = (*p_node); dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup;
dai_link->codec_of_node = args.np;
snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name);
/* additional name prefix */
priv->codec_conf.of_node = dai_link->codec_of_node;
priv->codec_conf.name_prefix = of_data->prefix; priv->codec_conf.name_prefix = of_data->prefix;
/* set dai_name */
snprintf(dai_props->dai_name, DAI_NAME_NUM, "be.%s",
dai_link->codec_dai_name);
} }
/* Simple Card assumes platform == cpu */
dai_link->platform_of_node = dai_link->cpu_of_node;
dai_link->dpcm_playback = 1;
dai_link->dpcm_capture = 1;
dai_link->name = dai_props->dai_name;
dai_link->stream_name = dai_props->dai_name;
dai_link->ops = &rsrc_card_ops;
dai_link->init = rsrc_card_dai_init;
return 0;
}
static int rsrc_card_parse_clk(struct device_node *np,
struct rsrc_card_priv *priv,
int idx, bool is_fe)
{
struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
struct clk *clk;
struct device_node *of_np = is_fe ? dai_link->cpu_of_node :
dai_link->codec_of_node;
u32 val;
/* /*
* Parse dai->sysclk come from "clocks = <&xxx>" * Parse dai->sysclk come from "clocks = <&xxx>"
* (if system has common clock) * (if system has common clock)
...@@ -286,103 +286,48 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv, ...@@ -286,103 +286,48 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv,
if (IS_ERR(clk)) if (IS_ERR(clk))
return PTR_ERR(clk); return PTR_ERR(clk);
dai->sysclk = clk_get_rate(clk); dai_props->sysclk = clk_get_rate(clk);
dai->clk = clk; dai_props->clk = clk;
} else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) {
dai->sysclk = val; dai_props->sysclk = val;
} else { } else {
clk = of_clk_get(args.np, 0); clk = of_clk_get(of_np, 0);
if (!IS_ERR(clk)) if (!IS_ERR(clk))
dai->sysclk = clk_get_rate(clk); dai_props->sysclk = clk_get_rate(clk);
} }
return 0; return 0;
} }
static int rsrc_card_dai_link_of(struct device_node *node, static int rsrc_card_dai_link_of(struct device_node *node,
struct device_node *np,
struct rsrc_card_priv *priv, struct rsrc_card_priv *priv,
int idx) int idx)
{ {
struct device *dev = rsrc_priv_to_dev(priv); struct device *dev = rsrc_priv_to_dev(priv);
struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx); struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx); bool is_fe = false;
struct device_node *cpu = NULL; int ret;
struct device_node *codec = NULL;
char *name = dai_props->dai_name;
char prop[128];
int ret, cpu_args;
cpu = of_get_child_by_name(node, "cpu");
codec = of_get_child_by_name(node, "codec");
if (!cpu || !codec) {
ret = -EINVAL;
dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
goto dai_link_of_err;
}
ret = rsrc_card_parse_daifmt(node, priv, codec, idx); if (0 == strcmp(np->name, "cpu"))
if (ret < 0) is_fe = true;
goto dai_link_of_err;
ret = rsrc_card_sub_parse_of(priv, (idx == IDX_CPU) ? cpu : NULL, ret = rsrc_card_parse_daifmt(node, np, priv, idx, is_fe);
&dai_props->cpu_dai,
dai_link,
&cpu_args);
if (ret < 0) if (ret < 0)
goto dai_link_of_err; return ret;
ret = rsrc_card_sub_parse_of(priv, (idx == IDX_CODEC) ? codec : NULL, ret = rsrc_card_parse_links(np, priv, idx, is_fe);
&dai_props->codec_dai,
dai_link,
NULL);
if (ret < 0) if (ret < 0)
goto dai_link_of_err; return ret;
if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
ret = -EINVAL;
goto dai_link_of_err;
}
/* Simple Card assumes platform == cpu */
dai_link->platform_of_node = dai_link->cpu_of_node;
snprintf(name, DAI_NAME_NUM, "%s.%s",
dai_link->dynamic ? "fe" : "be",
dai_link->dynamic ? dai_link->cpu_dai_name :
dai_link->codec_dai_name);
dai_link->name = dai_link->stream_name = name;
dai_link->ops = &rsrc_card_ops;
dai_link->init = rsrc_card_dai_init;
if (idx == IDX_CODEC)
dai_link->be_hw_params_fixup = rsrc_card_be_hw_params_fixup;
dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
dev_dbg(dev, "\tcpu : %s / %04x / %d\n",
dai_link->cpu_dai_name,
dai_props->cpu_dai.fmt,
dai_props->cpu_dai.sysclk);
dev_dbg(dev, "\tcodec : %s / %04x / %d\n",
dai_link->codec_dai_name,
dai_props->codec_dai.fmt,
dai_props->codec_dai.sysclk);
/* ret = rsrc_card_parse_clk(np, priv, idx, is_fe);
* In soc_bind_dai_link() will check cpu name after if (ret < 0)
* of_node matching if dai_link has cpu_dai_name. return ret;
* but, it will never match if name was created by
* fmt_single_name() remove cpu_dai_name if cpu_args
* was 0. See:
* fmt_single_name()
* fmt_multiple_name()
*/
if (!cpu_args)
dai_link->cpu_dai_name = NULL;
dai_link_of_err: dev_dbg(dev, "\t%s / %04x / %d\n",
of_node_put(cpu); dai_props->dai_name,
of_node_put(codec); dai_props->fmt,
dai_props->sysclk);
return ret; return ret;
} }
...@@ -392,9 +337,9 @@ static int rsrc_card_parse_of(struct device_node *node, ...@@ -392,9 +337,9 @@ static int rsrc_card_parse_of(struct device_node *node,
struct device *dev) struct device *dev)
{ {
const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev); const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev);
struct rsrc_card_dai_props *props; struct rsrc_card_dai *props;
struct snd_soc_dai_link *links; struct snd_soc_dai_link *links;
struct device_node *np;
int ret; int ret;
int i, num; int i, num;
...@@ -411,9 +356,6 @@ static int rsrc_card_parse_of(struct device_node *node, ...@@ -411,9 +356,6 @@ static int rsrc_card_parse_of(struct device_node *node,
priv->dai_link = links; priv->dai_link = links;
priv->dai_num = num; priv->dai_num = num;
/* Parse the card name from DT */
snd_soc_of_parse_card_name(&priv->snd_card, "card-name");
/* Init snd_soc_card */ /* Init snd_soc_card */
priv->snd_card.owner = THIS_MODULE; priv->snd_card.owner = THIS_MODULE;
priv->snd_card.dev = dev; priv->snd_card.dev = dev;
...@@ -424,6 +366,9 @@ static int rsrc_card_parse_of(struct device_node *node, ...@@ -424,6 +366,9 @@ static int rsrc_card_parse_of(struct device_node *node,
priv->snd_card.of_dapm_routes = of_data->routes; priv->snd_card.of_dapm_routes = of_data->routes;
priv->snd_card.num_of_dapm_routes = of_data->num_routes; priv->snd_card.num_of_dapm_routes = of_data->num_routes;
/* Parse the card name from DT */
snd_soc_of_parse_card_name(&priv->snd_card, "card-name");
/* sampling rate convert */ /* sampling rate convert */
of_property_read_u32(node, "convert-rate", &priv->convert_rate); of_property_read_u32(node, "convert-rate", &priv->convert_rate);
...@@ -431,11 +376,12 @@ static int rsrc_card_parse_of(struct device_node *node, ...@@ -431,11 +376,12 @@ static int rsrc_card_parse_of(struct device_node *node,
priv->snd_card.name ? priv->snd_card.name : "", priv->snd_card.name ? priv->snd_card.name : "",
priv->convert_rate); priv->convert_rate);
/* FE/BE */ i = 0;
for (i = 0; i < num; i++) { for_each_child_of_node(node, np) {
ret = rsrc_card_dai_link_of(node, priv, i); ret = rsrc_card_dai_link_of(node, np, priv, i);
if (ret < 0) if (ret < 0)
return ret; return ret;
i++;
} }
if (!priv->snd_card.name) if (!priv->snd_card.name)
......
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