summaryrefslogtreecommitdiff
path: root/sound/soc/sh/rcar/ssiu.c
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2015-12-17 03:00:10 +0000
committerMark Brown <broonie@kernel.org>2015-12-22 23:58:28 +0000
commitb4c83b171557815a0b31a36805900cc9f21c9ee4 (patch)
tree309df2f48e4291630edb2f280eff17d171585a93 /sound/soc/sh/rcar/ssiu.c
parent44bf5361e21d507e23f8cf8d696c0600f3795e54 (diff)
ASoC: rsnd: add Multi channel support
This patch adds Multi channel support on Renesas R-Car sound. This patch is tested on Salvator-X board, but it can't use Multi channel, because supported format is different between codec chip and R-Car. Thus, it was tested on board which doesn't mount codec chip, with oscilloscope. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sh/rcar/ssiu.c')
-rw-r--r--sound/soc/sh/rcar/ssiu.c55
1 files changed, 46 insertions, 9 deletions
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
index 7ae05a7621ae..3fe9e08e81a3 100644
--- a/sound/soc/sh/rcar/ssiu.c
+++ b/sound/soc/sh/rcar/ssiu.c
@@ -27,8 +27,11 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
struct rsnd_priv *priv)
{
struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+ u32 multi_ssi_slaves = rsnd_ssi_multi_slaves(io);
int use_busif = rsnd_ssi_use_busif(io);
int id = rsnd_mod_id(mod);
+ u32 mask1, val1;
+ u32 mask2, val2;
/*
* SSI_MODE0
@@ -38,6 +41,9 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
/*
* SSI_MODE1
*/
+ mask1 = (1 << 4) | (1 << 20); /* mask sync bit */
+ mask2 = (1 << 4); /* mask sync bit */
+ val1 = val2 = 0;
if (rsnd_ssi_is_pin_sharing(io)) {
int shift = -1;
@@ -51,15 +57,36 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
case 4:
shift = 16;
break;
+ default:
+ return -EINVAL;
}
- if (shift >= 0)
- rsnd_mod_bset(mod, SSI_MODE1,
- 0x3 << shift,
- rsnd_rdai_is_clk_master(rdai) ?
- 0x2 << shift : 0x1 << shift);
+ mask1 |= 0x3 << shift;
+ val1 = rsnd_rdai_is_clk_master(rdai) ?
+ 0x2 << shift : 0x1 << shift;
+
+ } else if (multi_ssi_slaves) {
+
+ mask2 |= 0x00000007;
+ mask1 |= 0x0000000f;
+
+ switch (multi_ssi_slaves) {
+ case 0x0206: /* SSI0/1/2/9 */
+ val2 = (1 << 4) | /* SSI0129 sync */
+ rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1;
+ /* fall through */
+ case 0x0006: /* SSI0/1/2 */
+ val1 = rsnd_rdai_is_clk_master(rdai) ?
+ 0xa : 0x5;
+
+ if (!val2) /* SSI012 sync */
+ val1 |= (1 << 4);
+ }
}
+ rsnd_mod_bset(mod, SSI_MODE1, mask1, val1);
+ rsnd_mod_bset(mod, SSI_MODE2, mask2, val2);
+
return 0;
}
@@ -104,8 +131,13 @@ static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
- if (rsnd_ssi_use_busif(io))
- rsnd_mod_write(mod, SSI_CTRL, 0x1);
+ if (!rsnd_ssi_use_busif(io))
+ return 0;
+
+ rsnd_mod_write(mod, SSI_CTRL, 0x1);
+
+ if (rsnd_ssi_multi_slaves(io))
+ rsnd_mod_write(mod, SSI_CONTROL, 0x1);
return 0;
}
@@ -114,8 +146,13 @@ static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
- if (rsnd_ssi_use_busif(io))
- rsnd_mod_write(mod, SSI_CTRL, 0);
+ if (!rsnd_ssi_use_busif(io))
+ return 0;
+
+ rsnd_mod_write(mod, SSI_CTRL, 0);
+
+ if (rsnd_ssi_multi_slaves(io))
+ rsnd_mod_write(mod, SSI_CONTROL, 0);
return 0;
}