aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2015-03-26 00:02:09 -0400
committerMark Brown <broonie@kernel.org>2015-03-27 18:59:17 -0400
commit2f78dd7f40264697afed4c2ac0890df8f0588e49 (patch)
tree9d37d40fef4bbf1161f9d447def5273d242dbf93 /sound/soc/sh
parentc517d838eb7d07bbe9507871fab3931deccff539 (diff)
ASoC: rsnd: call clk_prepare/unprepare() in probe/remove
clk_prepare_enable()/clk_disable_unprepare() uses mutex inside, in concretely clk_prepare()/clk_unprepare().And it uses __schedule(). Then, raw_spin_lock/unlock_irq() is called, and it breaks Renesas sound driver's spin lock irq. This patch separates thesse into clk_prepare()/clk_unprepare() and clk_enable/clk_disable. And call clk_prepare()/clk_unprepare() from probe/remove function. Special thanks to Das Biju. Reported-by: Das Biju <biju.das@bp.renesas.com> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sh')
-rw-r--r--sound/soc/sh/rcar/core.c24
-rw-r--r--sound/soc/sh/rcar/dvc.c17
-rw-r--r--sound/soc/sh/rcar/rsnd.h11
-rw-r--r--sound/soc/sh/rcar/src.c17
-rw-r--r--sound/soc/sh/rcar/ssi.c17
5 files changed, 76 insertions, 10 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 1b53605f7154..6046c10ef3c7 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -149,16 +149,29 @@ char *rsnd_mod_dma_name(struct rsnd_mod *mod)
149 return mod->ops->dma_name(mod); 149 return mod->ops->dma_name(mod);
150} 150}
151 151
152void rsnd_mod_init(struct rsnd_mod *mod, 152int rsnd_mod_init(struct rsnd_mod *mod,
153 struct rsnd_mod_ops *ops, 153 struct rsnd_mod_ops *ops,
154 struct clk *clk, 154 struct clk *clk,
155 enum rsnd_mod_type type, 155 enum rsnd_mod_type type,
156 int id) 156 int id)
157{ 157{
158 int ret = clk_prepare(clk);
159
160 if (ret)
161 return ret;
162
158 mod->id = id; 163 mod->id = id;
159 mod->ops = ops; 164 mod->ops = ops;
160 mod->type = type; 165 mod->type = type;
161 mod->clk = clk; 166 mod->clk = clk;
167
168 return ret;
169}
170
171void rsnd_mod_quit(struct rsnd_mod *mod)
172{
173 if (mod->clk)
174 clk_unprepare(mod->clk);
162} 175}
163 176
164/* 177/*
@@ -1290,6 +1303,12 @@ static int rsnd_remove(struct platform_device *pdev)
1290{ 1303{
1291 struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); 1304 struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev);
1292 struct rsnd_dai *rdai; 1305 struct rsnd_dai *rdai;
1306 void (*remove_func[])(struct platform_device *pdev,
1307 struct rsnd_priv *priv) = {
1308 rsnd_ssi_remove,
1309 rsnd_src_remove,
1310 rsnd_dvc_remove,
1311 };
1293 int ret = 0, i; 1312 int ret = 0, i;
1294 1313
1295 pm_runtime_disable(&pdev->dev); 1314 pm_runtime_disable(&pdev->dev);
@@ -1299,6 +1318,9 @@ static int rsnd_remove(struct platform_device *pdev)
1299 ret |= rsnd_dai_call(remove, &rdai->capture, priv); 1318 ret |= rsnd_dai_call(remove, &rdai->capture, priv);
1300 } 1319 }
1301 1320
1321 for (i = 0; i < ARRAY_SIZE(remove_func); i++)
1322 remove_func[i](pdev, priv);
1323
1302 snd_soc_unregister_component(&pdev->dev); 1324 snd_soc_unregister_component(&pdev->dev);
1303 snd_soc_unregister_platform(&pdev->dev); 1325 snd_soc_unregister_platform(&pdev->dev);
1304 1326
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index d7f9ed959c4e..261997a3f589 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -333,7 +333,7 @@ int rsnd_dvc_probe(struct platform_device *pdev,
333 struct rsnd_dvc *dvc; 333 struct rsnd_dvc *dvc;
334 struct clk *clk; 334 struct clk *clk;
335 char name[RSND_DVC_NAME_SIZE]; 335 char name[RSND_DVC_NAME_SIZE];
336 int i, nr; 336 int i, nr, ret;
337 337
338 rsnd_of_parse_dvc(pdev, of_data, priv); 338 rsnd_of_parse_dvc(pdev, of_data, priv);
339 339
@@ -366,11 +366,24 @@ int rsnd_dvc_probe(struct platform_device *pdev,
366 366
367 dvc->info = &info->dvc_info[i]; 367 dvc->info = &info->dvc_info[i];
368 368
369 rsnd_mod_init(&dvc->mod, &rsnd_dvc_ops, 369 ret = rsnd_mod_init(&dvc->mod, &rsnd_dvc_ops,
370 clk, RSND_MOD_DVC, i); 370 clk, RSND_MOD_DVC, i);
371 if (ret)
372 return ret;
371 373
372 dev_dbg(dev, "CMD%d probed\n", i); 374 dev_dbg(dev, "CMD%d probed\n", i);
373 } 375 }
374 376
375 return 0; 377 return 0;
376} 378}
379
380void rsnd_dvc_remove(struct platform_device *pdev,
381 struct rsnd_priv *priv)
382{
383 struct rsnd_dvc *dvc;
384 int i;
385
386 for_each_rsnd_dvc(dvc, priv, i) {
387 rsnd_mod_quit(&dvc->mod);
388 }
389}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index e7914bd610e2..1bccc5515b5a 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -260,14 +260,15 @@ struct rsnd_mod {
260#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) 260#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
261#define rsnd_mod_to_io(mod) ((mod)->io) 261#define rsnd_mod_to_io(mod) ((mod)->io)
262#define rsnd_mod_id(mod) ((mod)->id) 262#define rsnd_mod_id(mod) ((mod)->id)
263#define rsnd_mod_hw_start(mod) clk_prepare_enable((mod)->clk) 263#define rsnd_mod_hw_start(mod) clk_enable((mod)->clk)
264#define rsnd_mod_hw_stop(mod) clk_disable_unprepare((mod)->clk) 264#define rsnd_mod_hw_stop(mod) clk_disable((mod)->clk)
265 265
266void rsnd_mod_init(struct rsnd_mod *mod, 266int rsnd_mod_init(struct rsnd_mod *mod,
267 struct rsnd_mod_ops *ops, 267 struct rsnd_mod_ops *ops,
268 struct clk *clk, 268 struct clk *clk,
269 enum rsnd_mod_type type, 269 enum rsnd_mod_type type,
270 int id); 270 int id);
271void rsnd_mod_quit(struct rsnd_mod *mod);
271char *rsnd_mod_name(struct rsnd_mod *mod); 272char *rsnd_mod_name(struct rsnd_mod *mod);
272char *rsnd_mod_dma_name(struct rsnd_mod *mod); 273char *rsnd_mod_dma_name(struct rsnd_mod *mod);
273 274
@@ -480,6 +481,8 @@ int rsnd_kctrl_new_e(struct rsnd_mod *mod,
480int rsnd_src_probe(struct platform_device *pdev, 481int rsnd_src_probe(struct platform_device *pdev,
481 const struct rsnd_of_data *of_data, 482 const struct rsnd_of_data *of_data,
482 struct rsnd_priv *priv); 483 struct rsnd_priv *priv);
484void rsnd_src_remove(struct platform_device *pdev,
485 struct rsnd_priv *priv);
483struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); 486struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
484unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, 487unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
485 struct rsnd_dai_stream *io, 488 struct rsnd_dai_stream *io,
@@ -498,6 +501,8 @@ int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod);
498int rsnd_ssi_probe(struct platform_device *pdev, 501int rsnd_ssi_probe(struct platform_device *pdev,
499 const struct rsnd_of_data *of_data, 502 const struct rsnd_of_data *of_data,
500 struct rsnd_priv *priv); 503 struct rsnd_priv *priv);
504void rsnd_ssi_remove(struct platform_device *pdev,
505 struct rsnd_priv *priv);
501struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); 506struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
502int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); 507int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
503int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); 508int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 81c182b4bad5..c77d059edc84 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -850,7 +850,7 @@ int rsnd_src_probe(struct platform_device *pdev,
850 struct rsnd_mod_ops *ops; 850 struct rsnd_mod_ops *ops;
851 struct clk *clk; 851 struct clk *clk;
852 char name[RSND_SRC_NAME_SIZE]; 852 char name[RSND_SRC_NAME_SIZE];
853 int i, nr; 853 int i, nr, ret;
854 854
855 ops = NULL; 855 ops = NULL;
856 if (rsnd_is_gen1(priv)) 856 if (rsnd_is_gen1(priv))
@@ -890,10 +890,23 @@ int rsnd_src_probe(struct platform_device *pdev,
890 890
891 src->info = &info->src_info[i]; 891 src->info = &info->src_info[i];
892 892
893 rsnd_mod_init(&src->mod, ops, clk, RSND_MOD_SRC, i); 893 ret = rsnd_mod_init(&src->mod, ops, clk, RSND_MOD_SRC, i);
894 if (ret)
895 return ret;
894 896
895 dev_dbg(dev, "SRC%d probed\n", i); 897 dev_dbg(dev, "SRC%d probed\n", i);
896 } 898 }
897 899
898 return 0; 900 return 0;
899} 901}
902
903void rsnd_src_remove(struct platform_device *pdev,
904 struct rsnd_priv *priv)
905{
906 struct rsnd_src *src;
907 int i;
908
909 for_each_rsnd_src(src, priv, i) {
910 rsnd_mod_quit(&src->mod);
911 }
912}
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 9e7b627c08e2..f7cb1fd635a0 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -697,7 +697,7 @@ int rsnd_ssi_probe(struct platform_device *pdev,
697 struct clk *clk; 697 struct clk *clk;
698 struct rsnd_ssi *ssi; 698 struct rsnd_ssi *ssi;
699 char name[RSND_SSI_NAME_SIZE]; 699 char name[RSND_SSI_NAME_SIZE];
700 int i, nr; 700 int i, nr, ret;
701 701
702 rsnd_of_parse_ssi(pdev, of_data, priv); 702 rsnd_of_parse_ssi(pdev, of_data, priv);
703 703
@@ -732,10 +732,23 @@ int rsnd_ssi_probe(struct platform_device *pdev,
732 else if (rsnd_ssi_pio_available(ssi)) 732 else if (rsnd_ssi_pio_available(ssi))
733 ops = &rsnd_ssi_pio_ops; 733 ops = &rsnd_ssi_pio_ops;
734 734
735 rsnd_mod_init(&ssi->mod, ops, clk, RSND_MOD_SSI, i); 735 ret = rsnd_mod_init(&ssi->mod, ops, clk, RSND_MOD_SSI, i);
736 if (ret)
737 return ret;
736 738
737 rsnd_ssi_parent_clk_setup(priv, ssi); 739 rsnd_ssi_parent_clk_setup(priv, ssi);
738 } 740 }
739 741
740 return 0; 742 return 0;
741} 743}
744
745void rsnd_ssi_remove(struct platform_device *pdev,
746 struct rsnd_priv *priv)
747{
748 struct rsnd_ssi *ssi;
749 int i;
750
751 for_each_rsnd_ssi(ssi, priv, i) {
752 rsnd_mod_quit(&ssi->mod);
753 }
754}