aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2016-01-20 20:58:07 -0500
committerMark Brown <broonie@kernel.org>2016-01-22 12:12:25 -0500
commit5ba17b42e1755c3c5cfe96370cfd47f34d01f62c (patch)
tree32ad8ae98f2fbb622359c3cb0cebce2399cf6c97
parent72154e50728e8a08940332db20884b63dfa6590d (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.c2
-rw-r--r--sound/soc/sh/rcar/cmd.c3
-rw-r--r--sound/soc/sh/rcar/core.c21
-rw-r--r--sound/soc/sh/rcar/ctu.c2
-rw-r--r--sound/soc/sh/rcar/dma.c2
-rw-r--r--sound/soc/sh/rcar/dvc.c2
-rw-r--r--sound/soc/sh/rcar/mix.c2
-rw-r--r--sound/soc/sh/rcar/rsnd.h21
-rw-r--r--sound/soc/sh/rcar/src.c3
-rw-r--r--sound/soc/sh/rcar/ssi.c37
-rw-r--r--sound/soc/sh/rcar/ssiu.c3
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
141u32 *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
141int rsnd_mod_init(struct rsnd_priv *priv, 148int 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
287int rsnd_mod_init(struct rsnd_priv *priv, 291int 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);
293void rsnd_mod_quit(struct rsnd_mod *mod); 300void rsnd_mod_quit(struct rsnd_mod *mod);
294char *rsnd_mod_name(struct rsnd_mod *mod); 301char *rsnd_mod_name(struct rsnd_mod *mod);
295struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, 302struct 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,
297void rsnd_mod_interrupt(struct rsnd_mod *mod, 304void 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));
307u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io,
308 struct rsnd_mod *mod,
309 enum rsnd_mod_type type);
310
300void rsnd_parse_connect_common(struct rsnd_dai *rdai, 311void 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
860static 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
860int rsnd_ssi_probe(struct rsnd_priv *priv) 895int 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 }