diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-03-17 15:07:26 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-03-17 15:07:26 -0400 |
commit | da88b48b84e1a504b6a19aff9d5b8236a59e228a (patch) | |
tree | 1ec0fc6ecf51c7baf7bf6cfbd9250c3fee16a09b /sound | |
parent | d2314e0e27566f8830ebed3587cc049e07e6a4ee (diff) | |
parent | 85fab7802a4bc00cc752f430e22a0d9fc41fe199 (diff) |
Merge branch 'pxa-ssp' into for-2.6.30
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/pxa/pxa-ssp.c | 55 | ||||
-rw-r--r-- | sound/soc/pxa/zylonite.c | 55 |
2 files changed, 68 insertions, 42 deletions
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index d3fa6357a9fd..b0bf40973d5b 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 | * |
@@ -558,18 +557,18 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
558 | 557 | ||
559 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 558 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
560 | case SND_SOC_DAIFMT_I2S: | 559 | case SND_SOC_DAIFMT_I2S: |
561 | sscr0 |= SSCR0_MOD | SSCR0_PSP; | 560 | sscr0 |= SSCR0_PSP; |
562 | sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; | 561 | sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; |
563 | 562 | ||
563 | /* See hw_params() */ | ||
564 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 564 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
565 | case SND_SOC_DAIFMT_NB_NF: | 565 | case SND_SOC_DAIFMT_NB_NF: |
566 | sspsp |= SSPSP_FSRT; | 566 | sspsp |= SSPSP_SFRMP; |
567 | break; | 567 | break; |
568 | case SND_SOC_DAIFMT_NB_IF: | 568 | case SND_SOC_DAIFMT_NB_IF: |
569 | sspsp |= SSPSP_SFRMP | SSPSP_FSRT; | ||
570 | break; | 569 | break; |
571 | case SND_SOC_DAIFMT_IB_IF: | 570 | case SND_SOC_DAIFMT_IB_IF: |
572 | sspsp |= SSPSP_SFRMP; | 571 | sspsp |= SSPSP_SCMODE(3); |
573 | break; | 572 | break; |
574 | default: | 573 | default: |
575 | return -EINVAL; | 574 | return -EINVAL; |
@@ -655,33 +654,65 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | |||
655 | sscr0 |= SSCR0_FPCKE; | 654 | sscr0 |= SSCR0_FPCKE; |
656 | #endif | 655 | #endif |
657 | sscr0 |= SSCR0_DataSize(16); | 656 | sscr0 |= SSCR0_DataSize(16); |
658 | /* use network mode (2 slots) for 16 bit stereo */ | ||
659 | break; | 657 | break; |
660 | case SNDRV_PCM_FORMAT_S24_LE: | 658 | case SNDRV_PCM_FORMAT_S24_LE: |
661 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); | 659 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); |
662 | /* we must be in network mode (2 slots) for 24 bit stereo */ | ||
663 | break; | 660 | break; |
664 | case SNDRV_PCM_FORMAT_S32_LE: | 661 | case SNDRV_PCM_FORMAT_S32_LE: |
665 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); | 662 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); |
666 | /* we must be in network mode (2 slots) for 32 bit stereo */ | ||
667 | break; | 663 | break; |
668 | } | 664 | } |
669 | ssp_write_reg(ssp, SSCR0, sscr0); | 665 | ssp_write_reg(ssp, SSCR0, sscr0); |
670 | 666 | ||
671 | switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 667 | switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
672 | case SND_SOC_DAIFMT_I2S: | 668 | case SND_SOC_DAIFMT_I2S: |
673 | /* Cleared when the DAI format is set */ | 669 | sspsp = ssp_read_reg(ssp, SSPSP); |
674 | sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width); | 670 | |
671 | if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) && | ||
672 | (width == 16)) { | ||
673 | /* This is a special case where the bitclk is 64fs | ||
674 | * and we're not dealing with 2*32 bits of audio | ||
675 | * samples. | ||
676 | * | ||
677 | * The SSP values used for that are all found out by | ||
678 | * trying and failing a lot; some of the registers | ||
679 | * needed for that mode are only available on PXA3xx. | ||
680 | */ | ||
681 | |||
682 | #ifdef CONFIG_PXA3xx | ||
683 | if (!cpu_is_pxa3xx()) | ||
684 | return -EINVAL; | ||
685 | |||
686 | sspsp |= SSPSP_SFRMWDTH(width * 2); | ||
687 | sspsp |= SSPSP_SFRMDLY(width * 4); | ||
688 | sspsp |= SSPSP_EDMYSTOP(3); | ||
689 | sspsp |= SSPSP_DMYSTOP(3); | ||
690 | sspsp |= SSPSP_DMYSTRT(1); | ||
691 | #else | ||
692 | return -EINVAL; | ||
693 | #endif | ||
694 | } else { | ||
695 | /* The frame width is the width the LRCLK is | ||
696 | * asserted for; the delay is expressed in | ||
697 | * half cycle units. We need the extra cycle | ||
698 | * because the data starts clocking out one BCLK | ||
699 | * after LRCLK changes polarity. | ||
700 | */ | ||
701 | sspsp |= SSPSP_SFRMWDTH(width + 1); | ||
702 | sspsp |= SSPSP_SFRMDLY((width + 1) * 2); | ||
703 | sspsp |= SSPSP_DMYSTRT(1); | ||
704 | } | ||
705 | |||
675 | ssp_write_reg(ssp, SSPSP, sspsp); | 706 | ssp_write_reg(ssp, SSPSP, sspsp); |
676 | break; | 707 | break; |
677 | default: | 708 | default: |
678 | break; | 709 | break; |
679 | } | 710 | } |
680 | 711 | ||
681 | /* We always use a network mode so we always require TDM slots | 712 | /* When we use a network mode, we always require TDM slots |
682 | * - complain loudly and fail if they've not been set up yet. | 713 | * - complain loudly and fail if they've not been set up yet. |
683 | */ | 714 | */ |
684 | if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) { | 715 | if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) { |
685 | dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); | 716 | dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); |
686 | return -EINVAL; | 717 | return -EINVAL; |
687 | } | 718 | } |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 9f6116edbb84..9a386b4c4ed1 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -96,42 +96,35 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
96 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | 96 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; |
97 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 97 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
98 | unsigned int pll_out = 0; | 98 | unsigned int pll_out = 0; |
99 | unsigned int acds = 0; | ||
100 | unsigned int wm9713_div = 0; | 99 | unsigned int wm9713_div = 0; |
101 | int ret = 0; | 100 | int ret = 0; |
102 | 101 | int rate = params_rate(params); | |
103 | switch (params_rate(params)) { | 102 | int width = snd_pcm_format_physical_width(params_format(params)); |
103 | |||
104 | /* Only support ratios that we can generate neatly from the AC97 | ||
105 | * based master clock - in particular, this excludes 44.1kHz. | ||
106 | * In most applications the voice DAC will be used for telephony | ||
107 | * data so multiples of 8kHz will be the common case. | ||
108 | */ | ||
109 | switch (rate) { | ||
104 | case 8000: | 110 | case 8000: |
105 | wm9713_div = 12; | 111 | wm9713_div = 12; |
106 | pll_out = 2048000; | ||
107 | break; | 112 | break; |
108 | case 16000: | 113 | case 16000: |
109 | wm9713_div = 6; | 114 | wm9713_div = 6; |
110 | pll_out = 4096000; | ||
111 | break; | 115 | break; |
112 | case 48000: | 116 | case 48000: |
113 | default: | ||
114 | wm9713_div = 2; | 117 | wm9713_div = 2; |
115 | pll_out = 12288000; | ||
116 | acds = 1; | ||
117 | break; | 118 | break; |
119 | default: | ||
120 | /* Don't support OSS emulation */ | ||
121 | return -EINVAL; | ||
118 | } | 122 | } |
119 | 123 | ||
120 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | 124 | /* Add 1 to the width for the leading clock cycle */ |
121 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | 125 | pll_out = rate * (width + 1) * 8; |
122 | if (ret < 0) | ||
123 | return ret; | ||
124 | |||
125 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
126 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
127 | if (ret < 0) | ||
128 | return ret; | ||
129 | 126 | ||
130 | /* Use network mode for stereo, one slot per channel. */ | 127 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); |
131 | if (params_channels(params) > 1) | ||
132 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 2); | ||
133 | else | ||
134 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); | ||
135 | if (ret < 0) | 128 | if (ret < 0) |
136 | return ret; | 129 | return ret; |
137 | 130 | ||
@@ -139,14 +132,6 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
139 | if (ret < 0) | 132 | if (ret < 0) |
140 | return ret; | 133 | return ret; |
141 | 134 | ||
142 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); | ||
143 | if (ret < 0) | ||
144 | return ret; | ||
145 | |||
146 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); | ||
147 | if (ret < 0) | ||
148 | return ret; | ||
149 | |||
150 | if (clk_pout) | 135 | if (clk_pout) |
151 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, | 136 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_PLL_DIV, |
152 | WM9713_PCMDIV(wm9713_div)); | 137 | WM9713_PCMDIV(wm9713_div)); |
@@ -156,6 +141,16 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | |||
156 | if (ret < 0) | 141 | if (ret < 0) |
157 | return ret; | 142 | return ret; |
158 | 143 | ||
144 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
145 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
146 | if (ret < 0) | ||
147 | return ret; | ||
148 | |||
149 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
150 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
151 | if (ret < 0) | ||
152 | return ret; | ||
153 | |||
159 | return 0; | 154 | return 0; |
160 | } | 155 | } |
161 | 156 | ||