diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 19f5509f908deef2a401558b01a00806eafe6b90..d74e1ccc0f8f736828ec8172a633700419cc3f7e 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -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); diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index 4b2d50d9a68617dfe796f006a80d6e8a06b56af8..abb5eaac854a9b9c47027e278cd5204c18aceace 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -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; } diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ed0918967defabf26fc9c9da1f76666d18a7d05c..b460d714d088a8d5f027a676545f8c9303a91be1 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -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); \ diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index d53a225d19e9b724b2b326a32f5746c822e3c4b8..109930a2040109bee693bdf7673177414b7af56e 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -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; diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 418e6fdd06a338b1aac03d585e1a353bd21bfc26..d1cb3c1775729612932308117dacd881467113f5 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -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); diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index d45ffe496397f84b4f68adc3377699f2e94e2308..302c193f674d26fe6e5e4e23d00944525310c58c 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -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; diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index 65542b6a89e9e3452b312369035983c98b70077d..e0e337ad4206a7a114f7ab3d4caca96ccf923e5d 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c @@ -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; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c7b2ba0daf2a8814f3c0d02e9366d228ec2220ed..28602607cf5ee2f6947ad2ce9dcdd20147b42b47 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -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; diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index b438538a0a69e727b6c9b8365d1d44efdbcab75b..516b0c05451c1ff2e72324d00948c0a315350b76 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -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; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index df3ab74adf3eccea4ed0146aee7e44b40865ce44..e68f3a1c9cb499f65271ee62e39cf35d8606a47d 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -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; diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 06d72828e5bcdc210ceb1234880abd4d7a50186b..11e55889b40105c24e9a41b7e5eb3d64d7e0cd20 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -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; }