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
278static struct rsnd_mod_ops rsnd_ctu_ops = {
279 .name = CTU_NAME,
280 .probe = rsnd_ctu_probe_,
281 .init = rsnd_ctu_init,
282 .quit = rsnd_ctu_quit,
283 .pcm_new = rsnd_ctu_pcm_new,
284 .get_status = rsnd_mod_get_status,
285 .id = rsnd_ctu_id,
286 .id_sub = rsnd_ctu_id_sub,
287 .id_cmd = rsnd_mod_id_raw,
288};
289
290struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
291{
292 if (WARN_ON(id < 0 || id >= rsnd_ctu_nr(priv)))
293 id = 0;
294
295 return rsnd_mod_get(rsnd_ctu_get(priv, id));
296}
297
298int rsnd_ctu_probe(struct rsnd_priv *priv)
299{
300 struct device_node *node;
301 struct device_node *np;
302 struct device *dev = rsnd_priv_to_dev(priv);
303 struct rsnd_ctu *ctu;
304 struct clk *clk;
305 char name[CTU_NAME_SIZE];
306 int i, nr, ret;
307
308
309 if (rsnd_is_gen1(priv))
310 return 0;
311
312 node = rsnd_ctu_of_node(priv);
313 if (!node)
314 return 0;
315
316 nr = of_get_child_count(node);
317 if (!nr) {
318 ret = -EINVAL;
319 goto rsnd_ctu_probe_done;
320 }
321
322 ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL);
323 if (!ctu) {
324 ret = -ENOMEM;
325 goto rsnd_ctu_probe_done;
326 }
327
328 priv->ctu_nr = nr;
329 priv->ctu = ctu;
330
331 i = 0;
332 ret = 0;
333 for_each_child_of_node(node, np) {
334 ctu = rsnd_ctu_get(priv, i);
335
336
337
338
339
340 snprintf(name, CTU_NAME_SIZE, "%s.%d",
341 CTU_NAME, i / 4);
342
343 clk = devm_clk_get(dev, name);
344 if (IS_ERR(clk)) {
345 ret = PTR_ERR(clk);
346 of_node_put(np);
347 goto rsnd_ctu_probe_done;
348 }
349
350 ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
351 clk, RSND_MOD_CTU, i);
352 if (ret) {
353 of_node_put(np);
354 goto rsnd_ctu_probe_done;
355 }
356
357 i++;
358 }
359
360
361rsnd_ctu_probe_done:
362 of_node_put(node);
363
364 return ret;
365}
366
367void rsnd_ctu_remove(struct rsnd_priv *priv)
368{
369 struct rsnd_ctu *ctu;
370 int i;
371
372 for_each_rsnd_ctu(ctu, priv, i) {
373 rsnd_mod_quit(rsnd_mod_get(ctu));
374 }
375}
376