提交 5ba17b42 编写于 作者: K Kuninori Morimoto 提交者: Mark Brown

ASoC: rsnd: each mod has status again for CTU/MUX support

SSI will be used as normal SSI or as clock parent SSI. Therefor,
rsnd driver wants to control SSI and parent SSI separately. Otherwise it
can't use Playback/Capture in the same time.
And it has been done by c2dc47d5("ASoC: rsnd: rsnd_dai_stream has each
mod's status insted of rsnd_mod") before.

OTOH, rsnd driver doesn't want to control CTU/MUX/DVC/SSIU/SSI in
separately. Otherwise, these will be re-initialized during playing if
MUX merges 2 sounds.
Because of these picky reasons, this patch re-defines status on each mod,
and add new parent_ssi_status on rsnd_dai_stream.
Signed-off-by: NKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: NMark Brown <broonie@kernel.org>
上级 72154e50
......@@ -519,7 +519,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
}
rsnd_mod_init(priv, &adg->mod, &adg_ops,
NULL, 0, 0);
NULL, NULL, 0, 0);
rsnd_adg_get_clkin(priv, adg);
rsnd_adg_get_clkout(priv, adg);
......
......@@ -157,7 +157,8 @@ int rsnd_cmd_probe(struct rsnd_priv *priv)
for_each_rsnd_cmd(cmd, priv, i) {
ret = rsnd_mod_init(priv, rsnd_mod_get(cmd),
&rsnd_cmd_ops, NULL, RSND_MOD_CMD, i);
&rsnd_cmd_ops, NULL,
rsnd_mod_get_status, RSND_MOD_CMD, i);
if (ret)
return ret;
}
......
......@@ -138,12 +138,22 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
return mod->ops->dma_req(io, mod);
}
u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io,
struct rsnd_mod *mod,
enum rsnd_mod_type type)
{
return &mod->status;
}
int rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod,
struct rsnd_mod_ops *ops,
struct clk *clk,
enum rsnd_mod_type type,
int id)
struct rsnd_mod_ops *ops,
struct clk *clk,
u32* (*get_status)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod,
enum rsnd_mod_type type),
enum rsnd_mod_type type,
int id)
{
int ret = clk_prepare(clk);
......@@ -155,6 +165,7 @@ int rsnd_mod_init(struct rsnd_priv *priv,
mod->type = type;
mod->clk = clk;
mod->priv = priv;
mod->get_status = get_status;
return ret;
}
......@@ -325,7 +336,7 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \
struct rsnd_mod *mod = (io)->mod[idx]; \
struct device *dev = rsnd_priv_to_dev(priv); \
u32 *status = (io)->mod_status + idx; \
u32 *status = mod->get_status(io, mod, idx); \
u32 mask = 0xF << __rsnd_mod_shift_##func; \
u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \
u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \
......
......@@ -129,7 +129,7 @@ int rsnd_ctu_probe(struct rsnd_priv *priv)
}
ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
clk, RSND_MOD_CTU, i);
clk, rsnd_mod_get_status, RSND_MOD_CTU, i);
if (ret)
goto rsnd_ctu_probe_done;
......
......@@ -681,7 +681,7 @@ struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io,
dma_mod = rsnd_mod_get(dma);
ret = rsnd_mod_init(priv, dma_mod,
ops, NULL, type, dma_id);
ops, NULL, rsnd_mod_get_status, type, dma_id);
if (ret < 0)
return ERR_PTR(ret);
......
......@@ -373,7 +373,7 @@ int rsnd_dvc_probe(struct rsnd_priv *priv)
}
ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
clk, RSND_MOD_DVC, i);
clk, rsnd_mod_get_status, RSND_MOD_DVC, i);
if (ret)
goto rsnd_dvc_probe_done;
......
......@@ -172,7 +172,7 @@ int rsnd_mix_probe(struct rsnd_priv *priv)
}
ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
clk, RSND_MOD_MIX, i);
clk, rsnd_mod_get_status, RSND_MOD_MIX, i);
if (ret)
goto rsnd_mix_probe_done;
......
......@@ -233,6 +233,10 @@ struct rsnd_mod {
struct rsnd_mod_ops *ops;
struct rsnd_priv *priv;
struct clk *clk;
u32 *(*get_status)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod,
enum rsnd_mod_type type);
u32 status;
};
/*
* status
......@@ -286,10 +290,13 @@ struct rsnd_mod {
int rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod,
struct rsnd_mod_ops *ops,
struct clk *clk,
enum rsnd_mod_type type,
int id);
struct rsnd_mod_ops *ops,
struct clk *clk,
u32* (*get_status)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod,
enum rsnd_mod_type type),
enum rsnd_mod_type type,
int id);
void rsnd_mod_quit(struct rsnd_mod *mod);
char *rsnd_mod_name(struct rsnd_mod *mod);
struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
......@@ -297,6 +304,10 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
void rsnd_mod_interrupt(struct rsnd_mod *mod,
void (*callback)(struct rsnd_mod *mod,
struct rsnd_dai_stream *io));
u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io,
struct rsnd_mod *mod,
enum rsnd_mod_type type);
void rsnd_parse_connect_common(struct rsnd_dai *rdai,
struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
struct device_node *node,
......@@ -319,7 +330,7 @@ struct rsnd_dai_stream {
struct rsnd_mod *mod[RSND_MOD_MAX];
struct rsnd_dai_path_info *info; /* rcar_snd.h */
struct rsnd_dai *rdai;
u32 mod_status[RSND_MOD_MAX];
u32 parent_ssi_status;
int byte_pos;
int period_pos;
int byte_per_period;
......
......@@ -615,7 +615,8 @@ int rsnd_src_probe(struct rsnd_priv *priv)
}
ret = rsnd_mod_init(priv, rsnd_mod_get(src),
&rsnd_src_ops, clk, RSND_MOD_SRC, i);
&rsnd_src_ops, clk, rsnd_mod_get_status,
RSND_MOD_SRC, i);
if (ret)
goto rsnd_src_probe_done;
......
......@@ -857,6 +857,41 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE);
}
static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,
struct rsnd_mod *mod,
enum rsnd_mod_type type)
{
/*
* SSIP (= SSI parent) needs to be special, otherwise,
* 2nd SSI might doesn't start. see also rsnd_mod_call()
*
* We can't include parent SSI status on SSI, because we don't know
* how many SSI requests parent SSI. Thus, it is localed on "io" now.
* ex) trouble case
* Playback: SSI0
* Capture : SSI1 (needs SSI0)
*
* 1) start Capture -> SSI0/SSI1 are started.
* 2) start Playback -> SSI0 doesn't work, because it is already
* marked as "started" on 1)
*
* OTOH, using each mod's status is good for MUX case.
* It doesn't need to start in 2nd start
* ex)
* IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
* |
* IO-1: SRC1 -> CTU2 -+
*
* 1) start IO-0 -> start SSI0
* 2) start IO-1 -> SSI0 doesn't need to start, because it is
* already started on 1)
*/
if (type == RSND_MOD_SSIP)
return &io->parent_ssi_status;
return rsnd_mod_get_status(io, mod, type);
}
int rsnd_ssi_probe(struct rsnd_priv *priv)
{
struct device_node *node;
......@@ -919,7 +954,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
ops = &rsnd_ssi_dma_ops;
ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
RSND_MOD_SSI, i);
rsnd_ssi_get_status, RSND_MOD_SSI, i);
if (ret)
goto rsnd_ssi_probe_done;
......
......@@ -206,7 +206,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
for_each_rsnd_ssiu(ssiu, priv, i) {
ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
ops, NULL, RSND_MOD_SSIU, i);
ops, NULL, rsnd_mod_get_status,
RSND_MOD_SSIU, i);
if (ret)
return ret;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册