blob: 0adf0affe7df59e5e498cc0ca1293c0b2ddd36ef [file] [log] [blame]
From bfe8aecc9388f82d1e70c5384582c7fbbf60d92b Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Fri, 10 Apr 2015 08:50:30 +0000
Subject: [PATCH 099/129] ASoC: rsnd: make sure SSI parent/child uses same
number of sound channel.
SSI parent/child need to use same number of sound data channel
if these are sharing clock/ws pin. this patch makes it sure.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
(cherry picked from commit 919567d914b3c134e60c01db72a03a0adc5f41b9)
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
sound/soc/sh/rcar/ssi.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -67,6 +67,7 @@ struct rsnd_ssi {
u32 cr_own;
u32 cr_clk;
+ int chan;
int err;
unsigned int usrcnt;
};
@@ -265,6 +266,8 @@ static void rsnd_ssi_hw_stop(struct rsnd
}
rsnd_mod_hw_stop(&ssi->mod);
+
+ ssi->chan = 0;
}
dev_dbg(dev, "%s[%d] hw stopped\n",
@@ -341,6 +344,35 @@ static int rsnd_ssi_quit(struct rsnd_mod
return 0;
}
+static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+ struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi);
+ int chan = params_channels(params);
+
+ /*
+ * Already working.
+ * It will happen if SSI has parent/child connection.
+ */
+ if (ssi->usrcnt) {
+ /*
+ * it is error if child <-> parent SSI uses
+ * different channels.
+ */
+ if (ssi->chan != chan)
+ return -EIO;
+ }
+
+ /* It will be removed on rsnd_ssi_hw_stop */
+ ssi->chan = chan;
+ if (ssi_parent)
+ return rsnd_ssi_hw_params(&ssi_parent->mod, substream, params);
+
+ return 0;
+}
+
static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
{
/* under/over flow error */
@@ -468,6 +500,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_
.quit = rsnd_ssi_quit,
.start = rsnd_ssi_start,
.stop = rsnd_ssi_stop,
+ .hw_params = rsnd_ssi_hw_params,
};
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
@@ -577,6 +610,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_
.start = rsnd_ssi_dma_start,
.stop = rsnd_ssi_dma_stop,
.fallback = rsnd_ssi_fallback,
+ .hw_params = rsnd_ssi_hw_params,
};
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)