dma.c (d1208404dd477c142680437137c9996b95bfd508) | dma.c (5ba17b42e1755c3c5cfe96370cfd47f34d01f62c) |
---|---|
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 --- 8 unchanged lines hidden (view full) --- 17 */ 18#define PDMASAR 0x00 19#define PDMADAR 0x04 20#define PDMACHCR 0x0c 21 22/* PDMACHCR */ 23#define PDMACHCR_DE (1 << 0) 24 | 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 --- 8 unchanged lines hidden (view full) --- 17 */ 18#define PDMASAR 0x00 19#define PDMADAR 0x04 20#define PDMACHCR 0x0c 21 22/* PDMACHCR */ 23#define PDMACHCR_DE (1 << 0) 24 |
25 26struct rsnd_dmaen { 27 struct dma_chan *chan; 28}; 29 30struct rsnd_dmapp { 31 int dmapp_id; 32 u32 chcr; 33}; 34 35struct rsnd_dma { 36 struct rsnd_mod mod; 37 dma_addr_t src_addr; 38 dma_addr_t dst_addr; 39 union { 40 struct rsnd_dmaen en; 41 struct rsnd_dmapp pp; 42 } dma; 43}; 44 |
|
25struct rsnd_dma_ctrl { 26 void __iomem *base; | 45struct rsnd_dma_ctrl { 46 void __iomem *base; |
47 int dmaen_num; |
|
27 int dmapp_num; 28}; 29 | 48 int dmapp_num; 49}; 50 |
30struct rsnd_dma_ops { 31 char *name; 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 | |
39#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma) | 51#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma) |
52#define rsnd_mod_to_dma(_mod) container_of((_mod), struct rsnd_dma, mod) 53#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en) 54#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp) |
|
40 41/* 42 * Audio DMAC 43 */ 44static void __rsnd_dmaen_complete(struct rsnd_mod *mod, 45 struct rsnd_dai_stream *io) 46{ 47 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); --- 24 unchanged lines hidden (view full) --- 72 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 | 55 56/* 57 * Audio DMAC 58 */ 59static void __rsnd_dmaen_complete(struct rsnd_mod *mod, 60 struct rsnd_dai_stream *io) 61{ 62 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); --- 24 unchanged lines hidden (view full) --- 87 88static void rsnd_dmaen_complete(void *data) 89{ 90 struct rsnd_mod *mod = data; 91 92 rsnd_mod_interrupt(mod, __rsnd_dmaen_complete); 93} 94 |
80static void rsnd_dmaen_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) | 95static int rsnd_dmaen_stop(struct rsnd_mod *mod, 96 struct rsnd_dai_stream *io, 97 struct rsnd_priv *priv) |
81{ | 98{ |
99 struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
|
82 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); 83 84 dmaengine_terminate_all(dmaen->chan); | 100 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); 101 102 dmaengine_terminate_all(dmaen->chan); |
103 104 return 0; |
|
85} 86 | 105} 106 |
87static void rsnd_dmaen_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) | 107static int rsnd_dmaen_start(struct rsnd_mod *mod, 108 struct rsnd_dai_stream *io, 109 struct rsnd_priv *priv) |
88{ | 110{ |
111 struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
|
89 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | 112 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); |
90 struct rsnd_mod *mod = rsnd_dma_to_mod(dma); 91 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | |
92 struct snd_pcm_substream *substream = io->substream; 93 struct device *dev = rsnd_priv_to_dev(priv); 94 struct dma_async_tx_descriptor *desc; 95 int is_play = rsnd_io_is_play(io); 96 97 desc = dmaengine_prep_dma_cyclic(dmaen->chan, 98 substream->runtime->dma_addr, 99 snd_pcm_lib_buffer_bytes(substream), 100 snd_pcm_lib_period_bytes(substream), 101 is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, 102 DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 103 104 if (!desc) { 105 dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); | 113 struct snd_pcm_substream *substream = io->substream; 114 struct device *dev = rsnd_priv_to_dev(priv); 115 struct dma_async_tx_descriptor *desc; 116 int is_play = rsnd_io_is_play(io); 117 118 desc = dmaengine_prep_dma_cyclic(dmaen->chan, 119 substream->runtime->dma_addr, 120 snd_pcm_lib_buffer_bytes(substream), 121 snd_pcm_lib_period_bytes(substream), 122 is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, 123 DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 124 125 if (!desc) { 126 dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); |
106 return; | 127 return -EIO; |
107 } 108 109 desc->callback = rsnd_dmaen_complete; | 128 } 129 130 desc->callback = rsnd_dmaen_complete; |
110 desc->callback_param = mod; | 131 desc->callback_param = rsnd_mod_get(dma); |
111 112 if (dmaengine_submit(desc) < 0) { 113 dev_err(dev, "dmaengine_submit() fail\n"); | 132 133 if (dmaengine_submit(desc) < 0) { 134 dev_err(dev, "dmaengine_submit() fail\n"); |
114 return; | 135 return -EIO; |
115 } 116 117 dma_async_issue_pending(dmaen->chan); | 136 } 137 138 dma_async_issue_pending(dmaen->chan); |
139 140 return 0; |
|
118} 119 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; --- 21 unchanged lines hidden (view full) --- 147 return NULL; 148 149 if (mod_from) 150 return rsnd_mod_dma_req(io, mod_from); 151 else 152 return rsnd_mod_dma_req(io, mod_to); 153} 154 | 141} 142 143struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, 144 struct rsnd_mod *mod, char *name) 145{ 146 struct dma_chan *chan; 147 struct device_node *np; 148 int i = 0; --- 21 unchanged lines hidden (view full) --- 170 return NULL; 171 172 if (mod_from) 173 return rsnd_mod_dma_req(io, mod_from); 174 else 175 return rsnd_mod_dma_req(io, mod_to); 176} 177 |
155static int rsnd_dmaen_init(struct rsnd_dai_stream *io, | 178static int rsnd_dmaen_remove(struct rsnd_mod *mod, 179 struct rsnd_dai_stream *io, 180 struct rsnd_priv *priv) 181{ 182 struct rsnd_dma *dma = rsnd_mod_to_dma(mod); 183 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); 184 185 if (dmaen->chan) 186 dma_release_channel(dmaen->chan); 187 188 dmaen->chan = NULL; 189 190 return 0; 191} 192 193static int rsnd_dmaen_attach(struct rsnd_dai_stream *io, |
156 struct rsnd_dma *dma, int id, 157 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) 158{ | 194 struct rsnd_dma *dma, int id, 195 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) 196{ |
197 struct rsnd_mod *mod = rsnd_mod_get(dma); |
|
159 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); 160 struct rsnd_priv *priv = rsnd_io_to_priv(io); | 198 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); 199 struct rsnd_priv *priv = rsnd_io_to_priv(io); |
200 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); |
|
161 struct device *dev = rsnd_priv_to_dev(priv); 162 struct dma_slave_config cfg = {}; 163 int is_play = rsnd_io_is_play(io); 164 int ret; 165 166 if (dmaen->chan) { 167 dev_err(dev, "it already has dma channel\n"); 168 return -EIO; --- 17 unchanged lines hidden (view full) --- 186 } 187 188 cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; 189 cfg.src_addr = dma->src_addr; 190 cfg.dst_addr = dma->dst_addr; 191 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 192 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 193 | 201 struct device *dev = rsnd_priv_to_dev(priv); 202 struct dma_slave_config cfg = {}; 203 int is_play = rsnd_io_is_play(io); 204 int ret; 205 206 if (dmaen->chan) { 207 dev_err(dev, "it already has dma channel\n"); 208 return -EIO; --- 17 unchanged lines hidden (view full) --- 226 } 227 228 cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; 229 cfg.src_addr = dma->src_addr; 230 cfg.dst_addr = dma->dst_addr; 231 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 232 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 233 |
194 dev_dbg(dev, "%s %pad -> %pad\n", 195 dma->ops->name, | 234 dev_dbg(dev, "%s[%d] %pad -> %pad\n", 235 rsnd_mod_name(mod), rsnd_mod_id(mod), |
196 &cfg.src_addr, &cfg.dst_addr); 197 198 ret = dmaengine_slave_config(dmaen->chan, &cfg); 199 if (ret < 0) | 236 &cfg.src_addr, &cfg.dst_addr); 237 238 ret = dmaengine_slave_config(dmaen->chan, &cfg); 239 if (ret < 0) |
200 goto rsnd_dma_init_err; | 240 goto rsnd_dma_attach_err; |
201 | 241 |
242 dmac->dmaen_num++; 243 |
|
202 return 0; 203 | 244 return 0; 245 |
204rsnd_dma_init_err: 205 rsnd_dma_quit(io, dma); | 246rsnd_dma_attach_err: 247 rsnd_dmaen_remove(mod, io, priv); |
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 | 248rsnd_dma_channel_err: 249 250 /* 251 * DMA failed. try to PIO mode 252 * see 253 * rsnd_ssi_fallback() 254 * rsnd_rdai_continuance_probe() 255 */ 256 return -EAGAIN; 257} 258 |
217static void rsnd_dmaen_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma) 218{ 219 struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); 220 221 if (dmaen->chan) 222 dma_release_channel(dmaen->chan); 223 224 dmaen->chan = NULL; 225} 226 227static struct rsnd_dma_ops rsnd_dmaen_ops = { | 259static struct rsnd_mod_ops rsnd_dmaen_ops = { |
228 .name = "audmac", 229 .start = rsnd_dmaen_start, 230 .stop = rsnd_dmaen_stop, | 260 .name = "audmac", 261 .start = rsnd_dmaen_start, 262 .stop = rsnd_dmaen_stop, |
231 .init = rsnd_dmaen_init, 232 .quit = rsnd_dmaen_quit, | 263 .remove = rsnd_dmaen_remove, |
233}; 234 235/* 236 * Audio DMAC peri peri 237 */ 238static const u8 gen2_id_table_ssiu[] = { 239 0x00, /* SSI00 */ 240 0x04, /* SSI10 */ --- 61 unchanged lines hidden (view full) --- 302 (rsnd_dmapp_get_id(io, mod_to) << 16); 303} 304 305#define rsnd_dmapp_addr(dmac, dma, reg) \ 306 (dmac->base + 0x20 + reg + \ 307 (0x10 * rsnd_dma_to_dmapp(dma)->dmapp_id)) 308static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg) 309{ | 264}; 265 266/* 267 * Audio DMAC peri peri 268 */ 269static const u8 gen2_id_table_ssiu[] = { 270 0x00, /* SSI00 */ 271 0x04, /* SSI10 */ --- 61 unchanged lines hidden (view full) --- 333 (rsnd_dmapp_get_id(io, mod_to) << 16); 334} 335 336#define rsnd_dmapp_addr(dmac, dma, reg) \ 337 (dmac->base + 0x20 + reg + \ 338 (0x10 * rsnd_dma_to_dmapp(dma)->dmapp_id)) 339static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg) 340{ |
310 struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 341 struct rsnd_mod *mod = rsnd_mod_get(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{ | 342 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 343 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); 344 struct device *dev = rsnd_priv_to_dev(priv); 345 346 dev_dbg(dev, "w %p : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data); 347 348 iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg)); 349} 350 351static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg) 352{ |
322 struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 353 struct rsnd_mod *mod = rsnd_mod_get(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 | 354 struct rsnd_priv *priv = rsnd_mod_to_priv(mod); 355 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); 356 357 return ioread32(rsnd_dmapp_addr(dmac, dma, reg)); 358} 359 |
329static void rsnd_dmapp_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) | 360static int rsnd_dmapp_stop(struct rsnd_mod *mod, 361 struct rsnd_dai_stream *io, 362 struct rsnd_priv *priv) |
330{ | 363{ |
364 struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
|
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)) | 365 int i; 366 367 rsnd_dmapp_write(dma, 0, PDMACHCR); 368 369 for (i = 0; i < 1024; i++) { 370 if (0 == rsnd_dmapp_read(dma, PDMACHCR)) |
337 return; | 371 return 0; |
338 udelay(1); 339 } | 372 udelay(1); 373 } |
374 375 return -EIO; |
|
340} 341 | 376} 377 |
342static void rsnd_dmapp_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) | 378static int rsnd_dmapp_start(struct rsnd_mod *mod, 379 struct rsnd_dai_stream *io, 380 struct rsnd_priv *priv) |
343{ | 381{ |
382 struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
|
344 struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); 345 346 rsnd_dmapp_write(dma, dma->src_addr, PDMASAR); 347 rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR); 348 rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR); | 383 struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); 384 385 rsnd_dmapp_write(dma, dma->src_addr, PDMASAR); 386 rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR); 387 rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR); |
388 389 return 0; |
|
349} 350 | 390} 391 |
351static int rsnd_dmapp_init(struct rsnd_dai_stream *io, 352 struct rsnd_dma *dma, int id, 353 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) | 392static int rsnd_dmapp_attach(struct rsnd_dai_stream *io, 393 struct rsnd_dma *dma, int id, 394 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) |
354{ 355 struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); 356 struct rsnd_priv *priv = rsnd_io_to_priv(io); 357 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); 358 struct device *dev = rsnd_priv_to_dev(priv); 359 360 dmapp->dmapp_id = dmac->dmapp_num; 361 dmapp->chcr = rsnd_dmapp_get_chcr(io, mod_from, mod_to) | PDMACHCR_DE; 362 363 dmac->dmapp_num++; 364 | 395{ 396 struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); 397 struct rsnd_priv *priv = rsnd_io_to_priv(io); 398 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); 399 struct device *dev = rsnd_priv_to_dev(priv); 400 401 dmapp->dmapp_id = dmac->dmapp_num; 402 dmapp->chcr = rsnd_dmapp_get_chcr(io, mod_from, mod_to) | PDMACHCR_DE; 403 404 dmac->dmapp_num++; 405 |
365 rsnd_dmapp_stop(io, dma); 366 | |
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); 369 370 return 0; 371} 372 | 406 dev_dbg(dev, "id/src/dst/chcr = %d/%pad/%pad/%08x\n", 407 dmapp->dmapp_id, &dma->src_addr, &dma->dst_addr, dmapp->chcr); 408 409 return 0; 410} 411 |
373static struct rsnd_dma_ops rsnd_dmapp_ops = { | 412static struct rsnd_mod_ops rsnd_dmapp_ops = { |
374 .name = "audmac-pp", 375 .start = rsnd_dmapp_start, 376 .stop = rsnd_dmapp_stop, | 413 .name = "audmac-pp", 414 .start = rsnd_dmapp_start, 415 .stop = rsnd_dmapp_stop, |
377 .init = rsnd_dmapp_init, | |
378 .quit = rsnd_dmapp_stop, 379}; 380 381/* 382 * Common DMAC Interface 383 */ 384 385/* --- 106 unchanged lines hidden (view full) --- 492 493 if (!mod) 494 return 0; 495 496 return rsnd_gen2_dma_addr(io, mod, is_play, is_from); 497} 498 499#define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */ | 416 .quit = rsnd_dmapp_stop, 417}; 418 419/* 420 * Common DMAC Interface 421 */ 422 423/* --- 106 unchanged lines hidden (view full) --- 530 531 if (!mod) 532 return 0; 533 534 return rsnd_gen2_dma_addr(io, mod, is_play, is_from); 535} 536 537#define MOD_MAX (RSND_MOD_MAX + 1) /* +Memory */ |
500static void rsnd_dma_of_path(struct rsnd_dma *dma, | 538static void rsnd_dma_of_path(struct rsnd_mod *this, |
501 struct rsnd_dai_stream *io, 502 int is_play, 503 struct rsnd_mod **mod_from, 504 struct rsnd_mod **mod_to) 505{ | 539 struct rsnd_dai_stream *io, 540 int is_play, 541 struct rsnd_mod **mod_from, 542 struct rsnd_mod **mod_to) 543{ |
506 struct rsnd_mod *this = rsnd_dma_to_mod(dma); | |
507 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); 508 struct rsnd_mod *src = rsnd_io_to_mod_src(io); 509 struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io); 510 struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); 511 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); 512 struct rsnd_mod *mod[MOD_MAX]; 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); | 544 struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); 545 struct rsnd_mod *src = rsnd_io_to_mod_src(io); 546 struct rsnd_mod *ctu = rsnd_io_to_mod_ctu(io); 547 struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); 548 struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); 549 struct rsnd_mod *mod[MOD_MAX]; 550 struct rsnd_mod *mod_start, *mod_end; 551 struct rsnd_priv *priv = rsnd_mod_to_priv(this); 552 struct device *dev = rsnd_priv_to_dev(priv); |
516 int nr, i; | 553 int nr, i, idx; |
517 518 if (!ssi) 519 return; 520 521 nr = 0; 522 for (i = 0; i < MOD_MAX; i++) { 523 mod[i] = NULL; 524 nr += !!rsnd_io_to_mod(io, i); --- 12 unchanged lines hidden (view full) --- 537 * [E] = mem 538 * 539 * -*-> Audio DMAC 540 * -o-> Audio DMAC peri peri 541 */ 542 mod_start = (is_play) ? NULL : ssi; 543 mod_end = (is_play) ? ssi : NULL; 544 | 554 555 if (!ssi) 556 return; 557 558 nr = 0; 559 for (i = 0; i < MOD_MAX; i++) { 560 mod[i] = NULL; 561 nr += !!rsnd_io_to_mod(io, i); --- 12 unchanged lines hidden (view full) --- 574 * [E] = mem 575 * 576 * -*-> Audio DMAC 577 * -o-> Audio DMAC peri peri 578 */ 579 mod_start = (is_play) ? NULL : ssi; 580 mod_end = (is_play) ? ssi : NULL; 581 |
545 mod[0] = mod_start; | 582 idx = 0; 583 mod[idx++] = mod_start; |
546 for (i = 1; i < nr; i++) { 547 if (src) { | 584 for (i = 1; i < nr; i++) { 585 if (src) { |
548 mod[i] = src; | 586 mod[idx++] = src; |
549 src = NULL; 550 } else if (ctu) { | 587 src = NULL; 588 } else if (ctu) { |
551 mod[i] = ctu; | 589 mod[idx++] = ctu; |
552 ctu = NULL; 553 } else if (mix) { | 590 ctu = NULL; 591 } else if (mix) { |
554 mod[i] = mix; | 592 mod[idx++] = mix; |
555 mix = NULL; 556 } else if (dvc) { | 593 mix = NULL; 594 } else if (dvc) { |
557 mod[i] = dvc; | 595 mod[idx++] = dvc; |
558 dvc = NULL; 559 } 560 } | 596 dvc = NULL; 597 } 598 } |
561 mod[i] = mod_end; | 599 mod[idx] = mod_end; |
562 563 /* 564 * | SSI | SRC | 565 * -------------+-----+-----+ 566 * is_play | o | * | 567 * !is_play | * | o | 568 */ 569 if ((this == ssi) == (is_play)) { | 600 601 /* 602 * | SSI | SRC | 603 * -------------+-----+-----+ 604 * is_play | o | * | 605 * !is_play | * | o | 606 */ 607 if ((this == ssi) == (is_play)) { |
570 *mod_from = mod[nr - 1]; 571 *mod_to = mod[nr]; | 608 *mod_from = mod[idx - 1]; 609 *mod_to = mod[idx]; |
572 } else { 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)); | 610 } else { 611 *mod_from = mod[0]; 612 *mod_to = mod[1]; 613 } 614 615 dev_dbg(dev, "module connection (this is %s[%d])\n", 616 rsnd_mod_name(this), rsnd_mod_id(this)); |
579 for (i = 0; i <= nr; i++) { | 617 for (i = 0; i <= idx; 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" : ""); 584 } 585} 586 | 618 dev_dbg(dev, " %s[%d]%s\n", 619 rsnd_mod_name(mod[i]), rsnd_mod_id(mod[i]), 620 (mod[i] == *mod_from) ? " from" : 621 (mod[i] == *mod_to) ? " to" : ""); 622 } 623} 624 |
587void rsnd_dma_stop(struct rsnd_dai_stream *io, struct rsnd_dma *dma) | 625struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io, 626 struct rsnd_mod *mod, int id) |
588{ | 627{ |
589 dma->ops->stop(io, dma); 590} 591 592void rsnd_dma_start(struct rsnd_dai_stream *io, struct rsnd_dma *dma) 593{ 594 dma->ops->start(io, dma); 595} 596 597void rsnd_dma_quit(struct rsnd_dai_stream *io, struct rsnd_dma *dma) 598{ 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 606 dma->ops->quit(io, dma); 607} 608 609int rsnd_dma_init(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id) 610{ | 628 struct rsnd_mod *dma_mod; |
611 struct rsnd_mod *mod_from = NULL; 612 struct rsnd_mod *mod_to = NULL; 613 struct rsnd_priv *priv = rsnd_io_to_priv(io); 614 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); | 629 struct rsnd_mod *mod_from = NULL; 630 struct rsnd_mod *mod_to = NULL; 631 struct rsnd_priv *priv = rsnd_io_to_priv(io); 632 struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); |
633 struct rsnd_dma *dma; |
|
615 struct device *dev = rsnd_priv_to_dev(priv); | 634 struct device *dev = rsnd_priv_to_dev(priv); |
635 struct rsnd_mod_ops *ops; 636 enum rsnd_mod_type type; 637 int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id, 638 struct rsnd_mod *mod_from, struct rsnd_mod *mod_to); |
|
616 int is_play = rsnd_io_is_play(io); | 639 int is_play = rsnd_io_is_play(io); |
640 int ret, dma_id; |
|
617 618 /* 619 * DMA failed. try to PIO mode 620 * see 621 * rsnd_ssi_fallback() 622 * rsnd_rdai_continuance_probe() 623 */ 624 if (!dmac) | 641 642 /* 643 * DMA failed. try to PIO mode 644 * see 645 * rsnd_ssi_fallback() 646 * rsnd_rdai_continuance_probe() 647 */ 648 if (!dmac) |
625 return -EAGAIN; | 649 return ERR_PTR(-EAGAIN); |
626 | 650 |
627 rsnd_dma_of_path(dma, io, is_play, &mod_from, &mod_to); | 651 dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); 652 if (!dma) 653 return ERR_PTR(-ENOMEM); |
628 | 654 |
655 rsnd_dma_of_path(mod, io, is_play, &mod_from, &mod_to); 656 |
|
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); 631 632 /* for Gen2 */ | 657 dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1); 658 dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0); 659 660 /* for Gen2 */ |
633 if (mod_from && mod_to) 634 dma->ops = &rsnd_dmapp_ops; 635 else 636 dma->ops = &rsnd_dmaen_ops; | 661 if (mod_from && mod_to) { 662 ops = &rsnd_dmapp_ops; 663 attach = rsnd_dmapp_attach; 664 dma_id = dmac->dmapp_num; 665 type = RSND_MOD_AUDMAPP; 666 } else { 667 ops = &rsnd_dmaen_ops; 668 attach = rsnd_dmaen_attach; 669 dma_id = dmac->dmaen_num; 670 type = RSND_MOD_AUDMA; 671 } |
637 638 /* for Gen1, overwrite */ | 672 673 /* for Gen1, overwrite */ |
639 if (rsnd_is_gen1(priv)) 640 dma->ops = &rsnd_dmaen_ops; | 674 if (rsnd_is_gen1(priv)) { 675 ops = &rsnd_dmaen_ops; 676 attach = rsnd_dmaen_attach; 677 dma_id = dmac->dmaen_num; 678 type = RSND_MOD_AUDMA; 679 } |
641 | 680 |
642 dev_dbg(dev, "%s %s[%d] -> %s[%d]\n", 643 dma->ops->name, | 681 dma_mod = rsnd_mod_get(dma); 682 683 ret = rsnd_mod_init(priv, dma_mod, 684 ops, NULL, rsnd_mod_get_status, type, dma_id); 685 if (ret < 0) 686 return ERR_PTR(ret); 687 688 dev_dbg(dev, "%s[%d] %s[%d] -> %s[%d]\n", 689 rsnd_mod_name(dma_mod), rsnd_mod_id(dma_mod), |
644 rsnd_mod_name(mod_from), rsnd_mod_id(mod_from), 645 rsnd_mod_name(mod_to), rsnd_mod_id(mod_to)); 646 | 690 rsnd_mod_name(mod_from), rsnd_mod_id(mod_from), 691 rsnd_mod_name(mod_to), rsnd_mod_id(mod_to)); 692 |
647 return dma->ops->init(io, dma, id, mod_from, mod_to); | 693 ret = attach(io, dma, id, mod_from, mod_to); 694 if (ret < 0) 695 return ERR_PTR(ret); 696 697 ret = rsnd_dai_connect(dma_mod, io, type); 698 if (ret < 0) 699 return ERR_PTR(ret); 700 701 return rsnd_mod_get(dma); |
648} 649 | 702} 703 |
650int rsnd_dma_probe(struct platform_device *pdev, 651 const struct rsnd_of_data *of_data, 652 struct rsnd_priv *priv) | 704int rsnd_dma_probe(struct rsnd_priv *priv) |
653{ | 705{ |
706 struct platform_device *pdev = rsnd_priv_to_pdev(priv); |
|
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)) --- 21 unchanged lines hidden --- | 707 struct device *dev = rsnd_priv_to_dev(priv); 708 struct rsnd_dma_ctrl *dmac; 709 struct resource *res; 710 711 /* 712 * for Gen1 713 */ 714 if (rsnd_is_gen1(priv)) --- 21 unchanged lines hidden --- |