diff options
author | Nicolin Chen <b42378@freescale.com> | 2013-12-03 05:38:07 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-12-03 09:58:17 -0500 |
commit | 07a9483aaca5d3b5de8ee824ee576321d3f8b4c6 (patch) | |
tree | a81304e7d3ab5dd1e3f102986fa2737379880647 /sound/soc/fsl | |
parent | e73462f573d5d78df1aaec5561b3d6daae90f64a (diff) |
ASoC: fsl_ssi: Implement symmetric_channels and symmetric_samplebits
Since we introduced symmetric_channels and symmetric_samplebits, we implement
these two features to fsl_ssi so as to drop some no-more-needed code and make
the driver neat and clean.
Signed-off-by: Nicolin Chen <b42378@freescale.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 79 |
1 files changed, 9 insertions, 70 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 90ff1071e29c..f9f4569417ed 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -119,8 +119,6 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set) | |||
119 | * @ssi: pointer to the SSI's registers | 119 | * @ssi: pointer to the SSI's registers |
120 | * @ssi_phys: physical address of the SSI registers | 120 | * @ssi_phys: physical address of the SSI registers |
121 | * @irq: IRQ of this SSI | 121 | * @irq: IRQ of this SSI |
122 | * @first_stream: pointer to the stream that was opened first | ||
123 | * @second_stream: pointer to second stream | ||
124 | * @playback: the number of playback streams opened | 122 | * @playback: the number of playback streams opened |
125 | * @capture: the number of capture streams opened | 123 | * @capture: the number of capture streams opened |
126 | * @cpu_dai: the CPU DAI for this device | 124 | * @cpu_dai: the CPU DAI for this device |
@@ -132,8 +130,6 @@ struct fsl_ssi_private { | |||
132 | struct ccsr_ssi __iomem *ssi; | 130 | struct ccsr_ssi __iomem *ssi; |
133 | dma_addr_t ssi_phys; | 131 | dma_addr_t ssi_phys; |
134 | unsigned int irq; | 132 | unsigned int irq; |
135 | struct snd_pcm_substream *first_stream; | ||
136 | struct snd_pcm_substream *second_stream; | ||
137 | unsigned int fifo_depth; | 133 | unsigned int fifo_depth; |
138 | struct snd_soc_dai_driver cpu_dai_drv; | 134 | struct snd_soc_dai_driver cpu_dai_drv; |
139 | struct device_attribute dev_attr; | 135 | struct device_attribute dev_attr; |
@@ -438,54 +434,13 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
438 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 434 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
439 | struct fsl_ssi_private *ssi_private = | 435 | struct fsl_ssi_private *ssi_private = |
440 | snd_soc_dai_get_drvdata(rtd->cpu_dai); | 436 | snd_soc_dai_get_drvdata(rtd->cpu_dai); |
441 | int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; | ||
442 | 437 | ||
443 | /* | 438 | /* First, we only do fsl_ssi_setup() when SSI is going to be active. |
444 | * If this is the first stream opened, then request the IRQ | 439 | * Second, fsl_ssi_setup was already called by ac97_init earlier if |
445 | * and initialize the SSI registers. | 440 | * the driver is in ac97 mode. |
446 | */ | 441 | */ |
447 | if (!ssi_private->first_stream) { | 442 | if (!dai->active && !ssi_private->imx_ac97) |
448 | ssi_private->first_stream = substream; | 443 | fsl_ssi_setup(ssi_private); |
449 | |||
450 | /* | ||
451 | * fsl_ssi_setup was already called by ac97_init earlier if | ||
452 | * the driver is in ac97 mode. | ||
453 | */ | ||
454 | if (!ssi_private->imx_ac97) | ||
455 | fsl_ssi_setup(ssi_private); | ||
456 | } else { | ||
457 | if (synchronous) { | ||
458 | struct snd_pcm_runtime *first_runtime = | ||
459 | ssi_private->first_stream->runtime; | ||
460 | /* | ||
461 | * This is the second stream open, and we're in | ||
462 | * synchronous mode, so we need to impose sample | ||
463 | * sample size constraints. This is because STCCR is | ||
464 | * used for playback and capture in synchronous mode, | ||
465 | * so there's no way to specify different word | ||
466 | * lengths. | ||
467 | * | ||
468 | * Note that this can cause a race condition if the | ||
469 | * second stream is opened before the first stream is | ||
470 | * fully initialized. We provide some protection by | ||
471 | * checking to make sure the first stream is | ||
472 | * initialized, but it's not perfect. ALSA sometimes | ||
473 | * re-initializes the driver with a different sample | ||
474 | * rate or size. If the second stream is opened | ||
475 | * before the first stream has received its final | ||
476 | * parameters, then the second stream may be | ||
477 | * constrained to the wrong sample rate or size. | ||
478 | */ | ||
479 | if (first_runtime->sample_bits) { | ||
480 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
481 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | ||
482 | first_runtime->sample_bits, | ||
483 | first_runtime->sample_bits); | ||
484 | } | ||
485 | } | ||
486 | |||
487 | ssi_private->second_stream = substream; | ||
488 | } | ||
489 | 444 | ||
490 | return 0; | 445 | return 0; |
491 | } | 446 | } |
@@ -615,23 +570,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, | |||
615 | return 0; | 570 | return 0; |
616 | } | 571 | } |
617 | 572 | ||
618 | /** | ||
619 | * fsl_ssi_shutdown: shutdown the SSI | ||
620 | * | ||
621 | * Shutdown the SSI if there are no other substreams open. | ||
622 | */ | ||
623 | static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, | ||
624 | struct snd_soc_dai *dai) | ||
625 | { | ||
626 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
627 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai); | ||
628 | |||
629 | if (ssi_private->first_stream == substream) | ||
630 | ssi_private->first_stream = ssi_private->second_stream; | ||
631 | |||
632 | ssi_private->second_stream = NULL; | ||
633 | } | ||
634 | |||
635 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | 573 | static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) |
636 | { | 574 | { |
637 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); | 575 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai); |
@@ -647,7 +585,6 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) | |||
647 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { | 585 | static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { |
648 | .startup = fsl_ssi_startup, | 586 | .startup = fsl_ssi_startup, |
649 | .hw_params = fsl_ssi_hw_params, | 587 | .hw_params = fsl_ssi_hw_params, |
650 | .shutdown = fsl_ssi_shutdown, | ||
651 | .trigger = fsl_ssi_trigger, | 588 | .trigger = fsl_ssi_trigger, |
652 | }; | 589 | }; |
653 | 590 | ||
@@ -722,7 +659,6 @@ static int fsl_ssi_ac97_trigger(struct snd_pcm_substream *substream, int cmd, | |||
722 | 659 | ||
723 | static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { | 660 | static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { |
724 | .startup = fsl_ssi_startup, | 661 | .startup = fsl_ssi_startup, |
725 | .shutdown = fsl_ssi_shutdown, | ||
726 | .trigger = fsl_ssi_ac97_trigger, | 662 | .trigger = fsl_ssi_ac97_trigger, |
727 | }; | 663 | }; |
728 | 664 | ||
@@ -947,8 +883,11 @@ static int fsl_ssi_probe(struct platform_device *pdev) | |||
947 | } | 883 | } |
948 | 884 | ||
949 | /* Are the RX and the TX clocks locked? */ | 885 | /* Are the RX and the TX clocks locked? */ |
950 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) | 886 | if (!of_find_property(np, "fsl,ssi-asynchronous", NULL)) { |
951 | ssi_private->cpu_dai_drv.symmetric_rates = 1; | 887 | ssi_private->cpu_dai_drv.symmetric_rates = 1; |
888 | ssi_private->cpu_dai_drv.symmetric_channels = 1; | ||
889 | ssi_private->cpu_dai_drv.symmetric_samplebits = 1; | ||
890 | } | ||
952 | 891 | ||
953 | /* Determine the FIFO depth. */ | 892 | /* Determine the FIFO depth. */ |
954 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); | 893 | iprop = of_get_property(np, "fsl,fifo-depth", NULL); |