aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorNicolin Chen <b42378@freescale.com>2013-12-03 05:38:07 -0500
committerMark Brown <broonie@linaro.org>2013-12-03 09:58:17 -0500
commit07a9483aaca5d3b5de8ee824ee576321d3f8b4c6 (patch)
treea81304e7d3ab5dd1e3f102986fa2737379880647 /sound/soc/fsl
parente73462f573d5d78df1aaec5561b3d6daae90f64a (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.c79
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 */
623static 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
635static int fsl_ssi_dai_probe(struct snd_soc_dai *dai) 573static 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)
647static const struct snd_soc_dai_ops fsl_ssi_dai_ops = { 585static 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
723static const struct snd_soc_dai_ops fsl_ssi_ac97_dai_ops = { 660static 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);