ASoC: switch PXA SSP driver from network mode to PSP
authorDaniel Mack <daniel@caiaq.de>
Thu, 12 Mar 2009 10:27:49 +0000 (11:27 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Fri, 13 Mar 2009 13:23:34 +0000 (13:23 +0000)
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>
sound/soc/pxa/pxa-ssp.c

index d3fa6357a9fd9a1eabc29aeef41843dc118501f2..4dd0d7c57220326eaaae34c2319db5743e656733 100644 (file)
@@ -558,18 +558,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
-               sscr0 |= SSCR0_MOD | SSCR0_PSP;
+               sscr0 |= SSCR0_PSP;
                sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
 
                switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
                case SND_SOC_DAIFMT_NB_NF:
-                       sspsp |= SSPSP_FSRT;
                        break;
                case SND_SOC_DAIFMT_NB_IF:
-                       sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
+                       sspsp |= SSPSP_SFRMP;
                        break;
                case SND_SOC_DAIFMT_IB_IF:
-                       sspsp |= SSPSP_SFRMP;
+                       sspsp |= SSPSP_SFRMP | SSPSP_SCMODE(3);
                        break;
                default:
                        return -EINVAL;
@@ -655,33 +654,56 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
                        sscr0 |= SSCR0_FPCKE;
 #endif
                sscr0 |= SSCR0_DataSize(16);
-               /* use network mode (2 slots) for 16 bit stereo */
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
                sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
-               /* we must be in network mode (2 slots) for 24 bit stereo */
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
                sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
-               /* we must be in network mode (2 slots) for 32 bit stereo */
                break;
        }
        ssp_write_reg(ssp, SSCR0, sscr0);
 
        switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
-               /* Cleared when the DAI format is set */
-               sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width);
+              sspsp = ssp_read_reg(ssp, SSPSP);
+
+               if (((sscr0 & SSCR0_SCR) == SSCR0_SerClkDiv(4)) &&
+                    (width == 16)) {
+                       /* This is a special case where the bitclk is 64fs
+                       * and we're not dealing with 2*32 bits of audio
+                       * samples.
+                       *
+                       * The SSP values used for that are all found out by
+                       * trying and failing a lot; some of the registers
+                       * needed for that mode are only available on PXA3xx.
+                       */
+
+#ifdef CONFIG_PXA3xx
+                       if (!cpu_is_pxa3xx())
+                               return -EINVAL;
+
+                       sspsp |= SSPSP_SFRMWDTH(width * 2);
+                       sspsp |= SSPSP_SFRMDLY(width * 4);
+                       sspsp |= SSPSP_EDMYSTOP(3);
+                       sspsp |= SSPSP_DMYSTOP(3);
+                       sspsp |= SSPSP_DMYSTRT(1);
+#else
+                       return -EINVAL;
+#endif
+               } else
+                       sspsp |= SSPSP_SFRMWDTH(width);
+
                ssp_write_reg(ssp, SSPSP, sspsp);
                break;
        default:
                break;
        }
 
-       /* We always use a network mode so we always require TDM slots
+       /* When we use a network mode, we always require TDM slots
         * - complain loudly and fail if they've not been set up yet.
         */
-       if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) {
+       if ((sscr0 & SSCR0_MOD) && !(ssp_read_reg(ssp, SSTSA) & 0xf)) {
                dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
                return -EINVAL;
        }