summaryrefslogtreecommitdiffstats
path: root/sound/soc/sh
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2017-08-10 16:51:05 +0200
committerMark Brown <broonie@kernel.org>2017-08-10 16:51:05 +0200
commit880c15b1e66345cdd1bbd8fc4c9c2119c6eb2da3 (patch)
treed2992ff133cc036b1ea83655c25142e8e29f5bee /sound/soc/sh
parentASoC: rsnd: rsnd_ssi_can_output_clk() macro (diff)
parentASoC: rsnd: avoid duplicate free_irq() (diff)
downloadlinux-880c15b1e66345cdd1bbd8fc4c9c2119c6eb2da3.tar.xz
linux-880c15b1e66345cdd1bbd8fc4c9c2119c6eb2da3.zip
Merge branch 'fix/rcar' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-rcar
Diffstat (limited to 'sound/soc/sh')
-rw-r--r--sound/soc/sh/rcar/adg.c7
-rw-r--r--sound/soc/sh/rcar/core.c7
-rw-r--r--sound/soc/sh/rcar/ssi.c46
3 files changed, 44 insertions, 16 deletions
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 197cb3ec075f..5b5389e5b92b 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -610,6 +610,13 @@ void rsnd_adg_remove(struct rsnd_priv *priv)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
+ struct rsnd_adg *adg = priv->adg;
+ struct clk *clk;
+ int i;
+
+ for_each_rsnd_clkout(clk, adg, i)
+ if (adg->clkout[i])
+ clk_unregister_fixed_rate(adg->clkout[i]);
of_clk_del_provider(np);
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index c34562388cfa..2c12ad2b2b34 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -726,7 +726,6 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
case 2:
case 6:
case 8:
- case 16:
/* TDM Extend Mode */
rsnd_rdai_channels_set(rdai, slots);
rsnd_rdai_ssi_lane_set(rdai, 1);
@@ -740,7 +739,7 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
}
static unsigned int rsnd_soc_hw_channels_list[] = {
- 2, 6, 8, 16,
+ 2, 6, 8,
};
static unsigned int rsnd_soc_hw_rate_list[] = {
@@ -1025,7 +1024,7 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
drv->playback.rates = RSND_RATES;
drv->playback.formats = RSND_FMTS;
drv->playback.channels_min = 2;
- drv->playback.channels_max = 16;
+ drv->playback.channels_max = 8;
drv->playback.stream_name = rdai->playback.name;
snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE,
@@ -1033,7 +1032,7 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
drv->capture.rates = RSND_RATES;
drv->capture.formats = RSND_FMTS;
drv->capture.channels_min = 2;
- drv->capture.channels_max = 16;
+ drv->capture.channels_max = 8;
drv->capture.stream_name = rdai->capture.name;
rdai->playback.rdai = rdai;
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 434996d4054a..0309de58bf18 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -72,6 +72,7 @@ struct rsnd_ssi {
u32 cr_own;
u32 cr_clk;
u32 cr_mode;
+ u32 cr_en;
u32 wsr;
int chan;
int rate;
@@ -291,6 +292,16 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
if (ret < 0)
return ret;
+ /*
+ * SSI clock will be output contiguously
+ * by below settings.
+ * This means, rsnd_ssi_master_clk_start()
+ * and rsnd_ssi_register_setup() are necessary
+ * for SSI parent
+ *
+ * SSICR : FORCE, SCKD, SWSD
+ * SSIWSR : CONT
+ */
ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(idx);
ssi->wsr = CONT;
ssi->rate = rate;
@@ -395,7 +406,8 @@ static void rsnd_ssi_register_setup(struct rsnd_mod *mod)
rsnd_mod_write(mod, SSIWSR, ssi->wsr);
rsnd_mod_write(mod, SSICR, ssi->cr_own |
ssi->cr_clk |
- ssi->cr_mode); /* without EN */
+ ssi->cr_mode |
+ ssi->cr_en);
}
static void rsnd_ssi_pointer_init(struct rsnd_mod *mod,
@@ -545,6 +557,8 @@ static int rsnd_ssi_start(struct rsnd_mod *mod,
struct rsnd_dai_stream *io,
struct rsnd_priv *priv)
{
+ struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+
if (!rsnd_ssi_is_run_mods(mod, io))
return 0;
@@ -555,7 +569,19 @@ static int rsnd_ssi_start(struct rsnd_mod *mod,
if (rsnd_ssi_multi_slaves_runtime(io))
return 0;
- rsnd_mod_bset(mod, SSICR, EN, EN);
+ /*
+ * EN is for data output.
+ * SSI parent EN is not needed.
+ */
+ if (rsnd_ssi_is_parent(mod, io))
+ return 0;
+
+ ssi->cr_en = EN;
+
+ rsnd_mod_write(mod, SSICR, ssi->cr_own |
+ ssi->cr_clk |
+ ssi->cr_mode |
+ ssi->cr_en);
return 0;
}
@@ -570,13 +596,7 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
if (!rsnd_ssi_is_run_mods(mod, io))
return 0;
- /*
- * don't stop if not last user
- * see also
- * rsnd_ssi_start
- * rsnd_ssi_interrupt
- */
- if (ssi->usrcnt > 1)
+ if (rsnd_ssi_is_parent(mod, io))
return 0;
/*
@@ -596,6 +616,8 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod,
rsnd_mod_write(mod, SSICR, cr); /* disabled all */
rsnd_ssi_status_check(mod, IIRQ);
+ ssi->cr_en = 0;
+
return 0;
}
@@ -824,10 +846,10 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
struct rsnd_priv *priv)
{
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
- struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
+ struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io);
- /* Do nothing for SSI parent mod */
- if (ssi_parent_mod == mod)
+ /* Do nothing if non SSI (= SSI parent, multi SSI) mod */
+ if (pure_ssi_mod != mod)
return 0;
/* PIO will request IRQ again */