aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/ak4535.c3
-rw-r--r--sound/soc/codecs/twl4030.c59
-rw-r--r--sound/soc/codecs/twl4030.h1
-rw-r--r--sound/soc/codecs/wm9705.c37
-rw-r--r--sound/soc/fsl/fsl_dma.c29
-rw-r--r--sound/soc/fsl/fsl_ssi.c99
-rw-r--r--sound/soc/omap/omap-mcbsp.c11
-rw-r--r--sound/soc/pxa/Kconfig10
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/magician.c560
-rw-r--r--sound/soc/pxa/pxa-ssp.c12
-rw-r--r--sound/soc/soc-core.c20
12 files changed, 777 insertions, 66 deletions
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 1f63d387a2f4..dd3380202766 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -659,7 +659,8 @@ static int ak4535_remove(struct platform_device *pdev)
659 snd_soc_free_pcms(socdev); 659 snd_soc_free_pcms(socdev);
660 snd_soc_dapm_free(socdev); 660 snd_soc_dapm_free(socdev);
661#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 661#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
662 i2c_unregister_device(codec->control_data); 662 if (codec->control_data)
663 i2c_unregister_device(codec->control_data);
663 i2c_del_driver(&ak4535_i2c_driver); 664 i2c_del_driver(&ak4535_i2c_driver);
664#endif 665#endif
665 kfree(codec->private_data); 666 kfree(codec->private_data);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 97738e2ece04..bfda7a88e825 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -122,6 +122,9 @@ struct twl4030_priv {
122 unsigned int bypass_state; 122 unsigned int bypass_state;
123 unsigned int codec_powered; 123 unsigned int codec_powered;
124 unsigned int codec_muted; 124 unsigned int codec_muted;
125
126 struct snd_pcm_substream *master_substream;
127 struct snd_pcm_substream *slave_substream;
125}; 128};
126 129
127/* 130/*
@@ -1217,6 +1220,50 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec,
1217 return 0; 1220 return 0;
1218} 1221}
1219 1222
1223static int twl4030_startup(struct snd_pcm_substream *substream)
1224{
1225 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1226 struct snd_soc_device *socdev = rtd->socdev;
1227 struct snd_soc_codec *codec = socdev->codec;
1228 struct twl4030_priv *twl4030 = codec->private_data;
1229
1230 /* If we already have a playback or capture going then constrain
1231 * this substream to match it.
1232 */
1233 if (twl4030->master_substream) {
1234 struct snd_pcm_runtime *master_runtime;
1235 master_runtime = twl4030->master_substream->runtime;
1236
1237 snd_pcm_hw_constraint_minmax(substream->runtime,
1238 SNDRV_PCM_HW_PARAM_RATE,
1239 master_runtime->rate,
1240 master_runtime->rate);
1241
1242 snd_pcm_hw_constraint_minmax(substream->runtime,
1243 SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
1244 master_runtime->sample_bits,
1245 master_runtime->sample_bits);
1246
1247 twl4030->slave_substream = substream;
1248 } else
1249 twl4030->master_substream = substream;
1250
1251 return 0;
1252}
1253
1254static void twl4030_shutdown(struct snd_pcm_substream *substream)
1255{
1256 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1257 struct snd_soc_device *socdev = rtd->socdev;
1258 struct snd_soc_codec *codec = socdev->codec;
1259 struct twl4030_priv *twl4030 = codec->private_data;
1260
1261 if (twl4030->master_substream == substream)
1262 twl4030->master_substream = twl4030->slave_substream;
1263
1264 twl4030->slave_substream = NULL;
1265}
1266
1220static int twl4030_hw_params(struct snd_pcm_substream *substream, 1267static int twl4030_hw_params(struct snd_pcm_substream *substream,
1221 struct snd_pcm_hw_params *params, 1268 struct snd_pcm_hw_params *params,
1222 struct snd_soc_dai *dai) 1269 struct snd_soc_dai *dai)
@@ -1224,8 +1271,13 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1224 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1271 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1225 struct snd_soc_device *socdev = rtd->socdev; 1272 struct snd_soc_device *socdev = rtd->socdev;
1226 struct snd_soc_codec *codec = socdev->card->codec; 1273 struct snd_soc_codec *codec = socdev->card->codec;
1274 struct twl4030_priv *twl4030 = codec->private_data;
1227 u8 mode, old_mode, format, old_format; 1275 u8 mode, old_mode, format, old_format;
1228 1276
1277 if (substream == twl4030->slave_substream)
1278 /* Ignoring hw_params for slave substream */
1279 return 0;
1280
1229 /* bit rate */ 1281 /* bit rate */
1230 old_mode = twl4030_read_reg_cache(codec, 1282 old_mode = twl4030_read_reg_cache(codec,
1231 TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; 1283 TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
@@ -1259,6 +1311,9 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1259 case 48000: 1311 case 48000:
1260 mode |= TWL4030_APLL_RATE_48000; 1312 mode |= TWL4030_APLL_RATE_48000;
1261 break; 1313 break;
1314 case 96000:
1315 mode |= TWL4030_APLL_RATE_96000;
1316 break;
1262 default: 1317 default:
1263 printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n", 1318 printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
1264 params_rate(params)); 1319 params_rate(params));
@@ -1384,6 +1439,8 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
1384#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) 1439#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
1385 1440
1386static struct snd_soc_dai_ops twl4030_dai_ops = { 1441static struct snd_soc_dai_ops twl4030_dai_ops = {
1442 .startup = twl4030_startup,
1443 .shutdown = twl4030_shutdown,
1387 .hw_params = twl4030_hw_params, 1444 .hw_params = twl4030_hw_params,
1388 .set_sysclk = twl4030_set_dai_sysclk, 1445 .set_sysclk = twl4030_set_dai_sysclk,
1389 .set_fmt = twl4030_set_dai_fmt, 1446 .set_fmt = twl4030_set_dai_fmt,
@@ -1395,7 +1452,7 @@ struct snd_soc_dai twl4030_dai = {
1395 .stream_name = "Playback", 1452 .stream_name = "Playback",
1396 .channels_min = 2, 1453 .channels_min = 2,
1397 .channels_max = 2, 1454 .channels_max = 2,
1398 .rates = TWL4030_RATES, 1455 .rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
1399 .formats = TWL4030_FORMATS,}, 1456 .formats = TWL4030_FORMATS,},
1400 .capture = { 1457 .capture = {
1401 .stream_name = "Capture", 1458 .stream_name = "Capture",
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index 33dbb144dad1..cb63765db1df 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -109,6 +109,7 @@
109#define TWL4030_APLL_RATE_32000 0x80 109#define TWL4030_APLL_RATE_32000 0x80
110#define TWL4030_APLL_RATE_44100 0x90 110#define TWL4030_APLL_RATE_44100 0x90
111#define TWL4030_APLL_RATE_48000 0xA0 111#define TWL4030_APLL_RATE_48000 0xA0
112#define TWL4030_APLL_RATE_96000 0xE0
112#define TWL4030_SEL_16K 0x04 113#define TWL4030_SEL_16K 0x04
113#define TWL4030_CODECPDZ 0x02 114#define TWL4030_CODECPDZ 0x02
114#define TWL4030_OPT_MODE 0x01 115#define TWL4030_OPT_MODE 0x01
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 3265817c5c26..6e23a81dba78 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -317,6 +317,41 @@ static int wm9705_reset(struct snd_soc_codec *codec)
317 return -EIO; 317 return -EIO;
318} 318}
319 319
320#ifdef CONFIG_PM
321static int wm9705_soc_suspend(struct platform_device *pdev)
322{
323 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
324 struct snd_soc_codec *codec = socdev->card->codec;
325
326 soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
327
328 return 0;
329}
330
331static int wm9705_soc_resume(struct platform_device *pdev)
332{
333 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
334 struct snd_soc_codec *codec = socdev->card->codec;
335 int i, ret;
336 u16 *cache = codec->reg_cache;
337
338 ret = wm9705_reset(codec);
339 if (ret < 0) {
340 printk(KERN_ERR "could not reset AC97 codec\n");
341 return ret;
342 }
343
344 for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) {
345 soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
346 }
347
348 return 0;
349}
350#else
351#define wm9705_soc_suspend NULL
352#define wm9705_soc_resume NULL
353#endif
354
320static int wm9705_soc_probe(struct platform_device *pdev) 355static int wm9705_soc_probe(struct platform_device *pdev)
321{ 356{
322 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 357 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
@@ -407,6 +442,8 @@ static int wm9705_soc_remove(struct platform_device *pdev)
407struct snd_soc_codec_device soc_codec_dev_wm9705 = { 442struct snd_soc_codec_device soc_codec_dev_wm9705 = {
408 .probe = wm9705_soc_probe, 443 .probe = wm9705_soc_probe,
409 .remove = wm9705_soc_remove, 444 .remove = wm9705_soc_remove,
445 .suspend = wm9705_soc_suspend,
446 .resume = wm9705_soc_resume,
410}; 447};
411EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); 448EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705);
412 449
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index b3eb8570cd7b..b1a3a278819f 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -300,7 +300,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
300 if (!card->dev->coherent_dma_mask) 300 if (!card->dev->coherent_dma_mask)
301 card->dev->coherent_dma_mask = fsl_dma_dmamask; 301 card->dev->coherent_dma_mask = fsl_dma_dmamask;
302 302
303 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, 303 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
304 fsl_dma_hardware.buffer_bytes_max, 304 fsl_dma_hardware.buffer_bytes_max,
305 &pcm->streams[0].substream->dma_buffer); 305 &pcm->streams[0].substream->dma_buffer);
306 if (ret) { 306 if (ret) {
@@ -310,7 +310,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
310 return -ENOMEM; 310 return -ENOMEM;
311 } 311 }
312 312
313 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->dev, 313 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
314 fsl_dma_hardware.buffer_bytes_max, 314 fsl_dma_hardware.buffer_bytes_max,
315 &pcm->streams[1].substream->dma_buffer); 315 &pcm->streams[1].substream->dma_buffer);
316 if (ret) { 316 if (ret) {
@@ -418,7 +418,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
418 return -EBUSY; 418 return -EBUSY;
419 } 419 }
420 420
421 dma_private = dma_alloc_coherent(substream->pcm->dev, 421 dma_private = dma_alloc_coherent(substream->pcm->card->dev,
422 sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL); 422 sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL);
423 if (!dma_private) { 423 if (!dma_private) {
424 dev_err(substream->pcm->card->dev, 424 dev_err(substream->pcm->card->dev,
@@ -445,7 +445,7 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
445 dev_err(substream->pcm->card->dev, 445 dev_err(substream->pcm->card->dev,
446 "can't register ISR for IRQ %u (ret=%i)\n", 446 "can't register ISR for IRQ %u (ret=%i)\n",
447 dma_private->irq, ret); 447 dma_private->irq, ret);
448 dma_free_coherent(substream->pcm->dev, 448 dma_free_coherent(substream->pcm->card->dev,
449 sizeof(struct fsl_dma_private), 449 sizeof(struct fsl_dma_private),
450 dma_private, dma_private->ld_buf_phys); 450 dma_private, dma_private->ld_buf_phys);
451 return ret; 451 return ret;
@@ -697,6 +697,23 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
697 else 697 else
698 position = in_be32(&dma_channel->dar); 698 position = in_be32(&dma_channel->dar);
699 699
700 /*
701 * When capture is started, the SSI immediately starts to fill its FIFO.
702 * This means that the DMA controller is not started until the FIFO is
703 * full. However, ALSA calls this function before that happens, when
704 * MR.DAR is still zero. In this case, just return zero to indicate
705 * that nothing has been received yet.
706 */
707 if (!position)
708 return 0;
709
710 if ((position < dma_private->dma_buf_phys) ||
711 (position > dma_private->dma_buf_end)) {
712 dev_err(substream->pcm->card->dev,
713 "dma pointer is out of range, halting stream\n");
714 return SNDRV_PCM_POS_XRUN;
715 }
716
700 frames = bytes_to_frames(runtime, position - dma_private->dma_buf_phys); 717 frames = bytes_to_frames(runtime, position - dma_private->dma_buf_phys);
701 718
702 /* 719 /*
@@ -761,13 +778,13 @@ static int fsl_dma_close(struct snd_pcm_substream *substream)
761 free_irq(dma_private->irq, dma_private); 778 free_irq(dma_private->irq, dma_private);
762 779
763 if (dma_private->ld_buf_phys) { 780 if (dma_private->ld_buf_phys) {
764 dma_unmap_single(substream->pcm->dev, 781 dma_unmap_single(substream->pcm->card->dev,
765 dma_private->ld_buf_phys, 782 dma_private->ld_buf_phys,
766 sizeof(dma_private->link), DMA_TO_DEVICE); 783 sizeof(dma_private->link), DMA_TO_DEVICE);
767 } 784 }
768 785
769 /* Deallocate the fsl_dma_private structure */ 786 /* Deallocate the fsl_dma_private structure */
770 dma_free_coherent(substream->pcm->dev, 787 dma_free_coherent(substream->pcm->card->dev,
771 sizeof(struct fsl_dma_private), 788 sizeof(struct fsl_dma_private),
772 dma_private, dma_private->ld_buf_phys); 789 dma_private, dma_private->ld_buf_phys);
773 substream->runtime->private_data = NULL; 790 substream->runtime->private_data = NULL;
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 169bca295b78..3711d8454d96 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -60,6 +60,13 @@
60 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE) 60 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)
61#endif 61#endif
62 62
63/* SIER bitflag of interrupts to enable */
64#define SIER_FLAGS (CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE | \
65 CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN | \
66 CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN | \
67 CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE | \
68 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN)
69
63/** 70/**
64 * fsl_ssi_private: per-SSI private data 71 * fsl_ssi_private: per-SSI private data
65 * 72 *
@@ -140,7 +147,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
140 were interrupted for. We mask it with the Interrupt Enable register 147 were interrupted for. We mask it with the Interrupt Enable register
141 so that we only check for events that we're interested in. 148 so that we only check for events that we're interested in.
142 */ 149 */
143 sisr = in_be32(&ssi->sisr) & in_be32(&ssi->sier); 150 sisr = in_be32(&ssi->sisr) & SIER_FLAGS;
144 151
145 if (sisr & CCSR_SSI_SISR_RFRC) { 152 if (sisr & CCSR_SSI_SISR_RFRC) {
146 ssi_private->stats.rfrc++; 153 ssi_private->stats.rfrc++;
@@ -324,12 +331,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
324 */ 331 */
325 332
326 /* 4. Enable the interrupts and DMA requests */ 333 /* 4. Enable the interrupts and DMA requests */
327 out_be32(&ssi->sier, 334 out_be32(&ssi->sier, SIER_FLAGS);
328 CCSR_SSI_SIER_TFRC_EN | CCSR_SSI_SIER_TDMAE |
329 CCSR_SSI_SIER_TIE | CCSR_SSI_SIER_TUE0_EN |
330 CCSR_SSI_SIER_TUE1_EN | CCSR_SSI_SIER_RFRC_EN |
331 CCSR_SSI_SIER_RDMAE | CCSR_SSI_SIER_RIE |
332 CCSR_SSI_SIER_ROE0_EN | CCSR_SSI_SIER_ROE1_EN);
333 335
334 /* 336 /*
335 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We 337 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
@@ -466,28 +468,12 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
466 case SNDRV_PCM_TRIGGER_START: 468 case SNDRV_PCM_TRIGGER_START:
467 clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); 469 clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
468 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 470 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
469 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 471 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
470 setbits32(&ssi->scr, 472 setbits32(&ssi->scr,
471 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); 473 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE);
472 } else { 474 else
473 long timeout = jiffies + 10;
474
475 setbits32(&ssi->scr, 475 setbits32(&ssi->scr,
476 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); 476 CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE);
477
478 /* Wait until the SSI has filled its FIFO. Without this
479 * delay, ALSA complains about overruns. When the FIFO
480 * is full, the DMA controller initiates its first
481 * transfer. Until then, however, the DMA's DAR
482 * register is zero, which translates to an
483 * out-of-bounds pointer. This makes ALSA think an
484 * overrun has occurred.
485 */
486 while (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0) &&
487 (jiffies < timeout));
488 if (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0))
489 return -EIO;
490 }
491 break; 477 break;
492 478
493 case SNDRV_PCM_TRIGGER_STOP: 479 case SNDRV_PCM_TRIGGER_STOP:
@@ -606,39 +592,52 @@ static struct snd_soc_dai fsl_ssi_dai_template = {
606 .ops = &fsl_ssi_dai_ops, 592 .ops = &fsl_ssi_dai_ops,
607}; 593};
608 594
595/* Show the statistics of a flag only if its interrupt is enabled. The
596 * compiler will optimze this code to a no-op if the interrupt is not
597 * enabled.
598 */
599#define SIER_SHOW(flag, name) \
600 do { \
601 if (SIER_FLAGS & CCSR_SSI_SIER_##flag) \
602 length += sprintf(buf + length, #name "=%u\n", \
603 ssi_private->stats.name); \
604 } while (0)
605
606
609/** 607/**
610 * fsl_sysfs_ssi_show: display SSI statistics 608 * fsl_sysfs_ssi_show: display SSI statistics
611 * 609 *
612 * Display the statistics for the current SSI device. 610 * Display the statistics for the current SSI device. To avoid confusion,
611 * we only show those counts that are enabled.
613 */ 612 */
614static ssize_t fsl_sysfs_ssi_show(struct device *dev, 613static ssize_t fsl_sysfs_ssi_show(struct device *dev,
615 struct device_attribute *attr, char *buf) 614 struct device_attribute *attr, char *buf)
616{ 615{
617 struct fsl_ssi_private *ssi_private = 616 struct fsl_ssi_private *ssi_private =
618 container_of(attr, struct fsl_ssi_private, dev_attr); 617 container_of(attr, struct fsl_ssi_private, dev_attr);
619 ssize_t length; 618 ssize_t length = 0;
620 619
621 length = sprintf(buf, "rfrc=%u", ssi_private->stats.rfrc); 620 SIER_SHOW(RFRC_EN, rfrc);
622 length += sprintf(buf + length, "\ttfrc=%u", ssi_private->stats.tfrc); 621 SIER_SHOW(TFRC_EN, tfrc);
623 length += sprintf(buf + length, "\tcmdau=%u", ssi_private->stats.cmdau); 622 SIER_SHOW(CMDAU_EN, cmdau);
624 length += sprintf(buf + length, "\tcmddu=%u", ssi_private->stats.cmddu); 623 SIER_SHOW(CMDDU_EN, cmddu);
625 length += sprintf(buf + length, "\trxt=%u", ssi_private->stats.rxt); 624 SIER_SHOW(RXT_EN, rxt);
626 length += sprintf(buf + length, "\trdr1=%u", ssi_private->stats.rdr1); 625 SIER_SHOW(RDR1_EN, rdr1);
627 length += sprintf(buf + length, "\trdr0=%u", ssi_private->stats.rdr0); 626 SIER_SHOW(RDR0_EN, rdr0);
628 length += sprintf(buf + length, "\ttde1=%u", ssi_private->stats.tde1); 627 SIER_SHOW(TDE1_EN, tde1);
629 length += sprintf(buf + length, "\ttde0=%u", ssi_private->stats.tde0); 628 SIER_SHOW(TDE0_EN, tde0);
630 length += sprintf(buf + length, "\troe1=%u", ssi_private->stats.roe1); 629 SIER_SHOW(ROE1_EN, roe1);
631 length += sprintf(buf + length, "\troe0=%u", ssi_private->stats.roe0); 630 SIER_SHOW(ROE0_EN, roe0);
632 length += sprintf(buf + length, "\ttue1=%u", ssi_private->stats.tue1); 631 SIER_SHOW(TUE1_EN, tue1);
633 length += sprintf(buf + length, "\ttue0=%u", ssi_private->stats.tue0); 632 SIER_SHOW(TUE0_EN, tue0);
634 length += sprintf(buf + length, "\ttfs=%u", ssi_private->stats.tfs); 633 SIER_SHOW(TFS_EN, tfs);
635 length += sprintf(buf + length, "\trfs=%u", ssi_private->stats.rfs); 634 SIER_SHOW(RFS_EN, rfs);
636 length += sprintf(buf + length, "\ttls=%u", ssi_private->stats.tls); 635 SIER_SHOW(TLS_EN, tls);
637 length += sprintf(buf + length, "\trls=%u", ssi_private->stats.rls); 636 SIER_SHOW(RLS_EN, rls);
638 length += sprintf(buf + length, "\trff1=%u", ssi_private->stats.rff1); 637 SIER_SHOW(RFF1_EN, rff1);
639 length += sprintf(buf + length, "\trff0=%u", ssi_private->stats.rff0); 638 SIER_SHOW(RFF0_EN, rff0);
640 length += sprintf(buf + length, "\ttfe1=%u", ssi_private->stats.tfe1); 639 SIER_SHOW(TFE1_EN, tfe1);
641 length += sprintf(buf + length, "\ttfe0=%u\n", ssi_private->stats.tfe0); 640 SIER_SHOW(TFE0_EN, tfe0);
642 641
643 return length; 642 return length;
644} 643}
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index d6882be33452..9c09b94f0cf8 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -146,6 +146,17 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
146 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 146 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
147 int err = 0; 147 int err = 0;
148 148
149 if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) {
150 /*
151 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
152 * Set constraint for minimum buffer size to the same than FIFO
153 * size in order to avoid underruns in playback startup because
154 * HW is keeping the DMA request active until FIFO is filled.
155 */
156 snd_pcm_hw_constraint_minmax(substream->runtime,
157 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX);
158 }
159
149 if (!cpu_dai->active) 160 if (!cpu_dai->active)
150 err = omap_mcbsp_request(mcbsp_data->bus_id); 161 err = omap_mcbsp_request(mcbsp_data->bus_id);
151 162
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 5998ab366e83..ad8a10fe6298 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -116,6 +116,16 @@ config SND_SOC_ZYLONITE
116 Say Y if you want to add support for SoC audio on the 116 Say Y if you want to add support for SoC audio on the
117 Marvell Zylonite reference platform. 117 Marvell Zylonite reference platform.
118 118
119config SND_PXA2XX_SOC_MAGICIAN
120 tristate "SoC Audio support for HTC Magician"
121 depends on SND_PXA2XX_SOC && MACH_MAGICIAN
122 select SND_PXA2XX_SOC_I2S
123 select SND_PXA_SOC_SSP
124 select SND_SOC_UDA1380
125 help
126 Say Y if you want to add support for SoC audio on the
127 HTC Magician.
128
119config SND_PXA2XX_SOC_MIOA701 129config SND_PXA2XX_SOC_MIOA701
120 tristate "SoC Audio support for MIO A701" 130 tristate "SoC Audio support for MIO A701"
121 depends on SND_PXA2XX_SOC && MACH_MIOA701 131 depends on SND_PXA2XX_SOC && MACH_MIOA701
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 8ed881c5e5cc..4b90c3ccae45 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -20,6 +20,7 @@ snd-soc-spitz-objs := spitz.o
20snd-soc-em-x270-objs := em-x270.o 20snd-soc-em-x270-objs := em-x270.o
21snd-soc-palm27x-objs := palm27x.o 21snd-soc-palm27x-objs := palm27x.o
22snd-soc-zylonite-objs := zylonite.o 22snd-soc-zylonite-objs := zylonite.o
23snd-soc-magician-objs := magician.o
23snd-soc-mioa701-objs := mioa701_wm9713.o 24snd-soc-mioa701-objs := mioa701_wm9713.o
24 25
25obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o 26obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
@@ -31,5 +32,6 @@ obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
31obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o 32obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
32obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o 33obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
33obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o 34obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
35obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
34obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o 36obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
35obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o 37obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
new file mode 100644
index 000000000000..f7c4544f7859
--- /dev/null
+++ b/sound/soc/pxa/magician.c
@@ -0,0 +1,560 @@
1/*
2 * SoC audio for HTC Magician
3 *
4 * Copyright (c) 2006 Philipp Zabel <philipp.zabel@gmail.com>
5 *
6 * based on spitz.c,
7 * Authors: Liam Girdwood <lrg@slimlogic.co.uk>
8 * Richard Purdie <richard@openedhand.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/timer.h>
19#include <linux/interrupt.h>
20#include <linux/platform_device.h>
21#include <linux/delay.h>
22#include <linux/gpio.h>
23
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29
30#include <mach/pxa-regs.h>
31#include <mach/hardware.h>
32#include <mach/magician.h>
33#include <asm/mach-types.h>
34#include "../codecs/uda1380.h"
35#include "pxa2xx-pcm.h"
36#include "pxa2xx-i2s.h"
37#include "pxa-ssp.h"
38
39#define MAGICIAN_MIC 0
40#define MAGICIAN_MIC_EXT 1
41
42static int magician_hp_switch;
43static int magician_spk_switch = 1;
44static int magician_in_sel = MAGICIAN_MIC;
45
46static void magician_ext_control(struct snd_soc_codec *codec)
47{
48 if (magician_spk_switch)
49 snd_soc_dapm_enable_pin(codec, "Speaker");
50 else
51 snd_soc_dapm_disable_pin(codec, "Speaker");
52 if (magician_hp_switch)
53 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
54 else
55 snd_soc_dapm_disable_pin(codec, "Headphone Jack");
56
57 switch (magician_in_sel) {
58 case MAGICIAN_MIC:
59 snd_soc_dapm_disable_pin(codec, "Headset Mic");
60 snd_soc_dapm_enable_pin(codec, "Call Mic");
61 break;
62 case MAGICIAN_MIC_EXT:
63 snd_soc_dapm_disable_pin(codec, "Call Mic");
64 snd_soc_dapm_enable_pin(codec, "Headset Mic");
65 break;
66 }
67
68 snd_soc_dapm_sync(codec);
69}
70
71static int magician_startup(struct snd_pcm_substream *substream)
72{
73 struct snd_soc_pcm_runtime *rtd = substream->private_data;
74 struct snd_soc_codec *codec = rtd->socdev->card->codec;
75
76 /* check the jack status at stream startup */
77 magician_ext_control(codec);
78
79 return 0;
80}
81
82/*
83 * Magician uses SSP port for playback.
84 */
85static int magician_playback_hw_params(struct snd_pcm_substream *substream,
86 struct snd_pcm_hw_params *params)
87{
88 struct snd_soc_pcm_runtime *rtd = substream->private_data;
89 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
90 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
91 unsigned int acps, acds, width, rate;
92 unsigned int div4 = PXA_SSP_CLK_SCDB_4;
93 int ret = 0;
94
95 rate = params_rate(params);
96 width = snd_pcm_format_physical_width(params_format(params));
97
98 /*
99 * rate = SSPSCLK / (2 * width(16 or 32))
100 * SSPSCLK = (ACPS / ACDS) / SSPSCLKDIV(div4 or div1)
101 */
102 switch (params_rate(params)) {
103 case 8000:
104 /* off by a factor of 2: bug in the PXA27x audio clock? */
105 acps = 32842000;
106 switch (width) {
107 case 16:
108 /* 513156 Hz ~= _2_ * 8000 Hz * 32 (+0.23%) */
109 acds = PXA_SSP_CLK_AUDIO_DIV_16;
110 break;
111 case 32:
112 /* 1026312 Hz ~= _2_ * 8000 Hz * 64 (+0.23%) */
113 acds = PXA_SSP_CLK_AUDIO_DIV_8;
114 }
115 break;
116 case 11025:
117 acps = 5622000;
118 switch (width) {
119 case 16:
120 /* 351375 Hz ~= 11025 Hz * 32 (-0.41%) */
121 acds = PXA_SSP_CLK_AUDIO_DIV_4;
122 break;
123 case 32:
124 /* 702750 Hz ~= 11025 Hz * 64 (-0.41%) */
125 acds = PXA_SSP_CLK_AUDIO_DIV_2;
126 }
127 break;
128 case 22050:
129 acps = 5622000;
130 switch (width) {
131 case 16:
132 /* 702750 Hz ~= 22050 Hz * 32 (-0.41%) */
133 acds = PXA_SSP_CLK_AUDIO_DIV_2;
134 break;
135 case 32:
136 /* 1405500 Hz ~= 22050 Hz * 64 (-0.41%) */
137 acds = PXA_SSP_CLK_AUDIO_DIV_1;
138 }
139 break;
140 case 44100:
141 acps = 5622000;
142 switch (width) {
143 case 16:
144 /* 1405500 Hz ~= 44100 Hz * 32 (-0.41%) */
145 acds = PXA_SSP_CLK_AUDIO_DIV_2;
146 break;
147 case 32:
148 /* 2811000 Hz ~= 44100 Hz * 64 (-0.41%) */
149 acds = PXA_SSP_CLK_AUDIO_DIV_1;
150 }
151 break;
152 case 48000:
153 acps = 12235000;
154 switch (width) {
155 case 16:
156 /* 1529375 Hz ~= 48000 Hz * 32 (-0.44%) */
157 acds = PXA_SSP_CLK_AUDIO_DIV_2;
158 break;
159 case 32:
160 /* 3058750 Hz ~= 48000 Hz * 64 (-0.44%) */
161 acds = PXA_SSP_CLK_AUDIO_DIV_1;
162 }
163 break;
164 case 96000:
165 acps = 12235000;
166 switch (width) {
167 case 16:
168 /* 3058750 Hz ~= 96000 Hz * 32 (-0.44%) */
169 acds = PXA_SSP_CLK_AUDIO_DIV_1;
170 break;
171 case 32:
172 /* 6117500 Hz ~= 96000 Hz * 64 (-0.44%) */
173 acds = PXA_SSP_CLK_AUDIO_DIV_2;
174 div4 = PXA_SSP_CLK_SCDB_1;
175 break;
176 }
177 break;
178 }
179
180 /* set codec DAI configuration */
181 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_MSB |
182 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
183 if (ret < 0)
184 return ret;
185
186 /* set cpu DAI configuration */
187 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
188 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBS_CFS);
189 if (ret < 0)
190 return ret;
191
192 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1);
193 if (ret < 0)
194 return ret;
195
196 /* set audio clock as clock source */
197 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0,
198 SND_SOC_CLOCK_OUT);
199 if (ret < 0)
200 return ret;
201
202 /* set the SSP audio system clock ACDS divider */
203 ret = snd_soc_dai_set_clkdiv(cpu_dai,
204 PXA_SSP_AUDIO_DIV_ACDS, acds);
205 if (ret < 0)
206 return ret;
207
208 /* set the SSP audio system clock SCDB divider4 */
209 ret = snd_soc_dai_set_clkdiv(cpu_dai,
210 PXA_SSP_AUDIO_DIV_SCDB, div4);
211 if (ret < 0)
212 return ret;
213
214 /* set SSP audio pll clock */
215 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, acps);
216 if (ret < 0)
217 return ret;
218
219 return 0;
220}
221
222/*
223 * Magician uses I2S for capture.
224 */
225static int magician_capture_hw_params(struct snd_pcm_substream *substream,
226 struct snd_pcm_hw_params *params)
227{
228 struct snd_soc_pcm_runtime *rtd = substream->private_data;
229 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
230 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
231 int ret = 0;
232
233 /* set codec DAI configuration */
234 ret = snd_soc_dai_set_fmt(codec_dai,
235 SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
236 SND_SOC_DAIFMT_CBS_CFS);
237 if (ret < 0)
238 return ret;
239
240 /* set cpu DAI configuration */
241 ret = snd_soc_dai_set_fmt(cpu_dai,
242 SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
243 SND_SOC_DAIFMT_CBS_CFS);
244 if (ret < 0)
245 return ret;
246
247 /* set the I2S system clock as output */
248 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
249 SND_SOC_CLOCK_OUT);
250 if (ret < 0)
251 return ret;
252
253 return 0;
254}
255
256static struct snd_soc_ops magician_capture_ops = {
257 .startup = magician_startup,
258 .hw_params = magician_capture_hw_params,
259};
260
261static struct snd_soc_ops magician_playback_ops = {
262 .startup = magician_startup,
263 .hw_params = magician_playback_hw_params,
264};
265
266static int magician_get_hp(struct snd_kcontrol *kcontrol,
267 struct snd_ctl_elem_value *ucontrol)
268{
269 ucontrol->value.integer.value[0] = magician_hp_switch;
270 return 0;
271}
272
273static int magician_set_hp(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_value *ucontrol)
275{
276 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
277
278 if (magician_hp_switch == ucontrol->value.integer.value[0])
279 return 0;
280
281 magician_hp_switch = ucontrol->value.integer.value[0];
282 magician_ext_control(codec);
283 return 1;
284}
285
286static int magician_get_spk(struct snd_kcontrol *kcontrol,
287 struct snd_ctl_elem_value *ucontrol)
288{
289 ucontrol->value.integer.value[0] = magician_spk_switch;
290 return 0;
291}
292
293static int magician_set_spk(struct snd_kcontrol *kcontrol,
294 struct snd_ctl_elem_value *ucontrol)
295{
296 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
297
298 if (magician_spk_switch == ucontrol->value.integer.value[0])
299 return 0;
300
301 magician_spk_switch = ucontrol->value.integer.value[0];
302 magician_ext_control(codec);
303 return 1;
304}
305
306static int magician_get_input(struct snd_kcontrol *kcontrol,
307 struct snd_ctl_elem_value *ucontrol)
308{
309 ucontrol->value.integer.value[0] = magician_in_sel;
310 return 0;
311}
312
313static int magician_set_input(struct snd_kcontrol *kcontrol,
314 struct snd_ctl_elem_value *ucontrol)
315{
316 if (magician_in_sel == ucontrol->value.integer.value[0])
317 return 0;
318
319 magician_in_sel = ucontrol->value.integer.value[0];
320
321 switch (magician_in_sel) {
322 case MAGICIAN_MIC:
323 gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 1);
324 break;
325 case MAGICIAN_MIC_EXT:
326 gpio_set_value(EGPIO_MAGICIAN_IN_SEL1, 0);
327 }
328
329 return 1;
330}
331
332static int magician_spk_power(struct snd_soc_dapm_widget *w,
333 struct snd_kcontrol *k, int event)
334{
335 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, SND_SOC_DAPM_EVENT_ON(event));
336 return 0;
337}
338
339static int magician_hp_power(struct snd_soc_dapm_widget *w,
340 struct snd_kcontrol *k, int event)
341{
342 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, SND_SOC_DAPM_EVENT_ON(event));
343 return 0;
344}
345
346static int magician_mic_bias(struct snd_soc_dapm_widget *w,
347 struct snd_kcontrol *k, int event)
348{
349 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, SND_SOC_DAPM_EVENT_ON(event));
350 return 0;
351}
352
353/* magician machine dapm widgets */
354static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
355 SND_SOC_DAPM_HP("Headphone Jack", magician_hp_power),
356 SND_SOC_DAPM_SPK("Speaker", magician_spk_power),
357 SND_SOC_DAPM_MIC("Call Mic", magician_mic_bias),
358 SND_SOC_DAPM_MIC("Headset Mic", magician_mic_bias),
359};
360
361/* magician machine audio_map */
362static const struct snd_soc_dapm_route audio_map[] = {
363
364 /* Headphone connected to VOUTL, VOUTR */
365 {"Headphone Jack", NULL, "VOUTL"},
366 {"Headphone Jack", NULL, "VOUTR"},
367
368 /* Speaker connected to VOUTL, VOUTR */
369 {"Speaker", NULL, "VOUTL"},
370 {"Speaker", NULL, "VOUTR"},
371
372 /* Mics are connected to VINM */
373 {"VINM", NULL, "Headset Mic"},
374 {"VINM", NULL, "Call Mic"},
375};
376
377static const char *input_select[] = {"Call Mic", "Headset Mic"};
378static const struct soc_enum magician_in_sel_enum =
379 SOC_ENUM_SINGLE_EXT(2, input_select);
380
381static const struct snd_kcontrol_new uda1380_magician_controls[] = {
382 SOC_SINGLE_BOOL_EXT("Headphone Switch",
383 (unsigned long)&magician_hp_switch,
384 magician_get_hp, magician_set_hp),
385 SOC_SINGLE_BOOL_EXT("Speaker Switch",
386 (unsigned long)&magician_spk_switch,
387 magician_get_spk, magician_set_spk),
388 SOC_ENUM_EXT("Input Select", magician_in_sel_enum,
389 magician_get_input, magician_set_input),
390};
391
392/*
393 * Logic for a uda1380 as connected on a HTC Magician
394 */
395static int magician_uda1380_init(struct snd_soc_codec *codec)
396{
397 int err;
398
399 /* NC codec pins */
400 snd_soc_dapm_nc_pin(codec, "VOUTLHP");
401 snd_soc_dapm_nc_pin(codec, "VOUTRHP");
402
403 /* FIXME: is anything connected here? */
404 snd_soc_dapm_nc_pin(codec, "VINL");
405 snd_soc_dapm_nc_pin(codec, "VINR");
406
407 /* Add magician specific controls */
408 err = snd_soc_add_controls(codec, uda1380_magician_controls,
409 ARRAY_SIZE(uda1380_magician_controls));
410 if (err < 0)
411 return err;
412
413 /* Add magician specific widgets */
414 snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
415 ARRAY_SIZE(uda1380_dapm_widgets));
416
417 /* Set up magician specific audio path interconnects */
418 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
419
420 snd_soc_dapm_sync(codec);
421 return 0;
422}
423
424/* magician digital audio interface glue - connects codec <--> CPU */
425static struct snd_soc_dai_link magician_dai[] = {
426{
427 .name = "uda1380",
428 .stream_name = "UDA1380 Playback",
429 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1],
430 .codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK],
431 .init = magician_uda1380_init,
432 .ops = &magician_playback_ops,
433},
434{
435 .name = "uda1380",
436 .stream_name = "UDA1380 Capture",
437 .cpu_dai = &pxa_i2s_dai,
438 .codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE],
439 .ops = &magician_capture_ops,
440}
441};
442
443/* magician audio machine driver */
444static struct snd_soc_card snd_soc_card_magician = {
445 .name = "Magician",
446 .dai_link = magician_dai,
447 .num_links = ARRAY_SIZE(magician_dai),
448 .platform = &pxa2xx_soc_platform,
449};
450
451/* magician audio private data */
452static struct uda1380_setup_data magician_uda1380_setup = {
453 .i2c_address = 0x18,
454 .dac_clk = UDA1380_DAC_CLK_WSPLL,
455};
456
457/* magician audio subsystem */
458static struct snd_soc_device magician_snd_devdata = {
459 .card = &snd_soc_card_magician,
460 .codec_dev = &soc_codec_dev_uda1380,
461 .codec_data = &magician_uda1380_setup,
462};
463
464static struct platform_device *magician_snd_device;
465
466static int __init magician_init(void)
467{
468 int ret;
469
470 if (!machine_is_magician())
471 return -ENODEV;
472
473 ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER");
474 if (ret)
475 goto err_request_power;
476 ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET");
477 if (ret)
478 goto err_request_reset;
479 ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER");
480 if (ret)
481 goto err_request_spk;
482 ret = gpio_request(EGPIO_MAGICIAN_EP_POWER, "EP_POWER");
483 if (ret)
484 goto err_request_ep;
485 ret = gpio_request(EGPIO_MAGICIAN_MIC_POWER, "MIC_POWER");
486 if (ret)
487 goto err_request_mic;
488 ret = gpio_request(EGPIO_MAGICIAN_IN_SEL0, "IN_SEL0");
489 if (ret)
490 goto err_request_in_sel0;
491 ret = gpio_request(EGPIO_MAGICIAN_IN_SEL1, "IN_SEL1");
492 if (ret)
493 goto err_request_in_sel1;
494
495 gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1);
496 gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0);
497
498 /* we may need to have the clock running here - pH5 */
499 gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1);
500 udelay(5);
501 gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0);
502
503 magician_snd_device = platform_device_alloc("soc-audio", -1);
504 if (!magician_snd_device) {
505 ret = -ENOMEM;
506 goto err_pdev;
507 }
508
509 platform_set_drvdata(magician_snd_device, &magician_snd_devdata);
510 magician_snd_devdata.dev = &magician_snd_device->dev;
511 ret = platform_device_add(magician_snd_device);
512 if (ret) {
513 platform_device_put(magician_snd_device);
514 goto err_pdev;
515 }
516
517 return 0;
518
519err_pdev:
520 gpio_free(EGPIO_MAGICIAN_IN_SEL1);
521err_request_in_sel1:
522 gpio_free(EGPIO_MAGICIAN_IN_SEL0);
523err_request_in_sel0:
524 gpio_free(EGPIO_MAGICIAN_MIC_POWER);
525err_request_mic:
526 gpio_free(EGPIO_MAGICIAN_EP_POWER);
527err_request_ep:
528 gpio_free(EGPIO_MAGICIAN_SPK_POWER);
529err_request_spk:
530 gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
531err_request_reset:
532 gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
533err_request_power:
534 return ret;
535}
536
537static void __exit magician_exit(void)
538{
539 platform_device_unregister(magician_snd_device);
540
541 gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0);
542 gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0);
543 gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0);
544 gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0);
545
546 gpio_free(EGPIO_MAGICIAN_IN_SEL1);
547 gpio_free(EGPIO_MAGICIAN_IN_SEL0);
548 gpio_free(EGPIO_MAGICIAN_MIC_POWER);
549 gpio_free(EGPIO_MAGICIAN_EP_POWER);
550 gpio_free(EGPIO_MAGICIAN_SPK_POWER);
551 gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
552 gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
553}
554
555module_init(magician_init);
556module_exit(magician_exit);
557
558MODULE_AUTHOR("Philipp Zabel");
559MODULE_DESCRIPTION("ALSA SoC Magician");
560MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 7acd3febf8b0..308a657928d2 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -627,12 +627,18 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
627 u32 sscr0; 627 u32 sscr0;
628 u32 sspsp; 628 u32 sspsp;
629 int width = snd_pcm_format_physical_width(params_format(params)); 629 int width = snd_pcm_format_physical_width(params_format(params));
630 int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
630 631
631 /* select correct DMA params */ 632 /* select correct DMA params */
632 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 633 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
633 dma = 1; /* capture DMA offset is 1,3 */ 634 dma = 1; /* capture DMA offset is 1,3 */
634 if (chn == 2) 635 /* Network mode with one active slot (ttsa == 1) can be used
635 dma += 2; /* stereo DMA offset is 2, mono is 0 */ 636 * to force 16-bit frame width on the wire (for S16_LE), even
637 * with two channels. Use 16-bit DMA transfers for this case.
638 */
639 if (((chn == 2) && (ttsa != 1)) || (width == 32))
640 dma += 2; /* 32-bit DMA offset is 2, 16-bit is 0 */
641
636 cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma]; 642 cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
637 643
638 dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma); 644 dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
@@ -712,7 +718,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
712 /* When we use a network mode, we always require TDM slots 718 /* When we use a network mode, we always require TDM slots
713 * - complain loudly and fail if they've not been set up yet. 719 * - complain loudly and fail if they've not been set up yet.
714 */ 720 */
715 if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) { 721 if ((sscr0 & SSCR0_MOD) && !ttsa) {
716 dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); 722 dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
717 return -EINVAL; 723 return -EINVAL;
718 } 724 }
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 6e710f705a74..99712f652d0d 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -98,7 +98,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
98 int err; 98 int err;
99 99
100 codec->ac97->dev.bus = &ac97_bus_type; 100 codec->ac97->dev.bus = &ac97_bus_type;
101 codec->ac97->dev.parent = NULL; 101 codec->ac97->dev.parent = codec->card->dev;
102 codec->ac97->dev.release = soc_ac97_device_release; 102 codec->ac97->dev.release = soc_ac97_device_release;
103 103
104 dev_set_name(&codec->ac97->dev, "%d-%d:%s", 104 dev_set_name(&codec->ac97->dev, "%d-%d:%s",
@@ -767,11 +767,21 @@ static int soc_resume(struct platform_device *pdev)
767{ 767{
768 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 768 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
769 struct snd_soc_card *card = socdev->card; 769 struct snd_soc_card *card = socdev->card;
770 struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai;
770 771
771 dev_dbg(socdev->dev, "scheduling resume work\n"); 772 /* AC97 devices might have other drivers hanging off them so
772 773 * need to resume immediately. Other drivers don't have that
773 if (!schedule_work(&card->deferred_resume_work)) 774 * problem and may take a substantial amount of time to resume
774 dev_err(socdev->dev, "resume work item may be lost\n"); 775 * due to I/O costs and anti-pop so handle them out of line.
776 */
777 if (cpu_dai->ac97_control) {
778 dev_dbg(socdev->dev, "Resuming AC97 immediately\n");
779 soc_resume_deferred(&card->deferred_resume_work);
780 } else {
781 dev_dbg(socdev->dev, "Scheduling resume work\n");
782 if (!schedule_work(&card->deferred_resume_work))
783 dev_err(socdev->dev, "resume work item may be lost\n");
784 }
775 785
776 return 0; 786 return 0;
777} 787}