| From 46c96710342f4fef77b84a22c0c16816b0ab5a5e Mon Sep 17 00:00:00 2001 |
| From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Date: Thu, 8 May 2014 17:44:49 -0700 |
| Subject: ASoC: rsnd: add DVC support |
| |
| This patch adds DVC (Digital Volume Controller) |
| support which is member of CMD unit. |
| |
| Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Signed-off-by: Mark Brown <broonie@linaro.org> |
| (cherry picked from commit bff58ea4f43d9b4a9fd6fb05fabc8f50f68131f5) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| 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 a03268ec59c3..f4a706f82cb7 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 7d0051ced838..9ac536429800 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 41556b2ef21e..fc41a0e8b09f 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 1f34cd4e949d..964463dada87 100644 |
| --- a/sound/soc/sh/rcar/core.c |
| +++ b/sound/soc/sh/rcar/core.c |
| @@ -644,6 +644,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; |
| } |
| |
| @@ -868,6 +873,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, |
| @@ -907,6 +926,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 000000000000..74769b1be005 |
| --- /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 50a1ef3eb1c6..a135d4c9d080 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 6156ceebd58b..5aa790170b01 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 2a0f7e63ffc8..e3b078e7c3aa 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); |
| } |
| -- |
| 2.1.2 |
| |