|
@@ -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;
|
|
|
}
|