diff options
| author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2014-05-08 20:44:49 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2014-05-13 14:06:16 -0400 |
| commit | bff58ea4f43d9b4a9fd6fb05fabc8f50f68131f5 (patch) | |
| tree | 75fd6981582c0206a5152a6c9d377e3295a2eebf | |
| parent | 68b6af3656a1f3303cca094a19e26653fad1853a (diff) | |
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>
| -rw-r--r-- | include/sound/rcar_snd.h | 10 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/Makefile | 2 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/adg.c | 18 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/core.c | 20 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/dvc.c | 273 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/gen.c | 11 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 40 | ||||
| -rw-r--r-- | sound/soc/sh/rcar/src.c | 4 |
8 files changed, 376 insertions, 2 deletions
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 { | |||
| 56 | int dma_id; /* for Gen2 SCU */ | 56 | int dma_id; /* for Gen2 SCU */ |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | /* | ||
| 60 | * flags | ||
| 61 | */ | ||
| 62 | struct rsnd_dvc_platform_info { | ||
| 63 | u32 flags; | ||
| 64 | }; | ||
| 65 | |||
| 59 | struct rsnd_dai_path_info { | 66 | struct rsnd_dai_path_info { |
| 60 | struct rsnd_ssi_platform_info *ssi; | 67 | struct rsnd_ssi_platform_info *ssi; |
| 61 | struct rsnd_src_platform_info *src; | 68 | struct rsnd_src_platform_info *src; |
| 69 | struct rsnd_dvc_platform_info *dvc; | ||
| 62 | }; | 70 | }; |
| 63 | 71 | ||
| 64 | struct rsnd_dai_platform_info { | 72 | struct rsnd_dai_platform_info { |
| @@ -83,6 +91,8 @@ struct rcar_snd_info { | |||
| 83 | int ssi_info_nr; | 91 | int ssi_info_nr; |
| 84 | struct rsnd_src_platform_info *src_info; | 92 | struct rsnd_src_platform_info *src_info; |
| 85 | int src_info_nr; | 93 | int src_info_nr; |
| 94 | struct rsnd_dvc_platform_info *dvc_info; | ||
| 95 | int dvc_info_nr; | ||
| 86 | struct rsnd_dai_platform_info *dai_info; | 96 | struct rsnd_dai_platform_info *dai_info; |
| 87 | int dai_info_nr; | 97 | int dai_info_nr; |
| 88 | int (*start)(int id); | 98 | 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 @@ | |||
| 1 | snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o | 1 | snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o dvc.o |
| 2 | obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file | 2 | 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) | |||
| 57 | return (0x6 + ws) << 8; | 57 | return (0x6 + ws) << 8; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai, | ||
| 61 | struct rsnd_mod *mod, | ||
| 62 | struct rsnd_dai_stream *io) | ||
| 63 | { | ||
| 64 | int id = rsnd_mod_id(mod); | ||
| 65 | int shift = (id % 2) ? 16 : 0; | ||
| 66 | u32 mask, val; | ||
| 67 | |||
| 68 | val = rsnd_adg_ssi_ws_timing_gen2(io); | ||
| 69 | |||
| 70 | val = val << shift; | ||
| 71 | mask = 0xffff << shift; | ||
| 72 | |||
| 73 | rsnd_mod_bset(mod, CMDOUT_TIMSEL, mask, val); | ||
| 74 | |||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 60 | static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, | 78 | static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, |
| 61 | struct rsnd_mod *mod, | 79 | struct rsnd_mod *mod, |
| 62 | struct rsnd_dai_stream *io, | 80 | struct rsnd_dai_stream *io, |
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 378985b028ef..1f6981a56354 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, | |||
| 645 | if (ret < 0) | 645 | if (ret < 0) |
| 646 | return ret; | 646 | return ret; |
| 647 | 647 | ||
| 648 | /* DVC */ | ||
| 649 | ret = rsnd_path_parse(priv, io, dvc); | ||
| 650 | if (ret < 0) | ||
| 651 | return ret; | ||
| 652 | |||
| 648 | return ret; | 653 | return ret; |
| 649 | } | 654 | } |
| 650 | 655 | ||
| @@ -869,6 +874,20 @@ static struct snd_pcm_ops rsnd_pcm_ops = { | |||
| 869 | 874 | ||
| 870 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | 875 | static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) |
| 871 | { | 876 | { |
| 877 | struct rsnd_priv *priv = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
| 878 | struct rsnd_dai *rdai; | ||
| 879 | int i, ret; | ||
| 880 | |||
| 881 | for_each_rsnd_dai(rdai, priv, i) { | ||
| 882 | ret = rsnd_dai_call(pcm_new, &rdai->playback, rdai, rtd); | ||
| 883 | if (ret) | ||
| 884 | return ret; | ||
| 885 | |||
| 886 | ret = rsnd_dai_call(pcm_new, &rdai->capture, rdai, rtd); | ||
| 887 | if (ret) | ||
| 888 | return ret; | ||
| 889 | } | ||
| 890 | |||
| 872 | return snd_pcm_lib_preallocate_pages_for_all( | 891 | return snd_pcm_lib_preallocate_pages_for_all( |
| 873 | rtd->pcm, | 892 | rtd->pcm, |
| 874 | SNDRV_DMA_TYPE_DEV, | 893 | SNDRV_DMA_TYPE_DEV, |
| @@ -908,6 +927,7 @@ static int rsnd_probe(struct platform_device *pdev) | |||
| 908 | rsnd_gen_probe, | 927 | rsnd_gen_probe, |
| 909 | rsnd_ssi_probe, | 928 | rsnd_ssi_probe, |
| 910 | rsnd_src_probe, | 929 | rsnd_src_probe, |
| 930 | rsnd_dvc_probe, | ||
| 911 | rsnd_adg_probe, | 931 | rsnd_adg_probe, |
| 912 | rsnd_dai_probe, | 932 | rsnd_dai_probe, |
| 913 | }; | 933 | }; |
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 @@ | |||
| 1 | /* | ||
| 2 | * Renesas R-Car DVC support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Renesas Solutions Corp. | ||
| 5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | #include "rsnd.h" | ||
| 12 | |||
| 13 | #define RSND_DVC_NAME_SIZE 16 | ||
| 14 | #define RSND_DVC_VOLUME_MAX 100 | ||
| 15 | #define RSND_DVC_VOLUME_NUM 2 | ||
| 16 | struct rsnd_dvc { | ||
| 17 | struct rsnd_dvc_platform_info *info; /* rcar_snd.h */ | ||
| 18 | struct rsnd_mod mod; | ||
| 19 | struct clk *clk; | ||
| 20 | long volume[RSND_DVC_VOLUME_NUM]; | ||
| 21 | }; | ||
| 22 | |||
| 23 | #define rsnd_mod_to_dvc(_mod) \ | ||
| 24 | container_of((_mod), struct rsnd_dvc, mod) | ||
| 25 | |||
| 26 | #define for_each_rsnd_dvc(pos, priv, i) \ | ||
| 27 | for ((i) = 0; \ | ||
| 28 | ((i) < rsnd_dvc_nr(priv)) && \ | ||
| 29 | ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \ | ||
| 30 | i++) | ||
| 31 | |||
| 32 | static void rsnd_dvc_volume_update(struct rsnd_mod *mod) | ||
| 33 | { | ||
| 34 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
| 35 | u32 max = (0x00800000 - 1); | ||
| 36 | u32 vol[RSND_DVC_VOLUME_NUM]; | ||
| 37 | int i; | ||
| 38 | |||
| 39 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | ||
| 40 | vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; | ||
| 41 | |||
| 42 | rsnd_mod_write(mod, DVC_VOL0R, vol[0]); | ||
| 43 | rsnd_mod_write(mod, DVC_VOL1R, vol[1]); | ||
| 44 | } | ||
| 45 | |||
| 46 | static int rsnd_dvc_init(struct rsnd_mod *dvc_mod, | ||
| 47 | struct rsnd_dai *rdai) | ||
| 48 | { | ||
| 49 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(dvc_mod); | ||
| 50 | struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod); | ||
| 51 | struct rsnd_priv *priv = rsnd_mod_to_priv(dvc_mod); | ||
| 52 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | ||
| 53 | struct device *dev = rsnd_priv_to_dev(priv); | ||
| 54 | int dvc_id = rsnd_mod_id(dvc_mod); | ||
| 55 | int src_id = rsnd_mod_id(src_mod); | ||
| 56 | u32 route[] = { | ||
| 57 | [0] = 0x30000, | ||
| 58 | [1] = 0x30001, | ||
| 59 | [2] = 0x40000, | ||
| 60 | [3] = 0x10000, | ||
| 61 | [4] = 0x20000, | ||
| 62 | [5] = 0x40100 | ||
| 63 | }; | ||
| 64 | |||
| 65 | if (src_id >= ARRAY_SIZE(route)) { | ||
| 66 | dev_err(dev, "DVC%d isn't connected to SRC%d\n", dvc_id, src_id); | ||
| 67 | return -EINVAL; | ||
| 68 | } | ||
