| From 32f2350521c74d71d16b2c8e1f4701903fa6c6cf Mon Sep 17 00:00:00 2001 |
| From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Date: Mon, 3 Mar 2014 20:50:00 -0800 |
| Subject: ASoC: rsnd: Get correct SCU ID |
| |
| Current rsnd driver is assuming that SCU/SRU ID is |
| same as SSIU/SSI ID, because Gen1 can't select it. |
| But, Gen2 can select it. |
| The SCU/SRU/SSIU/SSI pair depends on the platform. |
| This patch get correct SCU ID from platform info. |
| To keep compatible, it still assuming SCU ID = SSI ID |
| if platform doesn't have info |
| |
| Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Signed-off-by: Mark Brown <broonie@linaro.org> |
| (cherry picked from commit 389933d9f6e55a1ef3a71549c36f6283b9f8c145) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| include/sound/rcar_snd.h | 1 + |
| sound/soc/sh/rcar/core.c | 47 +++++++++++++++++++++++++++++++++-------------- |
| sound/soc/sh/rcar/rsnd.h | 14 ++++++++++++++ |
| sound/soc/sh/rcar/scu.c | 21 ++++++++++++++++----- |
| sound/soc/sh/rcar/ssi.c | 9 ++++++++- |
| 5 files changed, 72 insertions(+), 20 deletions(-) |
| |
| diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h |
| index 698f7b5fc76d..1d8c68323f49 100644 |
| --- a/include/sound/rcar_snd.h |
| +++ b/include/sound/rcar_snd.h |
| @@ -70,6 +70,7 @@ struct rsnd_scu_platform_info { |
| |
| struct rsnd_dai_path_info { |
| struct rsnd_ssi_platform_info *ssi; |
| + struct rsnd_scu_platform_info *scu; |
| }; |
| |
| struct rsnd_dai_platform_info { |
| diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c |
| index 450472633eb1..7316d10e4649 100644 |
| --- a/sound/soc/sh/rcar/core.c |
| +++ b/sound/soc/sh/rcar/core.c |
| @@ -107,6 +107,11 @@ |
| (!(priv->info->func) ? 0 : \ |
| priv->info->func(param)) |
| |
| +#define rsnd_is_enable_path(io, name) \ |
| + ((io)->info ? (io)->info->name : NULL) |
| +#define rsnd_info_id(priv, io, name) \ |
| + ((io)->info->name - priv->info->name##_info) |
| + |
| /* |
| * rsnd_mod functions |
| */ |
| @@ -572,8 +577,10 @@ static int rsnd_path_init(struct rsnd_priv *priv, |
| struct rsnd_dai_stream *io) |
| { |
| struct rsnd_mod *mod; |
| + struct rsnd_dai_platform_info *dai_info = rdai->info; |
| int ret; |
| - int id; |
| + int ssi_id = -1; |
| + int scu_id = -1; |
| |
| /* |
| * Gen1 is created by SRU/SSI, and this SRU is base module of |
| @@ -584,29 +591,35 @@ static int rsnd_path_init(struct rsnd_priv *priv, |
| * |
| * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is |
| * using fixed path. |
| - * |
| - * Then, SSI id = SCU id here |
| */ |
| - /* get SSI's ID */ |
| - mod = rsnd_ssi_mod_get_frm_dai(priv, |
| - rsnd_dai_id(priv, rdai), |
| - rsnd_dai_is_play(rdai, io)); |
| - if (!mod) |
| - return 0; |
| - id = rsnd_mod_id(mod); |
| + if (dai_info) { |
| + if (rsnd_is_enable_path(io, ssi)) |
| + ssi_id = rsnd_info_id(priv, io, ssi); |
| + if (rsnd_is_enable_path(io, scu)) |
| + scu_id = rsnd_info_id(priv, io, scu); |
| + } else { |
| + /* get SSI's ID */ |
| + mod = rsnd_ssi_mod_get_frm_dai(priv, |
| + rsnd_dai_id(priv, rdai), |
| + rsnd_dai_is_play(rdai, io)); |
| + if (!mod) |
| + return 0; |
| + ssi_id = scu_id = rsnd_mod_id(mod); |
| + } |
| + |
| ret = 0; |
| |
| /* SCU */ |
| - mod = rsnd_scu_mod_get(priv, id); |
| - if (mod) { |
| + if (scu_id >= 0) { |
| + mod = rsnd_scu_mod_get(priv, scu_id); |
| ret = rsnd_dai_connect(mod, io); |
| if (ret < 0) |
| return ret; |
| } |
| |
| /* SSI */ |
| - mod = rsnd_ssi_mod_get(priv, id); |
| - if (mod) { |
| + if (ssi_id >= 0) { |
| + mod = rsnd_ssi_mod_get(priv, ssi_id); |
| ret = rsnd_dai_connect(mod, io); |
| if (ret < 0) |
| return ret; |
| @@ -699,6 +712,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, |
| drv[i].playback.formats = RSND_FMTS; |
| drv[i].playback.channels_min = 2; |
| drv[i].playback.channels_max = 2; |
| + |
| + if (info->dai_info) |
| + rdai[i].playback.info = &info->dai_info[i].playback; |
| rsnd_path_init(priv, &rdai[i], &rdai[i].playback); |
| } |
| if (cmod) { |
| @@ -706,6 +722,9 @@ static int rsnd_dai_probe(struct platform_device *pdev, |
| drv[i].capture.formats = RSND_FMTS; |
| drv[i].capture.channels_min = 2; |
| drv[i].capture.channels_max = 2; |
| + |
| + if (info->dai_info) |
| + rdai[i].capture.info = &info->dai_info[i].capture; |
| rsnd_path_init(priv, &rdai[i], &rdai[i].capture); |
| } |
| |
| diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h |
| index d5afdee6b6f2..3472631c7b35 100644 |
| --- a/sound/soc/sh/rcar/rsnd.h |
| +++ b/sound/soc/sh/rcar/rsnd.h |
| @@ -211,6 +211,7 @@ char *rsnd_mod_name(struct rsnd_mod *mod); |
| struct rsnd_dai_stream { |
| struct snd_pcm_substream *substream; |
| struct rsnd_mod *mod[RSND_MOD_MAX]; |
| + struct rsnd_dai_path_info *info; /* rcar_snd.h */ |
| int byte_pos; |
| int period_pos; |
| int byte_per_period; |
| @@ -328,6 +329,19 @@ struct rsnd_priv { |
| #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) |
| #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags) |
| |
| +#define rsnd_info_is_playback(priv, type) \ |
| +({ \ |
| + struct rcar_snd_info *info = rsnd_priv_to_info(priv); \ |
| + int i, is_play = 0; \ |
| + for (i = 0; i < info->dai_info_nr; i++) { \ |
| + if (info->dai_info[i].playback.type == (type)->info) { \ |
| + is_play = 1; \ |
| + break; \ |
| + } \ |
| + } \ |
| + is_play; \ |
| +}) |
| + |
| /* |
| * R-Car SCU |
| */ |
| diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c |
| index 1073d35486e3..b517300f32ce 100644 |
| --- a/sound/soc/sh/rcar/scu.c |
| +++ b/sound/soc/sh/rcar/scu.c |
| @@ -620,6 +620,9 @@ int rsnd_scu_probe(struct platform_device *pdev, |
| * init SCU |
| */ |
| nr = info->scu_info_nr; |
| + if (!nr) |
| + return 0; |
| + |
| scu = devm_kzalloc(dev, sizeof(*scu) * nr, GFP_KERNEL); |
| if (!scu) { |
| dev_err(dev, "SCU allocate failed\n"); |
| @@ -644,11 +647,19 @@ int rsnd_scu_probe(struct platform_device *pdev, |
| if (rsnd_is_gen1(priv)) |
| ops = &rsnd_scu_gen1_ops; |
| if (rsnd_is_gen2(priv)) { |
| - struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); |
| - int ret = rsnd_dma_init(priv, |
| - rsnd_mod_to_dma(&scu->mod), |
| - rsnd_ssi_is_play(ssi), |
| - scu->info->dma_id); |
| + int ret; |
| + int is_play; |
| + |
| + if (info->dai_info) { |
| + is_play = rsnd_info_is_playback(priv, scu); |
| + } else { |
| + struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); |
| + is_play = rsnd_ssi_is_play(ssi); |
| + } |
| + ret = rsnd_dma_init(priv, |
| + rsnd_mod_to_dma(&scu->mod), |
| + is_play, |
| + scu->info->dma_id); |
| if (ret < 0) |
| return ret; |
| |
| diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c |
| index 34234813f742..9162c2bb6cc5 100644 |
| --- a/sound/soc/sh/rcar/ssi.c |
| +++ b/sound/soc/sh/rcar/ssi.c |
| @@ -567,9 +567,16 @@ int rsnd_ssi_probe(struct platform_device *pdev, |
| * SSI DMA case |
| */ |
| if (pinfo->dma_id > 0) { |
| + int is_play; |
| + |
| + if (info->dai_info) |
| + is_play = rsnd_info_is_playback(priv, ssi); |
| + else |
| + is_play = rsnd_ssi_is_play(&ssi->mod); |
| + |
| ret = rsnd_dma_init( |
| priv, rsnd_mod_to_dma(&ssi->mod), |
| - rsnd_ssi_is_play(&ssi->mod), |
| + is_play, |
| pinfo->dma_id); |
| if (ret < 0) |
| dev_info(dev, "SSI DMA failed. try PIO transter\n"); |
| -- |
| 2.1.2 |
| |