diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2015-04-10 04:50:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-04-27 15:57:38 -0400 |
commit | 919567d914b3c134e60c01db72a03a0adc5f41b9 (patch) | |
tree | f46c5e4d47afae9e9f35dffd0dadc23577e39548 | |
parent | 8c5c79a1cd51ce1b4fec8bbaecd17d599478bd27 (diff) |
ASoC: rsnd: make sure SSI parent/child uses same number of sound channel.
SSI parent/child need to use same number of sound data channel
if these are sharing clock/ws pin. this patch makes it sure.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2ef48a44c4ab..5b89723c3206 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c | |||
@@ -66,6 +66,7 @@ struct rsnd_ssi { | |||
66 | 66 | ||
67 | u32 cr_own; | 67 | u32 cr_own; |
68 | u32 cr_clk; | 68 | u32 cr_clk; |
69 | int chan; | ||
69 | int err; | 70 | int err; |
70 | unsigned int usrcnt; | 71 | unsigned int usrcnt; |
71 | }; | 72 | }; |
@@ -264,6 +265,8 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi) | |||
264 | } | 265 | } |
265 | 266 | ||
266 | rsnd_mod_hw_stop(&ssi->mod); | 267 | rsnd_mod_hw_stop(&ssi->mod); |
268 | |||
269 | ssi->chan = 0; | ||
267 | } | 270 | } |
268 | 271 | ||
269 | dev_dbg(dev, "%s[%d] hw stopped\n", | 272 | dev_dbg(dev, "%s[%d] hw stopped\n", |
@@ -340,6 +343,35 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, | |||
340 | return 0; | 343 | return 0; |
341 | } | 344 | } |
342 | 345 | ||
346 | static int rsnd_ssi_hw_params(struct rsnd_mod *mod, | ||
347 | struct snd_pcm_substream *substream, | ||
348 | struct snd_pcm_hw_params *params) | ||
349 | { | ||
350 | struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); | ||
351 | struct rsnd_ssi *ssi_parent = rsnd_ssi_parent(ssi); | ||
352 | int chan = params_channels(params); | ||
353 | |||
354 | /* | ||
355 | * Already working. | ||
356 | * It will happen if SSI has parent/child connection. | ||
357 | */ | ||
358 | if (ssi->usrcnt) { | ||
359 | /* | ||
360 | * it is error if child <-> parent SSI uses | ||
361 | * different channels. | ||
362 | */ | ||
363 | if (ssi->chan != chan) | ||
364 | return -EIO; | ||
365 | } | ||
366 | |||
367 | /* It will be removed on rsnd_ssi_hw_stop */ | ||
368 | ssi->chan = chan; | ||
369 | if (ssi_parent) | ||
370 | return rsnd_ssi_hw_params(&ssi_parent->mod, substream, params); | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | |||
343 | static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) | 375 | static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status) |
344 | { | 376 | { |
345 | /* under/over flow error */ | 377 | /* under/over flow error */ |
@@ -460,6 +492,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { | |||
460 | .quit = rsnd_ssi_quit, | 492 | .quit = rsnd_ssi_quit, |
461 | .start = rsnd_ssi_start, | 493 | .start = rsnd_ssi_start, |
462 | .stop = rsnd_ssi_stop, | 494 | .stop = rsnd_ssi_stop, |
495 | .hw_params = rsnd_ssi_hw_params, | ||
463 | }; | 496 | }; |
464 | 497 | ||
465 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, | 498 | static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, |
@@ -569,6 +602,7 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { | |||
569 | .start = rsnd_ssi_dma_start, | 602 | .start = rsnd_ssi_dma_start, |
570 | .stop = rsnd_ssi_dma_stop, | 603 | .stop = rsnd_ssi_dma_stop, |
571 | .fallback = rsnd_ssi_fallback, | 604 | .fallback = rsnd_ssi_fallback, |
605 | .hw_params = rsnd_ssi_hw_params, | ||
572 | }; | 606 | }; |
573 | 607 | ||
574 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) | 608 | int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod) |