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 /sound/soc/sh | |
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>
Diffstat (limited to 'sound/soc/sh')
-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 |
7 files changed, 366 insertions, 2 deletions
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 | } | ||
69 | |||
70 | clk_prepare_enable(dvc->clk); | ||
71 | |||
72 | /* | ||
73 | * fixme | ||
74 | * it doesn't support CTU/MIX | ||
75 | */ | ||
76 | rsnd_mod_write(dvc_mod, CMD_ROUTE_SLCT, route[src_id]); | ||
77 | |||
78 | rsnd_mod_write(dvc_mod, DVC_SWRSR, 0); | ||
79 | rsnd_mod_write(dvc_mod, DVC_SWRSR, 1); | ||
80 | |||
81 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 1); | ||
82 | |||
83 | rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); | ||
84 | |||
85 | /* enable Volume */ | ||
86 | rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100); | ||
87 | |||
88 | /* ch0/ch1 Volume */ | ||
89 | rsnd_dvc_volume_update(dvc_mod); | ||
90 | |||
91 | rsnd_mod_write(dvc_mod, DVC_DVUIR, 0); | ||
92 | |||
93 | rsnd_mod_write(dvc_mod, DVC_DVUER, 1); | ||
94 | |||
95 | rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int rsnd_dvc_quit(struct rsnd_mod *mod, | ||
101 | struct rsnd_dai *rdai) | ||
102 | { | ||
103 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
104 | |||
105 | clk_disable_unprepare(dvc->clk); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int rsnd_dvc_start(struct rsnd_mod *mod, | ||
111 | struct rsnd_dai *rdai) | ||
112 | { | ||
113 | rsnd_mod_write(mod, CMD_CTRL, 0x10); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int rsnd_dvc_stop(struct rsnd_mod *mod, | ||
119 | struct rsnd_dai *rdai) | ||
120 | { | ||
121 | rsnd_mod_write(mod, CMD_CTRL, 0); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | ||
127 | struct snd_ctl_elem_info *uinfo) | ||
128 | { | ||
129 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
130 | uinfo->count = RSND_DVC_VOLUME_NUM; | ||
131 | uinfo->value.integer.min = 0; | ||
132 | uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl, | ||
138 | struct snd_ctl_elem_value *ucontrol) | ||
139 | { | ||
140 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | ||
141 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
142 | int i; | ||
143 | |||
144 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | ||
145 | ucontrol->value.integer.value[i] = dvc->volume[i]; | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl, | ||
151 | struct snd_ctl_elem_value *ucontrol) | ||
152 | { | ||
153 | struct rsnd_mod *mod = snd_kcontrol_chip(kctrl); | ||
154 | struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); | ||
155 | int i, change = 0; | ||
156 | |||
157 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) { | ||
158 | if (ucontrol->value.integer.value[i] < 0 || | ||
159 | ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX) | ||
160 | return -EINVAL; | ||
161 | |||
162 | change |= (ucontrol->value.integer.value[i] != dvc->volume[i]); | ||
163 | } | ||
164 | |||
165 | if (change) { | ||
166 | for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) | ||
167 | dvc->volume[i] = ucontrol->value.integer.value[i]; | ||
168 | |||
169 | rsnd_dvc_volume_update(mod); | ||
170 | } | ||
171 | |||
172 | return change; | ||
173 | } | ||
174 | |||
175 | static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | ||
176 | struct rsnd_dai *rdai, | ||
177 | struct snd_soc_pcm_runtime *rtd) | ||
178 | { | ||
179 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
180 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
181 | struct device *dev = rsnd_priv_to_dev(priv); | ||
182 | struct snd_card *card = rtd->card->snd_card; | ||
183 | struct snd_kcontrol *kctrl; | ||
184 | static struct snd_kcontrol_new knew = { | ||
185 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
186 | .name = "Playback Volume", | ||
187 | .info = rsnd_dvc_volume_info, | ||
188 | .get = rsnd_dvc_volume_get, | ||
189 | .put = rsnd_dvc_volume_put, | ||
190 | }; | ||
191 | int ret; | ||
192 | |||
193 | if (!rsnd_dai_is_play(rdai, io)) { | ||
194 | dev_err(dev, "DVC%d is connected to Capture DAI\n", | ||
195 | rsnd_mod_id(mod)); | ||
196 | return -EINVAL; | ||
197 | } | ||
198 | |||
199 | kctrl = snd_ctl_new1(&knew, mod); | ||
200 | if (!kctrl) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | ret = snd_ctl_add(card, kctrl); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static struct rsnd_mod_ops rsnd_dvc_ops = { | ||
211 | .name = "dvc (gen2)", | ||
212 | .init = rsnd_dvc_init, | ||
213 | .quit = rsnd_dvc_quit, | ||
214 | .start = rsnd_dvc_start, | ||
215 | .stop = rsnd_dvc_stop, | ||
216 | .pcm_new = rsnd_dvc_pcm_new, | ||
217 | }; | ||
218 | |||
219 | struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id) | ||
220 | { | ||
221 | if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv))) | ||
222 | id = 0; | ||
223 | |||
224 | return &((struct rsnd_dvc *)(priv->dvc) + id)->mod; | ||
225 | } | ||
226 | |||
227 | int rsnd_dvc_probe(struct platform_device *pdev, | ||
228 | const struct rsnd_of_data *of_data, | ||
229 | struct rsnd_priv *priv) | ||
230 | { | ||
231 | struct rcar_snd_info *info = rsnd_priv_to_info(priv); | ||
232 | struct device *dev = rsnd_priv_to_dev(priv); | ||
233 | struct rsnd_dvc *dvc; | ||
234 | struct clk *clk; | ||
235 | char name[RSND_DVC_NAME_SIZE]; | ||
236 | int i, nr; | ||
237 | |||
238 | nr = info->dvc_info_nr; | ||
239 | if (!nr) | ||
240 | return 0; | ||
241 | |||
242 | /* This driver doesn't support Gen1 at this point */ | ||
243 | if (rsnd_is_gen1(priv)) { | ||
244 | dev_warn(dev, "CMD is not supported on Gen1\n"); | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | |||
248 | dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL); | ||
249 | if (!dvc) { | ||
250 | dev_err(dev, "CMD allocate failed\n"); | ||
251 | return -ENOMEM; | ||
252 | } | ||
253 | |||
254 | priv->dvc_nr = nr; | ||
255 | priv->dvc = dvc; | ||
256 | |||
257 | for_each_rsnd_dvc(dvc, priv, i) { | ||
258 | snprintf(name, RSND_DVC_NAME_SIZE, "dvc.%d", i); | ||
259 | |||
260 | clk = devm_clk_get(dev, name); | ||
261 | if (IS_ERR(clk)) | ||
262 | return PTR_ERR(clk); | ||
263 | |||
264 | dvc->info = &info->dvc_info[i]; | ||
265 | dvc->clk = clk; | ||
266 | |||
267 | rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, RSND_MOD_DVC, i); | ||
268 | |||
269 | dev_dbg(dev, "CMD%d probed\n", i); | ||
270 | } | ||
271 | |||
272 | return 0; | ||
273 | } | ||
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) | |||
181 | RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), | 181 | RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), |
182 | RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), | 182 | RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), |
183 | RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), | 183 | RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), |
184 | RSND_GEN2_M_REG(gen, SCU, CMD_ROUTE_SLCT, 0x18c, 0x20), | ||
185 | RSND_GEN2_M_REG(gen, SCU, CMD_CTRL, 0x190, 0x20), | ||
184 | RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), | 186 | RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), |
185 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), | 187 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), |
186 | RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), | 188 | 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) | |||
189 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), | 191 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), |
190 | RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), | 192 | RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), |
191 | RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), | 193 | RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), |
194 | RSND_GEN2_M_REG(gen, SCU, DVC_SWRSR, 0xe00, 0x100), | ||
195 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUIR, 0xe04, 0x100), | ||
196 | RSND_GEN2_M_REG(gen, SCU, DVC_ADINR, 0xe08, 0x100), | ||
197 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUCR, 0xe10, 0x100), | ||
198 | RSND_GEN2_M_REG(gen, SCU, DVC_ZCMCR, 0xe14, 0x100), | ||
199 | RSND_GEN2_M_REG(gen, SCU, DVC_VOL0R, 0xe28, 0x100), | ||
200 | RSND_GEN2_M_REG(gen, SCU, DVC_VOL1R, 0xe2c, 0x100), | ||
201 | RSND_GEN2_M_REG(gen, SCU, DVC_DVUER, 0xe48, 0x100), | ||
192 | 202 | ||
193 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), | 203 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), |
194 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), | 204 | 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) | |||
207 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), | 217 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), |
208 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), | 218 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), |
209 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), | 219 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), |
220 | RSND_GEN2_S_REG(gen, ADG, CMDOUT_TIMSEL, 0x5c), | ||
210 | 221 | ||
211 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), | 222 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), |
212 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), | 223 | 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 { | |||
44 | RSND_REG_SRC_IFSCR, | 44 | RSND_REG_SRC_IFSCR, |
45 | RSND_REG_SRC_IFSVR, | 45 | RSND_REG_SRC_IFSVR, |
46 | RSND_REG_SRC_SRCCR, | 46 | RSND_REG_SRC_SRCCR, |
47 | RSND_REG_CMD_ROUTE_SLCT, | ||
48 | RSND_REG_DVC_SWRSR, | ||
49 | RSND_REG_DVC_DVUIR, | ||
50 | RSND_REG_DVC_ADINR, | ||
51 | RSND_REG_DVC_DVUCR, | ||
52 | RSND_REG_DVC_ZCMCR, | ||
53 | RSND_REG_DVC_VOL0R, | ||
54 | RSND_REG_DVC_VOL1R, | ||
55 | RSND_REG_DVC_DVUER, | ||
47 | 56 | ||
48 | /* ADG */ | 57 | /* ADG */ |
49 | RSND_REG_BRRA, | 58 | RSND_REG_BRRA, |
@@ -79,6 +88,8 @@ enum rsnd_reg { | |||
79 | RSND_REG_SHARE17, | 88 | RSND_REG_SHARE17, |
80 | RSND_REG_SHARE18, | 89 | RSND_REG_SHARE18, |
81 | RSND_REG_SHARE19, | 90 | RSND_REG_SHARE19, |
91 | RSND_REG_SHARE20, | ||
92 | RSND_REG_SHARE21, | ||
82 | 93 | ||
83 | RSND_REG_MAX, | 94 | RSND_REG_MAX, |
84 | }; | 95 | }; |
@@ -114,6 +125,8 @@ enum rsnd_reg { | |||
114 | #define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17 | 125 | #define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17 |
115 | #define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 | 126 | #define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18 |
116 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 | 127 | #define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19 |
128 | #define RSND_REG_CMD_CTRL RSND_REG_SHARE20 | ||
129 | #define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21 | ||
117 | 130 | ||
118 | struct rsnd_of_data; | 131 | struct rsnd_of_data; |
119 | struct rsnd_priv; | 132 | struct rsnd_priv; |
@@ -166,6 +179,7 @@ void rsnd_dma_quit(struct rsnd_priv *priv, | |||
166 | enum rsnd_mod_type { | 179 | enum rsnd_mod_type { |
167 | RSND_MOD_SRC = 0, | 180 | RSND_MOD_SRC = 0, |
168 | RSND_MOD_SSI, | 181 | RSND_MOD_SSI, |
182 | RSND_MOD_DVC, | ||
169 | RSND_MOD_MAX, | 183 | RSND_MOD_MAX, |
170 | }; | 184 | }; |
171 | 185 | ||
@@ -183,6 +197,9 @@ struct rsnd_mod_ops { | |||
183 | struct rsnd_dai *rdai); | 197 | struct rsnd_dai *rdai); |
184 | int (*stop)(struct rsnd_mod *mod, | 198 | int (*stop)(struct rsnd_mod *mod, |
185 | struct rsnd_dai *rdai); | 199 | struct rsnd_dai *rdai); |
200 | int (*pcm_new)(struct rsnd_mod *mod, | ||
201 | struct rsnd_dai *rdai, | ||
202 | struct snd_soc_pcm_runtime *rtd); | ||
186 | }; | 203 | }; |
187 | 204 | ||
188 | struct rsnd_dai_stream; | 205 | struct rsnd_dai_stream; |
@@ -223,6 +240,7 @@ struct rsnd_dai_stream { | |||
223 | }; | 240 | }; |
224 | #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) | 241 | #define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI]) |
225 | #define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) | 242 | #define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC]) |
243 | #define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC]) | ||
226 | 244 | ||
227 | struct rsnd_dai { | 245 | struct rsnd_dai { |
228 | char name[RSND_DAI_NAME_SIZE]; | 246 | char name[RSND_DAI_NAME_SIZE]; |
@@ -286,6 +304,9 @@ int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | |||
286 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, | 304 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, |
287 | struct rsnd_dai *rdai, | 305 | struct rsnd_dai *rdai, |
288 | struct rsnd_dai_stream *io); | 306 | struct rsnd_dai_stream *io); |
307 | int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_dai *rdai, | ||
308 | struct rsnd_mod *mod, | ||
309 | struct rsnd_dai_stream *io); | ||
289 | 310 | ||
290 | /* | 311 | /* |
291 | * R-Car sound priv | 312 | * R-Car sound priv |
@@ -323,6 +344,12 @@ struct rsnd_priv { | |||
323 | int ssi_nr; | 344 | int ssi_nr; |
324 | 345 | ||
325 | /* | 346 | /* |
347 | * below value will be filled on rsnd_dvc_probe() | ||
348 | */ | ||
349 | void *dvc; | ||
350 | int dvc_nr; | ||
351 | |||
352 | /* | ||
326 | * below value will be filled on rsnd_dai_probe() | 353 | * below value will be filled on rsnd_dai_probe() |
327 | */ | 354 | */ |
328 | struct snd_soc_dai_driver *daidrv; | 355 | struct snd_soc_dai_driver *daidrv; |
@@ -374,4 +401,17 @@ int rsnd_ssi_probe(struct platform_device *pdev, | |||
374 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); | 401 | struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); |
375 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); | 402 | int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); |
376 | 403 | ||
404 | /* | ||
405 | * R-Car DVC | ||
406 | */ | ||
407 | int rsnd_dvc_probe(struct platform_device *pdev, | ||
408 | const struct rsnd_of_data *of_data, | ||
409 | struct rsnd_priv *priv); | ||
410 | void rsnd_dvc_remove(struct platform_device *pdev, | ||
411 | struct rsnd_priv *priv); | ||
412 | struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id); | ||
413 | |||
414 | #define rsnd_dvc_nr(priv) ((priv)->dvc_nr) | ||
415 | |||
416 | |||
377 | #endif | 417 | #endif |
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 035eda2de239..7da87cde0bc3 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, | |||
536 | static int rsnd_src_start_gen2(struct rsnd_mod *mod, | 536 | static int rsnd_src_start_gen2(struct rsnd_mod *mod, |
537 | struct rsnd_dai *rdai) | 537 | struct rsnd_dai *rdai) |
538 | { | 538 | { |
539 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | ||
539 | struct rsnd_src *src = rsnd_mod_to_src(mod); | 540 | struct rsnd_src *src = rsnd_mod_to_src(mod); |
541 | u32 val = rsnd_io_to_mod_dvc(io) ? 0x01 : 0x11; | ||
540 | 542 | ||
541 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); | 543 | rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); |
542 | 544 | ||
543 | rsnd_mod_write(mod, SSI_CTRL, 0x1); | 545 | rsnd_mod_write(mod, SSI_CTRL, 0x1); |
544 | rsnd_mod_write(mod, SRC_CTRL, 0x11); | 546 | rsnd_mod_write(mod, SRC_CTRL, val); |
545 | 547 | ||
546 | return rsnd_src_start(mod, rdai); | 548 | return rsnd_src_start(mod, rdai); |
547 | } | 549 | } |