/** * fsl_ssi_hw_params - program the sample size * * Most of the SSI registers have been programmed in the startup function, * but the word length must be programmed here. Unfortunately, programming * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can * cause a problem with supporting simultaneous playback and capture. If * the SSI is already playing a stream, then that stream may be temporarily * stopped when you start capture. * * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the * clock master. */ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) { struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); if (substream == ssi_private->first_stream) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; unsigned int sample_size = snd_pcm_format_width(params_format(hw_params)); u32 wl = CCSR_SSI_SxCCR_WL(sample_size); /* The SSI should always be disabled at this points (SSIEN=0) */ /* In synchronous mode, the SSI uses STCCR for capture */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || !ssi_private->asynchronous) clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); else clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); } return 0; }
static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) { struct fsl_ssi_private *ssi_private = cpu_dai->private_data; if (substream == ssi_private->first_stream) { struct ccsr_ssi __iomem *ssi = ssi_private->ssi; unsigned int sample_size = snd_pcm_format_width(params_format(hw_params)); u32 wl = CCSR_SSI_SxCCR_WL(sample_size); if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || !ssi_private->asynchronous) clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); else clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); } return 0; }
/** * fsl_ssi_prepare: prepare the SSI. * * Most of the SSI registers have been programmed in the startup function, * but the word length must be programmed here. Unfortunately, programming * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can * cause a problem with supporting simultaneous playback and capture. If * the SSI is already playing a stream, then that stream may be temporarily * stopped when you start capture. * * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the * clock master. */ static int fsl_ssi_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; struct ccsr_ssi __iomem *ssi = ssi_private->ssi; if (substream == ssi_private->first_stream) { u32 wl; /* The SSI should always be disabled at this points (SSIEN=0) */ wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format)); /* In synchronous mode, the SSI uses STCCR for capture */ clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); } return 0; }
/** * fsl_ssi_hw_params - program the sample size * * Most of the SSI registers have been programmed in the startup function, * but the word length must be programmed here. Unfortunately, programming * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can * cause a problem with supporting simultaneous playback and capture. If * the SSI is already playing a stream, then that stream may be temporarily * stopped when you start capture. * * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the * clock master. */ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) { struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); struct ccsr_ssi __iomem *ssi = ssi_private->ssi; unsigned int sample_size = snd_pcm_format_width(params_format(hw_params)); u32 wl = CCSR_SSI_SxCCR_WL(sample_size); int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN; unsigned int channels = params_channels(hw_params); /* * If we're in synchronous mode, and the SSI is already enabled, * then STCCR is already set properly. */ if (enabled && ssi_private->cpu_dai_drv.symmetric_rates) return 0; /* * FIXME: The documentation says that SxCCR[WL] should not be * modified while the SSI is enabled. The only time this can * happen is if we're trying to do simultaneous playback and * capture in asynchronous mode. Unfortunately, I have been enable * to get that to work at all on the P1022DS. Therefore, we don't * bother to disable/enable the SSI when setting SxCCR[WL], because * the SSI will stop anyway. Maybe one day, this will get fixed. */ /* In synchronous mode, the SSI uses STCCR for capture */ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || ssi_private->cpu_dai_drv.symmetric_rates) write_ssi_mask(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); else write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); write_ssi_mask(&ssi->scr, CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK, channels == 1 ? 0 : ssi_private->i2s_mode); return 0; }
/** * fsl_ssi_prepare: prepare the SSI. * * Most of the SSI registers have been programmed in the startup function, * but the word length must be programmed here. Unfortunately, programming * the SxCCR.WL bits requires the SSI to be temporarily disabled. This can * cause a problem with supporting simultaneous playback and capture. If * the SSI is already playing a stream, then that stream may be temporarily * stopped when you start capture. * * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the * clock master. */ static int fsl_ssi_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; struct ccsr_ssi __iomem *ssi = ssi_private->ssi; u32 wl; wl = CCSR_SSI_SxCCR_WL(snd_pcm_format_width(runtime->format)); clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); else clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); setbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); return 0; }