[alsa-devel] [PATCH 0/5] ASoC: rsnd: add DVC support
Hi Mark
These patches add DVC support to Renesas sound driver. DVC is one of feature of CMD unit, it can control sound Volume.
Kuninori Morimoto (5): ASoC: rsnd: add rsnd_path_parse() macro ASoC: rsnd: add rsnd_get_adinr() ASoC: rsnd: remove duplicate parameter from rsnd_mod_ops ASoC: rsnd: enable to use multi parameter on rsnd_dai_call/rsnd_mod_call ASoC: rsnd: add DVC support
include/sound/rcar_snd.h | 10 ++ sound/soc/sh/rcar/Makefile | 2 +- sound/soc/sh/rcar/adg.c | 18 +++ sound/soc/sh/rcar/core.c | 117 +++++++++++++------ sound/soc/sh/rcar/dvc.c | 273 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/gen.c | 11 ++ sound/soc/sh/rcar/rsnd.h | 65 ++++++++--- sound/soc/sh/rcar/src.c | 121 +++++++------------- sound/soc/sh/rcar/ssi.c | 34 +++--- 9 files changed, 502 insertions(+), 149 deletions(-)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current R-Car sound supports only SRC/SSI, but, other module will be supported. This patch adds rsnd_path_parse() macro to share code
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/core.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 8ed8470..f74d02c 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -576,14 +576,27 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { .set_fmt = rsnd_soc_dai_set_fmt, };
+#define rsnd_path_parse(priv, io, type) \ +({ \ + struct rsnd_mod *mod; \ + int ret = 0; \ + int id = -1; \ + \ + if (rsnd_is_enable_path(io, type)) { \ + id = rsnd_info_id(priv, io, type); \ + if (id >= 0) { \ + mod = rsnd_##type##_mod_get(priv, id); \ + ret = rsnd_dai_connect(mod, io); \ + } \ + } \ + ret; \ +}) + static int rsnd_path_init(struct rsnd_priv *priv, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { - struct rsnd_mod *mod; int ret; - int ssi_id = -1; - int src_id = -1;
/* * Gen1 is created by SRU/SSI, and this SRU is base module of @@ -595,28 +608,16 @@ static int rsnd_path_init(struct rsnd_priv *priv, * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is * using fixed path. */ - if (rsnd_is_enable_path(io, ssi)) - ssi_id = rsnd_info_id(priv, io, ssi); - if (rsnd_is_enable_path(io, src)) - src_id = rsnd_info_id(priv, io, src); - - ret = 0;
/* SRC */ - if (src_id >= 0) { - mod = rsnd_src_mod_get(priv, src_id); - ret = rsnd_dai_connect(mod, io); - if (ret < 0) - return ret; - } + ret = rsnd_path_parse(priv, io, src); + if (ret < 0) + return ret;
/* SSI */ - if (ssi_id >= 0) { - mod = rsnd_ssi_mod_get(priv, ssi_id); - ret = rsnd_dai_connect(mod, io); - if (ret < 0) - return ret; - } + ret = rsnd_path_parse(priv, io, ssi); + if (ret < 0) + return ret;
return ret; }
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
SRC module needs ADINR register settings, but, it has many similar xxx_ADINR register, and needs same settings. This patch adds rsnd_get_adinr() to sharing code.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/core.c | 26 ++++++++++++++++++++++++++ sound/soc/sh/rcar/rsnd.h | 1 + sound/soc/sh/rcar/src.c | 26 +++----------------------- 3 files changed, 30 insertions(+), 23 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index f74d02c..e47aa53 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -310,6 +310,32 @@ void rsnd_dma_quit(struct rsnd_priv *priv, }
/* + * settting function + */ +u32 rsnd_get_adinr(struct rsnd_mod *mod) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); + struct device *dev = rsnd_priv_to_dev(priv); + u32 adinr = runtime->channels; + + switch (runtime->sample_bits) { + case 16: + adinr |= (8 << 16); + break; + case 32: + adinr |= (0 << 16); + break; + default: + dev_warn(dev, "not supported sample bits\n"); + return 0; + } + + return adinr; +} + +/* * rsnd_dai functions */ #define __rsnd_mod_call(mod, func, rdai, io) \ diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 061b04c..fee3ec2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -136,6 +136,7 @@ void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, u32 data); void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, u32 mask, u32 data); +u32 rsnd_get_adinr(struct rsnd_mod *mod);
/* * R-Car DMA diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index d51c59b..c90c36d 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -18,15 +18,6 @@ struct rsnd_src {
#define RSND_SRC_NAME_SIZE 16
-/* - * ADINR - */ -#define OTBL_24 (0 << 16) -#define OTBL_22 (2 << 16) -#define OTBL_20 (4 << 16) -#define OTBL_18 (6 << 16) -#define OTBL_16 (8 << 16) - #define rsnd_src_convert_rate(p) ((p)->info->convert_rate) #define rsnd_mod_to_src(_mod) \ container_of((_mod), struct rsnd_src, mod) @@ -197,7 +188,6 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_src *src = rsnd_mod_to_src(mod); u32 convert_rate = rsnd_src_convert_rate(src); - u32 adinr = runtime->channels; u32 fsrate = 0;
if (convert_rate) @@ -214,17 +204,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, rsnd_mod_write(mod, SRC_SRCIR, 1);
/* Set channel number and output bit length */ - switch (runtime->sample_bits) { - case 16: - adinr |= OTBL_16; - break; - case 32: - adinr |= OTBL_24; - break; - default: - return -EIO; - } - rsnd_mod_write(mod, SRC_ADINR, adinr); + rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod));
/* Enable the initial value of IFS */ if (fsrate) { @@ -487,8 +467,8 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, if (ret < 0) return ret;
- rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); - rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); + rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr(mod)); + rsnd_mod_write(mod, SSI_BUSIF_MODE, 1);
rsnd_mod_write(mod, SRC_SRCCR, 0x00011110);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Now, it can get rsnd_dai_stream pointer from rsnd_mod. Remove duplicate parameter from rsnd_mod_ops
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/core.c | 10 ++--- sound/soc/sh/rcar/rsnd.h | 24 ++++-------- sound/soc/sh/rcar/src.c | 91 +++++++++++++++++++--------------------------- sound/soc/sh/rcar/ssi.c | 34 +++++++---------- 4 files changed, 65 insertions(+), 94 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index e47aa53..86c9b78 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -338,19 +338,19 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) /* * rsnd_dai functions */ -#define __rsnd_mod_call(mod, func, rdai, io) \ +#define __rsnd_mod_call(mod, func, rdai) \ ({ \ struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ struct device *dev = rsnd_priv_to_dev(priv); \ dev_dbg(dev, "%s [%d] %s\n", \ rsnd_mod_name(mod), rsnd_mod_id(mod), #func); \ - (mod)->ops->func(mod, rdai, io); \ + (mod)->ops->func(mod, rdai); \ })
-#define rsnd_mod_call(mod, func, rdai, io) \ +#define rsnd_mod_call(mod, func, rdai) \ (!(mod) ? -ENODEV : \ !((mod)->ops->func) ? 0 : \ - __rsnd_mod_call(mod, func, (rdai), (io))) + __rsnd_mod_call(mod, func, (rdai)))
#define rsnd_dai_call(rdai, io, fn) \ ({ \ @@ -360,7 +360,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) mod = (io)->mod[i]; \ if (!mod) \ continue; \ - ret = rsnd_mod_call(mod, fn, (rdai), (io)); \ + ret = rsnd_mod_call(mod, fn, (rdai)); \ if (ret < 0) \ break; \ } \ diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index fee3ec2..6156cee 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -172,23 +172,17 @@ enum rsnd_mod_type { struct rsnd_mod_ops { char *name; int (*probe)(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); + struct rsnd_dai *rdai); int (*remove)(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); + struct rsnd_dai *rdai); int (*init)(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); + struct rsnd_dai *rdai); int (*quit)(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); + struct rsnd_dai *rdai); int (*start)(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); + struct rsnd_dai *rdai); int (*stop)(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); + struct rsnd_dai *rdai); };
struct rsnd_dai_stream; @@ -365,11 +359,9 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, struct rsnd_dai_stream *io, struct snd_pcm_runtime *runtime); int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); + struct rsnd_dai *rdai); int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io); + struct rsnd_dai *rdai);
#define rsnd_src_nr(priv) ((priv)->src_nr)
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index c90c36d..035eda2 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -105,9 +105,9 @@ struct rsnd_src { * Gen1/Gen2 common functions */ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { + struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); int ssi_id = rsnd_mod_id(ssi_mod);
@@ -145,8 +145,7 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, }
int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
@@ -182,9 +181,9 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, }
static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_src *src = rsnd_mod_to_src(mod); u32 convert_rate = rsnd_src_convert_rate(src); @@ -221,8 +220,7 @@ static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, }
static int rsnd_src_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_src *src = rsnd_mod_to_src(mod);
@@ -232,8 +230,7 @@ static int rsnd_src_init(struct rsnd_mod *mod, }
static int rsnd_src_quit(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_src *src = rsnd_mod_to_src(mod);
@@ -243,8 +240,7 @@ static int rsnd_src_quit(struct rsnd_mod *mod, }
static int rsnd_src_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_src *src = rsnd_mod_to_src(mod);
@@ -262,8 +258,7 @@ static int rsnd_src_start(struct rsnd_mod *mod,
static int rsnd_src_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_src *src = rsnd_mod_to_src(mod);
@@ -281,9 +276,9 @@ static struct rsnd_mod_ops rsnd_src_non_ops = { * Gen1 functions */ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct src_route_config { u32 mask; int shift; @@ -319,9 +314,9 @@ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, }
static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_src *src = rsnd_mod_to_src(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); @@ -378,12 +373,11 @@ static int rsnd_src_set_convert_timing_gen1(struct rsnd_mod *mod, }
static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { int ret;
- ret = rsnd_src_set_convert_rate(mod, rdai, io); + ret = rsnd_src_set_convert_rate(mod, rdai); if (ret < 0) return ret;
@@ -400,24 +394,23 @@ static int rsnd_src_set_convert_rate_gen1(struct rsnd_mod *mod, }
static int rsnd_src_init_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { int ret;
- ret = rsnd_src_init(mod, rdai, io); + ret = rsnd_src_init(mod, rdai); if (ret < 0) return ret;
- ret = rsnd_src_set_route_gen1(mod, rdai, io); + ret = rsnd_src_set_route_gen1(mod, rdai); if (ret < 0) return ret;
- ret = rsnd_src_set_convert_rate_gen1(mod, rdai, io); + ret = rsnd_src_set_convert_rate_gen1(mod, rdai); if (ret < 0) return ret;
- ret = rsnd_src_set_convert_timing_gen1(mod, rdai, io); + ret = rsnd_src_set_convert_timing_gen1(mod, rdai); if (ret < 0) return ret;
@@ -425,25 +418,23 @@ static int rsnd_src_init_gen1(struct rsnd_mod *mod, }
static int rsnd_src_start_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { int id = rsnd_mod_id(mod);
rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id));
- return rsnd_src_start(mod, rdai, io); + return rsnd_src_start(mod, rdai); }
static int rsnd_src_stop_gen1(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { int id = rsnd_mod_id(mod);
rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0);
- return rsnd_src_stop(mod, rdai, io); + return rsnd_src_stop(mod, rdai); }
static struct rsnd_mod_ops rsnd_src_gen1_ops = { @@ -458,12 +449,11 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = { * Gen2 functions */ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { int ret;
- ret = rsnd_src_set_convert_rate(mod, rdai, io); + ret = rsnd_src_set_convert_rate(mod, rdai); if (ret < 0) return ret;
@@ -479,9 +469,9 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod, }
static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_src *src = rsnd_mod_to_src(mod); u32 convert_rate = rsnd_src_convert_rate(src); @@ -498,8 +488,7 @@ static int rsnd_src_set_convert_timing_gen2(struct rsnd_mod *mod, }
static int rsnd_src_probe_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_src *src = rsnd_mod_to_src(mod); @@ -517,8 +506,7 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod, }
static int rsnd_src_remove_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod));
@@ -526,20 +514,19 @@ static int rsnd_src_remove_gen2(struct rsnd_mod *mod, }
static int rsnd_src_init_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { int ret;
- ret = rsnd_src_init(mod, rdai, io); + ret = rsnd_src_init(mod, rdai); if (ret < 0) return ret;
- ret = rsnd_src_set_convert_rate_gen2(mod, rdai, io); + ret = rsnd_src_set_convert_rate_gen2(mod, rdai); if (ret < 0) return ret;
- ret = rsnd_src_set_convert_timing_gen2(mod, rdai, io); + ret = rsnd_src_set_convert_timing_gen2(mod, rdai); if (ret < 0) return ret;
@@ -547,8 +534,7 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod, }
static int rsnd_src_start_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_src *src = rsnd_mod_to_src(mod);
@@ -557,12 +543,11 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod, rsnd_mod_write(mod, SSI_CTRL, 0x1); rsnd_mod_write(mod, SRC_CTRL, 0x11);
- return rsnd_src_start(mod, rdai, io); + return rsnd_src_start(mod, rdai); }
static int rsnd_src_stop_gen2(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_src *src = rsnd_mod_to_src(mod);
@@ -571,7 +556,7 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
rsnd_dma_stop(rsnd_mod_to_dma(&src->mod));
- return rsnd_src_stop(mod, rdai, io); + return rsnd_src_stop(mod, rdai); }
static struct rsnd_mod_ops rsnd_src_gen2_ops = { diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 77b7b60..4b13edb 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -240,10 +240,10 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi, * SSI mod common functions */ static int rsnd_ssi_init(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); u32 cr;
@@ -287,14 +287,13 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, ssi->cr_own = cr; ssi->err = -1; /* ignore 1st error */
- rsnd_src_ssi_mode_init(mod, rdai, io); + rsnd_src_ssi_mode_init(mod, rdai);
return 0; }
static int rsnd_ssi_quit(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); @@ -359,8 +358,7 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data) }
static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); @@ -379,15 +377,15 @@ static int rsnd_ssi_pio_probe(struct rsnd_mod *mod, }
static int rsnd_ssi_pio_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
/* enable PIO IRQ */ ssi->cr_etc = UIEN | OIEN | DIEN;
- rsnd_src_enable_ssi_irq(mod, rdai, io); + rsnd_src_enable_ssi_irq(mod, rdai);
rsnd_ssi_hw_start(ssi, rdai, io);
@@ -395,8 +393,7 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod, }
static int rsnd_ssi_pio_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
@@ -417,8 +414,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { };
static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); @@ -438,8 +434,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, }
static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod));
@@ -447,11 +442,11 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, }
static int rsnd_ssi_dma_start(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
/* enable DMA transfer */ ssi->cr_etc = DMEN; @@ -468,8 +463,7 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod, }
static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, - struct rsnd_dai *rdai, - struct rsnd_dai_stream *io) + struct rsnd_dai *rdai) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_dma *dma = rsnd_mod_to_dma(&ssi->mod);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
rsnd_mod_ops would like to come to use multi parameter. modify macro to enable it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/core.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 86c9b78..378985b 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -338,7 +338,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) /* * rsnd_dai functions */ -#define __rsnd_mod_call(mod, func, rdai) \ +#define __rsnd_mod_call(mod, func, rdai...) \ ({ \ struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ struct device *dev = rsnd_priv_to_dev(priv); \ @@ -347,12 +347,12 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) (mod)->ops->func(mod, rdai); \ })
-#define rsnd_mod_call(mod, func, rdai) \ +#define rsnd_mod_call(mod, func, rdai...) \ (!(mod) ? -ENODEV : \ !((mod)->ops->func) ? 0 : \ - __rsnd_mod_call(mod, func, (rdai))) + __rsnd_mod_call(mod, func, rdai))
-#define rsnd_dai_call(rdai, io, fn) \ +#define rsnd_dai_call(fn, io, rdai...) \ ({ \ struct rsnd_mod *mod; \ int ret = 0, i; \ @@ -360,7 +360,7 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod) mod = (io)->mod[i]; \ if (!mod) \ continue; \ - ret = rsnd_mod_call(mod, fn, (rdai)); \ + ret = rsnd_mod_call(mod, fn, rdai); \ if (ret < 0) \ break; \ } \ @@ -510,20 +510,20 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) goto dai_trigger_end;
- ret = rsnd_dai_call(rdai, io, init); + ret = rsnd_dai_call(init, io, rdai); if (ret < 0) goto dai_trigger_end;
- ret = rsnd_dai_call(rdai, io, start); + ret = rsnd_dai_call(start, io, rdai); if (ret < 0) goto dai_trigger_end; break; case SNDRV_PCM_TRIGGER_STOP: - ret = rsnd_dai_call(rdai, io, stop); + ret = rsnd_dai_call(stop, io, rdai); if (ret < 0) goto dai_trigger_end;
- ret = rsnd_dai_call(rdai, io, quit); + ret = rsnd_dai_call(quit, io, rdai); if (ret < 0) goto dai_trigger_end;
@@ -951,11 +951,11 @@ static int rsnd_probe(struct platform_device *pdev) }
for_each_rsnd_dai(rdai, priv, i) { - ret = rsnd_dai_call(rdai, &rdai->playback, probe); + ret = rsnd_dai_call(probe, &rdai->playback, rdai); if (ret) return ret;
- ret = rsnd_dai_call(rdai, &rdai->capture, probe); + ret = rsnd_dai_call(probe, &rdai->capture, rdai); if (ret) return ret; } @@ -998,11 +998,11 @@ static int rsnd_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev);
for_each_rsnd_dai(rdai, priv, i) { - ret = rsnd_dai_call(rdai, &rdai->playback, remove); + ret = rsnd_dai_call(remove, &rdai->playback, rdai); if (ret) return ret;
- ret = rsnd_dai_call(rdai, &rdai->capture, remove); + ret = rsnd_dai_call(remove, &rdai->capture, rdai); if (ret) return ret; }
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
This patch adds DVC (Digital Volume Controller) support which is member of CMD unit.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- include/sound/rcar_snd.h | 10 ++ sound/soc/sh/rcar/Makefile | 2 +- sound/soc/sh/rcar/adg.c | 18 +++ sound/soc/sh/rcar/core.c | 20 ++++ sound/soc/sh/rcar/dvc.c | 273 ++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/gen.c | 11 ++ sound/soc/sh/rcar/rsnd.h | 40 +++++++ sound/soc/sh/rcar/src.c | 4 +- 8 files changed, 376 insertions(+), 2 deletions(-) create mode 100644 sound/soc/sh/rcar/dvc.c
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index a03268e..f4a706f 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h @@ -56,9 +56,17 @@ struct rsnd_src_platform_info { int dma_id; /* for Gen2 SCU */ };
+/* + * flags + */ +struct rsnd_dvc_platform_info { + u32 flags; +}; + struct rsnd_dai_path_info { struct rsnd_ssi_platform_info *ssi; struct rsnd_src_platform_info *src; + struct rsnd_dvc_platform_info *dvc; };
struct rsnd_dai_platform_info { @@ -83,6 +91,8 @@ struct rcar_snd_info { int ssi_info_nr; struct rsnd_src_platform_info *src_info; int src_info_nr; + struct rsnd_dvc_platform_info *dvc_info; + int dvc_info_nr; struct rsnd_dai_platform_info *dai_info; int dai_info_nr; int (*start)(int id); diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index 7d0051c..9ac5364 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,2 +1,2 @@ -snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o +snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o dvc.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 41556b2..fc41a0e 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -57,6 +57,24 @@ static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) return (0x6 + ws) << 8; }
+int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io) +{ + int id = rsnd_mod_id(mod); + int shift = (id % 2) ? 16 : 0; + u32 mask, val; + + val = rsnd_adg_ssi_ws_timing_gen2(io); + + val = val << shift; + mask = 0xffff << shift; + + rsnd_mod_bset(mod, CMDOUT_TIMSEL, mask, val); + + return 0; +} + static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, struct rsnd_mod *mod, struct rsnd_dai_stream *io, diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 378985b..1f6981a 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -645,6 +645,11 @@ static int rsnd_path_init(struct rsnd_priv *priv, if (ret < 0) return ret;
+ /* DVC */ + ret = rsnd_path_parse(priv, io, dvc); + if (ret < 0) + return ret; + return ret; }
@@ -869,6 +874,20 @@ static struct snd_pcm_ops rsnd_pcm_ops = {
static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) { + struct rsnd_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); + struct rsnd_dai *rdai; + int i, ret; + + for_each_rsnd_dai(rdai, priv, i) { + ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); + if (ret) + return ret; + + ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); + if (ret) + return ret; + } + return snd_pcm_lib_preallocate_pages_for_all( rtd->pcm, SNDRV_DMA_TYPE_DEV, @@ -908,6 +927,7 @@ static int rsnd_probe(struct platform_device *pdev) rsnd_gen_probe, rsnd_ssi_probe, rsnd_src_probe, + rsnd_dvc_probe, rsnd_adg_probe, rsnd_dai_probe, }; diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c new file mode 100644 index 0000000..74769b1 --- /dev/null +++ b/sound/soc/sh/rcar/dvc.c @@ -0,0 +1,273 @@ +/* + * Renesas R-Car DVC support + * + * Copyright (C) 2014 Renesas Solutions Corp. + * Kuninori Morimoto kuninori.morimoto.gx@renesas.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "rsnd.h" + +#define RSND_DVC_NAME_SIZE 16 +#define RSND_DVC_VOLUME_MAX 100 +#define RSND_DVC_VOLUME_NUM 2 +struct rsnd_dvc { + struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ + struct rsnd_mod mod; + struct clk *clk; + long volume[RSND_DVC_VOLUME_NUM]; +}; + +#define rsnd_mod_to_dvc(_mod) \ + container_of((_mod), struct rsnd_dvc, mod) + +#define for_each_rsnd_dvc(pos, priv, i) \ + for ((i) = 0; \ + ((i) < rsnd_dvc_nr(priv)) && \ + ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \ + i++) + +static void rsnd_dvc_volume_update(struct rsnd_mod *mod) +{ + struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); + u32 max = (0x00800000 - 1); + u32 vol[RSND_DVC_VOLUME_NUM]; + int i; + + for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) + vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; + + rsnd_mod_write(mod, DVC_VOL0R, vol[0]); + rsnd_mod_write(mod, DVC_VOL1R, vol[1]); +} + +static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, + struct rsnd_dai *rdai) +{ + struct rsnd_dvc *dvc = rsnd_mod_to_dvc(dvc_mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod); + struct rsnd_priv *priv = rsnd_mod_to_priv(dvc_mod); + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + struct device *dev = rsnd_priv_to_dev(priv); + int dvc_id = rsnd_mod_id(dvc_mod); + int src_id = rsnd_mod_id(src_mod); + u32 route[] = { + [0] = 0x30000, + [1] = 0x30001, + [2] = 0x40000, + [3] = 0x10000, + [4] = 0x20000, + [5] = 0x40100 + }; + + if (src_id >= ARRAY_SIZE(route)) { + dev_err(dev, "DVC%d isn't connected to SRC%d\n", dvc_id, src_id); + return -EINVAL; + } + + clk_prepare_enable(dvc->clk); + + /* + * fixme + * it doesn't support CTU/MIX + */ + rsnd_mod_write(dvc_mod, CMD_ROUTE_SLCT, route[src_id]); + + rsnd_mod_write(dvc_mod, DVC_SWRSR, 0); + rsnd_mod_write(dvc_mod, DVC_SWRSR, 1); + + rsnd_mod_write(dvc_mod, DVC_DVUIR, 1); + + rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); + + /* enable Volume */ + rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100); + + /* ch0/ch1 Volume */ + rsnd_dvc_volume_update(dvc_mod); + + rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); + + rsnd_mod_write(dvc_mod, DVC_DVUER, 1); + + rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io); + + return 0; +} + +static int rsnd_dvc_quit(struct rsnd_mod *mod, + struct rsnd_dai *rdai) +{ + struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); + + clk_disable_unprepare(dvc->clk); + + return 0; +} + +static int rsnd_dvc_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai) +{ + rsnd_mod_write(mod, CMD_CTRL, 0x10); + + return 0; +} + +static int rsnd_dvc_stop(struct rsnd_mod *mod, + struct rsnd_dai *rdai) +{ + rsnd_mod_write(mod, CMD_CTRL, 0); + + return 0; +} + +static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = RSND_DVC_VOLUME_NUM; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; + + return 0; +} + +static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, + struct snd_ctl_elem_value *ucontrol) +{ + struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); + struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); + int i; + + for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) + ucontrol->value.integer.value[i] = dvc->volume[i]; + + return 0; +} + +static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl, + struct snd_ctl_elem_value *ucontrol) +{ + struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); + struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); + int i, change = 0; + + for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { + if (ucontrol->value.integer.value[i] < 0 || + ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX) + return -EINVAL; + + change |= (ucontrol->value.integer.value[i] != dvc->volume[i]); + } + + if (change) { + for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) + dvc->volume[i] = ucontrol->value.integer.value[i]; + + rsnd_dvc_volume_update(mod); + } + + return change; +} + +static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct snd_soc_pcm_runtime *rtd) +{ + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + struct snd_card *card = rtd->card->snd_card; + struct snd_kcontrol *kctrl; + static struct snd_kcontrol_new knew = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Playback Volume", + .info = rsnd_dvc_volume_info, + .get = rsnd_dvc_volume_get, + .put = rsnd_dvc_volume_put, + }; + int ret; + + if (!rsnd_dai_is_play(rdai, io)) { + dev_err(dev, "DVC%d is connected to Capture DAI\n", + rsnd_mod_id(mod)); + return -EINVAL; + } + + kctrl = snd_ctl_new1(&knew, mod); + if (!kctrl) + return -ENOMEM; + + ret = snd_ctl_add(card, kctrl); + if (ret < 0) + return ret; + + return 0; +} + +static struct rsnd_mod_ops rsnd_dvc_ops = { + .name = "dvc (gen2)", + .init = rsnd_dvc_init, + .quit = rsnd_dvc_quit, + .start = rsnd_dvc_start, + .stop = rsnd_dvc_stop, + .pcm_new = rsnd_dvc_pcm_new, +}; + +struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id) +{ + if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv))) + id = 0; + + return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; +} + +int rsnd_dvc_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct rcar_snd_info *info = rsnd_priv_to_info(priv); + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_dvc *dvc; + struct clk *clk; + char name[RSND_DVC_NAME_SIZE]; + int i, nr; + + nr = info->dvc_info_nr; + if (!nr) + return 0; + + /* This driver doesn't support Gen1 at this point */ + if (rsnd_is_gen1(priv)) { + dev_warn(dev, "CMD is not supported on Gen1\n"); + return -EINVAL; + } + + dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); + if (!dvc) { + dev_err(dev, "CMD allocate failed\n"); + return -ENOMEM; + } + + priv->dvc_nr = nr; + priv->dvc = dvc; + + for_each_rsnd_dvc(dvc, priv, i) { + snprintf(name, RSND_DVC_NAME_SIZE, "dvc.%d", i); + + clk = devm_clk_get(dev, name); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + dvc->info = &info->dvc_info[i]; + dvc->clk = clk; + + rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, RSND_MOD_DVC, i); + + dev_dbg(dev, "CMD%d probed\n", i); + } + + return 0; +} diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 50a1ef3..a135d4c 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -181,6 +181,8 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), + RSND_GEN2_M_REG(gen, SCU, CMD_ROUTE_SLCT, 0x18c, 0x20), + RSND_GEN2_M_REG(gen, SCU, CMD_CTRL, 0x190, 0x20), RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), @@ -189,6 +191,14 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), + RSND_GEN2_M_REG(gen, SCU, DVC_SWRSR, 0xe00, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_DVUIR, 0xe04, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_ADINR, 0xe08, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_DVUCR, 0xe10, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_ZCMCR, 0xe14, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_VOL0R, 0xe28, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_VOL1R, 0xe2c, 0x100), + RSND_GEN2_M_REG(gen, SCU, DVC_DVUER, 0xe48, 0x100),
RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), @@ -207,6 +217,7 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), + RSND_GEN2_S_REG(gen, ADG, CMDOUT_TIMSEL, 0x5c),
RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 6156cee..5aa7901 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -44,6 +44,15 @@ enum rsnd_reg { RSND_REG_SRC_IFSCR, RSND_REG_SRC_IFSVR, RSND_REG_SRC_SRCCR, + RSND_REG_CMD_ROUTE_SLCT, + RSND_REG_DVC_SWRSR, + RSND_REG_DVC_DVUIR, + RSND_REG_DVC_ADINR, + RSND_REG_DVC_DVUCR, + RSND_REG_DVC_ZCMCR, + RSND_REG_DVC_VOL0R, + RSND_REG_DVC_VOL1R, + RSND_REG_DVC_DVUER,
/* ADG */ RSND_REG_BRRA, @@ -79,6 +88,8 @@ enum rsnd_reg { RSND_REG_SHARE17, RSND_REG_SHARE18, RSND_REG_SHARE19, + RSND_REG_SHARE20, + RSND_REG_SHARE21,
RSND_REG_MAX, }; @@ -114,6 +125,8 @@ enum rsnd_reg { #define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17 #define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 +#define RSND_REG_CMD_CTRL RSND_REG_SHARE20 +#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
struct rsnd_of_data; struct rsnd_priv; @@ -166,6 +179,7 @@ void rsnd_dma_quit(struct rsnd_priv *priv, enum rsnd_mod_type { RSND_MOD_SRC = 0, RSND_MOD_SSI, + RSND_MOD_DVC, RSND_MOD_MAX, };
@@ -183,6 +197,9 @@ struct rsnd_mod_ops { struct rsnd_dai *rdai); int (*stop)(struct rsnd_mod *mod, struct rsnd_dai *rdai); + int (*pcm_new)(struct rsnd_mod *mod, + struct rsnd_dai *rdai, + struct snd_soc_pcm_runtime *rtd); };
struct rsnd_dai_stream; @@ -223,6 +240,7 @@ struct rsnd_dai_stream { }; #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) #define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) +#define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC])
struct rsnd_dai { char name[RSND_DAI_NAME_SIZE]; @@ -286,6 +304,9 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai, struct rsnd_dai_stream *io); +int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai, + struct rsnd_mod *mod, + struct rsnd_dai_stream *io);
/* * R-Car sound priv @@ -323,6 +344,12 @@ struct rsnd_priv { int ssi_nr;
/* + * below value will be filled on rsnd_dvc_probe() + */ + void *dvc; + int dvc_nr; + + /* * below value will be filled on rsnd_dai_probe() */ struct snd_soc_dai_driver *daidrv; @@ -374,4 +401,17 @@ int rsnd_ssi_probe(struct platform_device *pdev, struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
+/* + * R-Car DVC + */ +int rsnd_dvc_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv); +void rsnd_dvc_remove(struct platform_device *pdev, + struct rsnd_priv *priv); +struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id); + +#define rsnd_dvc_nr(priv) ((priv)->dvc_nr) + + #endif diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 035eda2..7da87cd 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -536,12 +536,14 @@ static int rsnd_src_init_gen2(struct rsnd_mod *mod, static int rsnd_src_start_gen2(struct rsnd_mod *mod, struct rsnd_dai *rdai) { + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct rsnd_src *src = rsnd_mod_to_src(mod); + u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11;
rsnd_dma_start(rsnd_mod_to_dma(&src->mod));
rsnd_mod_write(mod, SSI_CTRL, 0x1); - rsnd_mod_write(mod, SRC_CTRL, 0x11); + rsnd_mod_write(mod, SRC_CTRL, val);
return rsnd_src_start(mod, rdai); }
participants (2)
-
Kuninori Morimoto
-
Mark Brown