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 c2dc47d5cf("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: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
72154e5072
commit
5ba17b42e1
|
@ -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,10 +138,20 @@ 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,
|
||||
u32* (*get_status)(struct rsnd_dai_stream *io,
|
||||
struct rsnd_mod *mod,
|
||||
enum rsnd_mod_type type),
|
||||
enum rsnd_mod_type type,
|
||||
int id)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -288,6 +292,9 @@ int rsnd_mod_init(struct rsnd_priv *priv,
|
|||
struct rsnd_mod *mod,
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue