if (IS_ERR(clk_i2s))
return PTR_ERR(clk_i2s);
- if (!cpu_dai->active) {
- SACR0 |= SACR0_RST;
+ if (!cpu_dai->active)
SACR0 = 0;
- }
return 0;
}
/* is port used by another stream */
if (!(SACR0 & SACR0_ENB)) {
-
SACR0 = 0;
- SACR1 = 0;
if (pxa_i2s.master)
SACR0 |= SACR0_BCKD;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ SACR1 &= ~SACR1_DRPL;
+ else
+ SACR1 &= ~SACR1_DREC;
SACR0 |= SACR0_ENB;
break;
case SNDRV_PCM_TRIGGER_RESUME:
SAIMR &= ~SAIMR_RFS;
}
- if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
+ if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
SACR0 &= ~SACR0_ENB;
pxa_i2s_wait();
clk_disable(clk_i2s);
}
-
- clk_put(clk_i2s);
}
#ifdef CONFIG_PM
static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
{
- if (!dai->active)
- return 0;
-
/* store registers */
pxa_i2s.sacr0 = SACR0;
pxa_i2s.sacr1 = SACR1;
static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
{
- if (!dai->active)
- return 0;
-
pxa_i2s_wait();
- SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB;
+ SACR0 = pxa_i2s.sacr0 & ~SACR0_ENB;
SACR1 = pxa_i2s.sacr1;
SAIMR = pxa_i2s.saimr;
SADIV = pxa_i2s.sadiv;
- SACR0 |= SACR0_ENB;
+
+ SACR0 = pxa_i2s.sacr0;
return 0;
}
.rates = PXA2XX_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = &pxa_i2s_dai_ops,
+ .symmetric_rates = 1,
};
EXPORT_SYMBOL_GPL(pxa_i2s_dai);
if (ret != 0)
clk_put(clk_i2s);
+ /*
+ * PXA Developer's Manual:
+ * If SACR0[ENB] is toggled in the middle of a normal operation,
+ * the SACR0[RST] bit must also be set and cleared to reset all
+ * I2S controller registers.
+ */
+ SACR0 = SACR0_RST;
+ SACR0 = 0;
+ /* Make sure RPL and REC are disabled */
+ SACR1 = SACR1_DRPL | SACR1_DREC;
+ /* Along with FIFO servicing */
+ SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
+
return ret;
}