aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl/fsl_ssi.c
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2009-03-05 18:23:37 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-03-06 08:37:16 -0500
commita454dad19e78388d9f140ad0dfa6a849c57d385d (patch)
treef228d03393c681176fa031f04584a4119c7ad175 /sound/soc/fsl/fsl_ssi.c
parent499d8f4a528f1ebd0c19d89174fdc67130090c89 (diff)
ASoC: add support for SSI asynchronous mode to the Freescale SSI drivers
Add a new device tree property for the SSI node: "fsl,ssi-asynchronous". If defined, the SSI is programmed into asynchronous mode, otherwise it is programmed into synchronous mode. In asynchronous mode, pin SRCK must be connected to the same clock source as STFS, and pin SRFS must be connected to the same signal as STFS. Asynchronous mode allows playback and capture to use different sample sizes. It also technically allows different sample rates, but the driver does not support that. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/fsl/fsl_ssi.c')
-rw-r--r--sound/soc/fsl/fsl_ssi.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 6844009833db..8cb6bcf2c00f 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -72,6 +72,7 @@
72 * @dev: struct device pointer 72 * @dev: struct device pointer
73 * @playback: the number of playback streams opened 73 * @playback: the number of playback streams opened
74 * @capture: the number of capture streams opened 74 * @capture: the number of capture streams opened
75 * @asynchronous: 0=synchronous mode, 1=asynchronous mode
75 * @cpu_dai: the CPU DAI for this device 76 * @cpu_dai: the CPU DAI for this device
76 * @dev_attr: the sysfs device attribute structure 77 * @dev_attr: the sysfs device attribute structure
77 * @stats: SSI statistics 78 * @stats: SSI statistics
@@ -86,6 +87,7 @@ struct fsl_ssi_private {
86 struct device *dev; 87 struct device *dev;
87 unsigned int playback; 88 unsigned int playback;
88 unsigned int capture; 89 unsigned int capture;
90 int asynchronous;
89 struct snd_soc_dai cpu_dai; 91 struct snd_soc_dai cpu_dai;
90 struct device_attribute dev_attr; 92 struct device_attribute dev_attr;
91 93
@@ -301,9 +303,10 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
301 * 303 *
302 * FIXME: Little-endian samples require a different shift dir 304 * FIXME: Little-endian samples require a different shift dir
303 */ 305 */
304 clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK, 306 clrsetbits_be32(&ssi->scr,
305 CCSR_SSI_SCR_TFR_CLK_DIS | 307 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
306 CCSR_SSI_SCR_I2S_MODE_SLAVE | CCSR_SSI_SCR_SYN); 308 CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE
309 | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN));
307 310
308 out_be32(&ssi->stcr, 311 out_be32(&ssi->stcr,
309 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | 312 CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
@@ -382,10 +385,15 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
382 SNDRV_PCM_HW_PARAM_RATE, 385 SNDRV_PCM_HW_PARAM_RATE,
383 first_runtime->rate, first_runtime->rate); 386 first_runtime->rate, first_runtime->rate);
384 387
385 snd_pcm_hw_constraint_minmax(substream->runtime, 388 /* If we're in synchronous mode, then we need to constrain
386 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 389 * the sample size as well. We don't support independent sample
387 first_runtime->sample_bits, 390 * rates in asynchronous mode.
388 first_runtime->sample_bits); 391 */
392 if (!ssi_private->asynchronous)
393 snd_pcm_hw_constraint_minmax(substream->runtime,
394 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
395 first_runtime->sample_bits,
396 first_runtime->sample_bits);
389 397
390 ssi_private->second_stream = substream; 398 ssi_private->second_stream = substream;
391 } 399 }
@@ -421,13 +429,18 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
421 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 429 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
422 unsigned int sample_size = 430 unsigned int sample_size =
423 snd_pcm_format_width(params_format(hw_params)); 431 snd_pcm_format_width(params_format(hw_params));
424 u32 wl; 432 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
425 433
426 /* The SSI should always be disabled at this points (SSIEN=0) */ 434 /* The SSI should always be disabled at this points (SSIEN=0) */
427 wl = CCSR_SSI_SxCCR_WL(sample_size);
428 435
429 /* In synchronous mode, the SSI uses STCCR for capture */ 436 /* In synchronous mode, the SSI uses STCCR for capture */
430 clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); 437 if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
438 !ssi_private->asynchronous)
439 clrsetbits_be32(&ssi->stccr,
440 CCSR_SSI_SxCCR_WL_MASK, wl);
441 else
442 clrsetbits_be32(&ssi->srccr,
443 CCSR_SSI_SxCCR_WL_MASK, wl);
431 } 444 }
432 445
433 return 0; 446 return 0;
@@ -653,6 +666,7 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
653 ssi_private->ssi_phys = ssi_info->ssi_phys; 666 ssi_private->ssi_phys = ssi_info->ssi_phys;
654 ssi_private->irq = ssi_info->irq; 667 ssi_private->irq = ssi_info->irq;
655 ssi_private->dev = ssi_info->dev; 668 ssi_private->dev = ssi_info->dev;
669 ssi_private->asynchronous = ssi_info->asynchronous;
656 670
657 ssi_private->dev->driver_data = fsl_ssi_dai; 671 ssi_private->dev->driver_data = fsl_ssi_dai;
658 672
@@ -703,6 +717,14 @@ void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
703} 717}
704EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); 718EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
705 719
720static int __init fsl_ssi_init(void)
721{
722 printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
723
724 return 0;
725}
726module_init(fsl_ssi_init);
727
706MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 728MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
707MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); 729MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
708MODULE_LICENSE("GPL"); 730MODULE_LICENSE("GPL");