aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2014-11-09 23:00:58 -0500
committerMark Brown <broonie@kernel.org>2014-11-10 09:52:38 -0500
commitd3a768233243b5892a9c74b85896b9e8c017b259 (patch)
tree680670669a916065d34a9f7fd3f2b496370beeb1 /sound/soc/sh
parent30cc4faf703955cd5cd07da489bd817ae43e3fec (diff)
ASoC: rsnd: fallback to PIO mode if DMA mode was failed
Current Renesas R-Car sound driver probe will be failed if it try to use DMA mode and it couldn't use for some reasons. But PIO mode works even though in such case. This patch try to fallback to PIO mode if DMA mode probing was failed. 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.c74
-rw-r--r--sound/soc/sh/rcar/ssi.c15
2 files changed, 85 insertions, 4 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 5205618a1990..110b99da7acd 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -349,7 +349,7 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
349 dma_name); 349 dma_name);
350 if (!dma->chan) { 350 if (!dma->chan) {
351 dev_err(dev, "can't get dma channel\n"); 351 dev_err(dev, "can't get dma channel\n");
352 return -EIO; 352 goto rsnd_dma_channel_err;
353 } 353 }
354 354
355 ret = dmaengine_slave_config(dma->chan, &cfg); 355 ret = dmaengine_slave_config(dma->chan, &cfg);
@@ -363,8 +363,15 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
363 363
364rsnd_dma_init_err: 364rsnd_dma_init_err:
365 rsnd_dma_quit(priv, dma); 365 rsnd_dma_quit(priv, dma);
366rsnd_dma_channel_err:
366 367
367 return ret; 368 /*
369 * DMA failed. try to PIO mode
370 * see
371 * rsnd_ssi_dma_remove()
372 * rsnd_rdai_continuance_probe()
373 */
374 return -EAGAIN;
368} 375}
369 376
370void rsnd_dma_quit(struct rsnd_priv *priv, 377void rsnd_dma_quit(struct rsnd_priv *priv,
@@ -456,6 +463,13 @@ static int rsnd_dai_connect(struct rsnd_mod *mod,
456 return 0; 463 return 0;
457} 464}
458 465
466static void rsnd_dai_disconnect(struct rsnd_mod *mod,
467 struct rsnd_dai_stream *io)
468{
469 mod->io = NULL;
470 io->mod[mod->type] = NULL;
471}
472
459int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai) 473int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai)
460{ 474{
461 int id = rdai - priv->rdai; 475 int id = rdai - priv->rdai;
@@ -686,6 +700,20 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
686 ret; \ 700 ret; \
687}) 701})
688 702
703#define rsnd_path_break(priv, io, type) \
704{ \
705 struct rsnd_mod *mod; \
706 int id = -1; \
707 \
708 if (rsnd_is_enable_path(io, type)) { \
709 id = rsnd_info_id(priv, io, type); \
710 if (id >= 0) { \
711 mod = rsnd_##type##_mod_get(priv, id); \
712 rsnd_dai_disconnect(mod, io); \
713 } \
714 } \
715}
716
689static int rsnd_path_init(struct rsnd_priv *priv, 717static int rsnd_path_init(struct rsnd_priv *priv,
690 struct rsnd_dai *rdai, 718 struct rsnd_dai *rdai,
691 struct rsnd_dai_stream *io) 719 struct rsnd_dai_stream *io)
@@ -977,6 +1005,44 @@ static const struct snd_soc_component_driver rsnd_soc_component = {
977 .name = "rsnd", 1005 .name = "rsnd",
978}; 1006};
979 1007
1008static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,
1009 struct rsnd_dai *rdai,
1010 int is_play)
1011{
1012 struct rsnd_dai_stream *io = is_play ? &rdai->playback : &rdai->capture;
1013 int ret;
1014
1015 ret = rsnd_dai_call(probe, io, rdai);
1016 if (ret == -EAGAIN) {
1017 /*
1018 * Fallback to PIO mode
1019 */
1020
1021 /*
1022 * call "remove" for SSI/SRC/DVC
1023 * SSI will be switch to PIO mode if it was DMA mode
1024 * see
1025 * rsnd_dma_init()
1026 * rsnd_ssi_dma_remove()
1027 */
1028 rsnd_dai_call(remove, io, rdai);
1029
1030 /*
1031 * remove SRC/DVC from DAI,
1032 */
1033 rsnd_path_break(priv, io, src);
1034 rsnd_path_break(priv, io, dvc);
1035
1036 /*
1037 * retry to "probe".
1038 * DAI has SSI which is PIO mode only now.
1039 */
1040 ret = rsnd_dai_call(probe, io, rdai);
1041 }
1042
1043 return ret;
1044}
1045
980/* 1046/*
981 * rsnd probe 1047 * rsnd probe
982 */ 1048 */
@@ -1038,11 +1104,11 @@ static int rsnd_probe(struct platform_device *pdev)
1038 } 1104 }
1039 1105
1040 for_each_rsnd_dai(rdai, priv, i) { 1106 for_each_rsnd_dai(rdai, priv, i) {
1041 ret = rsnd_dai_call(probe, &rdai->playback, rdai); 1107 ret = rsnd_rdai_continuance_probe(priv, rdai, 1);
1042 if (ret) 1108 if (ret)
1043 goto exit_snd_probe; 1109 goto exit_snd_probe;
1044 1110
1045 ret = rsnd_dai_call(probe, &rdai->capture, rdai); 1111 ret = rsnd_rdai_continuance_probe(priv, rdai, 0);
1046 if (ret) 1112 if (ret)
1047 goto exit_snd_probe; 1113 goto exit_snd_probe;
1048 } 1114 }
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index cae08b7ffa53..346d3dc66d73 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -465,8 +465,23 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
465static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, 465static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
466 struct rsnd_dai *rdai) 466 struct rsnd_dai *rdai)
467{ 467{
468 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
469 struct device *dev = rsnd_priv_to_dev(priv);
470
468 rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod)); 471 rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod));
469 472
473 /*
474 * fallback to PIO
475 *
476 * SSI .probe might be called again.
477 * see
478 * rsnd_rdai_continuance_probe()
479 */
480 mod->ops = &rsnd_ssi_pio_ops;
481
482 dev_info(dev, "%s[%d] fallback to PIO mode\n",
483 rsnd_mod_name(mod), rsnd_mod_id(mod));
484
470 return 0; 485 return 0;
471} 486}
472 487