1
2
3
4
5
6
7#include "rsnd.h"
8
9#define CTU_NAME_SIZE 16
10#define CTU_NAME "ctu"
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72struct rsnd_ctu {
73 struct rsnd_mod mod;
74 struct rsnd_kctrl_cfg_m pass;
75 struct rsnd_kctrl_cfg_m sv[4];
76 struct rsnd_kctrl_cfg_s reset;
77 int channels;
78 u32 flags;
79};
80
81#define KCTRL_INITIALIZED (1 << 0)
82
83#define rsnd_ctu_nr(priv) ((priv)->ctu_nr)
84#define for_each_rsnd_ctu(pos, priv, i) \
85 for ((i) = 0; \
86 ((i) < rsnd_ctu_nr(priv)) && \
87 ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \
88 i++)
89
90#define rsnd_mod_to_ctu(_mod) \
91 container_of((_mod), struct rsnd_ctu, mod)
92
93#define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
94
95static void rsnd_ctu_activation(struct rsnd_mod *mod)
96{
97 rsnd_mod_write(mod, CTU_SWRSR, 0);
98 rsnd_mod_write(mod, CTU_SWRSR, 1);
99}
100
101static void rsnd_ctu_halt(struct rsnd_mod *mod)
102{
103 rsnd_mod_write(mod, CTU_CTUIR, 1);
104 rsnd_mod_write(mod, CTU_SWRSR, 0);
105}
106
107static int rsnd_ctu_probe_(struct rsnd_mod *mod,
108 struct rsnd_dai_stream *io,
109 struct rsnd_priv *priv)
110{
111 return rsnd_cmd_attach(io, rsnd_mod_id(mod));
112}
113
114static void rsnd_ctu_value_init(struct rsnd_dai_stream *io,
115 struct rsnd_mod *mod)
116{
117 struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
118 u32 cpmdr = 0;
119 u32 scmdr = 0;
120 int i, j;
121
122 for (i = 0; i < RSND_MAX_CHANNELS; i++) {
123 u32 val = rsnd_kctrl_valm(ctu->pass, i);
124
125 cpmdr |= val << (28 - (i * 4));
126
127 if ((val > 0x8) && (scmdr < (val - 0x8)))
128 scmdr = val - 0x8;
129 }
130
131 rsnd_mod_write(mod, CTU_CTUIR, 1);
132
133 rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
134
135 rsnd_mod_write(mod, CTU_CPMDR, cpmdr);
136
137 rsnd_mod_write(mod, CTU_SCMDR, scmdr);
138
139 for (i = 0; i < 4; i++) {
140
141 if (i >= scmdr)
142 break;
143
144 for (j = 0; j < RSND_MAX_CHANNELS; j++)
145 rsnd_mod_write(mod, CTU_SVxxR(i, j), rsnd_kctrl_valm(ctu->sv[i], j));
146 }
147
148 rsnd_mod_write(mod, CTU_CTUIR, 0);
149}
150
151static void rsnd_ctu_value_reset(struct rsnd_dai_stream *io,
152 struct rsnd_mod *mod)
153{
154 struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
155 int i;
156
157 if (!rsnd_kctrl_vals(ctu->reset))
158 return;
159
160 for (i = 0; i < RSND_MAX_CHANNELS; i++) {
161 rsnd_kctrl_valm(ctu->pass, i) = 0;
162 rsnd_kctrl_valm(ctu->sv[0], i) = 0;
163 rsnd_kctrl_valm(ctu->sv[1], i) = 0;
164 rsnd_kctrl_valm(ctu->sv[2], i) = 0;
165 rsnd_kctrl_valm(ctu->sv[3], i) = 0;
166 }
167 rsnd_kctrl_vals(ctu->reset) = 0;
168}
169
170static int rsnd_ctu_init(struct rsnd_mod *mod,
171 struct rsnd_dai_stream *io,
172 struct rsnd_priv *priv)
173{
174 rsnd_mod_power_on(mod);
175
176 rsnd_ctu_activation(mod);
177
178 rsnd_ctu_value_init(io, mod);
179
180 return 0;
181}
182
183static int rsnd_ctu_quit(struct rsnd_mod *mod,
184 struct rsnd_dai_stream *io,
185 struct rsnd_priv *priv)
186{
187 rsnd_ctu_halt(mod);
188
189 rsnd_mod_power_off(mod);
190
191 return 0;
192}
193
194static int rsnd_ctu_pcm_new(struct rsnd_mod *mod,
195 struct rsnd_dai_stream *io,
196 struct snd_soc_pcm_runtime *rtd)
197{
198 struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
199 int ret;
200
201 if (rsnd_flags_has(ctu, KCTRL_INITIALIZED))
202 return 0;
203
204
205 ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass",
206 rsnd_kctrl_accept_anytime,
207 NULL,
208 &ctu->pass, RSND_MAX_CHANNELS,
209 0xC);
210 if (ret < 0)
211 return ret;
212
213
214 ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0",
215 rsnd_kctrl_accept_anytime,
216 NULL,
217 &ctu->sv[0], RSND_MAX_CHANNELS,
218 0x00FFFFFF);
219 if (ret < 0)
220 return ret;
221
222
223 ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1",
224 rsnd_kctrl_accept_anytime,
225 NULL,
226 &ctu->sv[1], RSND_MAX_CHANNELS,
227 0x00FFFFFF);
228 if (ret < 0)
229 return ret;
230
231
232 ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2",
233 rsnd_kctrl_accept_anytime,
234 NULL,
235 &ctu->sv[2], RSND_MAX_CHANNELS,
236 0x00FFFFFF);
237 if (ret < 0)
238 return ret;
239
240
241 ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3",
242 rsnd_kctrl_accept_anytime,
243 NULL,
244 &ctu->sv[3], RSND_MAX_CHANNELS,
245 0x00FFFFFF);
246 if (ret < 0)
247 return ret;
248
249
250 ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset",
251 rsnd_kctrl_accept_anytime,
252 rsnd_ctu_value_reset,
253 &ctu->reset, 1);
254
255 rsnd_flags_set(ctu, KCTRL_INITIALIZED);
256
257 return ret;
258}
259
260static int rsnd_ctu_id(struct rsnd_mod *mod)
261{
262
263
264
265
266 return mod->id / 4;
267}
268
269static int rsnd_ctu_id_sub(struct rsnd_mod *mod)
270{
271
272
273
274
275 return mod->id % 4;
276}
277
278#ifdef CONFIG_DEBUG_FS
279static void rsnd_ctu_debug_info(struct seq_file *m,
280 struct rsnd_dai_stream *io,
281 struct rsnd_mod *mod)
282{
283 rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU,
284 0x500 + rsnd_mod_id_raw(mod) * 0x100, 0x100);
285}
286#define DEBUG_INFO .debug_info = rsnd_ctu_debug_info
287#else
288#define DEBUG_INFO
289#endif
290
291static struct rsnd_mod_ops rsnd_ctu_ops = {
292 .name = CTU_NAME,
293 .probe = rsnd_ctu_probe_,
294 .init = rsnd_ctu_init,
295 .quit = rsnd_ctu_quit,
296 .pcm_new = rsnd_ctu_pcm_new,
297 .get_status = rsnd_mod_get_status,
298 .id = rsnd_ctu_id,
299 .id_sub = rsnd_ctu_id_sub,
300 .id_cmd = rsnd_mod_id_raw,
301 DEBUG_INFO
302};
303
304struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
305{
306 if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
307 id = 0;
308
309 return rsnd_mod_get(rsnd_ctu_get(priv, id));
310}
311
312int rsnd_ctu_probe(struct rsnd_priv *priv)
313{
314 struct device_node *node;
315 struct device_node *np;
316 struct device *dev = rsnd_priv_to_dev(priv);
317 struct rsnd_ctu *ctu;
318 struct clk *clk;
319 char name[CTU_NAME_SIZE];
320 int i, nr, ret;
321
322
323 if (rsnd_is_gen1(priv))
324 return 0;
325
326 node = rsnd_ctu_of_node(priv);
327 if (!node)
328 return 0;
329
330 nr = of_get_child_count(node);
331 if (!nr) {
332 ret = -EINVAL;
333 goto rsnd_ctu_probe_done;
334 }
335
336 ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL);
337 if (!ctu) {
338 ret = -ENOMEM;
339 goto rsnd_ctu_probe_done;
340 }
341
342 priv->ctu_nr = nr;
343 priv->ctu = ctu;
344
345 i = 0;
346 ret = 0;
347 for_each_child_of_node(node, np) {
348 ctu = rsnd_ctu_get(priv, i);
349
350
351
352
353
354 snprintf(name, CTU_NAME_SIZE, "%s.%d",
355 CTU_NAME, i / 4);
356
357 clk = devm_clk_get(dev, name);
358 if (IS_ERR(clk)) {
359 ret = PTR_ERR(clk);
360 of_node_put(np);
361 goto rsnd_ctu_probe_done;
362 }
363
364 ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
365 clk, RSND_MOD_CTU, i);
366 if (ret) {
367 of_node_put(np);
368 goto rsnd_ctu_probe_done;
369 }
370
371 i++;
372 }
373
374
375rsnd_ctu_probe_done:
376 of_node_put(node);
377
378 return ret;
379}
380
381void rsnd_ctu_remove(struct rsnd_priv *priv)
382{
383 struct rsnd_ctu *ctu;
384 int i;
385
386 for_each_rsnd_ctu(ctu, priv, i) {
387 rsnd_mod_quit(rsnd_mod_get(ctu));
388 }
389}
390