ASoC: rcar ctu: Staticise local symbols
[linux-2.6-block.git] / sound / soc / sh / rcar / dma.c
CommitLineData
bfe834be
KM
1/*
2 * Renesas R-Car Audio DMAC support
3 *
4 * Copyright (C) 2015 Renesas Electronics Corp.
5 * Copyright (c) 2015 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 */
288f392e 11#include <linux/delay.h>
72adc61f 12#include <linux/of_dma.h>
bfe834be
KM
13#include "rsnd.h"
14
288f392e
KM
15/*
16 * Audio DMAC peri peri register
17 */
18#define PDMASAR 0x00
19#define PDMADAR 0x04
20#define PDMACHCR 0x0c
21
22/* PDMACHCR */
23#define PDMACHCR_DE (1 << 0)
24
25struct rsnd_dma_ctrl {
26 void __iomem *base;
27 int dmapp_num;
28};
29
98d358af 30struct rsnd_dma_ops {
ddea1b2e 31 char *name;
98d358af
KM
32 void (*start)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
33 void (*stop)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
34 int (*init)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
35 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
36 void (*quit)(struct rsnd_dai_stream *io, struct rsnd_dma *dma);
37};
38
288f392e
KM
39#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma)
40
41/*
42 * Audio DMAC
43 */
9b99e9a7
KM
44static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
45 struct rsnd_dai_stream *io)
bfe834be 46{
75defee0 47 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
75defee0
KM
48 bool elapsed = false;
49 unsigned long flags;
bfe834be
KM
50
51 /*
52 * Renesas sound Gen1 needs 1 DMAC,
53 * Gen2 needs 2 DMAC.
54 * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri.
55 * But, Audio-DMAC-peri-peri doesn't have interrupt,
56 * and this driver is assuming that here.
57 *
58 * If Audio-DMAC-peri-peri has interrpt,
59 * rsnd_dai_pointer_update() will be called twice,
60 * ant it will breaks io->byte_pos
61 */
75defee0
KM
62 spin_lock_irqsave(&priv->lock, flags);
63
d5bbe7de 64 if (rsnd_io_is_working(io))
9b99e9a7 65 elapsed = rsnd_dai_pointer_update(io, io->byte_per_period);
bfe834be 66
75defee0 67 spin_unlock_irqrestore(&priv->lock, flags);
bfe834be 68
75defee0
KM
69 if (elapsed)
70 rsnd_dai_period_elapsed(io);
bfe834be
KM
71}
72
9b99e9a7
KM
73static void rsnd_dmaen_complete(void *data)
74{
75 struct rsnd_mod *mod = data;
76
77 rsnd_mod_interrupt(mod, __rsnd_dmaen_complete);
78}
79
80static void rsnd_dmaen_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
bfe834be 81{
0d00a521
KM
82 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
83
84 dmaengine_terminate_all(dmaen->chan);
bfe834be
KM
85}
86
9b99e9a7 87static void rsnd_dmaen_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
bfe834be 88{
0d00a521 89 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
bfe834be
KM
90 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
91 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
bfe834be
KM
92 struct snd_pcm_substream *substream = io->substream;
93 struct device *dev = rsnd_priv_to_dev(priv);
94 struct dma_async_tx_descriptor *desc;
aaf4fce0 95 int is_play = rsnd_io_is_play(io);
bfe834be 96
0d00a521 97 desc = dmaengine_prep_dma_cyclic(dmaen->chan,
bfe834be
KM
98 substream->runtime->dma_addr,
99 snd_pcm_lib_buffer_bytes(substream),
100 snd_pcm_lib_period_bytes(substream),
aaf4fce0 101 is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
bfe834be
KM
102 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
103
104 if (!desc) {
105 dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
106 return;
107 }
108
3c68565b 109 desc->callback = rsnd_dmaen_complete;
9b99e9a7 110 desc->callback_param = mod;
bfe834be
KM
111
112 if (dmaengine_submit(desc) < 0) {
113 dev_err(dev, "dmaengine_submit() fail\n");
114 return;
115 }
116
0d00a521 117 dma_async_issue_pending(dmaen->chan);
bfe834be
KM
118}
119
72adc61f
KM
120struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
121 struct rsnd_mod *mod, char *name)
122{
123 struct dma_chan *chan;
124 struct device_node *np;
125 int i = 0;
126
127 for_each_child_of_node(of_node, np) {
128 if (i == rsnd_mod_id(mod))
129 break;
130 i++;
131 }
132
133 chan = of_dma_request_slave_channel(np, name);
134
135 of_node_put(np);
136 of_node_put(of_node);
137
138 return chan;
139}
140
9b99e9a7
KM
141static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io,
142 struct rsnd_mod *mod_from,
72adc61f
KM
143 struct rsnd_mod *mod_to)
144{
145 if ((!mod_from && !mod_to) ||
146 (mod_from && mod_to))
147 return NULL;
148
149 if (mod_from)
9b99e9a7 150 return rsnd_mod_dma_req(io, mod_from);
72adc61f 151 else
9b99e9a7 152 return rsnd_mod_dma_req(io, mod_to);
72adc61f
KM
153}
154
9b99e9a7
KM
155static int rsnd_dmaen_init(struct rsnd_dai_stream *io,
156 struct rsnd_dma *dma, int id,
3c68565b 157 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
bfe834be 158{
0d00a521 159 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
9b99e9a7 160 struct rsnd_priv *priv = rsnd_io_to_priv(io);
bfe834be
KM
161 struct device *dev = rsnd_priv_to_dev(priv);
162 struct dma_slave_config cfg = {};
bfe834be 163 int is_play = rsnd_io_is_play(io);
bfe834be
KM
164 int ret;
165
0d00a521 166 if (dmaen->chan) {
bfe834be
KM
167 dev_err(dev, "it already has dma channel\n");
168 return -EIO;
169 }
170
72adc61f 171 if (dev->of_node) {
9b99e9a7 172 dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
72adc61f
KM
173 } else {
174 dma_cap_mask_t mask;
bfe834be 175
72adc61f
KM
176 dma_cap_zero(mask);
177 dma_cap_set(DMA_SLAVE, mask);
178
179 dmaen->chan = dma_request_channel(mask, shdma_chan_filter,
180 (void *)id);
181 }
182 if (IS_ERR_OR_NULL(dmaen->chan)) {
d1acba2f 183 dmaen->chan = NULL;
72adc61f
KM
184 dev_err(dev, "can't get dma channel\n");
185 goto rsnd_dma_channel_err;
186 }
bfe834be
KM
187
188 cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
3c68565b
KM
189 cfg.src_addr = dma->src_addr;
190 cfg.dst_addr = dma->dst_addr;
bfe834be
KM
191 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
192 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
193
ddea1b2e
KM
194 dev_dbg(dev, "%s %pad -> %pad\n",
195 dma->ops->name,
72adc61f 196 &cfg.src_addr, &cfg.dst_addr);
bfe834be 197
0d00a521 198 ret = dmaengine_slave_config(dmaen->chan, &cfg);
bfe834be
KM
199 if (ret < 0)
200 goto rsnd_dma_init_err;
201
bfe834be
KM
202 return 0;
203
204rsnd_dma_init_err:
9b99e9a7 205 rsnd_dma_quit(io, dma);
bfe834be
KM
206rsnd_dma_channel_err:
207
208 /*
209 * DMA failed. try to PIO mode
210 * see
211 * rsnd_ssi_fallback()
212 * rsnd_rdai_continuance_probe()
213 */
214 return -EAGAIN;
215}
216
9b99e9a7 217static void rsnd_dmaen_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
bfe834be 218{
0d00a521
KM
219 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
220
221 if (dmaen->chan)
222 dma_release_channel(dmaen->chan);
bfe834be 223
0d00a521 224 dmaen->chan = NULL;
bfe834be
KM
225}
226
3c68565b 227static struct rsnd_dma_ops rsnd_dmaen_ops = {
ddea1b2e 228 .name = "audmac",
3c68565b
KM
229 .start = rsnd_dmaen_start,
230 .stop = rsnd_dmaen_stop,
231 .init = rsnd_dmaen_init,
232 .quit = rsnd_dmaen_quit,
233};
234
288f392e
KM
235/*
236 * Audio DMAC peri peri
237 */
238static const u8 gen2_id_table_ssiu[] = {
239 0x00, /* SSI00 */
240 0x04, /* SSI10 */
241 0x08, /* SSI20 */
242 0x0c, /* SSI3 */
243 0x0d, /* SSI4 */
244 0x0e, /* SSI5 */
245 0x0f, /* SSI6 */
246 0x10, /* SSI7 */
247 0x11, /* SSI8 */
248 0x12, /* SSI90 */
249};
250static const u8 gen2_id_table_scu[] = {
251 0x2d, /* SCU_SRCI0 */
252 0x2e, /* SCU_SRCI1 */
253 0x2f, /* SCU_SRCI2 */
254 0x30, /* SCU_SRCI3 */
255 0x31, /* SCU_SRCI4 */
256 0x32, /* SCU_SRCI5 */
257 0x33, /* SCU_SRCI6 */
258 0x34, /* SCU_SRCI7 */
259 0x35, /* SCU_SRCI8 */
260 0x36, /* SCU_SRCI9 */
261};
262static const u8 gen2_id_table_cmd[] = {
263 0x37, /* SCU_CMD0 */
264 0x38, /* SCU_CMD1 */
265};
266
9b99e9a7
KM
267static u32 rsnd_dmapp_get_id(struct rsnd_dai_stream *io,
268 struct rsnd_mod *mod)
288f392e 269{
288f392e
KM
270 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
271 struct rsnd_mod *src = rsnd_io_to_mod_src(io);
272 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
273 const u8 *entry = NULL;
274 int id = rsnd_mod_id(mod);
275 int size = 0;
276
277 if (mod == ssi) {
278 entry = gen2_id_table_ssiu;
279 size = ARRAY_SIZE(gen2_id_table_ssiu);
280 } else if (mod == src) {
281 entry = gen2_id_table_scu;
282 size = ARRAY_SIZE(gen2_id_table_scu);
283 } else if (mod == dvc) {
284 entry = gen2_id_table_cmd;
285 size = ARRAY_SIZE(gen2_id_table_cmd);
286 }
287
288 if (!entry)
289 return 0xFF;
290
291 if (size <= id)
292 return 0xFF;
293
294 return entry[id];
295}
296
9b99e9a7
KM
297static u32 rsnd_dmapp_get_chcr(struct rsnd_dai_stream *io,
298 struct rsnd_mod *mod_from,
288f392e
KM
299 struct rsnd_mod *mod_to)
300{
9b99e9a7
KM
301 return (rsnd_dmapp_get_id(io, mod_from) << 24) +
302 (rsnd_dmapp_get_id(io, mod_to) << 16);
288f392e
KM
303}
304
305#define rsnd_dmapp_addr(dmac, dma, reg) \
0d00a521
KM
306 (dmac->base + 0x20 + reg + \
307 (0x10 * rsnd_dma_to_dmapp(dma)->dmapp_id))
288f392e
KM
308static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg)
309{
310 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
311 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
312 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
313 struct device *dev = rsnd_priv_to_dev(priv);
314
315 dev_dbg(dev, "w %p : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data);
316
317 iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg));
318}
319
320static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg)
321{
322 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
323 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
324 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
325
326 return ioread32(rsnd_dmapp_addr(dmac, dma, reg));
327}
328
9b99e9a7 329static void rsnd_dmapp_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
288f392e
KM
330{
331 int i;
332
333 rsnd_dmapp_write(dma, 0, PDMACHCR);
334
335 for (i = 0; i < 1024; i++) {
336 if (0 == rsnd_dmapp_read(dma, PDMACHCR))
337 return;
338 udelay(1);
339 }
340}
341
9b99e9a7 342static void rsnd_dmapp_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
288f392e 343{
0d00a521
KM
344 struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
345
288f392e
KM
346 rsnd_dmapp_write(dma, dma->src_addr, PDMASAR);
347 rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR);
0d00a521 348 rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR);
288f392e
KM
349}
350
9b99e9a7
KM
351static int rsnd_dmapp_init(struct rsnd_dai_stream *io,
352 struct rsnd_dma *dma, int id,
288f392e
KM
353 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
354{
0d00a521 355 struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
9b99e9a7 356 struct rsnd_priv *priv = rsnd_io_to_priv(io);
288f392e
KM
357 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
358 struct device *dev = rsnd_priv_to_dev(priv);
359
0d00a521 360 dmapp->dmapp_id = dmac->dmapp_num;
9b99e9a7 361 dmapp->chcr = rsnd_dmapp_get_chcr(io, mod_from, mod_to) | PDMACHCR_DE;
288f392e
KM
362
363 dmac->dmapp_num++;
364
9b99e9a7 365 rsnd_dmapp_stop(io, dma);
288f392e 366
6ec6fb6f
GU
367 dev_dbg(dev, "id/src/dst/chcr = %d/%pad/%pad/%08x\n",
368 dmapp->dmapp_id, &dma->src_addr, &dma->dst_addr, dmapp->chcr);
288f392e
KM
369
370 return 0;
371}
372
373static struct rsnd_dma_ops rsnd_dmapp_ops = {
ddea1b2e 374 .name = "audmac-pp",
288f392e
KM
375 .start = rsnd_dmapp_start,
376 .stop = rsnd_dmapp_stop,
377 .init = rsnd_dmapp_init,
378 .quit = rsnd_dmapp_stop,
379};
380
381/*
382 * Common DMAC Interface
383 */
384
747c71b1
KM
385/*
386 * DMA read/write register offset
387 *
388 * RSND_xxx_I_N for Audio DMAC input
389 * RSND_xxx_O_N for Audio DMAC output
390 * RSND_xxx_I_P for Audio DMAC peri peri input
391 * RSND_xxx_O_P for Audio DMAC peri peri output
392 *
393 * ex) R-Car H2 case
394 * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
395 * SSI : 0xec541000 / 0xec241008 / 0xec24100c
396 * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
397 * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
398 * CMD : 0xec500000 / / 0xec008000 0xec308000
399 */
400#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
401#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
402
403#define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
404#define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
405
406#define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
407#define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
408
409#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
410#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
411
412#define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i))
413#define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i))
414
415#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
416#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
417
418static dma_addr_t
9b99e9a7 419rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
747c71b1
KM
420 struct rsnd_mod *mod,
421 int is_play, int is_from)
422{
9b99e9a7 423 struct rsnd_priv *priv = rsnd_io_to_priv(io);
747c71b1 424 struct device *dev = rsnd_priv_to_dev(priv);
747c71b1
KM
425 phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI);
426 phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU);
427 int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod);
428 int use_src = !!rsnd_io_to_mod_src(io);
9269e3c3 429 int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
70fb1052 430 !!rsnd_io_to_mod_mix(io) ||
9269e3c3 431 !!rsnd_io_to_mod_ctu(io);
747c71b1
KM
432 int id = rsnd_mod_id(mod);
433 struct dma_addr {
434 dma_addr_t out_addr;
435 dma_addr_t in_addr;
436 } dma_addrs[3][2][3] = {
437 /* SRC */
438 {{{ 0, 0 },
439 /* Capture */
440 { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) },
441 { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } },
442 /* Playback */
443 {{ 0, 0, },
444 { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) },
445 { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } }
446 },
447 /* SSI */
448 /* Capture */
449 {{{ RDMA_SSI_O_N(ssi, id), 0 },
450 { RDMA_SSIU_O_P(ssi, id), 0 },
451 { RDMA_SSIU_O_P(ssi, id), 0 } },
452 /* Playback */
453 {{ 0, RDMA_SSI_I_N(ssi, id) },
454 { 0, RDMA_SSIU_I_P(ssi, id) },
455 { 0, RDMA_SSIU_I_P(ssi, id) } }
456 },
457 /* SSIU */
458 /* Capture */
459 {{{ RDMA_SSIU_O_N(ssi, id), 0 },
460 { RDMA_SSIU_O_P(ssi, id), 0 },
461 { RDMA_SSIU_O_P(ssi, id), 0 } },
462 /* Playback */
463 {{ 0, RDMA_SSIU_I_N(ssi, id) },
464 { 0, RDMA_SSIU_I_P(ssi, id) },
465 { 0, RDMA_SSIU_I_P(ssi, id) } } },
466 };
467
468 /* it shouldn't happen */
9269e3c3 469 if (use_cmd && !use_src)
747c71b1
KM
470 dev_err(dev, "DVC is selected without SRC\n");
471
472 /* use SSIU or SSI ? */
bfc0cfe6 473 if (is_ssi && rsnd_ssi_use_busif(io, mod))
747c71b1
KM
474 is_ssi++;
475
476 return (is_from) ?
9269e3c3
KM
477 dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr :
478 dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
747c71b1
KM
479}
480
9b99e9a7 481static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
747c71b1
KM
482 struct rsnd_mod *mod,
483 int is_play, int is_from)
484{
9b99e9a7
KM
485 struct rsnd_priv *priv = rsnd_io_to_priv(io);
486
747c71b1
KM
487 /*
488 * gen1 uses default DMA addr
489 */
490 if (rsnd_is_gen1(priv))
491 return 0;
492
493 if (!mod)
494 return 0;
495
9b99e9a7 496 return rsnd_gen2_dma_addr(io, mod, is_play, is_from);
747c71b1
KM
497}
498
7dfb4919 499#define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */
bfe834be 500static void rsnd_dma_of_path(struct rsnd_dma *dma,
9b99e9a7 501 struct rsnd_dai_stream *io,
bfe834be
KM
502 int is_play,
503 struct rsnd_mod **mod_from,
504 struct rsnd_mod **mod_to)
505{
506 struct rsnd_mod *this = rsnd_dma_to_mod(dma);
bfe834be
KM
507 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
508 struct rsnd_mod *src = rsnd_io_to_mod_src(io);
9269e3c3 509 struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io);
70fb1052 510 struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
bfe834be
KM
511 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
512 struct rsnd_mod *mod[MOD_MAX];
7dfb4919
KM
513 struct rsnd_mod *mod_start, *mod_end;
514 struct rsnd_priv *priv = rsnd_mod_to_priv(this);
515 struct device *dev = rsnd_priv_to_dev(priv);
516 int nr, i;
bfe834be 517
7dfb4919
KM
518 if (!ssi)
519 return;
bfe834be 520
7dfb4919
KM
521 nr = 0;
522 for (i = 0; i < MOD_MAX; i++) {
bfe834be 523 mod[i] = NULL;
7dfb4919
KM
524 nr += !!rsnd_io_to_mod(io, i);
525 }
bfe834be
KM
526
527 /*
7dfb4919
KM
528 * [S] -*-> [E]
529 * [S] -*-> SRC -o-> [E]
530 * [S] -*-> SRC -> DVC -o-> [E]
531 * [S] -*-> SRC -> CTU -> MIX -> DVC -o-> [E]
532 *
533 * playback [S] = mem
534 * [E] = SSI
bfe834be 535 *
7dfb4919
KM
536 * capture [S] = SSI
537 * [E] = mem
bfe834be 538 *
7dfb4919
KM
539 * -*-> Audio DMAC
540 * -o-> Audio DMAC peri peri
bfe834be 541 */
7dfb4919
KM
542 mod_start = (is_play) ? NULL : ssi;
543 mod_end = (is_play) ? ssi : NULL;
bfe834be 544
7dfb4919
KM
545 mod[0] = mod_start;
546 for (i = 1; i < nr; i++) {
547 if (src) {
548 mod[i] = src;
bfe834be 549 src = NULL;
9269e3c3
KM
550 } else if (ctu) {
551 mod[i] = ctu;
552 ctu = NULL;
70fb1052
KM
553 } else if (mix) {
554 mod[i] = mix;
555 mix = NULL;
7dfb4919
KM
556 } else if (dvc) {
557 mod[i] = dvc;
bfe834be
KM
558 dvc = NULL;
559 }
bfe834be 560 }
7dfb4919 561 mod[i] = mod_end;
bfe834be 562
7dfb4919
KM
563 /*
564 * | SSI | SRC |
565 * -------------+-----+-----+
566 * is_play | o | * |
567 * !is_play | * | o |
568 */
569 if ((this == ssi) == (is_play)) {
570 *mod_from = mod[nr - 1];
571 *mod_to = mod[nr];
bfe834be 572 } else {
7dfb4919
KM
573 *mod_from = mod[0];
574 *mod_to = mod[1];
575 }
576
577 dev_dbg(dev, "module connection (this is %s[%d])\n",
578 rsnd_mod_name(this), rsnd_mod_id(this));
579 for (i = 0; i <= nr; i++) {
580 dev_dbg(dev, " %s[%d]%s\n",
581 rsnd_mod_name(mod[i]), rsnd_mod_id(mod[i]),
582 (mod[i] == *mod_from) ? " from" :
583 (mod[i] == *mod_to) ? " to" : "");
bfe834be
KM
584 }
585}
586
9b99e9a7 587void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
3c68565b 588{
9b99e9a7 589 dma->ops->stop(io, dma);
3c68565b
KM
590}
591
9b99e9a7 592void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
3c68565b 593{
9b99e9a7 594 dma->ops->start(io, dma);
3c68565b
KM
595}
596
9b99e9a7 597void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma)
3c68565b 598{
8537483a
KM
599 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
600 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
601 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
602
603 if (!dmac)
604 return;
605
9b99e9a7 606 dma->ops->quit(io, dma);
3c68565b
KM
607}
608
9b99e9a7 609int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id)
3c68565b 610{
7dfb4919
KM
611 struct rsnd_mod *mod_from = NULL;
612 struct rsnd_mod *mod_to = NULL;
9b99e9a7 613 struct rsnd_priv *priv = rsnd_io_to_priv(io);
8537483a 614 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
ddea1b2e 615 struct device *dev = rsnd_priv_to_dev(priv);
3c68565b
KM
616 int is_play = rsnd_io_is_play(io);
617
8537483a
KM
618 /*
619 * DMA failed. try to PIO mode
620 * see
621 * rsnd_ssi_fallback()
622 * rsnd_rdai_continuance_probe()
623 */
624 if (!dmac)
625 return -EAGAIN;
626
9b99e9a7 627 rsnd_dma_of_path(dma, io, is_play, &mod_from, &mod_to);
3c68565b 628
9b99e9a7
KM
629 dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1);
630 dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0);
3c68565b 631
288f392e
KM
632 /* for Gen2 */
633 if (mod_from && mod_to)
634 dma->ops = &rsnd_dmapp_ops;
635 else
636 dma->ops = &rsnd_dmaen_ops;
637
638 /* for Gen1, overwrite */
639 if (rsnd_is_gen1(priv))
640 dma->ops = &rsnd_dmaen_ops;
3c68565b 641
ddea1b2e
KM
642 dev_dbg(dev, "%s %s[%d] -> %s[%d]\n",
643 dma->ops->name,
644 rsnd_mod_name(mod_from), rsnd_mod_id(mod_from),
645 rsnd_mod_name(mod_to), rsnd_mod_id(mod_to));
646
9b99e9a7 647 return dma->ops->init(io, dma, id, mod_from, mod_to);
3c68565b 648}
288f392e
KM
649
650int rsnd_dma_probe(struct platform_device *pdev,
651 const struct rsnd_of_data *of_data,
652 struct rsnd_priv *priv)
653{
654 struct device *dev = rsnd_priv_to_dev(priv);
655 struct rsnd_dma_ctrl *dmac;
656 struct resource *res;
657
658 /*
659 * for Gen1
660 */
661 if (rsnd_is_gen1(priv))
662 return 0;
663
664 /*
665 * for Gen2
666 */
667 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp");
668 dmac = devm_kzalloc(dev, sizeof(*dmac), GFP_KERNEL);
669 if (!dmac || !res) {
670 dev_err(dev, "dma allocate failed\n");
8537483a 671 return 0; /* it will be PIO mode */
288f392e
KM
672 }
673
674 dmac->dmapp_num = 0;
675 dmac->base = devm_ioremap_resource(dev, res);
676 if (IS_ERR(dmac->base))
677 return PTR_ERR(dmac->base);
678
679 priv->dma = dmac;
680
681 return 0;
682}