summaryrefslogtreecommitdiff
path: root/sound/soc/sh/rcar
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh/rcar')
-rw-r--r--sound/soc/sh/rcar/adg.c15
-rw-r--r--sound/soc/sh/rcar/cmd.c15
-rw-r--r--sound/soc/sh/rcar/core.c103
-rw-r--r--sound/soc/sh/rcar/ctu.c2
-rw-r--r--sound/soc/sh/rcar/rsnd.h6
-rw-r--r--sound/soc/sh/rcar/src.c9
-rw-r--r--sound/soc/sh/rcar/ssi.c267
-rw-r--r--sound/soc/sh/rcar/ssiu.c22
8 files changed, 246 insertions, 193 deletions
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index abdfd9cf91e2..0b8ae3eee148 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -64,13 +64,13 @@ static const char * const clk_name[] = {
static u32 rsnd_adg_calculate_rbgx(unsigned long div)
{
- int i, ratio;
+ int i;
if (!div)
return 0;
for (i = 3; i >= 0; i--) {
- ratio = 2 << (i * 2);
+ int ratio = 2 << (i * 2);
if (0 == (div % ratio))
return (u32)((i << 8) | ((div / ratio) - 1));
}
@@ -111,7 +111,7 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
{
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct device *dev = rsnd_priv_to_dev(priv);
- int idx, sel, div, step;
+ int sel;
unsigned int val, en;
unsigned int min, diff;
unsigned int sel_rate[] = {
@@ -126,8 +126,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
val = 0;
en = 0;
for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {
- idx = 0;
- step = 2;
+ int idx = 0;
+ int step = 2;
+ int div;
if (!sel_rate[sel])
continue;
@@ -394,11 +395,11 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv,
struct rsnd_adg *adg)
{
struct device *dev = rsnd_priv_to_dev(priv);
- struct clk *clk;
int i;
for (i = 0; i < CLKMAX; i++) {
- clk = devm_clk_get(dev, clk_name[i]);
+ struct clk *clk = devm_clk_get(dev, clk_name[i]);
+
adg->clk[i] = IS_ERR(clk) ? NULL : clk;
}
}
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c
index e6bb6a9a0684..9fdb37c2cbc2 100644
--- a/sound/soc/sh/rcar/cmd.c
+++ b/sound/soc/sh/rcar/cmd.c
@@ -43,8 +43,6 @@ static int rsnd_cmd_init(struct rsnd_mod *mod,
if (mix) {
struct rsnd_dai *rdai;
- struct rsnd_mod *src;
- struct rsnd_dai_stream *tio;
int i;
/*
@@ -54,8 +52,9 @@ static int rsnd_cmd_init(struct rsnd_mod *mod,
*/
data = 0;
for_each_rsnd_dai(rdai, priv, i) {
- tio = &rdai->playback;
- src = rsnd_io_to_mod_src(tio);
+ struct rsnd_dai_stream *tio = &rdai->playback;
+ struct rsnd_mod *src = rsnd_io_to_mod_src(tio);
+
if (mix == rsnd_io_to_mod_mix(tio))
data |= path[rsnd_mod_id(src)];
@@ -142,7 +141,7 @@ int rsnd_cmd_probe(struct rsnd_priv *priv)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_cmd *cmd;
- int i, nr, ret;
+ int i, nr;
/* This driver doesn't support Gen1 at this point */
if (rsnd_is_gen1(priv))
@@ -161,9 +160,9 @@ int rsnd_cmd_probe(struct rsnd_priv *priv)
priv->cmd = cmd;
for_each_rsnd_cmd(cmd, priv, i) {
- ret = rsnd_mod_init(priv, rsnd_mod_get(cmd),
- &rsnd_cmd_ops, NULL,
- RSND_MOD_CMD, i);
+ int ret = rsnd_mod_init(priv, rsnd_mod_get(cmd),
+ &rsnd_cmd_ops, NULL,
+ RSND_MOD_CMD, i);
if (ret)
return ret;
}
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 1029d8d9d800..8696a993c478 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -216,7 +216,7 @@ int rsnd_mod_init(struct rsnd_priv *priv,
mod->clk = clk;
mod->priv = priv;
- return ret;
+ return 0;
}
void rsnd_mod_quit(struct rsnd_mod *mod)
@@ -230,12 +230,12 @@ void rsnd_mod_interrupt(struct rsnd_mod *mod,
struct rsnd_dai_stream *io))
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dai_stream *io;
struct rsnd_dai *rdai;
int i;
for_each_rsnd_dai(rdai, priv, i) {
- io = &rdai->playback;
+ struct rsnd_dai_stream *io = &rdai->playback;
+
if (mod == io->mod[mod->type])
callback(mod, io);
@@ -486,13 +486,12 @@ struct rsnd_mod *rsnd_mod_next(int *iterator,
enum rsnd_mod_type *array,
int array_size)
{
- struct rsnd_mod *mod;
- enum rsnd_mod_type type;
int max = array ? array_size : RSND_MOD_MAX;
for (; *iterator < max; (*iterator)++) {
- type = (array) ? array[*iterator] : *iterator;
- mod = rsnd_io_to_mod(io, type);
+ enum rsnd_mod_type type = (array) ? array[*iterator] : *iterator;
+ struct rsnd_mod *mod = rsnd_io_to_mod(io, type);
+
if (mod)
return mod;
}
@@ -1061,7 +1060,7 @@ static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv,
struct device_node *ssiu_np = rsnd_ssiu_of_node(priv);
struct device_node *np;
int is_play = rsnd_io_is_play(io);
- int i, j;
+ int i;
if (!ssiu_np)
return;
@@ -1078,13 +1077,11 @@ static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv,
if (!node)
break;
- j = 0;
for_each_child_of_node(ssiu_np, np) {
if (np == node) {
rsnd_flags_set(io, RSND_STREAM_TDM_SPLIT);
dev_dbg(dev, "%s is part of TDM Split\n", io->name);
}
- j++;
}
of_node_put(node);
@@ -1140,7 +1137,6 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai,
{
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
struct device_node *np;
- struct rsnd_mod *mod;
int i;
if (!node)
@@ -1148,7 +1144,8 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai,
i = 0;
for_each_child_of_node(node, np) {
- mod = mod_get(priv, i);
+ struct rsnd_mod *mod = mod_get(priv, i);
+
if (np == playback)
rsnd_dai_connect(mod, &rdai->playback, mod->type);
if (np == capture)
@@ -1258,7 +1255,6 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
struct device_node *dai_np,
int dai_i)
{
- struct device_node *playback, *capture;
struct rsnd_dai_stream *io_playback;
struct rsnd_dai_stream *io_capture;
struct snd_soc_dai_driver *drv;
@@ -1301,8 +1297,8 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
rsnd_rdai_width_set(rdai, 32); /* default 32bit width */
for (io_i = 0;; io_i++) {
- playback = of_parse_phandle(dai_np, "playback", io_i);
- capture = of_parse_phandle(dai_np, "capture", io_i);
+ struct device_node *playback = of_parse_phandle(dai_np, "playback", io_i);
+ struct device_node *capture = of_parse_phandle(dai_np, "capture", io_i);
if (!playback && !capture)
break;
@@ -1366,7 +1362,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
for_each_endpoint_of_node(dai_node, dai_np) {
__rsnd_dai_probe(priv, dai_np, dai_i);
if (rsnd_is_gen3(priv)) {
- struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i);
+ rdai = rsnd_rdai_get(priv, dai_i);
rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
rsnd_parse_connect_graph(priv, &rdai->capture, dai_np);
@@ -1377,7 +1373,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
for_each_child_of_node(dai_node, dai_np) {
__rsnd_dai_probe(priv, dai_np, dai_i);
if (rsnd_is_gen3(priv)) {
- struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i);
+ rdai = rsnd_rdai_get(priv, dai_i);
rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
rsnd_parse_connect_simple(priv, &rdai->capture, dai_np);
@@ -1416,11 +1412,11 @@ static int rsnd_hw_params(struct snd_soc_component *component,
struct rsnd_priv *priv = rsnd_io_to_priv(io);
struct device *dev = rsnd_priv_to_dev(priv);
struct snd_soc_dpcm *dpcm;
- struct snd_pcm_hw_params *be_params;
int stream = substream->stream;
for_each_dpcm_be(fe, stream, dpcm) {
- be_params = &dpcm->hw_params;
+ struct snd_pcm_hw_params *be_params = &dpcm->hw_params;
+
if (params_channels(hw_params) != params_channels(be_params))
io->converted_chan = params_channels(be_params);
if (params_rate(hw_params) != params_rate(be_params))
@@ -1428,8 +1424,75 @@ static int rsnd_hw_params(struct snd_soc_component *component,
}
if (io->converted_chan)
dev_dbg(dev, "convert channels = %d\n", io->converted_chan);
- if (io->converted_rate)
+ if (io->converted_rate) {
+ /*
+ * SRC supports convert rates from params_rate(hw_params)/k_down
+ * to params_rate(hw_params)*k_up, where k_up is always 6, and
+ * k_down depends on number of channels and SRC unit.
+ * So all SRC units can upsample audio up to 6 times regardless
+ * its number of channels. And all SRC units can downsample
+ * 2 channel audio up to 6 times too.
+ */
+ int k_up = 6;
+ int k_down = 6;
+ int channel;
+ struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
+
dev_dbg(dev, "convert rate = %d\n", io->converted_rate);
+
+ channel = io->converted_chan ? io->converted_chan :
+ params_channels(hw_params);
+
+ switch (rsnd_mod_id(src_mod)) {
+ /*
+ * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times.
+ * SRC1, SRC3 and SRC4 can downsample 4 channel audio
+ * up to 4 times.
+ * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio
+ * no more than twice.
+ */
+ case 1:
+ case 3:
+ case 4:
+ if (channel > 4) {
+ k_down = 2;
+ break;
+ }
+ fallthrough;
+ case 0:
+ if (channel > 2)
+ k_down = 4;
+ break;
+
+ /* Other SRC units do not support more than 2 channels */
+ default:
+ if (channel > 2)
+ return -EINVAL;
+ }
+
+ if (params_rate(hw_params) > io->converted_rate * k_down) {
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
+ io->converted_rate * k_down;
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
+ io->converted_rate * k_down;
+ hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
+ } else if (params_rate(hw_params) * k_up < io->converted_rate) {
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
+ (io->converted_rate + k_up - 1) / k_up;
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
+ (io->converted_rate + k_up - 1) / k_up;
+ hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
+ }
+
+ /*
+ * TBD: Max SRC input and output rates also depend on number
+ * of channels and SRC unit:
+ * SRC1, SRC3 and SRC4 do not support more than 128kHz
+ * for 6 channel and 96kHz for 8 channel audio.
+ * Perhaps this function should return EINVAL if the input or
+ * the output rate exceeds the limitation.
+ */
+ }
}
return rsnd_dai_call(hw_params, io, substream, hw_params);
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c
index 7647b3d4c0ba..20eecd088d13 100644
--- a/sound/soc/sh/rcar/ctu.c
+++ b/sound/soc/sh/rcar/ctu.c
@@ -207,6 +207,8 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod,
NULL,
&ctu->pass, RSND_MAX_CHANNELS,
0xC);
+ if (ret < 0)
+ return ret;
/* ROW0 */
ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0",
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 6b519370fd64..1255a85151db 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -597,15 +597,15 @@ phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id);
* R-Car ADG
*/
int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate);
-int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod);
-int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate);
+int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod);
+int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate);
int rsnd_adg_probe(struct rsnd_priv *priv);
void rsnd_adg_remove(struct rsnd_priv *priv);
int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
struct rsnd_dai_stream *io,
unsigned int in_rate,
unsigned int out_rate);
-int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
+int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod,
struct rsnd_dai_stream *io);
#define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1)
#define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0)
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 585ffba0244b..628af8f3920d 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -6,6 +6,15 @@
// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
/*
+ * You can use Synchronous Sampling Rate Convert (if no DVC)
+ *
+ * amixer set "SRC Out Rate" on
+ * aplay xxx.wav &
+ * amixer set "SRC Out Rate" 96000 // convert rate to 96000Hz
+ * amixer set "SRC Out Rate" 22050 // convert rate to 22050Hz
+ */
+
+/*
* you can enable below define if you don't need
* SSI interrupt status debug message when debugging
* see rsnd_dbg_irq_status()
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index d0ded427a836..e29482c26d6a 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -24,23 +24,23 @@
/*
* SSICR
*/
-#define FORCE (1 << 31) /* Fixed */
-#define DMEN (1 << 28) /* DMA Enable */
-#define UIEN (1 << 27) /* Underflow Interrupt Enable */
-#define OIEN (1 << 26) /* Overflow Interrupt Enable */
-#define IIEN (1 << 25) /* Idle Mode Interrupt Enable */
-#define DIEN (1 << 24) /* Data Interrupt Enable */
-#define CHNL_4 (1 << 22) /* Channels */
-#define CHNL_6 (2 << 22) /* Channels */
-#define CHNL_8 (3 << 22) /* Channels */
-#define DWL_MASK (7 << 19) /* Data Word Length mask */
-#define DWL_8 (0 << 19) /* Data Word Length */
-#define DWL_16 (1 << 19) /* Data Word Length */
-#define DWL_18 (2 << 19) /* Data Word Length */
-#define DWL_20 (3 << 19) /* Data Word Length */
-#define DWL_22 (4 << 19) /* Data Word Length */
-#define DWL_24 (5 << 19) /* Data Word Length */
-#define DWL_32 (6 << 19) /* Data Word Length */
+#define FORCE (1u << 31) /* Fixed */
+#define DMEN (1u << 28) /* DMA Enable */
+#define UIEN (1u << 27) /* Underflow Interrupt Enable */
+#define OIEN (1u << 26) /* Overflow Interrupt Enable */
+#define IIEN (1u << 25) /* Idle Mode Interrupt Enable */
+#define DIEN (1u << 24) /* Data Interrupt Enable */
+#define CHNL_4 (1u << 22) /* Channels */
+#define CHNL_6 (2u << 22) /* Channels */
+#define CHNL_8 (3u << 22) /* Channels */
+#define DWL_MASK (7u << 19) /* Data Word Length mask */
+#define DWL_8 (0u << 19) /* Data Word Length */
+#define DWL_16 (1u << 19) /* Data Word Length */
+#define DWL_18 (2u << 19) /* Data Word Length */
+#define DWL_20 (3u << 19) /* Data Word Length */
+#define DWL_22 (4u << 19) /* Data Word Length */
+#define DWL_24 (5u << 19) /* Data Word Length */
+#define DWL_32 (6u << 19) /* Data Word Length */
/*
* System word length
@@ -167,7 +167,6 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod,
static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io)
{
- struct rsnd_mod *mod;
enum rsnd_mod_type types[] = {
RSND_MOD_SSIM1,
RSND_MOD_SSIM2,
@@ -177,7 +176,8 @@ static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io)
mask = 0;
for (i = 0; i < ARRAY_SIZE(types); i++) {
- mod = rsnd_io_to_mod(io, types[i]);
+ struct rsnd_mod *mod = rsnd_io_to_mod(io, types[i]);
+
if (!mod)
continue;
@@ -359,6 +359,96 @@ static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod,
rsnd_adg_ssi_clk_stop(mod);
}
+/* enable busif buffer over/under run interrupt. */
+#define rsnd_ssi_busif_err_irq_enable(mod) rsnd_ssi_busif_err_irq_ctrl(mod, 1)
+#define rsnd_ssi_busif_err_irq_disable(mod) rsnd_ssi_busif_err_irq_ctrl(mod, 0)
+static void rsnd_ssi_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable)
+{
+ u32 sys_int_enable = 0;
+ int id = rsnd_mod_id(mod);
+ int i;
+
+ switch (id) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ for (i = 0; i < 4; i++) {
+ sys_int_enable = rsnd_mod_read(mod, SSI_SYS_INT_ENABLE(i * 2));
+ if (enable)
+ sys_int_enable |= 0xf << (id * 4);
+ else
+ sys_int_enable &= ~(0xf << (id * 4));
+ rsnd_mod_write(mod,
+ SSI_SYS_INT_ENABLE(i * 2),
+ sys_int_enable);
+ }
+ break;
+ case 9:
+ for (i = 0; i < 4; i++) {
+ sys_int_enable = rsnd_mod_read(mod, SSI_SYS_INT_ENABLE((i * 2) + 1));
+ if (enable)
+ sys_int_enable |= 0xf << 4;
+ else
+ sys_int_enable &= ~(0xf << 4);
+ rsnd_mod_write(mod,
+ SSI_SYS_INT_ENABLE((i * 2) + 1),
+ sys_int_enable);
+ }
+ break;
+ }
+}
+
+static bool rsnd_ssi_busif_err_status_clear(struct rsnd_mod *mod)
+{
+ struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+ struct device *dev = rsnd_priv_to_dev(priv);
+ u32 status;
+ bool stop = false;
+ int id = rsnd_mod_id(mod);
+ int i;
+
+ switch (id) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ for (i = 0; i < 4; i++) {
+ status = rsnd_mod_read(mod, SSI_SYS_STATUS(i * 2));
+ status &= 0xf << (id * 4);
+
+ if (status) {
+ rsnd_dbg_irq_status(dev, "%s err status : 0x%08x\n",
+ rsnd_mod_name(mod), status);
+ rsnd_mod_write(mod,
+ SSI_SYS_STATUS(i * 2),
+ 0xf << (id * 4));
+ stop = true;
+ }
+ }
+ break;
+ case 9:
+ for (i = 0; i < 4; i++) {
+ status = rsnd_mod_read(mod, SSI_SYS_STATUS((i * 2) + 1));
+ status &= 0xf << 4;
+
+ if (status) {
+ rsnd_dbg_irq_status(dev, "%s err status : 0x%08x\n",
+ rsnd_mod_name(mod), status);
+ rsnd_mod_write(mod,
+ SSI_SYS_STATUS((i * 2) + 1),
+ 0xf << 4);
+ stop = true;
+ }
+ }
+ break;
+ }
+
+ return stop;
+}
+
static void rsnd_ssi_config_init(struct rsnd_mod *mod,
struct rsnd_dai_stream *io)
{
@@ -372,9 +462,6 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
u32 wsr = ssi->wsr;
int width;
int is_tdm, is_tdm_split;
- int id = rsnd_mod_id(mod);
- int i;
- u32 sys_int_enable = 0;
is_tdm = rsnd_runtime_is_tdm(io);
is_tdm_split = rsnd_runtime_is_tdm_split(io);
@@ -400,7 +487,6 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
* see
* rsnd_ssiu_init_gen2()
*/
- wsr = ssi->wsr;
if (is_tdm || is_tdm_split) {
wsr |= WS_MODE;
cr_own |= CHNL_8;
@@ -451,36 +537,8 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
}
/* enable busif buffer over/under run interrupt. */
- if (is_tdm || is_tdm_split) {
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- for (i = 0; i < 4; i++) {
- sys_int_enable = rsnd_mod_read(mod,
- SSI_SYS_INT_ENABLE(i * 2));
- sys_int_enable |= 0xf << (id * 4);
- rsnd_mod_write(mod,
- SSI_SYS_INT_ENABLE(i * 2),
- sys_int_enable);
- }
-
- break;
- case 9:
- for (i = 0; i < 4; i++) {
- sys_int_enable = rsnd_mod_read(mod,
- SSI_SYS_INT_ENABLE((i * 2) + 1));
- sys_int_enable |= 0xf << 4;
- rsnd_mod_write(mod,
- SSI_SYS_INT_ENABLE((i * 2) + 1),
- sys_int_enable);
- }
-
- break;
- }
- }
+ if (is_tdm || is_tdm_split)
+ rsnd_ssi_busif_err_irq_enable(mod);
init_end:
ssi->cr_own = cr_own;
@@ -507,10 +565,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+ int ret;
if (!rsnd_ssi_is_run_mods(mod, io))
return 0;
+ ret = rsnd_ssi_master_clk_start(mod, io);
+ if (ret < 0)
+ return ret;
+
ssi->usrcnt++;
rsnd_mod_power_on(mod);
@@ -532,9 +595,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct device *dev = rsnd_priv_to_dev(priv);
int is_tdm, is_tdm_split;
- int id = rsnd_mod_id(mod);
- int i;
- u32 sys_int_enable = 0;
is_tdm = rsnd_runtime_is_tdm(io);
is_tdm_split = rsnd_runtime_is_tdm_split(io);
@@ -560,36 +620,8 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
}
/* disable busif buffer over/under run interrupt. */
- if (is_tdm || is_tdm_split) {
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- for (i = 0; i < 4; i++) {
- sys_int_enable = rsnd_mod_read(mod,
- SSI_SYS_INT_ENABLE(i * 2));
- sys_int_enable &= ~(0xf << (id * 4));
- rsnd_mod_write(mod,
- SSI_SYS_INT_ENABLE(i * 2),
- sys_int_enable);
- }
-
- break;
- case 9:
- for (i = 0; i < 4; i++) {
- sys_int_enable = rsnd_mod_read(mod,
- SSI_SYS_INT_ENABLE((i * 2) + 1));
- sys_int_enable &= ~(0xf << 4);
- rsnd_mod_write(mod,
- SSI_SYS_INT_ENABLE((i * 2) + 1),
- sys_int_enable);
- }
-
- break;
- }
- }
+ if (is_tdm || is_tdm_split)
+ rsnd_ssi_busif_err_irq_disable(mod);
return 0;
}
@@ -743,8 +775,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
u32 status;
bool elapsed = false;
bool stop = false;
- int id = rsnd_mod_id(mod);
- int i;
int is_tdm, is_tdm_split;
is_tdm = rsnd_runtime_is_tdm(io);
@@ -770,52 +800,8 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
stop = true;
}
- status = 0;
-
- if (is_tdm || is_tdm_split) {
- switch (id) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- for (i = 0; i < 4; i++) {
- status = rsnd_mod_read(mod,
- SSI_SYS_STATUS(i * 2));
- status &= 0xf << (id * 4);
-
- if (status) {
- rsnd_dbg_irq_status(dev,
- "%s err status : 0x%08x\n",
- rsnd_mod_name(mod), status);
- rsnd_mod_write(mod,
- SSI_SYS_STATUS(i * 2),
- 0xf << (id * 4));
- stop = true;
- break;
- }
- }
- break;
- case 9:
- for (i = 0; i < 4; i++) {
- status = rsnd_mod_read(mod,
- SSI_SYS_STATUS((i * 2) + 1));
- status &= 0xf << 4;
-
- if (status) {
- rsnd_dbg_irq_status(dev,
- "%s err status : 0x%08x\n",
- rsnd_mod_name(mod), status);
- rsnd_mod_write(mod,
- SSI_SYS_STATUS((i * 2) + 1),
- 0xf << 4);
- stop = true;
- break;
- }
- }
- break;
- }
- }
+ if (is_tdm || is_tdm_split)
+ stop |= rsnd_ssi_busif_err_status_clear(mod);
rsnd_ssi_status_clear(mod);
rsnd_ssi_interrupt_out:
@@ -1060,13 +1046,6 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
return 0;
}
-static int rsnd_ssi_prepare(struct rsnd_mod *mod,
- struct rsnd_dai_stream *io,
- struct rsnd_priv *priv)
-{
- return rsnd_ssi_master_clk_start(mod, io);
-}
-
static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.name = SSI_NAME,
.probe = rsnd_ssi_common_probe,
@@ -1079,7 +1058,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.pointer = rsnd_ssi_pio_pointer,
.pcm_new = rsnd_ssi_pcm_new,
.hw_params = rsnd_ssi_hw_params,
- .prepare = rsnd_ssi_prepare,
.get_status = rsnd_ssi_get_status,
};
@@ -1166,7 +1144,6 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
.pcm_new = rsnd_ssi_pcm_new,
.fallback = rsnd_ssi_fallback,
.hw_params = rsnd_ssi_hw_params,
- .prepare = rsnd_ssi_prepare,
.get_status = rsnd_ssi_get_status,
};
@@ -1210,7 +1187,6 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
struct device_node *node;
struct device_node *np;
- struct rsnd_mod *mod;
int i;
node = rsnd_ssi_of_node(priv);
@@ -1219,7 +1195,8 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
i = 0;
for_each_child_of_node(node, np) {
- mod = rsnd_ssi_mod_get(priv, i);
+ struct rsnd_mod *mod = rsnd_ssi_mod_get(priv, i);
+
if (np == playback)
rsnd_ssi_connect(mod, &rdai->playback);
if (np == capture)
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
index f29bd72f3a26..852cdeedf7e9 100644
--- a/sound/soc/sh/rcar/ssiu.c
+++ b/sound/soc/sh/rcar/ssiu.c
@@ -209,7 +209,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
struct rsnd_mod *pos;
u32 val;
- int i, shift;
+ int i;
i = rsnd_mod_id(ssi_mod);
@@ -221,7 +221,8 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
i;
for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) {
- shift = (i * 4) + 20;
+ int shift = (i * 4) + 20;
+
val = (val & ~(0xF << shift)) |
rsnd_mod_id(pos) << shift;
}
@@ -334,7 +335,6 @@ static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv,
struct rsnd_dai_stream *io)
{
struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
- struct rsnd_mod *mod;
struct rsnd_ssiu *ssiu;
int i;
@@ -343,7 +343,7 @@ static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv,
/* select BUSIF0 */
for_each_rsnd_ssiu(ssiu, priv, i) {
- mod = rsnd_mod_get(ssiu);
+ struct rsnd_mod *mod = rsnd_mod_get(ssiu);
if ((rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) &&
(rsnd_mod_id_sub(mod) == 0)) {
@@ -359,17 +359,17 @@ void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
{
struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
struct device_node *node = rsnd_ssiu_of_node(priv);
- struct device_node *np;
- struct rsnd_mod *mod;
struct rsnd_dai_stream *io_p = &rdai->playback;
struct rsnd_dai_stream *io_c = &rdai->capture;
- int i;
/* use rcar_sound,ssiu if exist */
if (node) {
- i = 0;
+ struct device_node *np;
+ int i = 0;
+
for_each_child_of_node(node, np) {
- mod = rsnd_ssiu_mod_get(priv, i);
+ struct rsnd_mod *mod = rsnd_ssiu_mod_get(priv, i);
+
if (np == playback)
rsnd_dai_connect(mod, io_p, mod->type);
if (np == capture)
@@ -394,7 +394,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
struct rsnd_ssiu *ssiu;
struct rsnd_mod_ops *ops;
const int *list = NULL;
- int i, nr, ret;
+ int i, nr;
/*
* Keep DT compatibility.
@@ -441,6 +441,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
}
for_each_rsnd_ssiu(ssiu, priv, i) {
+ int ret;
+
if (node) {
int j;