diff options
author | Daniel Mack <daniel@caiaq.de> | 2009-03-12 06:27:49 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-03-13 09:23:34 -0400 |
commit | 72d7466468b471f99cefae3c5f4a414bbbaa0bdd (patch) | |
tree | f5cee2480802bd31efa066eb65c2bc9dfe0b3d2a /sound | |
parent | 77dd7e17b86bd81b3638e01d784a72652071508b (diff) |
ASoC: switch PXA SSP driver from network mode to PSP
This switches the pxa ssp port usage from network mode to PSP mode.
Removed some comments and checks for configured TDM channels.
A special case is added to support configuration where BCLK = 64fs. We
need to do some black magic in this case which doesn't look nice but
there is unfortunately no other option than that.
Diagnosed-by: Tim Ruetz <tim@caiaq.de>
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/pxa/pxa-ssp.c | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index d3fa6357a9f..4dd0d7c5722 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -558,18 +558,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
558 | 558 | ||
559 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 559 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
560 | case SND_SOC_DAIFMT_I2S: | 560 | case SND_SOC_DAIFMT_I2S: |
561 | sscr0 |= SSCR0_MOD | SSCR0_PSP; | 561 | sscr0 |= SSCR0_PSP; |
562 | sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; | 562 | sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; |
563 | 563 | ||
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; | ||
567 | break; | 566 | break; |
568 | case SND_SOC_DAIFMT_NB_IF: | 567 | case SND_SOC_DAIFMT_NB_IF: |
569 | sspsp |= SSPSP_SFRMP | SSPSP_FSRT; | 568 | sspsp |= SSPSP_SFRMP; |
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_SFRMP | SSPSP_SCMODE(3); |
573 | break; | 572 | break; |
574 | default: | 573 | default: |
575 | return -EINVAL; | 574 | return -EINVAL; |
@@ -655,33 +654,56 @@ 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 | sspsp |= SSPSP_SFRMWDTH(width); | ||
696 | |||
675 | ssp_write_reg(ssp, SSPSP, sspsp); | 697 | ssp_write_reg(ssp, SSPSP, sspsp); |
676 | break; | 698 | break; |
677 | default: | 699 | default: |
678 | break; | 700 | break; |
679 | } | 701 | } |
680 | 702 | ||
681 | /* We always use a network mode so we always require TDM slots | 703 | /* When we use a network mode, we always require TDM slots |
682 | * - complain loudly and fail if they've not been set up yet. | 704 | * - complain loudly and fail if they've not been set up yet. |
683 | */ | 705 | */ |
684 | if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) { | 706 | if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) { |
685 | dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); | 707 | dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); |
686 | return -EINVAL; | 708 | return -EINVAL; |
687 | } | 709 | } |