aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2014-06-22 20:56:23 -0400
committerMark Brown <broonie@linaro.org>2014-06-28 09:41:19 -0400
commitd9288d0ba12de1b5efb830b9128e4cc6877318fc (patch)
treef02a9aabd4c12c16bb320e18b827270a25b48689 /sound/soc/sh
parent8457e0e9e274cae4898f84dd5aaeb5d2098126c8 (diff)
ASoC: rsnd: SSI + DMA can select BUSIF
Sound data needs to be sent to R-Car sound SSI when playback. But, there are 2 interfaces for it. 1st is SSITDR/SSIRDR which are mapped on SSI. 2nd is SSIn_BUSIF which are mapped on SSIU. 2nd SSIn_BUSIF is used when DMA transfer, and it is always used if sound data came from via SRC. But, we can use it when SSI+DMA case too. (Current driver is assuming 1st SSITDR/SSIRDR for it) 2nd SSIn_BUSIF can be used as FIFO. This is very helpful/useful for SSI+DMA. But DMA address / DMA ID are not same between 1st/2nd cases. This patch care about these settings. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/sh')
-rw-r--r--sound/soc/sh/rcar/core.c22
-rw-r--r--sound/soc/sh/rcar/gen.c64
-rw-r--r--sound/soc/sh/rcar/rsnd.h10
-rw-r--r--sound/soc/sh/rcar/src.c37
-rw-r--r--sound/soc/sh/rcar/ssi.c33
5 files changed, 121 insertions, 45 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 7f68b33dcbbb..8c3707a68603 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod)
138 return mod->ops->name; 138 return mod->ops->name;
139} 139}
140 140
141char *rsnd_mod_dma_name(struct rsnd_mod *mod)
142{
143 if (!mod || !mod->ops)
144 return "unknown";
145
146 if (!mod->ops->dma_name)
147 return mod->ops->name;
148
149 return mod->ops->dma_name(mod);
150}
151
141void rsnd_mod_init(struct rsnd_priv *priv, 152void rsnd_mod_init(struct rsnd_priv *priv,
142 struct rsnd_mod *mod, 153 struct rsnd_mod *mod,
143 struct rsnd_mod_ops *ops, 154 struct rsnd_mod_ops *ops,
@@ -261,7 +272,7 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod)
261{ 272{
262 if (mod) 273 if (mod)
263 return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", 274 return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d",
264 rsnd_mod_name(mod), rsnd_mod_id(mod)); 275 rsnd_mod_dma_name(mod), rsnd_mod_id(mod));
265 else 276 else
266 return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); 277 return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem");
267 278
@@ -343,11 +354,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
343 dma_cap_zero(mask); 354 dma_cap_zero(mask);
344 dma_cap_set(DMA_SLAVE, mask); 355 dma_cap_set(DMA_SLAVE, mask);
345 356
346 if (dev->of_node) 357 rsnd_dma_of_name(dma, is_play, dma_name);
347 rsnd_dma_of_name(dma, is_play, dma_name); 358 rsnd_gen_dma_addr(priv, dma, &cfg, is_play, id);
348 else
349 snprintf(dma_name, DMA_NAME_SIZE,
350 is_play ? "tx" : "rx");
351 359
352 dev_dbg(dev, "dma name : %s\n", dma_name); 360 dev_dbg(dev, "dma name : %s\n", dma_name);
353 361
@@ -359,8 +367,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
359 return -EIO; 367 return -EIO;
360 } 368 }
361 369
362 rsnd_gen_dma_addr(priv, dma, &cfg, is_play, id);
363
364 ret = dmaengine_slave_config(dma->chan, &cfg); 370 ret = dmaengine_slave_config(dma->chan, &cfg);
365 if (ret < 0) 371 if (ret < 0)
366 goto rsnd_dma_init_err; 372 goto rsnd_dma_init_err;
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 0280a11c0899..46677af6c748 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -165,15 +165,19 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
165 * 165 *
166 * ex) R-Car H2 case 166 * ex) R-Car H2 case
167 * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out 167 * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
168 * SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000 168 * SSI : 0xec541000 / 0xec241008 / 0xec24100c
169 * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
169 * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 170 * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
170 * CMD : 0xec500000 / 0xec008000 0xec308000 171 * CMD : 0xec500000 / 0xec008000 0xec308000
171 */ 172 */
172#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) 173#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
173#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) 174#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
174 175
175#define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) 176#define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
176#define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) 177#define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
178
179#define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
180#define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
177 181
178#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) 182#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
179#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) 183#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
@@ -204,26 +208,36 @@ static void rsnd_gen2_dma_addr(struct rsnd_priv *priv,
204 struct dma_addr { 208 struct dma_addr {
205 dma_addr_t src_addr; 209 dma_addr_t src_addr;
206 dma_addr_t dst_addr; 210 dma_addr_t dst_addr;
207 } dma_addrs[2][2][3] = { 211 } dma_addrs[3][2][3] = {
208 { /* SRC */ 212 /* SRC */
209 /* Capture */ 213 {{{ 0, 0 },
210 {{ 0, 0 }, 214 /* Capture */
211 { RDMA_SRC_O_N(src, id), 0 }, 215 { RDMA_SRC_O_N(src, id), 0 },
212 { RDMA_CMD_O_N(src, id), 0 }}, 216 { RDMA_CMD_O_N(src, id), 0 } },
213 /* Playback */ 217 /* Playback */
214 {{ 0, 0, }, 218 {{ 0, 0, },
215 { 0, RDMA_SRC_I_N(src, id) }, 219 { 0, RDMA_SRC_I_N(src, id) },
216 { 0, RDMA_SRC_I_N(src, id) }} 220 { 0, RDMA_SRC_I_N(src, id) } }
217 }, { /* SSI */ 221 },
218 /* Capture */ 222 /* SSI */
219 {{ RDMA_SSI_O_N(ssi, id), 0 }, 223 /* Capture */
220 { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }, 224 {{{ RDMA_SSI_O_N(ssi, id), 0 },
221 { RDMA_SSI_O_P(ssi, id), RDMA_SRC_I_P(src, id) }}, 225 { 0, 0 },
222 /* Playback */ 226 { 0, 0 } },
223 {{ 0, RDMA_SSI_I_N(ssi, id) }, 227 /* Playback */
224 { RDMA_SRC_O_P(src, id), RDMA_SSI_I_P(ssi, id) }, 228 {{ 0, RDMA_SSI_I_N(ssi, id) },
225 { RDMA_CMD_O_P(src, id), RDMA_SSI_I_P(ssi, id) }} 229 { 0, 0 },
226 } 230 { 0, 0 } }
231 },
232 /* SSIU */
233 /* Capture */
234 {{{ RDMA_SSIU_O_N(ssi, id), 0 },
235 { RDMA_SSIU_O_P(ssi, id), RDMA_SRC_I_P(src, id) },
236 { RDMA_SSIU_O_P(ssi, id), RDMA_SRC_I_P(src, id) } },
237 /* Playback */
238 {{ 0, RDMA_SSIU_I_N(ssi, id) },
239 { RDMA_SRC_O_P(src, id), RDMA_SSIU_I_P(ssi, id) },
240 { RDMA_CMD_O_P(src, id), RDMA_SSIU_I_P(ssi, id) } } },
227 }; 241 };
228 242
229 /* it shouldn't happen */ 243 /* it shouldn't happen */
@@ -232,6 +246,10 @@ static void rsnd_gen2_dma_addr(struct rsnd_priv *priv,
232 return; 246 return;
233 } 247 }
234 248
249 /* use SSIU or SSI ? */
250 if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu")))
251 is_ssi++;
252
235 cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr; 253 cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr;
236 cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr; 254 cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr;
237 255
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 067a89e9f25c..a1466c1570bc 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -185,6 +185,7 @@ enum rsnd_mod_type {
185 185
186struct rsnd_mod_ops { 186struct rsnd_mod_ops {
187 char *name; 187 char *name;
188 char* (*dma_name)(struct rsnd_mod *mod);
188 int (*probe)(struct rsnd_mod *mod, 189 int (*probe)(struct rsnd_mod *mod,
189 struct rsnd_dai *rdai); 190 struct rsnd_dai *rdai);
190 int (*remove)(struct rsnd_mod *mod, 191 int (*remove)(struct rsnd_mod *mod,
@@ -224,6 +225,7 @@ void rsnd_mod_init(struct rsnd_priv *priv,
224 enum rsnd_mod_type type, 225 enum rsnd_mod_type type,
225 int id); 226 int id);
226char *rsnd_mod_name(struct rsnd_mod *mod); 227char *rsnd_mod_name(struct rsnd_mod *mod);
228char *rsnd_mod_dma_name(struct rsnd_mod *mod);
227 229
228/* 230/*
229 * R-Car sound DAI 231 * R-Car sound DAI
@@ -391,8 +393,12 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
391unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, 393unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
392 struct rsnd_dai_stream *io, 394 struct rsnd_dai_stream *io,
393 struct snd_pcm_runtime *runtime); 395 struct snd_pcm_runtime *runtime);
394int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, 396int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
395 struct rsnd_dai *rdai); 397 struct rsnd_dai *rdai,
398 int use_busif);
399int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
400 struct rsnd_dai *rdai,
401 int use_busif);
396int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod, 402int rsnd_src_enable_ssi_irq(struct rsnd_mod *ssi_mod,
397 struct rsnd_dai *rdai); 403 struct rsnd_dai *rdai);
398 404
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 200eda019bc7..4d39505c21cf 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -106,18 +106,17 @@ struct rsnd_src {
106/* 106/*
107 * Gen1/Gen2 common functions 107 * Gen1/Gen2 common functions
108 */ 108 */
109int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod, 109int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
110 struct rsnd_dai *rdai) 110 struct rsnd_dai *rdai,
111 int use_busif)
111{ 112{
112 struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod);
113 struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
114 int ssi_id = rsnd_mod_id(ssi_mod); 113 int ssi_id = rsnd_mod_id(ssi_mod);
115 114
116 /* 115 /*
117 * SSI_MODE0 116 * SSI_MODE0
118 */ 117 */
119 rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), 118 rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id),
120 src_mod ? 0 : (1 << ssi_id)); 119 !use_busif << ssi_id);
121 120
122 /* 121 /*
123 * SSI_MODE1 122 * SSI_MODE1
@@ -143,6 +142,29 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
143 0x2 << shift : 0x1 << shift); 142 0x2 << shift : 0x1 << shift);
144 } 143 }
145 144
145 /*
146 * DMA settings for SSIU
147 */
148 if (use_busif) {
149 rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR,
150 rsnd_get_adinr(ssi_mod));
151 rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1);
152 rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1);
153 }
154
155 return 0;
156}
157
158int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod,
159 struct rsnd_dai *rdai,
160 int use_busif)
161{
162 /*
163 * DMA settings for SSIU
164 */
165 if (use_busif)
166 rsnd_mod_write(ssi_mod, SSI_CTRL, 0);
167
146 return 0; 168 return 0;
147} 169}
148 170
@@ -467,9 +489,6 @@ static int rsnd_src_set_convert_rate_gen2(struct rsnd_mod *mod,
467 if (ret < 0) 489 if (ret < 0)
468 return ret; 490 return ret;
469 491
470 rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr(mod));
471 rsnd_mod_write(mod, SSI_BUSIF_MODE, 1);
472
473 rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); 492 rsnd_mod_write(mod, SRC_SRCCR, 0x00011110);
474 493
475 rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); 494 rsnd_mod_write(mod, SRC_BSDSR, 0x01800000);
@@ -554,7 +573,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod,
554 573
555 rsnd_dma_start(rsnd_mod_to_dma(&src->mod)); 574 rsnd_dma_start(rsnd_mod_to_dma(&src->mod));
556 575
557 rsnd_mod_write(mod, SSI_CTRL, 0x1);
558 rsnd_mod_write(mod, SRC_CTRL, val); 576 rsnd_mod_write(mod, SRC_CTRL, val);
559 577
560 return rsnd_src_start(mod, rdai); 578 return rsnd_src_start(mod, rdai);
@@ -565,7 +583,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
565{ 583{
566 struct rsnd_src *src = rsnd_mod_to_src(mod); 584 struct rsnd_src *src = rsnd_mod_to_src(mod);
567 585
568 rsnd_mod_write(mod, SSI_CTRL, 0);
569 rsnd_mod_write(mod, SRC_CTRL, 0); 586 rsnd_mod_write(mod, SRC_CTRL, 0);
570 587
571 rsnd_dma_stop(rsnd_mod_to_dma(&src->mod)); 588 rsnd_dma_stop(rsnd_mod_to_dma(&src->mod));
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 2df723df5d19..34e84009162b 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -90,6 +90,20 @@ struct rsnd_ssi {
90#define rsnd_ssi_mode_flags(p) ((p)->info->flags) 90#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
91#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) 91#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
92 92
93static int rsnd_ssi_use_busif(struct rsnd_mod *mod)
94{
95 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
96 struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
97 int use_busif = 0;
98
99 if (!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_NO_BUSIF))
100 use_busif = 1;
101 if (rsnd_io_to_mod_src(io))
102 use_busif = 1;
103
104 return use_busif;
105}
106
93static void rsnd_ssi_status_check(struct rsnd_mod *mod, 107static void rsnd_ssi_status_check(struct rsnd_mod *mod,
94 u32 bit) 108 u32 bit)
95{ 109{
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
289 ssi->cr_own = cr; 303 ssi->cr_own = cr;
290 ssi->err = -1; /* ignore 1st error */ 304 ssi->err = -1; /* ignore 1st error */
291 305
292 rsnd_src_ssi_mode_init(mod, rdai);
293
294 return 0; 306 return 0;
295} 307}
296 308
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
389 /* enable PIO IRQ */ 401 /* enable PIO IRQ */
390 ssi->cr_etc = UIEN | OIEN | DIEN; 402 ssi->cr_etc = UIEN | OIEN | DIEN;
391 403
404 rsnd_src_ssiu_start(mod, rdai, 0);
405
392 rsnd_src_enable_ssi_irq(mod, rdai); 406 rsnd_src_enable_ssi_irq(mod, rdai);
393 407
394 rsnd_ssi_hw_start(ssi, rdai, io); 408 rsnd_ssi_hw_start(ssi, rdai, io);
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
405 419
406 rsnd_ssi_hw_stop(ssi, rdai); 420 rsnd_ssi_hw_stop(ssi, rdai);
407 421
422 rsnd_src_ssiu_stop(mod, rdai, 0);
423
408 return 0; 424 return 0;
409} 425}
410 426
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
457 /* enable DMA transfer */ 473 /* enable DMA transfer */
458 ssi->cr_etc = DMEN; 474 ssi->cr_etc = DMEN;
459 475
476 rsnd_src_ssiu_start(mod, rdai, rsnd_ssi_use_busif(mod));
477
460 rsnd_dma_start(dma); 478 rsnd_dma_start(dma);
461 479
462 rsnd_ssi_hw_start(ssi, ssi->rdai, io); 480 rsnd_ssi_hw_start(ssi, ssi->rdai, io);
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
482 500
483 rsnd_dma_stop(dma); 501 rsnd_dma_stop(dma);
484 502
503 rsnd_src_ssiu_stop(mod, rdai, 1);
504
485 return 0; 505 return 0;
486} 506}
487 507
508static char *rsnd_ssi_dma_name(struct rsnd_mod *mod)
509{
510 return rsnd_ssi_use_busif(mod) ? "ssiu" : SSI_NAME;
511}
512
488static struct rsnd_mod_ops rsnd_ssi_dma_ops = { 513static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
489 .name = SSI_NAME, 514 .name = SSI_NAME,
515 .dma_name = rsnd_ssi_dma_name,
490 .probe = rsnd_ssi_dma_probe, 516 .probe = rsnd_ssi_dma_probe,
491 .remove = rsnd_ssi_dma_remove, 517 .remove = rsnd_ssi_dma_remove,
492 .init = rsnd_ssi_init, 518 .init = rsnd_ssi_init,
@@ -595,6 +621,9 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev,
595 */ 621 */
596 ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ? 622 ssi_info->dma_id = of_get_property(np, "pio-transfer", NULL) ?
597 0 : 1; 623 0 : 1;
624
625 if (of_get_property(np, "no-busif", NULL))
626 ssi_info->flags |= RSND_SSI_NO_BUSIF;
598 } 627 }
599 628
600rsnd_of_parse_ssi_end: 629rsnd_of_parse_ssi_end: