diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2016-01-20 20:58:07 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-01-22 12:12:25 -0500 |
commit | 5ba17b42e1755c3c5cfe96370cfd47f34d01f62c (patch) | |
tree | 32ad8ae98f2fbb622359c3cb0cebce2399cf6c97 | |
parent | 72154e50728e8a08940332db20884b63dfa6590d (diff) |
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>
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/cmd.c | 3 | ||||
-rw-r--r-- | sound/soc/sh/rcar/core.c | 21 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ctu.c | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/dma.c | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/dvc.c | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/mix.c | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 21 | ||||
-rw-r--r-- | sound/soc/sh/rcar/src.c | 3 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 37 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssiu.c | 3 |
11 files changed, 79 insertions, 19 deletions
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 19f5509f908d..d74e1ccc0f8f 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) | |||
519 | } | 519 | } |
520 | 520 | ||
521 | rsnd_mod_init(priv, &adg->mod, &adg_ops, | 521 | rsnd_mod_init(priv, &adg->mod, &adg_ops, |
522 | NULL, 0, 0); | 522 | NULL, NULL, 0, 0); |
523 | 523 | ||
524 | rsnd_adg_get_clkin(priv, adg); | 524 | rsnd_adg_get_clkin(priv, adg); |
525 | rsnd_adg_get_clkout(priv, adg); | 525 | rsnd_adg_get_clkout(priv, adg); |
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index 4b2d50d9a686..abb5eaac854a 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) | |||
157 | 157 | ||
158 | for_each_rsnd_cmd(cmd, priv, i) { | 158 | for_each_rsnd_cmd(cmd, priv, i) { |
159 | ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), | 159 | ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), |
160 | &rsnd_cmd_ops, NULL, RSND_MOD_CMD, i); | 160 | &rsnd_cmd_ops, NULL, |
161 | rsnd_mod_get_status, RSND_MOD_CMD, i); | ||
161 | if (ret) | 162 | if (ret) |
162 | return ret; | 163 | return ret; |
163 | } | 164 | } |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ed0918967def..b460d714d088 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, | |||
138 | return mod->ops->dma_req(io, mod); | 138 | return mod->ops->dma_req(io, mod); |
139 | } | 139 | } |
140 | 140 | ||
141 | u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io, | ||
142 | struct rsnd_mod *mod, | ||
143 | enum rsnd_mod_type type) | ||
144 | { | ||
145 | return &mod->status; | ||
146 | } | ||
147 | |||
141 | int rsnd_mod_init(struct rsnd_priv *priv, | 148 | int rsnd_mod_init(struct rsnd_priv *priv, |
142 | struct rsnd_mod *mod, | 149 | struct rsnd_mod *mod, |
143 | struct rsnd_mod_ops *ops, | 150 | struct rsnd_mod_ops *ops, |
144 | struct clk *clk, | 151 | struct clk *clk, |
145 | enum rsnd_mod_type type, | 152 | u32* (*get_status)(struct rsnd_dai_stream *io, |
146 | int id) | 153 | struct rsnd_mod *mod, |
154 | enum rsnd_mod_type type), | ||
155 | enum rsnd_mod_type type, | ||
156 | int id) | ||
147 | { | 157 | { |
148 | int ret = clk_prepare(clk); | 158 | int ret = clk_prepare(clk); |
149 | 159 | ||
@@ -155,6 +165,7 @@ int rsnd_mod_init(struct rsnd_priv *priv, | |||
155 | mod->type = type; | 165 | mod->type = type; |
156 | mod->clk = clk; | 166 | mod->clk = clk; |
157 | mod->priv = priv; | 167 | mod->priv = priv; |
168 | mod->get_status = get_status; | ||
158 | 169 | ||
159 | return ret; | 170 | return ret; |
160 | } | 171 | } |
@@ -325,7 +336,7 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) | |||
325 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ | 336 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ |
326 | struct rsnd_mod *mod = (io)->mod[idx]; \ | 337 | struct rsnd_mod *mod = (io)->mod[idx]; \ |
327 | struct device *dev = rsnd_priv_to_dev(priv); \ | 338 | struct device *dev = rsnd_priv_to_dev(priv); \ |
328 | u32 *status = (io)->mod_status + idx; \ | 339 | u32 *status = mod->get_status(io, mod, idx); \ |
329 | u32 mask = 0xF << __rsnd_mod_shift_##func; \ | 340 | u32 mask = 0xF << __rsnd_mod_shift_##func; \ |
330 | u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \ | 341 | u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \ |
331 | u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \ | 342 | 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 d53a225d19e9..109930a20401 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) | |||
129 | } | 129 | } |
130 | 130 | ||
131 | ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops, | 131 | ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops, |
132 | clk, RSND_MOD_CTU, i); | 132 | clk, rsnd_mod_get_status, RSND_MOD_CTU, i); |
133 | if (ret) | 133 | if (ret) |
134 | goto rsnd_ctu_probe_done; | 134 | goto rsnd_ctu_probe_done; |
135 | 135 | ||
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 418e6fdd06a3..d1cb3c177572 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, | |||
681 | dma_mod = rsnd_mod_get(dma); | 681 | dma_mod = rsnd_mod_get(dma); |
682 | 682 | ||
683 | ret = rsnd_mod_init(priv, dma_mod, | 683 | ret = rsnd_mod_init(priv, dma_mod, |
684 | ops, NULL, type, dma_id); | 684 | ops, NULL, rsnd_mod_get_status, type, dma_id); |
685 | if (ret < 0) | 685 | if (ret < 0) |
686 | return ERR_PTR(ret); | 686 | return ERR_PTR(ret); |
687 | 687 | ||
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index d45ffe496397..302c193f674d 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) | |||
373 | } | 373 | } |
374 | 374 | ||
375 | ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops, | 375 | ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops, |
376 | clk, RSND_MOD_DVC, i); | 376 | clk, rsnd_mod_get_status, RSND_MOD_DVC, i); |
377 | if (ret) | 377 | if (ret) |
378 | goto rsnd_dvc_probe_done; | 378 | goto rsnd_dvc_probe_done; |
379 | 379 | ||
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index 65542b6a89e9..e0e337ad4206 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) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops, | 174 | ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops, |
175 | clk, RSND_MOD_MIX, i); | 175 | clk, rsnd_mod_get_status, RSND_MOD_MIX, i); |
176 | if (ret) | 176 | if (ret) |
177 | goto rsnd_mix_probe_done; | 177 | goto rsnd_mix_probe_done; |
178 | 178 | ||
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c7b2ba0daf2a..28602607cf5e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -233,6 +233,10 @@ struct rsnd_mod { | |||
233 | struct rsnd_mod_ops *ops; | 233 | struct rsnd_mod_ops *ops; |
234 | struct rsnd_priv *priv; | 234 | struct rsnd_priv *priv; |
235 | struct clk *clk; | 235 | struct clk *clk; |
236 | u32 *(*get_status)(struct rsnd_dai_stream *io, | ||
237 | struct rsnd_mod *mod, | ||
238 | enum rsnd_mod_type type); | ||
239 | u32 status; | ||
236 | }; | 240 | }; |
237 | /* | 241 | /* |
238 | * status | 242 | * status |
@@ -286,10 +290,13 @@ struct rsnd_mod { | |||
286 | 290 | ||
287 | int rsnd_mod_init(struct rsnd_priv *priv, | 291 | int rsnd_mod_init(struct rsnd_priv *priv, |
288 | struct rsnd_mod *mod, | 292 | struct rsnd_mod *mod, |
289 | struct rsnd_mod_ops *ops, | 293 | struct rsnd_mod_ops *ops, |
290 | struct clk *clk, | 294 | struct clk *clk, |
291 | enum rsnd_mod_type type, | 295 | u32* (*get_status)(struct rsnd_dai_stream *io, |
292 | int id); | 296 | struct rsnd_mod *mod, |
297 | enum rsnd_mod_type type), | ||
298 | enum rsnd_mod_type type, | ||
299 | int id); | ||
293 | void rsnd_mod_quit(struct rsnd_mod *mod); | 300 | void rsnd_mod_quit(struct rsnd_mod *mod); |
294 | char *rsnd_mod_name(struct rsnd_mod *mod); | 301 | char *rsnd_mod_name(struct rsnd_mod *mod); |
295 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, | 302 | 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, | |||
297 | void rsnd_mod_interrupt(struct rsnd_mod *mod, | 304 | void rsnd_mod_interrupt(struct rsnd_mod *mod, |
298 | void (*callback)(struct rsnd_mod *mod, | 305 | void (*callback)(struct rsnd_mod *mod, |
299 | struct rsnd_dai_stream *io)); | 306 | struct rsnd_dai_stream *io)); |
307 | u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io, | ||
308 | struct rsnd_mod *mod, | ||
309 | enum rsnd_mod_type type); | ||
310 | |||
300 | void rsnd_parse_connect_common(struct rsnd_dai *rdai, | 311 | void rsnd_parse_connect_common(struct rsnd_dai *rdai, |
301 | struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id), | 312 | struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id), |
302 | struct device_node *node, | 313 | struct device_node *node, |
@@ -319,7 +330,7 @@ struct rsnd_dai_stream { | |||
319 | struct rsnd_mod *mod[RSND_MOD_MAX]; | 330 | struct rsnd_mod *mod[RSND_MOD_MAX]; |
320 | struct rsnd_dai_path_info *info; /* rcar_snd.h */ | 331 | struct rsnd_dai_path_info *info; /* rcar_snd.h */ |
321 | struct rsnd_dai *rdai; | 332 | struct rsnd_dai *rdai; |
322 | u32 mod_status[RSND_MOD_MAX]; | 333 | u32 parent_ssi_status; |
323 | int byte_pos; | 334 | int byte_pos; |
324 | int period_pos; | 335 | int period_pos; |
325 | int byte_per_period; | 336 | int byte_per_period; |
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index b438538a0a69..516b0c05451c 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) | |||
615 | } | 615 | } |
616 | 616 | ||
617 | ret = rsnd_mod_init(priv, rsnd_mod_get(src), | 617 | ret = rsnd_mod_init(priv, rsnd_mod_get(src), |
618 | &rsnd_src_ops, clk, RSND_MOD_SRC, i); | 618 | &rsnd_src_ops, clk, rsnd_mod_get_status, |
619 | RSND_MOD_SRC, i); | ||
619 | if (ret) | 620 | if (ret) |
620 | goto rsnd_src_probe_done; | 621 | goto rsnd_src_probe_done; |
621 | 622 | ||
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index df3ab74adf3e..e68f3a1c9cb4 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) | |||
857 | return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); | 857 | return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); |
858 | } | 858 | } |
859 | 859 | ||
860 | static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io, | ||
861 | struct rsnd_mod *mod, | ||
862 | enum rsnd_mod_type type) | ||
863 | { | ||
864 | /* | ||
865 | * SSIP (= SSI parent) needs to be special, otherwise, | ||
866 | * 2nd SSI might doesn't start. see also rsnd_mod_call() | ||
867 | * | ||
868 | * We can't include parent SSI status on SSI, because we don't know | ||
869 | * how many SSI requests parent SSI. Thus, it is localed on "io" now. | ||
870 | * ex) trouble case | ||
871 | * Playback: SSI0 | ||
872 | * Capture : SSI1 (needs SSI0) | ||
873 | * | ||
874 | * 1) start Capture -> SSI0/SSI1 are started. | ||
875 | * 2) start Playback -> SSI0 doesn't work, because it is already | ||
876 | * marked as "started" on 1) | ||
877 | * | ||
878 | * OTOH, using each mod's status is good for MUX case. | ||
879 | * It doesn't need to start in 2nd start | ||
880 | * ex) | ||
881 | * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0 | ||
882 | * | | ||
883 | * IO-1: SRC1 -> CTU2 -+ | ||
884 | * | ||
885 | * 1) start IO-0 -> start SSI0 | ||
886 | * 2) start IO-1 -> SSI0 doesn't need to start, because it is | ||
887 | * already started on 1) | ||
888 | */ | ||
889 | if (type == RSND_MOD_SSIP) | ||
890 | return &io->parent_ssi_status; | ||
891 | |||
892 | return rsnd_mod_get_status(io, mod, type); | ||
893 | } | ||
894 | |||
860 | int rsnd_ssi_probe(struct rsnd_priv *priv) | 895 | int rsnd_ssi_probe(struct rsnd_priv *priv) |
861 | { | 896 | { |
862 | struct device_node *node; | 897 | struct device_node *node; |
@@ -919,7 +954,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) | |||
919 | ops = &rsnd_ssi_dma_ops; | 954 | ops = &rsnd_ssi_dma_ops; |
920 | 955 | ||
921 | ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk, | 956 | ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk, |
922 | RSND_MOD_SSI, i); | 957 | rsnd_ssi_get_status, RSND_MOD_SSI, i); |
923 | if (ret) | 958 | if (ret) |
924 | goto rsnd_ssi_probe_done; | 959 | goto rsnd_ssi_probe_done; |
925 | 960 | ||
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 06d72828e5bc..11e55889b401 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) | |||
206 | 206 | ||
207 | for_each_rsnd_ssiu(ssiu, priv, i) { | 207 | for_each_rsnd_ssiu(ssiu, priv, i) { |
208 | ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), | 208 | ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), |
209 | ops, NULL, RSND_MOD_SSIU, i); | 209 | ops, NULL, rsnd_mod_get_status, |
210 | RSND_MOD_SSIU, i); | ||
210 | if (ret) | 211 | if (ret) |
211 | return ret; | 212 | return ret; |
212 | } | 213 | } |