mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-15 21:30:43 +00:00
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: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Tested-by: Keita Kobayashi <keita.kobayashi.ym@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
061015f7bf
commit
047000278d
@ -45,23 +45,20 @@ static const struct of_device_id rsrc_card_of_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rsrc_card_of_match);
|
||||
|
||||
#define DAI_NAME_NUM 32
|
||||
struct rsrc_card_dai {
|
||||
unsigned int fmt;
|
||||
unsigned int sysclk;
|
||||
struct clk *clk;
|
||||
char dai_name[DAI_NAME_NUM];
|
||||
};
|
||||
|
||||
#define IDX_CPU 0
|
||||
#define IDX_CODEC 1
|
||||
#define DAI_NAME_NUM 32
|
||||
struct rsrc_card_priv {
|
||||
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 rsrc_card_dai *dai_props;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
int dai_num;
|
||||
u32 convert_rate;
|
||||
@ -76,31 +73,22 @@ static int rsrc_card_startup(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
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);
|
||||
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)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
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);
|
||||
|
||||
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||
|
||||
clk_disable_unprepare(dai_props->codec_dai.clk);
|
||||
clk_disable_unprepare(dai_props->clk);
|
||||
}
|
||||
|
||||
static struct snd_soc_ops rsrc_card_ops = {
|
||||
@ -108,21 +96,31 @@ static struct snd_soc_ops rsrc_card_ops = {
|
||||
.shutdown = rsrc_card_shutdown,
|
||||
};
|
||||
|
||||
static int __rsrc_card_dai_init(struct snd_soc_dai *dai,
|
||||
struct rsrc_card_dai *set)
|
||||
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 *dai;
|
||||
struct snd_soc_dai_link *dai_link;
|
||||
struct rsrc_card_dai *dai_props;
|
||||
int num = rtd - rtd->card->rtd;
|
||||
int ret;
|
||||
|
||||
if (set->fmt) {
|
||||
ret = snd_soc_dai_set_fmt(dai, set->fmt);
|
||||
dai_link = rsrc_priv_to_link(priv, num);
|
||||
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) {
|
||||
dev_err(dai->dev, "set_fmt error\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (set->sysclk) {
|
||||
ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0);
|
||||
if (dai_props->sysclk) {
|
||||
ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0);
|
||||
if (ret && ret != -ENOTSUPP) {
|
||||
dev_err(dai->dev, "set_sysclk error\n");
|
||||
goto err;
|
||||
@ -135,27 +133,6 @@ err:
|
||||
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,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
@ -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,
|
||||
struct device_node *np,
|
||||
struct rsrc_card_priv *priv,
|
||||
struct device_node *codec,
|
||||
int idx)
|
||||
int idx, bool is_fe)
|
||||
{
|
||||
struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
|
||||
struct device_node *bitclkmaster = NULL;
|
||||
struct device_node *framemaster = NULL;
|
||||
struct rsrc_card_dai_props *dai_props = rsrc_priv_to_props(priv, idx);
|
||||
struct rsrc_card_dai *cpu_dai = &dai_props->cpu_dai;
|
||||
struct rsrc_card_dai *codec_dai = &dai_props->codec_dai;
|
||||
struct device_node *codec = is_fe ? NULL : np;
|
||||
unsigned int daifmt;
|
||||
|
||||
daifmt = snd_soc_of_parse_daifmt(node, NULL,
|
||||
@ -197,8 +173,7 @@ static int rsrc_card_parse_daifmt(struct device_node *node,
|
||||
daifmt |= (codec == framemaster) ?
|
||||
SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
|
||||
|
||||
cpu_dai->fmt = daifmt;
|
||||
codec_dai->fmt = daifmt;
|
||||
dai_props->fmt = daifmt;
|
||||
|
||||
of_node_put(bitclkmaster);
|
||||
of_node_put(framemaster);
|
||||
@ -206,41 +181,15 @@ static int rsrc_card_parse_daifmt(struct device_node *node,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rsrc_card_sub_parse_of(struct rsrc_card_priv *priv,
|
||||
struct device_node *np,
|
||||
struct rsrc_card_dai *dai,
|
||||
struct snd_soc_dai_link *dai_link,
|
||||
int *args_count)
|
||||
static int rsrc_card_parse_links(struct device_node *np,
|
||||
struct rsrc_card_priv *priv,
|
||||
int idx, bool is_fe)
|
||||
{
|
||||
struct device *dev = rsrc_priv_to_dev(priv);
|
||||
const struct rsrc_card_of_data *of_data = rsrc_dev_to_of_data(dev);
|
||||
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 of_phandle_args args;
|
||||
struct device_node **p_node;
|
||||
struct clk *clk;
|
||||
const char **dai_name;
|
||||
const char **name;
|
||||
u32 val;
|
||||
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>"
|
||||
* 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,
|
||||
if (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 */
|
||||
ret = snd_soc_of_get_dai_name(np, dai_name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* FE settings */
|
||||
dai_link->dynamic = 1;
|
||||
dai_link->dpcm_merged_format = 1;
|
||||
dai_link->cpu_of_node = args.np;
|
||||
snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name);
|
||||
|
||||
/*
|
||||
* FIXME
|
||||
*
|
||||
* rsrc assumes DPCM playback/capture
|
||||
*/
|
||||
dai_link->dpcm_playback = 1;
|
||||
dai_link->dpcm_capture = 1;
|
||||
/* set dai_name */
|
||||
snprintf(dai_props->dai_name, DAI_NAME_NUM, "fe.%s",
|
||||
dai_link->cpu_dai_name);
|
||||
|
||||
if (args_count) {
|
||||
*args_count = args.args_count;
|
||||
dai_link->dynamic = 1;
|
||||
dai_link->dpcm_merged_format = 1;
|
||||
/*
|
||||
* In soc_bind_dai_link() will check cpu name after
|
||||
* of_node matching if dai_link has cpu_dai_name.
|
||||
* 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 (!args.args_count)
|
||||
dai_link->cpu_dai_name = NULL;
|
||||
} else {
|
||||
dai_link->no_pcm = 1;
|
||||
priv->codec_conf.of_node = (*p_node);
|
||||
priv->codec_conf.name_prefix = of_data->prefix;
|
||||
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->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;
|
||||
|
||||
/* 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>"
|
||||
* (if system has common clock)
|
||||
@ -286,103 +286,48 @@ rsrc_card_sub_parse_of(struct rsrc_card_priv *priv,
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
dai->sysclk = clk_get_rate(clk);
|
||||
dai->clk = clk;
|
||||
dai_props->sysclk = clk_get_rate(clk);
|
||||
dai_props->clk = clk;
|
||||
} else if (!of_property_read_u32(np, "system-clock-frequency", &val)) {
|
||||
dai->sysclk = val;
|
||||
dai_props->sysclk = val;
|
||||
} else {
|
||||
clk = of_clk_get(args.np, 0);
|
||||
clk = of_clk_get(of_np, 0);
|
||||
if (!IS_ERR(clk))
|
||||
dai->sysclk = clk_get_rate(clk);
|
||||
dai_props->sysclk = clk_get_rate(clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsrc_card_dai_link_of(struct device_node *node,
|
||||
struct device_node *np,
|
||||
struct rsrc_card_priv *priv,
|
||||
int idx)
|
||||
{
|
||||
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_props *dai_props = rsrc_priv_to_props(priv, idx);
|
||||
struct device_node *cpu = NULL;
|
||||
struct device_node *codec = NULL;
|
||||
char *name = dai_props->dai_name;
|
||||
char prop[128];
|
||||
int ret, cpu_args;
|
||||
struct rsrc_card_dai *dai_props = rsrc_priv_to_props(priv, idx);
|
||||
bool is_fe = false;
|
||||
int ret;
|
||||
|
||||
cpu = of_get_child_by_name(node, "cpu");
|
||||
codec = of_get_child_by_name(node, "codec");
|
||||
if (0 == strcmp(np->name, "cpu"))
|
||||
is_fe = true;
|
||||
|
||||
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);
|
||||
ret = rsrc_card_parse_daifmt(node, np, priv, idx, is_fe);
|
||||
if (ret < 0)
|
||||
goto dai_link_of_err;
|
||||
return ret;
|
||||
|
||||
ret = rsrc_card_sub_parse_of(priv, (idx == IDX_CPU) ? cpu : NULL,
|
||||
&dai_props->cpu_dai,
|
||||
dai_link,
|
||||
&cpu_args);
|
||||
ret = rsrc_card_parse_links(np, priv, idx, is_fe);
|
||||
if (ret < 0)
|
||||
goto dai_link_of_err;
|
||||
return ret;
|
||||
|
||||
ret = rsrc_card_sub_parse_of(priv, (idx == IDX_CODEC) ? codec : NULL,
|
||||
&dai_props->codec_dai,
|
||||
dai_link,
|
||||
NULL);
|
||||
ret = rsrc_card_parse_clk(np, priv, idx, is_fe);
|
||||
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);
|
||||
|
||||
/*
|
||||
* In soc_bind_dai_link() will check cpu name after
|
||||
* of_node matching if dai_link has cpu_dai_name.
|
||||
* 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:
|
||||
of_node_put(cpu);
|
||||
of_node_put(codec);
|
||||
dev_dbg(dev, "\t%s / %04x / %d\n",
|
||||
dai_props->dai_name,
|
||||
dai_props->fmt,
|
||||
dai_props->sysclk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -392,9 +337,9 @@ static int rsrc_card_parse_of(struct device_node *node,
|
||||
struct device *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 device_node *np;
|
||||
int ret;
|
||||
int i, num;
|
||||
|
||||
@ -411,9 +356,6 @@ static int rsrc_card_parse_of(struct device_node *node,
|
||||
priv->dai_link = links;
|
||||
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 */
|
||||
priv->snd_card.owner = THIS_MODULE;
|
||||
priv->snd_card.dev = dev;
|
||||
@ -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.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 */
|
||||
of_property_read_u32(node, "convert-rate", &priv->convert_rate);
|
||||
|
||||
@ -431,11 +376,12 @@ static int rsrc_card_parse_of(struct device_node *node,
|
||||
priv->snd_card.name ? priv->snd_card.name : "",
|
||||
priv->convert_rate);
|
||||
|
||||
/* FE/BE */
|
||||
for (i = 0; i < num; i++) {
|
||||
ret = rsrc_card_dai_link_of(node, priv, i);
|
||||
i = 0;
|
||||
for_each_child_of_node(node, np) {
|
||||
ret = rsrc_card_dai_link_of(node, np, priv, i);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!priv->snd_card.name)
|
||||
|
Loading…
Reference in New Issue
Block a user