aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/pxa-ssp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/pxa/pxa-ssp.c')
-rw-r--r--sound/soc/pxa/pxa-ssp.c162
1 files changed, 90 insertions, 72 deletions
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 73cb6b4c2f2d..308a657928d2 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -1,4 +1,3 @@
1#define DEBUG
2/* 1/*
3 * pxa-ssp.c -- ALSA Soc Audio Layer 2 * pxa-ssp.c -- ALSA Soc Audio Layer
4 * 3 *
@@ -21,6 +20,8 @@
21#include <linux/clk.h> 20#include <linux/clk.h>
22#include <linux/io.h> 21#include <linux/io.h>
23 22
23#include <asm/irq.h>
24
24#include <sound/core.h> 25#include <sound/core.h>
25#include <sound/pcm.h> 26#include <sound/pcm.h>
26#include <sound/initval.h> 27#include <sound/initval.h>
@@ -29,7 +30,7 @@
29#include <sound/pxa2xx-lib.h> 30#include <sound/pxa2xx-lib.h>
30 31
31#include <mach/hardware.h> 32#include <mach/hardware.h>
32#include <mach/pxa-regs.h> 33#include <mach/dma.h>
33#include <mach/regs-ssp.h> 34#include <mach/regs-ssp.h>
34#include <mach/audio.h> 35#include <mach/audio.h>
35#include <mach/ssp.h> 36#include <mach/ssp.h>
@@ -221,9 +222,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
221 int ret = 0; 222 int ret = 0;
222 223
223 if (!cpu_dai->active) { 224 if (!cpu_dai->active) {
224 ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ); 225 priv->dev.port = cpu_dai->id + 1;
225 if (ret < 0) 226 priv->dev.irq = NO_IRQ;
226 return ret; 227 clk_enable(priv->dev.ssp->clk);
227 ssp_disable(&priv->dev); 228 ssp_disable(&priv->dev);
228 } 229 }
229 return ret; 230 return ret;
@@ -238,7 +239,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
238 239
239 if (!cpu_dai->active) { 240 if (!cpu_dai->active) {
240 ssp_disable(&priv->dev); 241 ssp_disable(&priv->dev);
241 ssp_exit(&priv->dev); 242 clk_disable(priv->dev.ssp->clk);
242 } 243 }
243} 244}
244 245
@@ -298,7 +299,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
298 int val; 299 int val;
299 300
300 u32 sscr0 = ssp_read_reg(ssp, SSCR0) & 301 u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
301 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); 302 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
302 303
303 dev_dbg(&ssp->pdev->dev, 304 dev_dbg(&ssp->pdev->dev,
304 "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n", 305 "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n",
@@ -326,7 +327,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
326 case PXA_SSP_CLK_AUDIO: 327 case PXA_SSP_CLK_AUDIO:
327 priv->sysclk = 0; 328 priv->sysclk = 0;
328 ssp_set_scr(&priv->dev, 1); 329 ssp_set_scr(&priv->dev, 1);
329 sscr0 |= SSCR0_ADC; 330 sscr0 |= SSCR0_ACS;
330 break; 331 break;
331 default: 332 default:
332 return -ENODEV; 333 return -ENODEV;
@@ -520,9 +521,20 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
520 u32 sscr1; 521 u32 sscr1;
521 u32 sspsp; 522 u32 sspsp;
522 523
524 /* check if we need to change anything at all */
525 if (priv->dai_fmt == fmt)
526 return 0;
527
528 /* we can only change the settings if the port is not in use */
529 if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) {
530 dev_err(&ssp->pdev->dev,
531 "can't change hardware dai format: stream is in use");
532 return -EINVAL;
533 }
534
523 /* reset port settings */ 535 /* reset port settings */
524 sscr0 = ssp_read_reg(ssp, SSCR0) & 536 sscr0 = ssp_read_reg(ssp, SSCR0) &
525 (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); 537 (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
526 sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); 538 sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
527 sspsp = 0; 539 sspsp = 0;
528 540
@@ -545,18 +557,18 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
545 557
546 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 558 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
547 case SND_SOC_DAIFMT_I2S: 559 case SND_SOC_DAIFMT_I2S:
548 sscr0 |= SSCR0_MOD | SSCR0_PSP; 560 sscr0 |= SSCR0_PSP;
549 sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; 561 sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
550 562
563 /* See hw_params() */
551 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 564 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
552 case SND_SOC_DAIFMT_NB_NF: 565 case SND_SOC_DAIFMT_NB_NF:
553 sspsp |= SSPSP_FSRT; 566 sspsp |= SSPSP_SFRMP;
554 break; 567 break;
555 case SND_SOC_DAIFMT_NB_IF: 568 case SND_SOC_DAIFMT_NB_IF:
556 sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
557 break; 569 break;
558 case SND_SOC_DAIFMT_IB_IF: 570 case SND_SOC_DAIFMT_IB_IF:
559 sspsp |= SSPSP_SFRMP; 571 sspsp |= SSPSP_SCMODE(3);
560 break; 572 break;
561 default: 573 default:
562 return -EINVAL; 574 return -EINVAL;
@@ -615,12 +627,18 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
615 u32 sscr0; 627 u32 sscr0;
616 u32 sspsp; 628 u32 sspsp;
617 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;
618 631
619 /* select correct DMA params */ 632 /* select correct DMA params */
620 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) 633 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
621 dma = 1; /* capture DMA offset is 1,3 */ 634 dma = 1; /* capture DMA offset is 1,3 */
622 if (chn == 2) 635 /* Network mode with one active slot (ttsa == 1) can be used
623 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
624 cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma]; 642 cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
625 643
626 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);
@@ -642,34 +660,65 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
642 sscr0 |= SSCR0_FPCKE; 660 sscr0 |= SSCR0_FPCKE;
643#endif 661#endif
644 sscr0 |= SSCR0_DataSize(16); 662 sscr0 |= SSCR0_DataSize(16);
645 if (params_channels(params) > 1)
646 sscr0 |= SSCR0_EDSS;
647 break; 663 break;
648 case SNDRV_PCM_FORMAT_S24_LE: 664 case SNDRV_PCM_FORMAT_S24_LE:
649 sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); 665 sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
650 /* we must be in network mode (2 slots) for 24 bit stereo */
651 break; 666 break;
652 case SNDRV_PCM_FORMAT_S32_LE: 667 case SNDRV_PCM_FORMAT_S32_LE:
653 sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); 668 sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
654 /* we must be in network mode (2 slots) for 32 bit stereo */
655 break; 669 break;
656 } 670 }
657 ssp_write_reg(ssp, SSCR0, sscr0); 671 ssp_write_reg(ssp, SSCR0, sscr0);
658 672
659 switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 673 switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
660 case SND_SOC_DAIFMT_I2S: 674 case SND_SOC_DAIFMT_I2S:
661 /* Cleared when the DAI format is set */ 675 sspsp = ssp_read_reg(ssp, SSPSP);
662 sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width); 676
677 if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) &&
678 (width == 16)) {
679 /* This is a special case where the bitclk is 64fs
680 * and we're not dealing with 2*32 bits of audio
681 * samples.
682 *
683 * The SSP values used for that are all found out by
684 * trying and failing a lot; some of the registers
685 * needed for that mode are only available on PXA3xx.
686 */
687
688#ifdef CONFIG_PXA3xx
689 if (!cpu_is_pxa3xx())
690 return -EINVAL;
691
692 sspsp |= SSPSP_SFRMWDTH(width * 2);
693 sspsp |= SSPSP_SFRMDLY(width * 4);
694 sspsp |= SSPSP_EDMYSTOP(3);
695 sspsp |= SSPSP_DMYSTOP(3);
696 sspsp |= SSPSP_DMYSTRT(1);
697#else
698 return -EINVAL;
699#endif
700 } else {
701 /* The frame width is the width the LRCLK is
702 * asserted for; the delay is expressed in
703 * half cycle units. We need the extra cycle
704 * because the data starts clocking out one BCLK
705 * after LRCLK changes polarity.
706 */
707 sspsp |= SSPSP_SFRMWDTH(width + 1);
708 sspsp |= SSPSP_SFRMDLY((width + 1) * 2);
709 sspsp |= SSPSP_DMYSTRT(1);
710 }
711
663 ssp_write_reg(ssp, SSPSP, sspsp); 712 ssp_write_reg(ssp, SSPSP, sspsp);
664 break; 713 break;
665 default: 714 default:
666 break; 715 break;
667 } 716 }
668 717
669 /* We always use a network mode so we always require TDM slots 718 /* When we use a network mode, we always require TDM slots
670 * - 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.
671 */ 720 */
672 if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) { 721 if ((sscr0 & SSCR0_MOD) && !ttsa) {
673 dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); 722 dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
674 return -EINVAL; 723 return -EINVAL;
675 } 724 }
@@ -751,7 +800,7 @@ static int pxa_ssp_probe(struct platform_device *pdev,
751 if (!priv) 800 if (!priv)
752 return -ENOMEM; 801 return -ENOMEM;
753 802
754 priv->dev.ssp = ssp_request(dai->id, "SoC audio"); 803 priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio");
755 if (priv->dev.ssp == NULL) { 804 if (priv->dev.ssp == NULL) {
756 ret = -ENODEV; 805 ret = -ENODEV;
757 goto err_priv; 806 goto err_priv;
@@ -782,6 +831,19 @@ static void pxa_ssp_remove(struct platform_device *pdev,
782 SNDRV_PCM_FMTBIT_S24_LE | \ 831 SNDRV_PCM_FMTBIT_S24_LE | \
783 SNDRV_PCM_FMTBIT_S32_LE) 832 SNDRV_PCM_FMTBIT_S32_LE)
784 833
834static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
835 .startup = pxa_ssp_startup,
836 .shutdown = pxa_ssp_shutdown,
837 .trigger = pxa_ssp_trigger,
838 .hw_params = pxa_ssp_hw_params,
839 .set_sysclk = pxa_ssp_set_dai_sysclk,
840 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
841 .set_pll = pxa_ssp_set_dai_pll,
842 .set_fmt = pxa_ssp_set_dai_fmt,
843 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
844 .set_tristate = pxa_ssp_set_dai_tristate,
845};
846
785struct snd_soc_dai pxa_ssp_dai[] = { 847struct snd_soc_dai pxa_ssp_dai[] = {
786 { 848 {
787 .name = "pxa2xx-ssp1", 849 .name = "pxa2xx-ssp1",
@@ -802,18 +864,7 @@ struct snd_soc_dai pxa_ssp_dai[] = {
802 .rates = PXA_SSP_RATES, 864 .rates = PXA_SSP_RATES,
803 .formats = PXA_SSP_FORMATS, 865 .formats = PXA_SSP_FORMATS,
804 }, 866 },
805 .ops = { 867 .ops = &pxa_ssp_dai_ops,
806 .startup = pxa_ssp_startup,
807 .shutdown = pxa_ssp_shutdown,
808 .trigger = pxa_ssp_trigger,
809 .hw_params = pxa_ssp_hw_params,
810 .set_sysclk = pxa_ssp_set_dai_sysclk,
811 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
812 .set_pll = pxa_ssp_set_dai_pll,
813 .set_fmt = pxa_ssp_set_dai_fmt,
814 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
815 .set_tristate = pxa_ssp_set_dai_tristate,
816 },
817 }, 868 },
818 { .name = "pxa2xx-ssp2", 869 { .name = "pxa2xx-ssp2",
819 .id = 1, 870 .id = 1,
@@ -833,18 +884,7 @@ struct snd_soc_dai pxa_ssp_dai[] = {
833 .rates = PXA_SSP_RATES, 884 .rates = PXA_SSP_RATES,
834 .formats = PXA_SSP_FORMATS, 885 .formats = PXA_SSP_FORMATS,
835 }, 886 },
836 .ops = { 887 .ops = &pxa_ssp_dai_ops,
837 .startup = pxa_ssp_startup,
838 .shutdown = pxa_ssp_shutdown,
839 .trigger = pxa_ssp_trigger,
840 .hw_params = pxa_ssp_hw_params,
841 .set_sysclk = pxa_ssp_set_dai_sysclk,
842 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
843 .set_pll = pxa_ssp_set_dai_pll,
844 .set_fmt = pxa_ssp_set_dai_fmt,
845 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
846 .set_tristate = pxa_ssp_set_dai_tristate,
847 },
848 }, 888 },
849 { 889 {
850 .name = "pxa2xx-ssp3", 890 .name = "pxa2xx-ssp3",
@@ -865,18 +905,7 @@ struct snd_soc_dai pxa_ssp_dai[] = {
865 .rates = PXA_SSP_RATES, 905 .rates = PXA_SSP_RATES,
866 .formats = PXA_SSP_FORMATS, 906 .formats = PXA_SSP_FORMATS,
867 }, 907 },
868 .ops = { 908 .ops = &pxa_ssp_dai_ops,
869 .startup = pxa_ssp_startup,
870 .shutdown = pxa_ssp_shutdown,
871 .trigger = pxa_ssp_trigger,
872 .hw_params = pxa_ssp_hw_params,
873 .set_sysclk = pxa_ssp_set_dai_sysclk,
874 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
875 .set_pll = pxa_ssp_set_dai_pll,
876 .set_fmt = pxa_ssp_set_dai_fmt,
877 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
878 .set_tristate = pxa_ssp_set_dai_tristate,
879 },
880 }, 909 },
881 { 910 {
882 .name = "pxa2xx-ssp4", 911 .name = "pxa2xx-ssp4",
@@ -897,18 +926,7 @@ struct snd_soc_dai pxa_ssp_dai[] = {
897 .rates = PXA_SSP_RATES, 926 .rates = PXA_SSP_RATES,
898 .formats = PXA_SSP_FORMATS, 927 .formats = PXA_SSP_FORMATS,
899 }, 928 },
900 .ops = { 929 .ops = &pxa_ssp_dai_ops,
901 .startup = pxa_ssp_startup,
902 .shutdown = pxa_ssp_shutdown,
903 .trigger = pxa_ssp_trigger,
904 .hw_params = pxa_ssp_hw_params,
905 .set_sysclk = pxa_ssp_set_dai_sysclk,
906 .set_clkdiv = pxa_ssp_set_dai_clkdiv,
907 .set_pll = pxa_ssp_set_dai_pll,
908 .set_fmt = pxa_ssp_set_dai_fmt,
909 .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
910 .set_tristate = pxa_ssp_set_dai_tristate,
911 },
912 }, 930 },
913}; 931};
914EXPORT_SYMBOL_GPL(pxa_ssp_dai); 932EXPORT_SYMBOL_GPL(pxa_ssp_dai);