aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_ssi.c42
-rw-r--r--sound/soc/fsl/fsl_ssi.h2
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c5
3 files changed, 39 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");
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index 83b44d700e33..eade01feaab6 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -208,6 +208,7 @@ struct ccsr_ssi {
208 * ssi_phys: physical address of the SSI registers 208 * ssi_phys: physical address of the SSI registers
209 * irq: IRQ of this SSI 209 * irq: IRQ of this SSI
210 * dev: struct device, used to create the sysfs statistics file 210 * dev: struct device, used to create the sysfs statistics file
211 * asynchronous: 0=synchronous mode, 1=asynchronous mode
211*/ 212*/
212struct fsl_ssi_info { 213struct fsl_ssi_info {
213 unsigned int id; 214 unsigned int id;
@@ -215,6 +216,7 @@ struct fsl_ssi_info {
215 dma_addr_t ssi_phys; 216 dma_addr_t ssi_phys;
216 unsigned int irq; 217 unsigned int irq;
217 struct device *dev; 218 struct device *dev;
219 int asynchronous;
218}; 220};
219 221
220struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info); 222struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index acf39a646b2f..ef67d1cdffe7 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -353,6 +353,11 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,
353 } 353 }
354 ssi_info.irq = machine_data->ssi_irq; 354 ssi_info.irq = machine_data->ssi_irq;
355 355
356 /* Do we want to use asynchronous mode? */
357 ssi_info.asynchronous =
358 of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0;
359 if (ssi_info.asynchronous)
360 dev_info(&ofdev->dev, "using asynchronous mode\n");
356 361
357 /* Map the global utilities registers. */ 362 /* Map the global utilities registers. */
358 guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); 363 guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");