Commit 5ba17b42 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by 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: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 72154e50
...@@ -519,7 +519,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv) ...@@ -519,7 +519,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
} }
rsnd_mod_init(priv, &adg->mod, &adg_ops, rsnd_mod_init(priv, &adg->mod, &adg_ops,
NULL, 0, 0); NULL, NULL, 0, 0);
rsnd_adg_get_clkin(priv, adg); rsnd_adg_get_clkin(priv, adg);
rsnd_adg_get_clkout(priv, adg); rsnd_adg_get_clkout(priv, adg);
......
...@@ -157,7 +157,8 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) ...@@ -157,7 +157,8 @@ int rsnd_cmd_probe(struct rsnd_priv *priv)
for_each_rsnd_cmd(cmd, priv, i) { for_each_rsnd_cmd(cmd, priv, i) {
ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), 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) if (ret)
return ret; return ret;
} }
......
...@@ -138,10 +138,20 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, ...@@ -138,10 +138,20 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
return mod->ops->dma_req(io, mod); 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, int rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod, struct rsnd_mod *mod,
struct rsnd_mod_ops *ops, struct rsnd_mod_ops *ops,
struct clk *clk, 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, enum rsnd_mod_type type,
int id) int id)
{ {
...@@ -155,6 +165,7 @@ int rsnd_mod_init(struct rsnd_priv *priv, ...@@ -155,6 +165,7 @@ int rsnd_mod_init(struct rsnd_priv *priv,
mod->type = type; mod->type = type;
mod->clk = clk; mod->clk = clk;
mod->priv = priv; mod->priv = priv;
mod->get_status = get_status;
return ret; return ret;
} }
...@@ -325,7 +336,7 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) ...@@ -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_priv *priv = rsnd_mod_to_priv(mod); \
struct rsnd_mod *mod = (io)->mod[idx]; \ struct rsnd_mod *mod = (io)->mod[idx]; \
struct device *dev = rsnd_priv_to_dev(priv); \ 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; \ u32 mask = 0xF << __rsnd_mod_shift_##func; \
u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \ u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \
u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \ u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \
......
...@@ -129,7 +129,7 @@ int rsnd_ctu_probe(struct rsnd_priv *priv) ...@@ -129,7 +129,7 @@ int rsnd_ctu_probe(struct rsnd_priv *priv)
} }
ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops, 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) if (ret)
goto rsnd_ctu_probe_done; goto rsnd_ctu_probe_done;
......
...@@ -681,7 +681,7 @@ struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io, ...@@ -681,7 +681,7 @@ struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io,
dma_mod = rsnd_mod_get(dma); dma_mod = rsnd_mod_get(dma);
ret = rsnd_mod_init(priv, dma_mod, ret = rsnd_mod_init(priv, dma_mod,
ops, NULL, type, dma_id); ops, NULL, rsnd_mod_get_status, type, dma_id);
if (ret < 0) if (ret < 0)
return ERR_PTR(ret); return ERR_PTR(ret);
......
...@@ -373,7 +373,7 @@ int rsnd_dvc_probe(struct rsnd_priv *priv) ...@@ -373,7 +373,7 @@ int rsnd_dvc_probe(struct rsnd_priv *priv)
} }
ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops, 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) if (ret)
goto rsnd_dvc_probe_done; goto rsnd_dvc_probe_done;
......
...@@ -172,7 +172,7 @@ int rsnd_mix_probe(struct rsnd_priv *priv) ...@@ -172,7 +172,7 @@ int rsnd_mix_probe(struct rsnd_priv *priv)
} }
ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops, 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) if (ret)
goto rsnd_mix_probe_done; goto rsnd_mix_probe_done;
......
...@@ -233,6 +233,10 @@ struct rsnd_mod { ...@@ -233,6 +233,10 @@ struct rsnd_mod {
struct rsnd_mod_ops *ops; struct rsnd_mod_ops *ops;
struct rsnd_priv *priv; struct rsnd_priv *priv;
struct clk *clk; struct clk *clk;
u32 *(*get_status)(struct rsnd_dai_stream *io,
struct rsnd_mod *mod,
enum rsnd_mod_type type);
u32 status;
}; };
/* /*
* status * status
...@@ -288,6 +292,9 @@ int rsnd_mod_init(struct rsnd_priv *priv, ...@@ -288,6 +292,9 @@ int rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod, struct rsnd_mod *mod,
struct rsnd_mod_ops *ops, struct rsnd_mod_ops *ops,
struct clk *clk, 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, enum rsnd_mod_type type,
int id); int id);
void rsnd_mod_quit(struct rsnd_mod *mod); void rsnd_mod_quit(struct rsnd_mod *mod);
...@@ -297,6 +304,10 @@ 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 rsnd_mod_interrupt(struct rsnd_mod *mod,
void (*callback)(struct rsnd_mod *mod, void (*callback)(struct rsnd_mod *mod,
struct rsnd_dai_stream *io)); 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, void rsnd_parse_connect_common(struct rsnd_dai *rdai,
struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id), struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id),
struct device_node *node, struct device_node *node,
...@@ -319,7 +330,7 @@ struct rsnd_dai_stream { ...@@ -319,7 +330,7 @@ struct rsnd_dai_stream {
struct rsnd_mod *mod[RSND_MOD_MAX]; struct rsnd_mod *mod[RSND_MOD_MAX];
struct rsnd_dai_path_info *info; /* rcar_snd.h */ struct rsnd_dai_path_info *info; /* rcar_snd.h */
struct rsnd_dai *rdai; struct rsnd_dai *rdai;
u32 mod_status[RSND_MOD_MAX]; u32 parent_ssi_status;
int byte_pos; int byte_pos;
int period_pos; int period_pos;
int byte_per_period; int byte_per_period;
......
...@@ -615,7 +615,8 @@ int rsnd_src_probe(struct rsnd_priv *priv) ...@@ -615,7 +615,8 @@ int rsnd_src_probe(struct rsnd_priv *priv)
} }
ret = rsnd_mod_init(priv, rsnd_mod_get(src), 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) if (ret)
goto rsnd_src_probe_done; goto rsnd_src_probe_done;
......
...@@ -857,6 +857,41 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) ...@@ -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); 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) int rsnd_ssi_probe(struct rsnd_priv *priv)
{ {
struct device_node *node; struct device_node *node;
...@@ -919,7 +954,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) ...@@ -919,7 +954,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
ops = &rsnd_ssi_dma_ops; ops = &rsnd_ssi_dma_ops;
ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk, 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) if (ret)
goto rsnd_ssi_probe_done; goto rsnd_ssi_probe_done;
......
...@@ -206,7 +206,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) ...@@ -206,7 +206,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
for_each_rsnd_ssiu(ssiu, priv, i) { for_each_rsnd_ssiu(ssiu, priv, i) {
ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), 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) if (ret)
return ret; return ret;
} }
......
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