blob: b449763ebd434817c73d5500f378038c7457b4c0 [file] [log] [blame]
Kuninori Morimotobfe834b2015-02-20 10:25:55 +00001/*
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 */
Kuninori Morimoto288f3922015-02-20 10:27:42 +000011#include <linux/delay.h>
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000012#include "rsnd.h"
13
Kuninori Morimoto288f3922015-02-20 10:27:42 +000014/*
15 * Audio DMAC peri peri register
16 */
17#define PDMASAR 0x00
18#define PDMADAR 0x04
19#define PDMACHCR 0x0c
20
21/* PDMACHCR */
22#define PDMACHCR_DE (1 << 0)
23
24struct rsnd_dma_ctrl {
25 void __iomem *base;
26 int dmapp_num;
27};
28
29#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma)
30
31/*
32 * Audio DMAC
33 */
Kuninori Morimoto3c685652015-02-20 10:27:12 +000034static void rsnd_dmaen_complete(void *data)
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000035{
36 struct rsnd_dma *dma = (struct rsnd_dma *)data;
37 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
38 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
39
40 /*
41 * Renesas sound Gen1 needs 1 DMAC,
42 * Gen2 needs 2 DMAC.
43 * In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri.
44 * But, Audio-DMAC-peri-peri doesn't have interrupt,
45 * and this driver is assuming that here.
46 *
47 * If Audio-DMAC-peri-peri has interrpt,
48 * rsnd_dai_pointer_update() will be called twice,
49 * ant it will breaks io->byte_pos
50 */
51
52 rsnd_dai_pointer_update(io, io->byte_per_period);
53}
54
55#define DMA_NAME_SIZE 16
Kuninori Morimoto3c685652015-02-20 10:27:12 +000056static int _rsnd_dmaen_of_name(char *dma_name, struct rsnd_mod *mod)
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000057{
58 if (mod)
59 return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d",
60 rsnd_mod_dma_name(mod), rsnd_mod_id(mod));
61 else
62 return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem");
63
64}
65
Kuninori Morimoto3c685652015-02-20 10:27:12 +000066static void rsnd_dmaen_of_name(struct rsnd_mod *mod_from,
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000067 struct rsnd_mod *mod_to,
68 char *dma_name)
69{
70 int index = 0;
71
Kuninori Morimoto3c685652015-02-20 10:27:12 +000072 index = _rsnd_dmaen_of_name(dma_name + index, mod_from);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000073 *(dma_name + index++) = '_';
Kuninori Morimoto3c685652015-02-20 10:27:12 +000074 index = _rsnd_dmaen_of_name(dma_name + index, mod_to);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000075}
76
Kuninori Morimoto3c685652015-02-20 10:27:12 +000077static void rsnd_dmaen_stop(struct rsnd_dma *dma)
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000078{
Kuninori Morimoto0d00a522015-02-20 10:29:13 +000079 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
80
81 dmaengine_terminate_all(dmaen->chan);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000082}
83
Kuninori Morimoto3c685652015-02-20 10:27:12 +000084static void rsnd_dmaen_start(struct rsnd_dma *dma)
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000085{
Kuninori Morimoto0d00a522015-02-20 10:29:13 +000086 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000087 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
88 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
89 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
90 struct snd_pcm_substream *substream = io->substream;
91 struct device *dev = rsnd_priv_to_dev(priv);
92 struct dma_async_tx_descriptor *desc;
Kuninori Morimotoaaf4fce2015-02-20 10:28:32 +000093 int is_play = rsnd_io_is_play(io);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000094
Kuninori Morimoto0d00a522015-02-20 10:29:13 +000095 desc = dmaengine_prep_dma_cyclic(dmaen->chan,
Kuninori Morimotobfe834b2015-02-20 10:25:55 +000096 substream->runtime->dma_addr,
97 snd_pcm_lib_buffer_bytes(substream),
98 snd_pcm_lib_period_bytes(substream),
Kuninori Morimotoaaf4fce2015-02-20 10:28:32 +000099 is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000100 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
101
102 if (!desc) {
103 dev_err(dev, "dmaengine_prep_slave_sg() fail\n");
104 return;
105 }
106
Kuninori Morimoto3c685652015-02-20 10:27:12 +0000107 desc->callback = rsnd_dmaen_complete;
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000108 desc->callback_param = dma;
109
110 if (dmaengine_submit(desc) < 0) {
111 dev_err(dev, "dmaengine_submit() fail\n");
112 return;
113 }
114
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000115 dma_async_issue_pending(dmaen->chan);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000116}
117
Kuninori Morimoto3c685652015-02-20 10:27:12 +0000118static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id,
119 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000120{
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000121 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000122 struct device *dev = rsnd_priv_to_dev(priv);
123 struct dma_slave_config cfg = {};
124 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000125 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
126 int is_play = rsnd_io_is_play(io);
127 char dma_name[DMA_NAME_SIZE];
128 dma_cap_mask_t mask;
129 int ret;
130
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000131 if (dmaen->chan) {
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000132 dev_err(dev, "it already has dma channel\n");
133 return -EIO;
134 }
135
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000136 dev_dbg(dev, "Audio DMAC init\n");
137
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000138 dma_cap_zero(mask);
139 dma_cap_set(DMA_SLAVE, mask);
140
Kuninori Morimoto3c685652015-02-20 10:27:12 +0000141 rsnd_dmaen_of_name(mod_from, mod_to, dma_name);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000142
143 cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
Kuninori Morimoto3c685652015-02-20 10:27:12 +0000144 cfg.src_addr = dma->src_addr;
145 cfg.dst_addr = dma->dst_addr;
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000146 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
147 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
148
149 dev_dbg(dev, "dma : %s %pad -> %pad\n",
150 dma_name, &cfg.src_addr, &cfg.dst_addr);
151
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000152 dmaen->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000153 (void *)id, dev,
154 dma_name);
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000155 if (!dmaen->chan) {
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000156 dev_err(dev, "can't get dma channel\n");
157 goto rsnd_dma_channel_err;
158 }
159
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000160 ret = dmaengine_slave_config(dmaen->chan, &cfg);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000161 if (ret < 0)
162 goto rsnd_dma_init_err;
163
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000164 return 0;
165
166rsnd_dma_init_err:
167 rsnd_dma_quit(dma);
168rsnd_dma_channel_err:
169
170 /*
171 * DMA failed. try to PIO mode
172 * see
173 * rsnd_ssi_fallback()
174 * rsnd_rdai_continuance_probe()
175 */
176 return -EAGAIN;
177}
178
Kuninori Morimoto3c685652015-02-20 10:27:12 +0000179static void rsnd_dmaen_quit(struct rsnd_dma *dma)
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000180{
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000181 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000182
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000183 if (dmaen->chan)
184 dma_release_channel(dmaen->chan);
185
186 dmaen->chan = NULL;
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000187}
188
Kuninori Morimoto3c685652015-02-20 10:27:12 +0000189static struct rsnd_dma_ops rsnd_dmaen_ops = {
190 .start = rsnd_dmaen_start,
191 .stop = rsnd_dmaen_stop,
192 .init = rsnd_dmaen_init,
193 .quit = rsnd_dmaen_quit,
194};
195
Kuninori Morimoto747c71b2015-02-20 10:26:29 +0000196/*
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000197 * Audio DMAC peri peri
198 */
199static const u8 gen2_id_table_ssiu[] = {
200 0x00, /* SSI00 */
201 0x04, /* SSI10 */
202 0x08, /* SSI20 */
203 0x0c, /* SSI3 */
204 0x0d, /* SSI4 */
205 0x0e, /* SSI5 */
206 0x0f, /* SSI6 */
207 0x10, /* SSI7 */
208 0x11, /* SSI8 */
209 0x12, /* SSI90 */
210};
211static const u8 gen2_id_table_scu[] = {
212 0x2d, /* SCU_SRCI0 */
213 0x2e, /* SCU_SRCI1 */
214 0x2f, /* SCU_SRCI2 */
215 0x30, /* SCU_SRCI3 */
216 0x31, /* SCU_SRCI4 */
217 0x32, /* SCU_SRCI5 */
218 0x33, /* SCU_SRCI6 */
219 0x34, /* SCU_SRCI7 */
220 0x35, /* SCU_SRCI8 */
221 0x36, /* SCU_SRCI9 */
222};
223static const u8 gen2_id_table_cmd[] = {
224 0x37, /* SCU_CMD0 */
225 0x38, /* SCU_CMD1 */
226};
227
228static u32 rsnd_dmapp_get_id(struct rsnd_mod *mod)
229{
230 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
231 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
232 struct rsnd_mod *src = rsnd_io_to_mod_src(io);
233 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
234 const u8 *entry = NULL;
235 int id = rsnd_mod_id(mod);
236 int size = 0;
237
238 if (mod == ssi) {
239 entry = gen2_id_table_ssiu;
240 size = ARRAY_SIZE(gen2_id_table_ssiu);
241 } else if (mod == src) {
242 entry = gen2_id_table_scu;
243 size = ARRAY_SIZE(gen2_id_table_scu);
244 } else if (mod == dvc) {
245 entry = gen2_id_table_cmd;
246 size = ARRAY_SIZE(gen2_id_table_cmd);
247 }
248
249 if (!entry)
250 return 0xFF;
251
252 if (size <= id)
253 return 0xFF;
254
255 return entry[id];
256}
257
258static u32 rsnd_dmapp_get_chcr(struct rsnd_mod *mod_from,
259 struct rsnd_mod *mod_to)
260{
261 return (rsnd_dmapp_get_id(mod_from) << 24) +
262 (rsnd_dmapp_get_id(mod_to) << 16);
263}
264
265#define rsnd_dmapp_addr(dmac, dma, reg) \
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000266 (dmac->base + 0x20 + reg + \
267 (0x10 * rsnd_dma_to_dmapp(dma)->dmapp_id))
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000268static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg)
269{
270 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
271 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
272 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
273 struct device *dev = rsnd_priv_to_dev(priv);
274
275 dev_dbg(dev, "w %p : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data);
276
277 iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg));
278}
279
280static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg)
281{
282 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
283 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
284 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
285
286 return ioread32(rsnd_dmapp_addr(dmac, dma, reg));
287}
288
289static void rsnd_dmapp_stop(struct rsnd_dma *dma)
290{
291 int i;
292
293 rsnd_dmapp_write(dma, 0, PDMACHCR);
294
295 for (i = 0; i < 1024; i++) {
296 if (0 == rsnd_dmapp_read(dma, PDMACHCR))
297 return;
298 udelay(1);
299 }
300}
301
302static void rsnd_dmapp_start(struct rsnd_dma *dma)
303{
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000304 struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
305
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000306 rsnd_dmapp_write(dma, dma->src_addr, PDMASAR);
307 rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR);
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000308 rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR);
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000309}
310
311static int rsnd_dmapp_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id,
312 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
313{
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000314 struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000315 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
316 struct device *dev = rsnd_priv_to_dev(priv);
317
318 dev_dbg(dev, "Audio DMAC peri peri init\n");
319
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000320 dmapp->dmapp_id = dmac->dmapp_num;
321 dmapp->chcr = rsnd_dmapp_get_chcr(mod_from, mod_to) | PDMACHCR_DE;
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000322
323 dmac->dmapp_num++;
324
325 rsnd_dmapp_stop(dma);
326
327 dev_dbg(dev, "id/src/dst/chcr = %d/%x/%x/%08x\n",
Kuninori Morimoto0d00a522015-02-20 10:29:13 +0000328 dmapp->dmapp_id, dma->src_addr, dma->dst_addr, dmapp->chcr);
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000329
330 return 0;
331}
332
333static struct rsnd_dma_ops rsnd_dmapp_ops = {
334 .start = rsnd_dmapp_start,
335 .stop = rsnd_dmapp_stop,
336 .init = rsnd_dmapp_init,
337 .quit = rsnd_dmapp_stop,
338};
339
340/*
341 * Common DMAC Interface
342 */
343
344/*
Kuninori Morimoto747c71b2015-02-20 10:26:29 +0000345 * DMA read/write register offset
346 *
347 * RSND_xxx_I_N for Audio DMAC input
348 * RSND_xxx_O_N for Audio DMAC output
349 * RSND_xxx_I_P for Audio DMAC peri peri input
350 * RSND_xxx_O_P for Audio DMAC peri peri output
351 *
352 * ex) R-Car H2 case
353 * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
354 * SSI : 0xec541000 / 0xec241008 / 0xec24100c
355 * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
356 * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
357 * CMD : 0xec500000 / / 0xec008000 0xec308000
358 */
359#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
360#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
361
362#define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
363#define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
364
365#define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
366#define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
367
368#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
369#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
370
371#define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i))
372#define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i))
373
374#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
375#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
376
377static dma_addr_t
378rsnd_gen2_dma_addr(struct rsnd_priv *priv,
379 struct rsnd_mod *mod,
380 int is_play, int is_from)
381{
382 struct device *dev = rsnd_priv_to_dev(priv);
383 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
384 phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI);
385 phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU);
386 int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod);
387 int use_src = !!rsnd_io_to_mod_src(io);
388 int use_dvc = !!rsnd_io_to_mod_dvc(io);
389 int id = rsnd_mod_id(mod);
390 struct dma_addr {
391 dma_addr_t out_addr;
392 dma_addr_t in_addr;
393 } dma_addrs[3][2][3] = {
394 /* SRC */
395 {{{ 0, 0 },
396 /* Capture */
397 { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) },
398 { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } },
399 /* Playback */
400 {{ 0, 0, },
401 { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) },
402 { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } }
403 },
404 /* SSI */
405 /* Capture */
406 {{{ RDMA_SSI_O_N(ssi, id), 0 },
407 { RDMA_SSIU_O_P(ssi, id), 0 },
408 { RDMA_SSIU_O_P(ssi, id), 0 } },
409 /* Playback */
410 {{ 0, RDMA_SSI_I_N(ssi, id) },
411 { 0, RDMA_SSIU_I_P(ssi, id) },
412 { 0, RDMA_SSIU_I_P(ssi, id) } }
413 },
414 /* SSIU */
415 /* Capture */
416 {{{ RDMA_SSIU_O_N(ssi, id), 0 },
417 { RDMA_SSIU_O_P(ssi, id), 0 },
418 { RDMA_SSIU_O_P(ssi, id), 0 } },
419 /* Playback */
420 {{ 0, RDMA_SSIU_I_N(ssi, id) },
421 { 0, RDMA_SSIU_I_P(ssi, id) },
422 { 0, RDMA_SSIU_I_P(ssi, id) } } },
423 };
424
425 /* it shouldn't happen */
426 if (use_dvc && !use_src)
427 dev_err(dev, "DVC is selected without SRC\n");
428
429 /* use SSIU or SSI ? */
430 if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu")))
431 is_ssi++;
432
433 return (is_from) ?
434 dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr :
435 dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr;
436}
437
438static dma_addr_t rsnd_dma_addr(struct rsnd_priv *priv,
439 struct rsnd_mod *mod,
440 int is_play, int is_from)
441{
442 /*
443 * gen1 uses default DMA addr
444 */
445 if (rsnd_is_gen1(priv))
446 return 0;
447
448 if (!mod)
449 return 0;
450
451 return rsnd_gen2_dma_addr(priv, mod, is_play, is_from);
452}
453
454#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */
Kuninori Morimotobfe834b2015-02-20 10:25:55 +0000455static void rsnd_dma_of_path(struct rsnd_dma *dma,
456 int is_play,
457 struct rsnd_mod **mod_from,
458 struct rsnd_mod **mod_to)
459{
460 struct rsnd_mod *this = rsnd_dma_to_mod(dma);
461 struct rsnd_dai_stream *io = rsnd_mod_to_io(this);
462 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
463 struct rsnd_mod *src = rsnd_io_to_mod_src(io);
464 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
465 struct rsnd_mod *mod[MOD_MAX];
466 int i, index;
467
468
469 for (i = 0; i < MOD_MAX; i++)
470 mod[i] = NULL;
471
472 /*
473 * in play case...
474 *
475 * src -> dst
476 *
477 * mem -> SSI
478 * mem -> SRC -> SSI
479 * mem -> SRC -> DVC -> SSI
480 */
481 mod[0] = NULL; /* for "mem" */
482 index = 1;
483 for (i = 1; i < MOD_MAX; i++) {
484 if (!src) {
485 mod[i] = ssi;
486 } else if (!dvc) {
487 mod[i] = src;
488 src = NULL;
489 } else {
490 if ((!is_play) && (this == src))
491 this = dvc;
492
493 mod[i] = (is_play) ? src : dvc;
494 i++;
495 mod[i] = (is_play) ? dvc : src;
496 src = NULL;
497 dvc = NULL;
498 }
499
500 if (mod[i] == this)
501 index = i;
502
503 if (mod[i] == ssi)
504 break;
505 }
506
507 if (is_play) {
508 *mod_from = mod[index - 1];
509 *mod_to = mod[index];
510 } else {
511 *mod_from = mod[index];
512 *mod_to = mod[index - 1];
513 }
514}
515
Kuninori Morimoto3c685652015-02-20 10:27:12 +0000516void rsnd_dma_stop(struct rsnd_dma *dma)
517{
518 dma->ops->stop(dma);
519}
520
521void rsnd_dma_start(struct rsnd_dma *dma)
522{
523 dma->ops->start(dma);
524}
525
526void rsnd_dma_quit(struct rsnd_dma *dma)
527{
528 dma->ops->quit(dma);
529}
530
531int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id)
532{
533 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
534 struct rsnd_mod *mod_from;
535 struct rsnd_mod *mod_to;
536 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
537 int is_play = rsnd_io_is_play(io);
538
539 rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to);
540
541 dma->src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1);
542 dma->dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0);
543
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000544 /* for Gen2 */
545 if (mod_from && mod_to)
546 dma->ops = &rsnd_dmapp_ops;
547 else
548 dma->ops = &rsnd_dmaen_ops;
549
550 /* for Gen1, overwrite */
551 if (rsnd_is_gen1(priv))
552 dma->ops = &rsnd_dmaen_ops;
Kuninori Morimoto3c685652015-02-20 10:27:12 +0000553
554 return dma->ops->init(priv, dma, id, mod_from, mod_to);
555}
Kuninori Morimoto288f3922015-02-20 10:27:42 +0000556
557int rsnd_dma_probe(struct platform_device *pdev,
558 const struct rsnd_of_data *of_data,
559 struct rsnd_priv *priv)
560{
561 struct device *dev = rsnd_priv_to_dev(priv);
562 struct rsnd_dma_ctrl *dmac;
563 struct resource *res;
564
565 /*
566 * for Gen1
567 */
568 if (rsnd_is_gen1(priv))
569 return 0;
570
571 /*
572 * for Gen2
573 */
574 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp");
575 dmac = devm_kzalloc(dev, sizeof(*dmac), GFP_KERNEL);
576 if (!dmac || !res) {
577 dev_err(dev, "dma allocate failed\n");
578 return -ENOMEM;
579 }
580
581 dmac->dmapp_num = 0;
582 dmac->base = devm_ioremap_resource(dev, res);
583 if (IS_ERR(dmac->base))
584 return PTR_ERR(dmac->base);
585
586 priv->dma = dmac;
587
588 return 0;
589}