diff options
author | Mark Brown <broonie@kernel.org> | 2017-11-10 16:30:57 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-11-10 16:30:57 -0500 |
commit | f904f84609b679c4bd056095a8d778bb40a049cb (patch) | |
tree | 8a3ff7acd944e928b79a807a516091eb9e4f320e | |
parent | 1cae41464ca8a1cced5ce00832f76e5881d2d23b (diff) | |
parent | c409c2a963475f0288ba3bb47a10f04f6441ffb9 (diff) |
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
-rw-r--r-- | Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt | 5 | ||||
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 72 | ||||
-rw-r--r-- | sound/soc/sh/rcar/core.c | 51 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ctu.c | 88 | ||||
-rw-r--r-- | sound/soc/sh/rcar/dma.c | 84 | ||||
-rw-r--r-- | sound/soc/sh/rcar/dvc.c | 60 | ||||
-rw-r--r-- | sound/soc/sh/rcar/mix.c | 158 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 22 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 53 |
9 files changed, 403 insertions, 190 deletions
diff --git a/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt index 8b8afe9fcb31..441dd6f29df1 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt +++ b/Documentation/devicetree/bindings/sound/audio-graph-scu-card.txt | |||
@@ -43,7 +43,7 @@ Example 1. Sampling Rate Conversion | |||
43 | label = "sound-card"; | 43 | label = "sound-card"; |
44 | prefix = "codec"; | 44 | prefix = "codec"; |
45 | routing = "codec Playback", "DAI0 Playback", | 45 | routing = "codec Playback", "DAI0 Playback", |
46 | "codec Playback", "DAI1 Playback"; | 46 | "DAI0 Capture", "codec Capture"; |
47 | convert-rate = <48000>; | 47 | convert-rate = <48000>; |
48 | 48 | ||
49 | dais = <&cpu_port>; | 49 | dais = <&cpu_port>; |
@@ -79,7 +79,8 @@ Example 2. 2 CPU 1 Codec (Mixing) | |||
79 | label = "sound-card"; | 79 | label = "sound-card"; |
80 | prefix = "codec"; | 80 | prefix = "codec"; |
81 | routing = "codec Playback", "DAI0 Playback", | 81 | routing = "codec Playback", "DAI0 Playback", |
82 | "codec Playback", "DAI1 Playback"; | 82 | "codec Playback", "DAI1 Playback", |
83 | "DAI0 Capture", "codec Capture"; | ||
83 | convert-rate = <48000>; | 84 | convert-rate = <48000>; |
84 | 85 | ||
85 | dais = <&cpu_port0 | 86 | dais = <&cpu_port0 |
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index e11ce5036bcf..8ddb08714faa 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -44,7 +44,6 @@ struct rsnd_adg { | |||
44 | 44 | ||
45 | #define LRCLK_ASYNC (1 << 0) | 45 | #define LRCLK_ASYNC (1 << 0) |
46 | #define AUDIO_OUT_48 (1 << 1) | 46 | #define AUDIO_OUT_48 (1 << 1) |
47 | #define adg_mode_flags(adg) (adg->flags) | ||
48 | 47 | ||
49 | #define for_each_rsnd_clk(pos, adg, i) \ | 48 | #define for_each_rsnd_clk(pos, adg, i) \ |
50 | for (i = 0; \ | 49 | for (i = 0; \ |
@@ -58,6 +57,13 @@ struct rsnd_adg { | |||
58 | i++) | 57 | i++) |
59 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) | 58 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) |
60 | 59 | ||
60 | static const char * const clk_name[] = { | ||
61 | [CLKA] = "clk_a", | ||
62 | [CLKB] = "clk_b", | ||
63 | [CLKC] = "clk_c", | ||
64 | [CLKI] = "clk_i", | ||
65 | }; | ||
66 | |||
61 | static u32 rsnd_adg_calculate_rbgx(unsigned long div) | 67 | static u32 rsnd_adg_calculate_rbgx(unsigned long div) |
62 | { | 68 | { |
63 | int i, ratio; | 69 | int i, ratio; |
@@ -280,6 +286,7 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val) | |||
280 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); | 286 | struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); |
281 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | 287 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); |
282 | struct rsnd_mod *adg_mod = rsnd_mod_get(adg); | 288 | struct rsnd_mod *adg_mod = rsnd_mod_get(adg); |
289 | struct device *dev = rsnd_priv_to_dev(priv); | ||
283 | int id = rsnd_mod_id(ssi_mod); | 290 | int id = rsnd_mod_id(ssi_mod); |
284 | int shift = (id % 4) * 8; | 291 | int shift = (id % 4) * 8; |
285 | u32 mask = 0xFF << shift; | 292 | u32 mask = 0xFF << shift; |
@@ -306,12 +313,13 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val) | |||
306 | rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL2, mask, val); | 313 | rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL2, mask, val); |
307 | break; | 314 | break; |
308 | } | 315 | } |
316 | |||
317 | dev_dbg(dev, "AUDIO_CLK_SEL is 0x%x\n", val); | ||
309 | } | 318 | } |
310 | 319 | ||
311 | int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) | 320 | int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) |
312 | { | 321 | { |
313 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | 322 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); |
314 | struct device *dev = rsnd_priv_to_dev(priv); | ||
315 | struct clk *clk; | 323 | struct clk *clk; |
316 | int i; | 324 | int i; |
317 | int sel_table[] = { | 325 | int sel_table[] = { |
@@ -321,8 +329,6 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) | |||
321 | [CLKI] = 0x0, | 329 | [CLKI] = 0x0, |
322 | }; | 330 | }; |
323 | 331 | ||
324 | dev_dbg(dev, "request clock = %d\n", rate); | ||
325 | |||
326 | /* | 332 | /* |
327 | * find suitable clock from | 333 | * find suitable clock from |
328 | * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. | 334 | * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. |
@@ -366,8 +372,8 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) | |||
366 | 372 | ||
367 | rsnd_adg_set_ssi_clk(ssi_mod, data); | 373 | rsnd_adg_set_ssi_clk(ssi_mod, data); |
368 | 374 | ||
369 | if (adg_mode_flags(adg) & LRCLK_ASYNC) { | 375 | if (rsnd_flags_has(adg, LRCLK_ASYNC)) { |
370 | if (adg_mode_flags(adg) & AUDIO_OUT_48) | 376 | if (rsnd_flags_has(adg, AUDIO_OUT_48)) |
371 | ckr = 0x80000000; | 377 | ckr = 0x80000000; |
372 | } else { | 378 | } else { |
373 | if (0 == (rate % 8000)) | 379 | if (0 == (rate % 8000)) |
@@ -378,9 +384,10 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) | |||
378 | rsnd_mod_write(adg_mod, BRRA, adg->rbga); | 384 | rsnd_mod_write(adg_mod, BRRA, adg->rbga); |
379 | rsnd_mod_write(adg_mod, BRRB, adg->rbgb); | 385 | rsnd_mod_write(adg_mod, BRRB, adg->rbgb); |
380 | 386 | ||
381 | dev_dbg(dev, "ADG: %s[%d] selects 0x%x for %d\n", | 387 | dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n", |
382 | rsnd_mod_name(ssi_mod), rsnd_mod_id(ssi_mod), | 388 | (ckr) ? 'B' : 'A', |
383 | data, rate); | 389 | (ckr) ? adg->rbgb_rate_for_48khz : |
390 | adg->rbga_rate_for_441khz); | ||
384 | 391 | ||
385 | return 0; | 392 | return 0; |
386 | } | 393 | } |
@@ -409,21 +416,12 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv, | |||
409 | { | 416 | { |
410 | struct device *dev = rsnd_priv_to_dev(priv); | 417 | struct device *dev = rsnd_priv_to_dev(priv); |
411 | struct clk *clk; | 418 | struct clk *clk; |
412 | static const char * const clk_name[] = { | ||
413 | [CLKA] = "clk_a", | ||
414 | [CLKB] = "clk_b", | ||
415 | [CLKC] = "clk_c", | ||
416 | [CLKI] = "clk_i", | ||
417 | }; | ||
418 | int i; | 419 | int i; |
419 | 420 | ||
420 | for (i = 0; i < CLKMAX; i++) { | 421 | for (i = 0; i < CLKMAX; i++) { |
421 | clk = devm_clk_get(dev, clk_name[i]); | 422 | clk = devm_clk_get(dev, clk_name[i]); |
422 | adg->clk[i] = IS_ERR(clk) ? NULL : clk; | 423 | adg->clk[i] = IS_ERR(clk) ? NULL : clk; |
423 | } | 424 | } |
424 | |||
425 | for_each_rsnd_clk(clk, adg, i) | ||
426 | dev_dbg(dev, "clk %d : %p : %ld\n", i, clk, clk_get_rate(clk)); | ||
427 | } | 425 | } |
428 | 426 | ||
429 | static void rsnd_adg_get_clkout(struct rsnd_priv *priv, | 427 | static void rsnd_adg_get_clkout(struct rsnd_priv *priv, |
@@ -479,10 +477,10 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, | |||
479 | } | 477 | } |
480 | 478 | ||
481 | if (req_rate[0] % 48000 == 0) | 479 | if (req_rate[0] % 48000 == 0) |
482 | adg->flags |= AUDIO_OUT_48; | 480 | rsnd_flags_set(adg, AUDIO_OUT_48); |
483 | 481 | ||
484 | if (of_get_property(np, "clkout-lr-asynchronous", NULL)) | 482 | if (of_get_property(np, "clkout-lr-asynchronous", NULL)) |
485 | adg->flags |= LRCLK_ASYNC; | 483 | rsnd_flags_set(adg, LRCLK_ASYNC); |
486 | 484 | ||
487 | /* | 485 | /* |
488 | * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC | 486 | * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC |
@@ -512,7 +510,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, | |||
512 | adg->rbga_rate_for_441khz = rate / div; | 510 | adg->rbga_rate_for_441khz = rate / div; |
513 | ckr |= brg_table[i] << 20; | 511 | ckr |= brg_table[i] << 20; |
514 | if (req_441kHz_rate && | 512 | if (req_441kHz_rate && |
515 | !(adg_mode_flags(adg) & AUDIO_OUT_48)) | 513 | !rsnd_flags_has(adg, AUDIO_OUT_48)) |
516 | parent_clk_name = __clk_get_name(clk); | 514 | parent_clk_name = __clk_get_name(clk); |
517 | } | 515 | } |
518 | } | 516 | } |
@@ -528,7 +526,7 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, | |||
528 | adg->rbgb_rate_for_48khz = rate / div; | 526 | adg->rbgb_rate_for_48khz = rate / div; |
529 | ckr |= brg_table[i] << 16; | 527 | ckr |= brg_table[i] << 16; |
530 | if (req_48kHz_rate && | 528 | if (req_48kHz_rate && |
531 | (adg_mode_flags(adg) & AUDIO_OUT_48)) | 529 | rsnd_flags_has(adg, AUDIO_OUT_48)) |
532 | parent_clk_name = __clk_get_name(clk); | 530 | parent_clk_name = __clk_get_name(clk); |
533 | } | 531 | } |
534 | } | 532 | } |
@@ -572,12 +570,35 @@ rsnd_adg_get_clkout_end: | |||
572 | adg->ckr = ckr; | 570 | adg->ckr = ckr; |
573 | adg->rbga = rbga; | 571 | adg->rbga = rbga; |
574 | adg->rbgb = rbgb; | 572 | adg->rbgb = rbgb; |
573 | } | ||
574 | |||
575 | #ifdef DEBUG | ||
576 | static void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct rsnd_adg *adg) | ||
577 | { | ||
578 | struct device *dev = rsnd_priv_to_dev(priv); | ||
579 | struct clk *clk; | ||
580 | int i; | ||
581 | |||
582 | for_each_rsnd_clk(clk, adg, i) | ||
583 | dev_dbg(dev, "%s : %p : %ld\n", | ||
584 | clk_name[i], clk, clk_get_rate(clk)); | ||
575 | 585 | ||
576 | for_each_rsnd_clkout(clk, adg, i) | ||
577 | dev_dbg(dev, "clkout %d : %p : %ld\n", i, clk, clk_get_rate(clk)); | ||
578 | dev_dbg(dev, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", | 586 | dev_dbg(dev, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", |
579 | ckr, rbga, rbgb); | 587 | adg->ckr, adg->rbga, adg->rbgb); |
588 | dev_dbg(dev, "BRGA (for 44100 base) = %d\n", adg->rbga_rate_for_441khz); | ||
589 | dev_dbg(dev, "BRGB (for 48000 base) = %d\n", adg->rbgb_rate_for_48khz); | ||
590 | |||
591 | /* | ||
592 | * Actual CLKOUT will be exchanged in rsnd_adg_ssi_clk_try_start() | ||
593 | * by BRGCKR::BRGCKR_31 | ||
594 | */ | ||
595 | for_each_rsnd_clkout(clk, adg, i) | ||
596 | dev_dbg(dev, "clkout %d : %p : %ld\n", i, | ||
597 | clk, clk_get_rate(clk)); | ||
580 | } | 598 | } |
599 | #else | ||
600 | #define rsnd_adg_clk_dbg_info(priv, adg) | ||
601 | #endif | ||
581 | 602 | ||
582 | int rsnd_adg_probe(struct rsnd_priv *priv) | 603 | int rsnd_adg_probe(struct rsnd_priv *priv) |
583 | { | 604 | { |
@@ -596,6 +617,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv) | |||
596 | 617 | ||
597 | rsnd_adg_get_clkin(priv, adg); | 618 | rsnd_adg_get_clkin(priv, adg); |
598 | rsnd_adg_get_clkout(priv, adg); | 619 | rsnd_adg_get_clkout(priv, adg); |
620 | rsnd_adg_clk_dbg_info(priv, adg); | ||
599 | 621 | ||
600 | priv->adg = adg; | 622 | priv->adg = adg; |
601 | 623 | ||
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 107133297e8d..c70eb2097816 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -121,14 +121,6 @@ void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type) | |||
121 | } | 121 | } |
122 | } | 122 | } |
123 | 123 | ||
124 | char *rsnd_mod_name(struct rsnd_mod *mod) | ||
125 | { | ||
126 | if (!mod || !mod->ops) | ||
127 | return "unknown"; | ||
128 | |||
129 | return mod->ops->name; | ||
130 | } | ||
131 | |||
132 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, | 124 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, |
133 | struct rsnd_mod *mod) | 125 | struct rsnd_mod *mod) |
134 | { | 126 | { |
@@ -172,8 +164,7 @@ int rsnd_mod_init(struct rsnd_priv *priv, | |||
172 | 164 | ||
173 | void rsnd_mod_quit(struct rsnd_mod *mod) | 165 | void rsnd_mod_quit(struct rsnd_mod *mod) |
174 | { | 166 | { |
175 | if (mod->clk) | 167 | clk_unprepare(mod->clk); |
176 | clk_unprepare(mod->clk); | ||
177 | mod->clk = NULL; | 168 | mod->clk = NULL; |
178 | } | 169 | } |
179 | 170 | ||
@@ -200,7 +191,10 @@ void rsnd_mod_interrupt(struct rsnd_mod *mod, | |||
200 | int rsnd_io_is_working(struct rsnd_dai_stream *io) | 191 | int rsnd_io_is_working(struct rsnd_dai_stream *io) |
201 | { | 192 | { |
202 | /* see rsnd_dai_stream_init/quit() */ | 193 | /* see rsnd_dai_stream_init/quit() */ |
203 | return !!io->substream; | 194 | if (io->substream) |
195 | return snd_pcm_running(io->substream); | ||
196 | |||
197 | return 0; | ||
204 | } | 198 | } |
205 | 199 | ||
206 | int rsnd_runtime_channel_original(struct rsnd_dai_stream *io) | 200 | int rsnd_runtime_channel_original(struct rsnd_dai_stream *io) |
@@ -407,11 +401,9 @@ struct rsnd_mod *rsnd_mod_next(int *iterator, | |||
407 | 401 | ||
408 | for (; *iterator < max; (*iterator)++) { | 402 | for (; *iterator < max; (*iterator)++) { |
409 | type = (array) ? array[*iterator] : *iterator; | 403 | type = (array) ? array[*iterator] : *iterator; |
410 | mod = io->mod[type]; | 404 | mod = rsnd_io_to_mod(io, type); |
411 | if (!mod) | 405 | if (mod) |
412 | continue; | 406 | return mod; |
413 | |||
414 | return mod; | ||
415 | } | 407 | } |
416 | 408 | ||
417 | return NULL; | 409 | return NULL; |
@@ -1242,6 +1234,33 @@ struct rsnd_kctrl_cfg *rsnd_kctrl_init_s(struct rsnd_kctrl_cfg_s *cfg) | |||
1242 | return &cfg->cfg; | 1234 | return &cfg->cfg; |
1243 | } | 1235 | } |
1244 | 1236 | ||
1237 | const char * const volume_ramp_rate[] = { | ||
1238 | "128 dB/1 step", /* 00000 */ | ||
1239 | "64 dB/1 step", /* 00001 */ | ||
1240 | "32 dB/1 step", /* 00010 */ | ||
1241 | "16 dB/1 step", /* 00011 */ | ||
1242 | "8 dB/1 step", /* 00100 */ | ||
1243 | "4 dB/1 step", /* 00101 */ | ||
1244 | "2 dB/1 step", /* 00110 */ | ||
1245 | "1 dB/1 step", /* 00111 */ | ||
1246 | "0.5 dB/1 step", /* 01000 */ | ||
1247 | "0.25 dB/1 step", /* 01001 */ | ||
1248 | "0.125 dB/1 step", /* 01010 = VOLUME_RAMP_MAX_MIX */ | ||
1249 | "0.125 dB/2 steps", /* 01011 */ | ||
1250 | "0.125 dB/4 steps", /* 01100 */ | ||
1251 | "0.125 dB/8 steps", /* 01101 */ | ||
1252 | "0.125 dB/16 steps", /* 01110 */ | ||
1253 | "0.125 dB/32 steps", /* 01111 */ | ||
1254 | "0.125 dB/64 steps", /* 10000 */ | ||
1255 | "0.125 dB/128 steps", /* 10001 */ | ||
1256 | "0.125 dB/256 steps", /* 10010 */ | ||
1257 | "0.125 dB/512 steps", /* 10011 */ | ||
1258 | "0.125 dB/1024 steps", /* 10100 */ | ||
1259 | "0.125 dB/2048 steps", /* 10101 */ | ||
1260 | "0.125 dB/4096 steps", /* 10110 */ | ||
1261 | "0.125 dB/8192 steps", /* 10111 = VOLUME_RAMP_MAX_DVC */ | ||
1262 | }; | ||
1263 | |||
1245 | int rsnd_kctrl_new(struct rsnd_mod *mod, | 1264 | int rsnd_kctrl_new(struct rsnd_mod *mod, |
1246 | struct rsnd_dai_stream *io, | 1265 | struct rsnd_dai_stream *io, |
1247 | struct snd_soc_pcm_runtime *rtd, | 1266 | struct snd_soc_pcm_runtime *rtd, |
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index e7f53f44165d..d201d551866d 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c | |||
@@ -81,8 +81,11 @@ struct rsnd_ctu { | |||
81 | struct rsnd_kctrl_cfg_m sv3; | 81 | struct rsnd_kctrl_cfg_m sv3; |
82 | struct rsnd_kctrl_cfg_s reset; | 82 | struct rsnd_kctrl_cfg_s reset; |
83 | int channels; | 83 | int channels; |
84 | u32 flags; | ||
84 | }; | 85 | }; |
85 | 86 | ||
87 | #define KCTRL_INITIALIZED (1 << 0) | ||
88 | |||
86 | #define rsnd_ctu_nr(priv) ((priv)->ctu_nr) | 89 | #define rsnd_ctu_nr(priv) ((priv)->ctu_nr) |
87 | #define for_each_rsnd_ctu(pos, priv, i) \ | 90 | #define for_each_rsnd_ctu(pos, priv, i) \ |
88 | for ((i) = 0; \ | 91 | for ((i) = 0; \ |
@@ -130,7 +133,7 @@ static void rsnd_ctu_value_init(struct rsnd_dai_stream *io, | |||
130 | int i; | 133 | int i; |
131 | 134 | ||
132 | for (i = 0; i < RSND_MAX_CHANNELS; i++) { | 135 | for (i = 0; i < RSND_MAX_CHANNELS; i++) { |
133 | u32 val = ctu->pass.val[i]; | 136 | u32 val = rsnd_kctrl_valm(ctu->pass, i); |
134 | 137 | ||
135 | cpmdr |= val << (28 - (i * 4)); | 138 | cpmdr |= val << (28 - (i * 4)); |
136 | 139 | ||
@@ -147,44 +150,44 @@ static void rsnd_ctu_value_init(struct rsnd_dai_stream *io, | |||
147 | rsnd_mod_write(mod, CTU_SCMDR, scmdr); | 150 | rsnd_mod_write(mod, CTU_SCMDR, scmdr); |
148 | 151 | ||
149 | if (scmdr > 0) { | 152 | if (scmdr > 0) { |
150 | rsnd_mod_write(mod, CTU_SV00R, ctu->sv0.val[0]); | 153 | rsnd_mod_write(mod, CTU_SV00R, rsnd_kctrl_valm(ctu->sv0, 0)); |
151 | rsnd_mod_write(mod, CTU_SV01R, ctu->sv0.val[1]); | 154 | rsnd_mod_write(mod, CTU_SV01R, rsnd_kctrl_valm(ctu->sv0, 1)); |
152 | rsnd_mod_write(mod, CTU_SV02R, ctu->sv0.val[2]); | 155 | rsnd_mod_write(mod, CTU_SV02R, rsnd_kctrl_valm(ctu->sv0, 2)); |
153 | rsnd_mod_write(mod, CTU_SV03R, ctu->sv0.val[3]); | 156 | rsnd_mod_write(mod, CTU_SV03R, rsnd_kctrl_valm(ctu->sv0, 3)); |
154 | rsnd_mod_write(mod, CTU_SV04R, ctu->sv0.val[4]); | 157 | rsnd_mod_write(mod, CTU_SV04R, rsnd_kctrl_valm(ctu->sv0, 4)); |
155 | rsnd_mod_write(mod, CTU_SV05R, ctu->sv0.val[5]); | 158 | rsnd_mod_write(mod, CTU_SV05R, rsnd_kctrl_valm(ctu->sv0, 5)); |
156 | rsnd_mod_write(mod, CTU_SV06R, ctu->sv0.val[6]); | 159 | rsnd_mod_write(mod, CTU_SV06R, rsnd_kctrl_valm(ctu->sv0, 6)); |
157 | rsnd_mod_write(mod, CTU_SV07R, ctu->sv0.val[7]); | 160 | rsnd_mod_write(mod, CTU_SV07R, rsnd_kctrl_valm(ctu->sv0, 7)); |
158 | } | 161 | } |
159 | if (scmdr > 1) { | 162 | if (scmdr > 1) { |
160 | rsnd_mod_write(mod, CTU_SV10R, ctu->sv1.val[0]); | 163 | rsnd_mod_write(mod, CTU_SV10R, rsnd_kctrl_valm(ctu->sv1, 0)); |
161 | rsnd_mod_write(mod, CTU_SV11R, ctu->sv1.val[1]); | 164 | rsnd_mod_write(mod, CTU_SV11R, rsnd_kctrl_valm(ctu->sv1, 1)); |
162 | rsnd_mod_write(mod, CTU_SV12R, ctu->sv1.val[2]); | 165 | rsnd_mod_write(mod, CTU_SV12R, rsnd_kctrl_valm(ctu->sv1, 2)); |
163 | rsnd_mod_write(mod, CTU_SV13R, ctu->sv1.val[3]); | 166 | rsnd_mod_write(mod, CTU_SV13R, rsnd_kctrl_valm(ctu->sv1, 3)); |
164 | rsnd_mod_write(mod, CTU_SV14R, ctu->sv1.val[4]); | 167 | rsnd_mod_write(mod, CTU_SV14R, rsnd_kctrl_valm(ctu->sv1, 4)); |
165 | rsnd_mod_write(mod, CTU_SV15R, ctu->sv1.val[5]); | 168 | rsnd_mod_write(mod, CTU_SV15R, rsnd_kctrl_valm(ctu->sv1, 5)); |
166 | rsnd_mod_write(mod, CTU_SV16R, ctu->sv1.val[6]); | 169 | rsnd_mod_write(mod, CTU_SV16R, rsnd_kctrl_valm(ctu->sv1, 6)); |
167 | rsnd_mod_write(mod, CTU_SV17R, ctu->sv1.val[7]); | 170 | rsnd_mod_write(mod, CTU_SV17R, rsnd_kctrl_valm(ctu->sv1, 7)); |
168 | } | 171 | } |
169 | if (scmdr > 2) { | 172 | if (scmdr > 2) { |
170 | rsnd_mod_write(mod, CTU_SV20R, ctu->sv2.val[0]); | 173 | rsnd_mod_write(mod, CTU_SV20R, rsnd_kctrl_valm(ctu->sv2, 0)); |
171 | rsnd_mod_write(mod, CTU_SV21R, ctu->sv2.val[1]); | 174 | rsnd_mod_write(mod, CTU_SV21R, rsnd_kctrl_valm(ctu->sv2, 1)); |
172 | rsnd_mod_write(mod, CTU_SV22R, ctu->sv2.val[2]); | 175 | rsnd_mod_write(mod, CTU_SV22R, rsnd_kctrl_valm(ctu->sv2, 2)); |
173 | rsnd_mod_write(mod, CTU_SV23R, ctu->sv2.val[3]); | 176 | rsnd_mod_write(mod, CTU_SV23R, rsnd_kctrl_valm(ctu->sv2, 3)); |
174 | rsnd_mod_write(mod, CTU_SV24R, ctu->sv2.val[4]); | 177 | rsnd_mod_write(mod, CTU_SV24R, rsnd_kctrl_valm(ctu->sv2, 4)); |
175 | rsnd_mod_write(mod, CTU_SV25R, ctu->sv2.val[5]); | 178 | rsnd_mod_write(mod, CTU_SV25R, rsnd_kctrl_valm(ctu->sv2, 5)); |
176 | rsnd_mod_write(mod, CTU_SV26R, ctu->sv2.val[6]); | 179 | rsnd_mod_write(mod, CTU_SV26R, rsnd_kctrl_valm(ctu->sv2, 6)); |
177 | rsnd_mod_write(mod, CTU_SV27R, ctu->sv2.val[7]); | 180 | rsnd_mod_write(mod, CTU_SV27R, rsnd_kctrl_valm(ctu->sv2, 7)); |
178 | } | 181 | } |
179 | if (scmdr > 3) { | 182 | if (scmdr > 3) { |
180 | rsnd_mod_write(mod, CTU_SV30R, ctu->sv3.val[0]); | 183 | rsnd_mod_write(mod, CTU_SV30R, rsnd_kctrl_valm(ctu->sv3, 0)); |
181 | rsnd_mod_write(mod, CTU_SV31R, ctu->sv3.val[1]); | 184 | rsnd_mod_write(mod, CTU_SV31R, rsnd_kctrl_valm(ctu->sv3, 1)); |
182 | rsnd_mod_write(mod, CTU_SV32R, ctu->sv3.val[2]); | 185 | rsnd_mod_write(mod, CTU_SV32R, rsnd_kctrl_valm(ctu->sv3, 2)); |
183 | rsnd_mod_write(mod, CTU_SV33R, ctu->sv3.val[3]); | 186 | rsnd_mod_write(mod, CTU_SV33R, rsnd_kctrl_valm(ctu->sv3, 3)); |
184 | rsnd_mod_write(mod, CTU_SV34R, ctu->sv3.val[4]); | 187 | rsnd_mod_write(mod, CTU_SV34R, rsnd_kctrl_valm(ctu->sv3, 4)); |
185 | rsnd_mod_write(mod, CTU_SV35R, ctu->sv3.val[5]); | 188 | rsnd_mod_write(mod, CTU_SV35R, rsnd_kctrl_valm(ctu->sv3, 5)); |
186 | rsnd_mod_write(mod, CTU_SV36R, ctu->sv3.val[6]); | 189 | rsnd_mod_write(mod, CTU_SV36R, rsnd_kctrl_valm(ctu->sv3, 6)); |
187 | rsnd_mod_write(mod, CTU_SV37R, ctu->sv3.val[7]); | 190 | rsnd_mod_write(mod, CTU_SV37R, rsnd_kctrl_valm(ctu->sv3, 7)); |
188 | } | 191 | } |
189 | 192 | ||
190 | rsnd_mod_write(mod, CTU_CTUIR, 0); | 193 | rsnd_mod_write(mod, CTU_CTUIR, 0); |
@@ -196,17 +199,17 @@ static void rsnd_ctu_value_reset(struct rsnd_dai_stream *io, | |||
196 | struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); | 199 | struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); |
197 | int i; | 200 | int i; |
198 | 201 | ||
199 | if (!ctu->reset.val) | 202 | if (!rsnd_kctrl_vals(ctu->reset)) |
200 | return; | 203 | return; |
201 | 204 | ||
202 | for (i = 0; i < RSND_MAX_CHANNELS; i++) { | 205 | for (i = 0; i < RSND_MAX_CHANNELS; i++) { |
203 | ctu->pass.val[i] = 0; | 206 | rsnd_kctrl_valm(ctu->pass, i) = 0; |
204 | ctu->sv0.val[i] = 0; | 207 | rsnd_kctrl_valm(ctu->sv0, i) = 0; |
205 | ctu->sv1.val[i] = 0; | 208 | rsnd_kctrl_valm(ctu->sv1, i) = 0; |
206 | ctu->sv2.val[i] = 0; | 209 | rsnd_kctrl_valm(ctu->sv2, i) = 0; |
207 | ctu->sv3.val[i] = 0; | 210 | rsnd_kctrl_valm(ctu->sv3, i) = 0; |
208 | } | 211 | } |
209 | ctu->reset.val = 0; | 212 | rsnd_kctrl_vals(ctu->reset) = 0; |
210 | } | 213 | } |
211 | 214 | ||
212 | static int rsnd_ctu_init(struct rsnd_mod *mod, | 215 | static int rsnd_ctu_init(struct rsnd_mod *mod, |
@@ -277,6 +280,9 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, | |||
277 | struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); | 280 | struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); |
278 | int ret; | 281 | int ret; |
279 | 282 | ||
283 | if (rsnd_flags_has(ctu, KCTRL_INITIALIZED)) | ||
284 | return 0; | ||
285 | |||
280 | /* CTU Pass */ | 286 | /* CTU Pass */ |
281 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass", | 287 | ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass", |
282 | rsnd_kctrl_accept_anytime, | 288 | rsnd_kctrl_accept_anytime, |
@@ -326,6 +332,8 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, | |||
326 | rsnd_ctu_value_reset, | 332 | rsnd_ctu_value_reset, |
327 | &ctu->reset, 1); | 333 | &ctu->reset, 1); |
328 | 334 | ||
335 | rsnd_flags_set(ctu, KCTRL_INITIALIZED); | ||
336 | |||
329 | return ret; | 337 | return ret; |
330 | } | 338 | } |
331 | 339 | ||
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 041ec1080d52..fd557abfe390 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c | |||
@@ -60,6 +60,14 @@ struct rsnd_dma_ctrl { | |||
60 | #define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en) | 60 | #define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en) |
61 | #define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp) | 61 | #define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp) |
62 | 62 | ||
63 | /* for DEBUG */ | ||
64 | static struct rsnd_mod_ops mem_ops = { | ||
65 | .name = "mem", | ||
66 | }; | ||
67 | |||
68 | static struct rsnd_mod mem = { | ||
69 | }; | ||
70 | |||
63 | /* | 71 | /* |
64 | * Audio DMAC | 72 | * Audio DMAC |
65 | */ | 73 | */ |
@@ -211,11 +219,9 @@ static int rsnd_dmaen_nolock_start(struct rsnd_mod *mod, | |||
211 | dma->mod_from, | 219 | dma->mod_from, |
212 | dma->mod_to); | 220 | dma->mod_to); |
213 | if (IS_ERR_OR_NULL(dmaen->chan)) { | 221 | if (IS_ERR_OR_NULL(dmaen->chan)) { |
214 | int ret = PTR_ERR(dmaen->chan); | ||
215 | |||
216 | dmaen->chan = NULL; | 222 | dmaen->chan = NULL; |
217 | dev_err(dev, "can't get dma channel\n"); | 223 | dev_err(dev, "can't get dma channel\n"); |
218 | return ret; | 224 | return -EIO; |
219 | } | 225 | } |
220 | 226 | ||
221 | return 0; | 227 | return 0; |
@@ -747,20 +753,22 @@ static void rsnd_dma_of_path(struct rsnd_mod *this, | |||
747 | rsnd_mod_name(this), rsnd_mod_id(this)); | 753 | rsnd_mod_name(this), rsnd_mod_id(this)); |
748 | for (i = 0; i <= idx; i++) { | 754 | for (i = 0; i <= idx; i++) { |
749 | dev_dbg(dev, " %s[%d]%s\n", | 755 | dev_dbg(dev, " %s[%d]%s\n", |
750 | rsnd_mod_name(mod[i]), rsnd_mod_id(mod[i]), | 756 | rsnd_mod_name(mod[i] ? mod[i] : &mem), |
751 | (mod[i] == *mod_from) ? " from" : | 757 | rsnd_mod_id (mod[i] ? mod[i] : &mem), |
752 | (mod[i] == *mod_to) ? " to" : ""); | 758 | (mod[i] == *mod_from) ? " from" : |
759 | (mod[i] == *mod_to) ? " to" : ""); | ||
753 | } | 760 | } |
754 | } | 761 | } |
755 | 762 | ||
756 | int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod, | 763 | static int rsnd_dma_alloc(struct rsnd_dai_stream *io, struct rsnd_mod *mod, |
757 | struct rsnd_mod **dma_mod) | 764 | struct rsnd_mod **dma_mod) |
758 | { | 765 | { |
759 | struct rsnd_mod *mod_from = NULL; | 766 | struct rsnd_mod *mod_from = NULL; |
760 | struct rsnd_mod *mod_to = NULL; | 767 | struct rsnd_mod *mod_to = NULL; |
761 | struct rsnd_priv *priv = rsnd_io_to_priv(io); | 768 | struct rsnd_priv *priv = rsnd_io_to_priv(io); |
762 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); | 769 | struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); |
763 | struct device *dev = rsnd_priv_to_dev(priv); | 770 | struct device *dev = rsnd_priv_to_dev(priv); |
771 | struct rsnd_dma *dma; | ||
764 | struct rsnd_mod_ops *ops; | 772 | struct rsnd_mod_ops *ops; |
765 | enum rsnd_mod_type type; | 773 | enum rsnd_mod_type type; |
766 | int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, | 774 | int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, |
@@ -800,40 +808,47 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod, | |||
800 | type = RSND_MOD_AUDMA; | 808 | type = RSND_MOD_AUDMA; |
801 | } | 809 | } |
802 | 810 | ||
803 | if (!(*dma_mod)) { | 811 | dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); |
804 | struct rsnd_dma *dma; | 812 | if (!dma) |
813 | return -ENOMEM; | ||
805 | 814 | ||
806 | dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); | 815 | *dma_mod = rsnd_mod_get(dma); |
807 | if (!dma) | ||
808 | return -ENOMEM; | ||
809 | 816 | ||
810 | *dma_mod = rsnd_mod_get(dma); | 817 | ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, |
818 | rsnd_mod_get_status, type, dma_id); | ||
819 | if (ret < 0) | ||
820 | return ret; | ||
811 | 821 | ||
812 | ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, | 822 | dev_dbg(dev, "%s[%d] %s[%d] -> %s[%d]\n", |
813 | rsnd_mod_get_status, type, dma_id); | 823 | rsnd_mod_name(*dma_mod), rsnd_mod_id(*dma_mod), |
814 | if (ret < 0) | 824 | rsnd_mod_name(mod_from ? mod_from : &mem), |
815 | return ret; | 825 | rsnd_mod_id (mod_from ? mod_from : &mem), |
826 | rsnd_mod_name(mod_to ? mod_to : &mem), | ||
827 | rsnd_mod_id (mod_to ? mod_to : &mem)); | ||
816 | 828 | ||
817 | dev_dbg(dev, "%s[%d] %s[%d] -> %s[%d]\n", | 829 | ret = attach(io, dma, mod_from, mod_to); |
818 | rsnd_mod_name(*dma_mod), rsnd_mod_id(*dma_mod), | 830 | if (ret < 0) |
819 | rsnd_mod_name(mod_from), rsnd_mod_id(mod_from), | 831 | return ret; |
820 | rsnd_mod_name(mod_to), rsnd_mod_id(mod_to)); | 832 | |
833 | dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1); | ||
834 | dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0); | ||
835 | dma->mod_from = mod_from; | ||
836 | dma->mod_to = mod_to; | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod, | ||
842 | struct rsnd_mod **dma_mod) | ||
843 | { | ||
844 | if (!(*dma_mod)) { | ||
845 | int ret = rsnd_dma_alloc(io, mod, dma_mod); | ||
821 | 846 | ||
822 | ret = attach(io, dma, mod_from, mod_to); | ||
823 | if (ret < 0) | 847 | if (ret < 0) |
824 | return ret; | 848 | return ret; |
825 | |||
826 | dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1); | ||
827 | dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0); | ||
828 | dma->mod_from = mod_from; | ||
829 | dma->mod_to = mod_to; | ||
830 | } | 849 | } |
831 | 850 | ||
832 | ret = rsnd_dai_connect(*dma_mod, io, type); | 851 | return rsnd_dai_connect(*dma_mod, io, (*dma_mod)->type); |
833 | if (ret < 0) | ||
834 | return ret; | ||
835 | |||
836 | return 0; | ||
837 | } | 852 | } |
838 | 853 | ||
839 | int rsnd_dma_probe(struct rsnd_priv *priv) | 854 | int rsnd_dma_probe(struct rsnd_priv *priv) |
@@ -866,5 +881,6 @@ int rsnd_dma_probe(struct rsnd_priv *priv) | |||
866 | 881 | ||
867 | priv->dma = dmac; | 882 | priv->dma = dmac; |
868 | 883 | ||
869 | return 0; | 884 | /* dummy mem mod for debug */ |
885 | return rsnd_mod_init(NULL, &mem, &mem_ops, NULL, NULL, 0, 0); | ||
870 | } | 886 | } |
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 1743ade3cc55..dbe54f024d68 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c | |||
@@ -44,8 +44,11 @@ struct rsnd_dvc { | |||
44 | struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */ | 44 | struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */ |
45 | struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */ | 45 | struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */ |
46 | struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */ | 46 | struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */ |
47 | u32 flags; | ||
47 | }; | 48 | }; |
48 | 49 | ||
50 | #define KCTRL_INITIALIZED (1 << 0) | ||
51 | |||
49 | #define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id) | 52 | #define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id) |
50 | #define rsnd_dvc_nr(priv) ((priv)->dvc_nr) | 53 | #define rsnd_dvc_nr(priv) ((priv)->dvc_nr) |
51 | 54 | ||
@@ -58,33 +61,6 @@ struct rsnd_dvc { | |||
58 | ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \ | 61 | ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \ |
59 | i++) | 62 | i++) |
60 | 63 | ||
61 | static const char * const dvc_ramp_rate[] = { | ||
62 | "128 dB/1 step", /* 00000 */ | ||
63 | "64 dB/1 step", /* 00001 */ | ||
64 | "32 dB/1 step", /* 00010 */ | ||
65 | "16 dB/1 step", /* 00011 */ | ||
66 | "8 dB/1 step", /* 00100 */ | ||
67 | "4 dB/1 step", /* 00101 */ | ||
68 | "2 dB/1 step", /* 00110 */ | ||
69 | "1 dB/1 step", /* 00111 */ | ||
70 | "0.5 dB/1 step", /* 01000 */ | ||
71 | "0.25 dB/1 step", /* 01001 */ | ||
72 | "0.125 dB/1 step", /* 01010 */ | ||
73 | "0.125 dB/2 steps", /* 01011 */ | ||
74 | "0.125 dB/4 steps", /* 01100 */ | ||
75 | "0.125 dB/8 steps", /* 01101 */ | ||
76 | "0.125 dB/16 steps", /* 01110 */ | ||
77 | "0.125 dB/32 steps", /* 01111 */ | ||
78 | "0.125 dB/64 steps", /* 10000 */ | ||
79 | "0.125 dB/128 steps", /* 10001 */ | ||
80 | "0.125 dB/256 steps", /* 10010 */ | ||
81 | "0.125 dB/512 steps", /* 10011 */ | ||
82 | "0.125 dB/1024 steps", /* 10100 */ | ||
83 | "0.125 dB/2048 steps", /* 10101 */ | ||
84 | "0.125 dB/4096 steps", /* 10110 */ | ||
85 | "0.125 dB/8192 steps", /* 10111 */ | ||
86 | }; | ||
87 | |||
88 | static void rsnd_dvc_activation(struct rsnd_mod *mod) | 64 | static void rsnd_dvc_activation(struct rsnd_mod *mod) |
89 | { | 65 | { |
90 | rsnd_mod_write(mod, DVC_SWRSR, 0); | 66 | rsnd_mod_write(mod, DVC_SWRSR, 0); |
@@ -97,8 +73,9 @@ static void rsnd_dvc_halt(struct rsnd_mod *mod) | |||
97 | rsnd_mod_write(mod, DVC_SWRSR, 0); | 73 | rsnd_mod_write(mod, DVC_SWRSR, 0); |
98 | } | 74 | } |
99 | 75 | ||
100 | #define rsnd_dvc_get_vrpdr(dvc) (dvc->rup.val << 8 | dvc->rdown.val) | 76 | #define rsnd_dvc_get_vrpdr(dvc) (rsnd_kctrl_vals(dvc->rup) << 8 | \ |
101 | #define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (dvc->volume.val[0] >> 13)) | 77 | rsnd_kctrl_vals(dvc->rdown)) |
78 | #define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (rsnd_kctrl_valm(dvc->volume, 0) >> 13)) | ||
102 | 79 | ||
103 | static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io, | 80 | static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io, |
104 | struct rsnd_mod *mod) | 81 | struct rsnd_mod *mod) |
@@ -108,12 +85,12 @@ static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io, | |||
108 | int i; | 85 | int i; |
109 | 86 | ||
110 | /* Enable Ramp */ | 87 | /* Enable Ramp */ |
111 | if (dvc->ren.val) | 88 | if (rsnd_kctrl_vals(dvc->ren)) |
112 | for (i = 0; i < RSND_MAX_CHANNELS; i++) | 89 | for (i = 0; i < RSND_MAX_CHANNELS; i++) |
113 | val[i] = dvc->volume.cfg.max; | 90 | val[i] = rsnd_kctrl_max(dvc->volume); |
114 | else | 91 | else |
115 | for (i = 0; i < RSND_MAX_CHANNELS; i++) | 92 | for (i = 0; i < RSND_MAX_CHANNELS; i++) |
116 | val[i] = dvc->volume.val[i]; | 93 | val[i] = rsnd_kctrl_valm(dvc->volume, i); |
117 | 94 | ||
118 | /* Enable Digital Volume */ | 95 | /* Enable Digital Volume */ |
119 | rsnd_mod_write(mod, DVC_VOL0R, val[0]); | 96 | rsnd_mod_write(mod, DVC_VOL0R, val[0]); |
@@ -143,7 +120,7 @@ static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io, | |||
143 | dvucr |= 0x101; | 120 | dvucr |= 0x101; |
144 | 121 | ||
145 | /* Enable Ramp */ | 122 | /* Enable Ramp */ |
146 | if (dvc->ren.val) { | 123 | if (rsnd_kctrl_vals(dvc->ren)) { |
147 | dvucr |= 0x10; | 124 | dvucr |= 0x10; |
148 | 125 | ||
149 | /* | 126 | /* |
@@ -185,10 +162,10 @@ static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io, | |||
185 | u32 vrdbr = 0; | 162 | u32 vrdbr = 0; |
186 | int i; | 163 | int i; |
187 | 164 | ||
188 | for (i = 0; i < dvc->mute.cfg.size; i++) | 165 | for (i = 0; i < rsnd_kctrl_size(dvc->mute); i++) |
189 | zcmcr |= (!!dvc->mute.cfg.val[i]) << i; | 166 | zcmcr |= (!!rsnd_kctrl_valm(dvc->mute, i)) << i; |
190 | 167 | ||
191 | if (dvc->ren.val) { | 168 | if (rsnd_kctrl_vals(dvc->ren)) { |
192 | vrpdr = rsnd_dvc_get_vrpdr(dvc); | 169 | vrpdr = rsnd_dvc_get_vrpdr(dvc); |
193 | vrdbr = rsnd_dvc_get_vrdbr(dvc); | 170 | vrdbr = rsnd_dvc_get_vrdbr(dvc); |
194 | } | 171 | } |
@@ -254,6 +231,9 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
254 | int channels = rsnd_rdai_channels_get(rdai); | 231 | int channels = rsnd_rdai_channels_get(rdai); |
255 | int ret; | 232 | int ret; |
256 | 233 | ||
234 | if (rsnd_flags_has(dvc, KCTRL_INITIALIZED)) | ||
235 | return 0; | ||
236 | |||
257 | /* Volume */ | 237 | /* Volume */ |
258 | ret = rsnd_kctrl_new_m(mod, io, rtd, | 238 | ret = rsnd_kctrl_new_m(mod, io, rtd, |
259 | is_play ? | 239 | is_play ? |
@@ -292,7 +272,8 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
292 | rsnd_kctrl_accept_anytime, | 272 | rsnd_kctrl_accept_anytime, |
293 | rsnd_dvc_volume_update, | 273 | rsnd_dvc_volume_update, |
294 | &dvc->rup, | 274 | &dvc->rup, |
295 | dvc_ramp_rate); | 275 | volume_ramp_rate, |
276 | VOLUME_RAMP_MAX_DVC); | ||
296 | if (ret < 0) | 277 | if (ret < 0) |
297 | return ret; | 278 | return ret; |
298 | 279 | ||
@@ -302,11 +283,14 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, | |||
302 | rsnd_kctrl_accept_anytime, | 283 | rsnd_kctrl_accept_anytime, |
303 | rsnd_dvc_volume_update, | 284 | rsnd_dvc_volume_update, |
304 | &dvc->rdown, | 285 | &dvc->rdown, |
305 | dvc_ramp_rate); | 286 | volume_ramp_rate, |
287 | VOLUME_RAMP_MAX_DVC); | ||
306 | 288 | ||
307 | if (ret < 0) | 289 | if (ret < 0) |
308 | return ret; | 290 | return ret; |
309 | 291 | ||
292 | rsnd_flags_set(dvc, KCTRL_INITIALIZED); | ||
293 | |||
310 | return 0; | 294 | return 0; |
311 | } | 295 | } |
312 | 296 | ||
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index 6c4826c189a4..7998380766f6 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c | |||
@@ -7,6 +7,33 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | |||
11 | /* | ||
12 | * CTUn MIXn | ||
13 | * +------+ +------+ | ||
14 | * [SRC3 / SRC6] -> |CTU n0| -> [MIX n0| -> | ||
15 | * [SRC4 / SRC9] -> |CTU n1| -> [MIX n1| -> | ||
16 | * [SRC0 / SRC1] -> |CTU n2| -> [MIX n2| -> | ||
17 | * [SRC2 / SRC5] -> |CTU n3| -> [MIX n3| -> | ||
18 | * +------+ +------+ | ||
19 | * | ||
20 | * ex) | ||
21 | * DAI0 : playback = <&src0 &ctu02 &mix0 &dvc0 &ssi0>; | ||
22 | * DAI1 : playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>; | ||
23 | * | ||
24 | * MIX Volume | ||
25 | * amixer set "MIX",0 100% // DAI0 Volume | ||
26 | * amixer set "MIX",1 100% // DAI1 Volume | ||
27 | * | ||
28 | * Volume Ramp | ||
29 | * amixer set "MIX Ramp Up Rate" "0.125 dB/1 step" | ||
30 | * amixer set "MIX Ramp Down Rate" "4 dB/1 step" | ||
31 | * amixer set "MIX Ramp" on | ||
32 | * aplay xxx.wav & | ||
33 | * amixer set "MIX",0 80% // DAI0 Volume Down | ||
34 | * amixer set "MIX",1 100% // DAI1 Volume Up | ||
35 | */ | ||
36 | |||
10 | #include "rsnd.h" | 37 | #include "rsnd.h" |
11 | 38 | ||
12 | #define MIX_NAME_SIZE 16 | 39 | #define MIX_NAME_SIZE 16 |
@@ -14,8 +41,27 @@ | |||
14 | 41 | ||
15 | struct rsnd_mix { | 42 | struct rsnd_mix { |
16 | struct rsnd_mod mod; | 43 | struct rsnd_mod mod; |
44 | struct rsnd_kctrl_cfg_s volumeA; /* MDBAR */ | ||
45 | struct rsnd_kctrl_cfg_s volumeB; /* MDBBR */ | ||
46 | struct rsnd_kctrl_cfg_s volumeC; /* MDBCR */ | ||
47 | struct rsnd_kctrl_cfg_s volumeD; /* MDBDR */ | ||
48 | struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */ | ||
49 | struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */ | ||
50 | struct rsnd_kctrl_cfg_s rdw; /* Ramp Rate Down */ | ||
51 | u32 flags; | ||
17 | }; | 52 | }; |
18 | 53 | ||
54 | #define ONCE_KCTRL_INITIALIZED (1 << 0) | ||
55 | #define HAS_VOLA (1 << 1) | ||
56 | #define HAS_VOLB (1 << 2) | ||
57 | #define HAS_VOLC (1 << 3) | ||
58 | #define HAS_VOLD (1 << 4) | ||
59 | |||
60 | #define VOL_MAX 0x3ff | ||
61 | |||
62 | #define rsnd_mod_to_mix(_mod) \ | ||
63 | container_of((_mod), struct rsnd_mix, mod) | ||
64 | |||
19 | #define rsnd_mix_get(priv, id) ((struct rsnd_mix *)(priv->mix) + id) | 65 | #define rsnd_mix_get(priv, id) ((struct rsnd_mix *)(priv->mix) + id) |
20 | #define rsnd_mix_nr(priv) ((priv)->mix_nr) | 66 | #define rsnd_mix_nr(priv) ((priv)->mix_nr) |
21 | #define for_each_rsnd_mix(pos, priv, i) \ | 67 | #define for_each_rsnd_mix(pos, priv, i) \ |
@@ -36,26 +82,43 @@ static void rsnd_mix_halt(struct rsnd_mod *mod) | |||
36 | rsnd_mod_write(mod, MIX_SWRSR, 0); | 82 | rsnd_mod_write(mod, MIX_SWRSR, 0); |
37 | } | 83 | } |
38 | 84 | ||
85 | #define rsnd_mix_get_vol(mix, X) \ | ||
86 | rsnd_flags_has(mix, HAS_VOL##X) ? \ | ||
87 | (VOL_MAX - rsnd_kctrl_vals(mix->volume##X)) : 0 | ||
39 | static void rsnd_mix_volume_parameter(struct rsnd_dai_stream *io, | 88 | static void rsnd_mix_volume_parameter(struct rsnd_dai_stream *io, |
40 | struct rsnd_mod *mod) | 89 | struct rsnd_mod *mod) |
41 | { | 90 | { |
42 | rsnd_mod_write(mod, MIX_MDBAR, 0); | 91 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
43 | rsnd_mod_write(mod, MIX_MDBBR, 0); | 92 | struct device *dev = rsnd_priv_to_dev(priv); |
44 | rsnd_mod_write(mod, MIX_MDBCR, 0); | 93 | struct rsnd_mix *mix = rsnd_mod_to_mix(mod); |
45 | rsnd_mod_write(mod, MIX_MDBDR, 0); | 94 | u32 volA = rsnd_mix_get_vol(mix, A); |
95 | u32 volB = rsnd_mix_get_vol(mix, B); | ||
96 | u32 volC = rsnd_mix_get_vol(mix, C); | ||
97 | u32 volD = rsnd_mix_get_vol(mix, D); | ||
98 | |||
99 | dev_dbg(dev, "MIX A/B/C/D = %02x/%02x/%02x/%02x\n", | ||
100 | volA, volB, volC, volD); | ||
101 | |||
102 | rsnd_mod_write(mod, MIX_MDBAR, volA); | ||
103 | rsnd_mod_write(mod, MIX_MDBBR, volB); | ||
104 | rsnd_mod_write(mod, MIX_MDBCR, volC); | ||
105 | rsnd_mod_write(mod, MIX_MDBDR, volD); | ||
46 | } | 106 | } |
47 | 107 | ||
48 | static void rsnd_mix_volume_init(struct rsnd_dai_stream *io, | 108 | static void rsnd_mix_volume_init(struct rsnd_dai_stream *io, |
49 | struct rsnd_mod *mod) | 109 | struct rsnd_mod *mod) |
50 | { | 110 | { |
111 | struct rsnd_mix *mix = rsnd_mod_to_mix(mod); | ||
112 | |||
51 | rsnd_mod_write(mod, MIX_MIXIR, 1); | 113 | rsnd_mod_write(mod, MIX_MIXIR, 1); |
52 | 114 | ||
53 | /* General Information */ | 115 | /* General Information */ |
54 | rsnd_mod_write(mod, MIX_ADINR, rsnd_runtime_channel_after_ctu(io)); | 116 | rsnd_mod_write(mod, MIX_ADINR, rsnd_runtime_channel_after_ctu(io)); |
55 | 117 | ||
56 | /* volume step */ | 118 | /* volume step */ |
57 | rsnd_mod_write(mod, MIX_MIXMR, 0); | 119 | rsnd_mod_write(mod, MIX_MIXMR, rsnd_kctrl_vals(mix->ren)); |
58 | rsnd_mod_write(mod, MIX_MVPDR, 0); | 120 | rsnd_mod_write(mod, MIX_MVPDR, rsnd_kctrl_vals(mix->rup) << 8 | |
121 | rsnd_kctrl_vals(mix->rdw)); | ||
59 | 122 | ||
60 | /* common volume parameter */ | 123 | /* common volume parameter */ |
61 | rsnd_mix_volume_parameter(io, mod); | 124 | rsnd_mix_volume_parameter(io, mod); |
@@ -109,11 +172,94 @@ static int rsnd_mix_quit(struct rsnd_mod *mod, | |||
109 | return 0; | 172 | return 0; |
110 | } | 173 | } |
111 | 174 | ||
175 | static int rsnd_mix_pcm_new(struct rsnd_mod *mod, | ||
176 | struct rsnd_dai_stream *io, | ||
177 | struct snd_soc_pcm_runtime *rtd) | ||
178 | { | ||
179 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
180 | struct device *dev = rsnd_priv_to_dev(priv); | ||
181 | struct rsnd_mix *mix = rsnd_mod_to_mix(mod); | ||
182 | struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); | ||
183 | struct rsnd_kctrl_cfg_s *volume; | ||
184 | int ret; | ||
185 | |||
186 | switch (rsnd_mod_id(src_mod)) { | ||
187 | case 3: | ||
188 | case 6: /* MDBAR */ | ||
189 | volume = &mix->volumeA; | ||
190 | rsnd_flags_set(mix, HAS_VOLA); | ||
191 | break; | ||
192 | case 4: | ||
193 | case 9: /* MDBBR */ | ||
194 | volume = &mix->volumeB; | ||
195 | rsnd_flags_set(mix, HAS_VOLB); | ||
196 | break; | ||
197 | case 0: | ||
198 | case 1: /* MDBCR */ | ||
199 | volume = &mix->volumeC; | ||
200 | rsnd_flags_set(mix, HAS_VOLC); | ||
201 | break; | ||
202 | case 2: | ||
203 | case 5: /* MDBDR */ | ||
204 | volume = &mix->volumeD; | ||
205 | rsnd_flags_set(mix, HAS_VOLD); | ||
206 | break; | ||
207 | default: | ||
208 | dev_err(dev, "unknown SRC is connected\n"); | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | |||
212 | /* Volume */ | ||
213 | ret = rsnd_kctrl_new_s(mod, io, rtd, | ||
214 | "MIX Playback Volume", | ||
215 | rsnd_kctrl_accept_anytime, | ||
216 | rsnd_mix_volume_update, | ||
217 | volume, VOL_MAX); | ||
218 | if (ret < 0) | ||
219 | return ret; | ||
220 | rsnd_kctrl_vals(*volume) = VOL_MAX; | ||
221 | |||
222 | if (rsnd_flags_has(mix, ONCE_KCTRL_INITIALIZED)) | ||
223 | return ret; | ||
224 | |||
225 | /* Ramp */ | ||
226 | ret = rsnd_kctrl_new_s(mod, io, rtd, | ||
227 | "MIX Ramp Switch", | ||
228 | rsnd_kctrl_accept_anytime, | ||
229 | rsnd_mix_volume_update, | ||
230 | &mix->ren, 1); | ||
231 | if (ret < 0) | ||
232 | return ret; | ||
233 | |||
234 | ret = rsnd_kctrl_new_e(mod, io, rtd, | ||
235 | "MIX Ramp Up Rate", | ||
236 | rsnd_kctrl_accept_anytime, | ||
237 | rsnd_mix_volume_update, | ||
238 | &mix->rup, | ||
239 | volume_ramp_rate, | ||
240 | VOLUME_RAMP_MAX_MIX); | ||
241 | if (ret < 0) | ||
242 | return ret; | ||
243 | |||
244 | ret = rsnd_kctrl_new_e(mod, io, rtd, | ||
245 | "MIX Ramp Down Rate", | ||
246 | rsnd_kctrl_accept_anytime, | ||
247 | rsnd_mix_volume_update, | ||
248 | &mix->rdw, | ||
249 | volume_ramp_rate, | ||
250 | VOLUME_RAMP_MAX_MIX); | ||
251 | |||
252 | rsnd_flags_set(mix, ONCE_KCTRL_INITIALIZED); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
112 | static struct rsnd_mod_ops rsnd_mix_ops = { | 257 | static struct rsnd_mod_ops rsnd_mix_ops = { |
113 | .name = MIX_NAME, | 258 | .name = MIX_NAME, |
114 | .probe = rsnd_mix_probe_, | 259 | .probe = rsnd_mix_probe_, |
115 | .init = rsnd_mix_init, | 260 | .init = rsnd_mix_init, |
116 | .quit = rsnd_mix_quit, | 261 | .quit = rsnd_mix_quit, |
262 | .pcm_new = rsnd_mix_pcm_new, | ||
117 | }; | 263 | }; |
118 | 264 | ||
119 | struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id) | 265 | struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id) |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c5de71f2dc8c..57cd2bc773c2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -355,8 +355,9 @@ struct rsnd_mod { | |||
355 | #define __rsnd_mod_call_nolock_start 0 | 355 | #define __rsnd_mod_call_nolock_start 0 |
356 | #define __rsnd_mod_call_nolock_stop 1 | 356 | #define __rsnd_mod_call_nolock_stop 1 |
357 | 357 | ||
358 | #define rsnd_mod_to_priv(mod) ((mod)->priv) | 358 | #define rsnd_mod_to_priv(mod) ((mod)->priv) |
359 | #define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1) | 359 | #define rsnd_mod_name(mod) ((mod)->ops->name) |
360 | #define rsnd_mod_id(mod) ((mod)->id) | ||
360 | #define rsnd_mod_power_on(mod) clk_enable((mod)->clk) | 361 | #define rsnd_mod_power_on(mod) clk_enable((mod)->clk) |
361 | #define rsnd_mod_power_off(mod) clk_disable((mod)->clk) | 362 | #define rsnd_mod_power_off(mod) clk_disable((mod)->clk) |
362 | #define rsnd_mod_get(ip) (&(ip)->mod) | 363 | #define rsnd_mod_get(ip) (&(ip)->mod) |
@@ -371,7 +372,6 @@ int rsnd_mod_init(struct rsnd_priv *priv, | |||
371 | enum rsnd_mod_type type, | 372 | enum rsnd_mod_type type, |
372 | int id); | 373 | int id); |
373 | void rsnd_mod_quit(struct rsnd_mod *mod); | 374 | void rsnd_mod_quit(struct rsnd_mod *mod); |
374 | char *rsnd_mod_name(struct rsnd_mod *mod); | ||
375 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, | 375 | struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, |
376 | struct rsnd_mod *mod); | 376 | struct rsnd_mod *mod); |
377 | void rsnd_mod_interrupt(struct rsnd_mod *mod, | 377 | void rsnd_mod_interrupt(struct rsnd_mod *mod, |
@@ -601,6 +601,10 @@ struct rsnd_priv { | |||
601 | #define rsnd_is_gen1(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN1) | 601 | #define rsnd_is_gen1(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN1) |
602 | #define rsnd_is_gen2(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2) | 602 | #define rsnd_is_gen2(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2) |
603 | 603 | ||
604 | #define rsnd_flags_has(p, f) ((p)->flags & (f)) | ||
605 | #define rsnd_flags_set(p, f) ((p)->flags |= (f)) | ||
606 | #define rsnd_flags_del(p, f) ((p)->flags &= ~(f)) | ||
607 | |||
604 | /* | 608 | /* |
605 | * rsnd_kctrl | 609 | * rsnd_kctrl |
606 | */ | 610 | */ |
@@ -627,6 +631,10 @@ struct rsnd_kctrl_cfg_s { | |||
627 | struct rsnd_kctrl_cfg cfg; | 631 | struct rsnd_kctrl_cfg cfg; |
628 | u32 val; | 632 | u32 val; |
629 | }; | 633 | }; |
634 | #define rsnd_kctrl_size(x) ((x).cfg.size) | ||
635 | #define rsnd_kctrl_max(x) ((x).cfg.max) | ||
636 | #define rsnd_kctrl_valm(x, i) ((x).val[i]) /* = (x).cfg.val[i] */ | ||
637 | #define rsnd_kctrl_vals(x) ((x).val) /* = (x).cfg.val[0] */ | ||
630 | 638 | ||
631 | int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io); | 639 | int rsnd_kctrl_accept_anytime(struct rsnd_dai_stream *io); |
632 | int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io); | 640 | int rsnd_kctrl_accept_runtime(struct rsnd_dai_stream *io); |
@@ -652,9 +660,13 @@ int rsnd_kctrl_new(struct rsnd_mod *mod, | |||
652 | rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \ | 660 | rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \ |
653 | NULL, 1, max) | 661 | NULL, 1, max) |
654 | 662 | ||
655 | #define rsnd_kctrl_new_e(mod, io, rtd, name, accept, update, cfg, texts) \ | 663 | #define rsnd_kctrl_new_e(mod, io, rtd, name, accept, update, cfg, texts, size) \ |
656 | rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \ | 664 | rsnd_kctrl_new(mod, io, rtd, name, accept, update, rsnd_kctrl_init_s(cfg), \ |
657 | texts, 1, ARRAY_SIZE(texts)) | 665 | texts, 1, size) |
666 | |||
667 | extern const char * const volume_ramp_rate[]; | ||
668 | #define VOLUME_RAMP_MAX_DVC (0x17 + 1) | ||
669 | #define VOLUME_RAMP_MAX_MIX (0x0a + 1) | ||
658 | 670 | ||
659 | /* | 671 | /* |
660 | * R-Car SSI | 672 | * R-Car SSI |
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 03c2a1f02643..fece1e5f582f 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -101,9 +101,6 @@ struct rsnd_ssi { | |||
101 | #define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id) | 101 | #define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id) |
102 | #define rsnd_ssi_nr(priv) ((priv)->ssi_nr) | 102 | #define rsnd_ssi_nr(priv) ((priv)->ssi_nr) |
103 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) | 103 | #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) |
104 | #define rsnd_ssi_flags_has(p, f) ((p)->flags & f) | ||
105 | #define rsnd_ssi_flags_set(p, f) ((p)->flags |= f) | ||
106 | #define rsnd_ssi_flags_del(p, f) ((p)->flags = ((p)->flags & ~f)) | ||
107 | #define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io)) | 104 | #define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io)) |
108 | #define rsnd_ssi_is_multi_slave(mod, io) \ | 105 | #define rsnd_ssi_is_multi_slave(mod, io) \ |
109 | (rsnd_ssi_multi_slaves(io) & (1 << rsnd_mod_id(mod))) | 106 | (rsnd_ssi_multi_slaves(io) & (1 << rsnd_mod_id(mod))) |
@@ -116,10 +113,10 @@ int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io) | |||
116 | struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); | 113 | struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); |
117 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 114 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
118 | 115 | ||
119 | if (rsnd_ssi_flags_has(ssi, RSND_SSI_HDMI0)) | 116 | if (rsnd_flags_has(ssi, RSND_SSI_HDMI0)) |
120 | return RSND_SSI_HDMI_PORT0; | 117 | return RSND_SSI_HDMI_PORT0; |
121 | 118 | ||
122 | if (rsnd_ssi_flags_has(ssi, RSND_SSI_HDMI1)) | 119 | if (rsnd_flags_has(ssi, RSND_SSI_HDMI1)) |
123 | return RSND_SSI_HDMI_PORT1; | 120 | return RSND_SSI_HDMI_PORT1; |
124 | 121 | ||
125 | return 0; | 122 | return 0; |
@@ -134,7 +131,7 @@ int rsnd_ssi_use_busif(struct rsnd_dai_stream *io) | |||
134 | if (!rsnd_ssi_is_dma_mode(mod)) | 131 | if (!rsnd_ssi_is_dma_mode(mod)) |
135 | return 0; | 132 | return 0; |
136 | 133 | ||
137 | if (!(rsnd_ssi_flags_has(ssi, RSND_SSI_NO_BUSIF))) | 134 | if (!(rsnd_flags_has(ssi, RSND_SSI_NO_BUSIF))) |
138 | use_busif = 1; | 135 | use_busif = 1; |
139 | if (rsnd_io_to_mod_src(io)) | 136 | if (rsnd_io_to_mod_src(io)) |
140 | use_busif = 1; | 137 | use_busif = 1; |
@@ -198,10 +195,15 @@ static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io) | |||
198 | { | 195 | { |
199 | struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); | 196 | struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); |
200 | struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); | 197 | struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); |
198 | u32 mods; | ||
201 | 199 | ||
202 | return rsnd_ssi_multi_slaves_runtime(io) | | 200 | mods = rsnd_ssi_multi_slaves_runtime(io) | |
203 | 1 << rsnd_mod_id(ssi_mod) | | 201 | 1 << rsnd_mod_id(ssi_mod); |
204 | 1 << rsnd_mod_id(ssi_parent_mod); | 202 | |
203 | if (ssi_parent_mod) | ||
204 | mods |= 1 << rsnd_mod_id(ssi_parent_mod); | ||
205 | |||
206 | return mods; | ||
205 | } | 207 | } |
206 | 208 | ||
207 | u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io) | 209 | u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io) |
@@ -601,15 +603,18 @@ static int rsnd_ssi_stop(struct rsnd_mod *mod, | |||
601 | if (rsnd_ssi_is_parent(mod, io)) | 603 | if (rsnd_ssi_is_parent(mod, io)) |
602 | return 0; | 604 | return 0; |
603 | 605 | ||
604 | /* | ||
605 | * disable all IRQ, | ||
606 | * and, wait all data was sent | ||
607 | */ | ||
608 | cr = ssi->cr_own | | 606 | cr = ssi->cr_own | |
609 | ssi->cr_clk; | 607 | ssi->cr_clk; |
610 | 608 | ||
611 | rsnd_mod_write(mod, SSICR, cr | EN); | 609 | /* |
612 | rsnd_ssi_status_check(mod, DIRQ); | 610 | * disable all IRQ, |
611 | * Playback: Wait all data was sent | ||
612 | * Capture: It might not receave data. Do nothing | ||
613 | */ | ||
614 | if (rsnd_io_is_play(io)) { | ||
615 | rsnd_mod_write(mod, SSICR, cr | EN); | ||
616 | rsnd_ssi_status_check(mod, DIRQ); | ||
617 | } | ||
613 | 618 | ||
614 | /* | 619 | /* |
615 | * disable SSI, | 620 | * disable SSI, |
@@ -793,13 +798,13 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod, | |||
793 | * But it don't need to call request_irq() many times. | 798 | * But it don't need to call request_irq() many times. |
794 | * Let's control it by RSND_SSI_PROBED flag. | 799 | * Let's control it by RSND_SSI_PROBED flag. |
795 | */ | 800 | */ |
796 | if (!rsnd_ssi_flags_has(ssi, RSND_SSI_PROBED)) { | 801 | if (!rsnd_flags_has(ssi, RSND_SSI_PROBED)) { |
797 | ret = request_irq(ssi->irq, | 802 | ret = request_irq(ssi->irq, |
798 | rsnd_ssi_interrupt, | 803 | rsnd_ssi_interrupt, |
799 | IRQF_SHARED, | 804 | IRQF_SHARED, |
800 | dev_name(dev), mod); | 805 | dev_name(dev), mod); |
801 | 806 | ||
802 | rsnd_ssi_flags_set(ssi, RSND_SSI_PROBED); | 807 | rsnd_flags_set(ssi, RSND_SSI_PROBED); |
803 | } | 808 | } |
804 | 809 | ||
805 | return ret; | 810 | return ret; |
@@ -817,10 +822,10 @@ static int rsnd_ssi_common_remove(struct rsnd_mod *mod, | |||
817 | return 0; | 822 | return 0; |
818 | 823 | ||
819 | /* PIO will request IRQ again */ | 824 | /* PIO will request IRQ again */ |
820 | if (rsnd_ssi_flags_has(ssi, RSND_SSI_PROBED)) { | 825 | if (rsnd_flags_has(ssi, RSND_SSI_PROBED)) { |
821 | free_irq(ssi->irq, mod); | 826 | free_irq(ssi->irq, mod); |
822 | 827 | ||
823 | rsnd_ssi_flags_del(ssi, RSND_SSI_PROBED); | 828 | rsnd_flags_del(ssi, RSND_SSI_PROBED); |
824 | } | 829 | } |
825 | 830 | ||
826 | return 0; | 831 | return 0; |
@@ -1003,13 +1008,13 @@ static void __rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv, | |||
1003 | ssi = rsnd_mod_to_ssi(mod); | 1008 | ssi = rsnd_mod_to_ssi(mod); |
1004 | 1009 | ||
1005 | if (strstr(remote_ep->full_name, "hdmi0")) { | 1010 | if (strstr(remote_ep->full_name, "hdmi0")) { |
1006 | rsnd_ssi_flags_set(ssi, RSND_SSI_HDMI0); | 1011 | rsnd_flags_set(ssi, RSND_SSI_HDMI0); |
1007 | dev_dbg(dev, "%s[%d] connected to HDMI0\n", | 1012 | dev_dbg(dev, "%s[%d] connected to HDMI0\n", |
1008 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 1013 | rsnd_mod_name(mod), rsnd_mod_id(mod)); |
1009 | } | 1014 | } |
1010 | 1015 | ||
1011 | if (strstr(remote_ep->full_name, "hdmi1")) { | 1016 | if (strstr(remote_ep->full_name, "hdmi1")) { |
1012 | rsnd_ssi_flags_set(ssi, RSND_SSI_HDMI1); | 1017 | rsnd_flags_set(ssi, RSND_SSI_HDMI1); |
1013 | dev_dbg(dev, "%s[%d] connected to HDMI1\n", | 1018 | dev_dbg(dev, "%s[%d] connected to HDMI1\n", |
1014 | rsnd_mod_name(mod), rsnd_mod_id(mod)); | 1019 | rsnd_mod_name(mod), rsnd_mod_id(mod)); |
1015 | } | 1020 | } |
@@ -1042,7 +1047,7 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) | |||
1042 | { | 1047 | { |
1043 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | 1048 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); |
1044 | 1049 | ||
1045 | return !!(rsnd_ssi_flags_has(ssi, RSND_SSI_CLK_PIN_SHARE)); | 1050 | return !!(rsnd_flags_has(ssi, RSND_SSI_CLK_PIN_SHARE)); |
1046 | } | 1051 | } |
1047 | 1052 | ||
1048 | static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io, | 1053 | static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io, |
@@ -1128,10 +1133,10 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) | |||
1128 | } | 1133 | } |
1129 | 1134 | ||
1130 | if (of_get_property(np, "shared-pin", NULL)) | 1135 | if (of_get_property(np, "shared-pin", NULL)) |
1131 | rsnd_ssi_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE); | 1136 | rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE); |
1132 | 1137 | ||
1133 | if (of_get_property(np, "no-busif", NULL)) | 1138 | if (of_get_property(np, "no-busif", NULL)) |
1134 | rsnd_ssi_flags_set(ssi, RSND_SSI_NO_BUSIF); | 1139 | rsnd_flags_set(ssi, RSND_SSI_NO_BUSIF); |
1135 | 1140 | ||
1136 | ssi->irq = irq_of_parse_and_map(np, 0); | 1141 | ssi->irq = irq_of_parse_and_map(np, 0); |
1137 | if (!ssi->irq) { | 1142 | if (!ssi->irq) { |