aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2015-02-20 05:27:42 -0500
committerMark Brown <broonie@kernel.org>2015-03-07 10:04:30 -0500
commit288f392e729dd4d3719c2319c7c3f8d4c820488b (patch)
treea77b10af60d30302dbaced4dab7da5984127ca66
parent3c68565b6cb68b731b51eb21b59dce901002fc6e (diff)
ASoC: rsnd: add Audio DMAC peri peri support rework
Renesas R-Car sound (= rsnd) needs 2 DMAC which are called as Audio DMAC (= 1st DMAC) and Audio DMAC peri peri (2nd DMAC). And rsnd had assumed that 1st / 2nd DMACs are implemented as DMAEngine. But, in result of DMA ML discussion, 2nd DMAC was concluded that it is not a general purpose DMAC (2nd DMAC is for Device to Device inside sound system). Additionally, current DMAEngine can't support Device to Device, and we don't have correct DT bindings for it at this point. So the easiest solution for it is that move it from DMAEngine to rsnd driver. Audio DMAC peri peri is controlled from sound driver without DMAEngine by this patch. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/sh/rcar/core.c1
-rw-r--r--sound/soc/sh/rcar/dma.c211
-rw-r--r--sound/soc/sh/rcar/rsnd.h11
3 files changed, 221 insertions, 2 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 9beea9ba338a..3b6e21948c71 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -974,6 +974,7 @@ static int rsnd_probe(struct platform_device *pdev)
974 const struct rsnd_of_data *of_data, 974 const struct rsnd_of_data *of_data,
975 struct rsnd_priv *priv) = { 975 struct rsnd_priv *priv) = {
976 rsnd_gen_probe, 976 rsnd_gen_probe,
977 rsnd_dma_probe,
977 rsnd_ssi_probe, 978 rsnd_ssi_probe,
978 rsnd_src_probe, 979 rsnd_src_probe,
979 rsnd_dvc_probe, 980 rsnd_dvc_probe,
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index c911c079fdd0..a01bb8c6b068 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -8,8 +8,29 @@
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11#include <linux/delay.h>
11#include "rsnd.h" 12#include "rsnd.h"
12 13
14/*
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 */
13static void rsnd_dmaen_complete(void *data) 34static void rsnd_dmaen_complete(void *data)
14{ 35{
15 struct rsnd_dma *dma = (struct rsnd_dma *)data; 36 struct rsnd_dma *dma = (struct rsnd_dma *)data;
@@ -108,6 +129,8 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id,
108 return -EIO; 129 return -EIO;
109 } 130 }
110 131
132 dev_dbg(dev, "Audio DMAC init\n");
133
111 dma_cap_zero(mask); 134 dma_cap_zero(mask);
112 dma_cap_set(DMA_SLAVE, mask); 135 dma_cap_set(DMA_SLAVE, mask);
113 136
@@ -168,6 +191,150 @@ static struct rsnd_dma_ops rsnd_dmaen_ops = {
168}; 191};
169 192
170/* 193/*
194 * Audio DMAC peri peri
195 */
196static const u8 gen2_id_table_ssiu[] = {
197 0x00, /* SSI00 */
198 0x04, /* SSI10 */
199 0x08, /* SSI20 */
200 0x0c, /* SSI3 */
201 0x0d, /* SSI4 */
202 0x0e, /* SSI5 */
203 0x0f, /* SSI6 */
204 0x10, /* SSI7 */
205 0x11, /* SSI8 */
206 0x12, /* SSI90 */
207};
208static const u8 gen2_id_table_scu[] = {
209 0x2d, /* SCU_SRCI0 */
210 0x2e, /* SCU_SRCI1 */
211 0x2f, /* SCU_SRCI2 */
212 0x30, /* SCU_SRCI3 */
213 0x31, /* SCU_SRCI4 */
214 0x32, /* SCU_SRCI5 */
215 0x33, /* SCU_SRCI6 */
216 0x34, /* SCU_SRCI7 */
217 0x35, /* SCU_SRCI8 */
218 0x36, /* SCU_SRCI9 */
219};
220static const u8 gen2_id_table_cmd[] = {
221 0x37, /* SCU_CMD0 */
222 0x38, /* SCU_CMD1 */
223};
224
225static u32 rsnd_dmapp_get_id(struct rsnd_mod *mod)
226{
227 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
228 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io);
229 struct rsnd_mod *src = rsnd_io_to_mod_src(io);
230 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
231 const u8 *entry = NULL;
232 int id = rsnd_mod_id(mod);
233 int size = 0;
234
235 if (mod == ssi) {
236 entry = gen2_id_table_ssiu;
237 size = ARRAY_SIZE(gen2_id_table_ssiu);
238 } else if (mod == src) {
239 entry = gen2_id_table_scu;
240 size = ARRAY_SIZE(gen2_id_table_scu);
241 } else if (mod == dvc) {
242 entry = gen2_id_table_cmd;
243 size = ARRAY_SIZE(gen2_id_table_cmd);
244 }
245
246 if (!entry)
247 return 0xFF;
248
249 if (size <= id)
250 return 0xFF;
251
252 return entry[id];
253}
254
255static u32 rsnd_dmapp_get_chcr(struct rsnd_mod *mod_from,
256 struct rsnd_mod *mod_to)
257{
258 return (rsnd_dmapp_get_id(mod_from) << 24) +
259 (rsnd_dmapp_get_id(mod_to) << 16);
260}
261
262#define rsnd_dmapp_addr(dmac, dma, reg) \
263 (dmac->base + 0x20 + (0x10 * dma->dmapp_id) + reg)
264static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg)
265{
266 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
267 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
268 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
269 struct device *dev = rsnd_priv_to_dev(priv);
270
271 dev_dbg(dev, "w %p : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data);
272
273 iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg));
274}
275
276static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg)
277{
278 struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
279 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
280 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
281
282 return ioread32(rsnd_dmapp_addr(dmac, dma, reg));
283}
284
285static void rsnd_dmapp_stop(struct rsnd_dma *dma)
286{
287 int i;
288
289 rsnd_dmapp_write(dma, 0, PDMACHCR);
290
291 for (i = 0; i < 1024; i++) {
292 if (0 == rsnd_dmapp_read(dma, PDMACHCR))
293 return;
294 udelay(1);
295 }
296}
297
298static void rsnd_dmapp_start(struct rsnd_dma *dma)
299{
300 rsnd_dmapp_write(dma, dma->src_addr, PDMASAR);
301 rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR);
302 rsnd_dmapp_write(dma, dma->chcr, PDMACHCR);
303}
304
305static int rsnd_dmapp_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id,
306 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
307{
308 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
309 struct device *dev = rsnd_priv_to_dev(priv);
310
311 dev_dbg(dev, "Audio DMAC peri peri init\n");
312
313 dma->dmapp_id = dmac->dmapp_num;
314 dma->chcr = rsnd_dmapp_get_chcr(mod_from, mod_to) | PDMACHCR_DE;
315
316 dmac->dmapp_num++;
317
318 rsnd_dmapp_stop(dma);
319
320 dev_dbg(dev, "id/src/dst/chcr = %d/%x/%x/%08x\n",
321 dma->dmapp_id, dma->src_addr, dma->dst_addr, dma->chcr);
322
323 return 0;
324}
325
326static struct rsnd_dma_ops rsnd_dmapp_ops = {
327 .start = rsnd_dmapp_start,
328 .stop = rsnd_dmapp_stop,
329 .init = rsnd_dmapp_init,
330 .quit = rsnd_dmapp_stop,
331};
332
333/*
334 * Common DMAC Interface
335 */
336
337/*
171 * DMA read/write register offset 338 * DMA read/write register offset
172 * 339 *
173 * RSND_xxx_I_N for Audio DMAC input 340 * RSND_xxx_I_N for Audio DMAC input
@@ -367,7 +534,49 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id)
367 dma->src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1); 534 dma->src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1);
368 dma->dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0); 535 dma->dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0);
369 536
370 dma->ops = &rsnd_dmaen_ops; 537 /* for Gen2 */
538 if (mod_from && mod_to)
539 dma->ops = &rsnd_dmapp_ops;
540 else
541 dma->ops = &rsnd_dmaen_ops;
542
543 /* for Gen1, overwrite */
544 if (rsnd_is_gen1(priv))
545 dma->ops = &rsnd_dmaen_ops;
371 546
372 return dma->ops->init(priv, dma, id, mod_from, mod_to); 547 return dma->ops->init(priv, dma, id, mod_from, mod_to);
373} 548}
549
550int rsnd_dma_probe(struct platform_device *pdev,
551 const struct rsnd_of_data *of_data,
552 struct rsnd_priv *priv)
553{
554 struct device *dev = rsnd_priv_to_dev(priv);
555 struct rsnd_dma_ctrl *dmac;
556 struct resource *res;
557
558 /*
559 * for Gen1
560 */
561 if (rsnd_is_gen1(priv))
562 return 0;
563
564 /*
565 * for Gen2
566 */
567 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp");
568 dmac = devm_kzalloc(dev, sizeof(*dmac), GFP_KERNEL);
569 if (!dmac || !res) {
570 dev_err(dev, "dma allocate failed\n");
571 return -ENOMEM;
572 }
573
574 dmac->dmapp_num = 0;
575 dmac->base = devm_ioremap_resource(dev, res);
576 if (IS_ERR(dmac->base))
577 return PTR_ERR(dmac->base);
578
579 priv->dma = dmac;
580
581 return 0;
582}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index c7299f74cf83..9e67142c82bd 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -184,6 +184,8 @@ struct rsnd_dma {
184 struct rsnd_dma_ops *ops; 184 struct rsnd_dma_ops *ops;
185 enum dma_transfer_direction dir; 185 enum dma_transfer_direction dir;
186 dma_addr_t addr; 186 dma_addr_t addr;
187 int dmapp_id;
188 u32 chcr;
187 dma_addr_t src_addr; 189 dma_addr_t src_addr;
188 dma_addr_t dst_addr; 190 dma_addr_t dst_addr;
189}; 191};
@@ -192,7 +194,9 @@ void rsnd_dma_start(struct rsnd_dma *dma);
192void rsnd_dma_stop(struct rsnd_dma *dma); 194void rsnd_dma_stop(struct rsnd_dma *dma);
193int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id); 195int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id);
194void rsnd_dma_quit(struct rsnd_dma *dma); 196void rsnd_dma_quit(struct rsnd_dma *dma);
195 197int rsnd_dma_probe(struct platform_device *pdev,
198 const struct rsnd_of_data *of_data,
199 struct rsnd_priv *priv);
196 200
197#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) 201#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
198 202
@@ -396,6 +400,11 @@ struct rsnd_priv {
396 void *adg; 400 void *adg;
397 401
398 /* 402 /*
403 * below value will be filled on rsnd_dma_probe()
404 */
405 void *dma;
406
407 /*
399 * below value will be filled on rsnd_ssi_probe() 408 * below value will be filled on rsnd_ssi_probe()
400 */ 409 */
401 void *ssi; 410 void *ssi;