diff options
author | Jarkko Nikula <jarkko.nikula@nokia.com> | 2008-10-20 08:29:59 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-10-20 11:03:21 -0400 |
commit | ba9d0fd0f0af3eb7ec463847b409dd88f8e5c031 (patch) | |
tree | c80d2d5712bba95af3fd08c01fe2c91c049bab23 /sound/soc | |
parent | 7c2dfee84863628f9af109131edd4344ce567d16 (diff) |
ALSA: ASoC: OMAP: Fix DSP DAI format in McBSP DAI driver
Fix word clock length which must equal to one bit clock cycle in DSP mode.
Surprisingly McBSP is able synchronize into wrong length when it's
slave but e.g. TLV320AIC33 codec in slave configuration is outputting
some amount of noise if word clock length is longer than one bit clock
cycle.
Fix also bit clock and frame sync polarities in DSP mode since they are
opposite from I2S.
Signed-off-by: Jarkko Nikula <jarkko.nikula@nokia.com>
Cc: Arun KS <arunks@mistralsolutions.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 0a063a98a661..853b33ae3435 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -43,6 +43,7 @@ | |||
43 | struct omap_mcbsp_data { | 43 | struct omap_mcbsp_data { |
44 | unsigned int bus_id; | 44 | unsigned int bus_id; |
45 | struct omap_mcbsp_reg_cfg regs; | 45 | struct omap_mcbsp_reg_cfg regs; |
46 | unsigned int fmt; | ||
46 | /* | 47 | /* |
47 | * Flags indicating is the bus already activated and configured by | 48 | * Flags indicating is the bus already activated and configured by |
48 | * another substream | 49 | * another substream |
@@ -200,6 +201,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
200 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 201 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); |
201 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 202 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
202 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; | 203 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; |
204 | int wlen; | ||
203 | unsigned long port; | 205 | unsigned long port; |
204 | 206 | ||
205 | if (cpu_class_is_omap1()) { | 207 | if (cpu_class_is_omap1()) { |
@@ -244,19 +246,29 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
244 | switch (params_format(params)) { | 246 | switch (params_format(params)) { |
245 | case SNDRV_PCM_FORMAT_S16_LE: | 247 | case SNDRV_PCM_FORMAT_S16_LE: |
246 | /* Set word lengths */ | 248 | /* Set word lengths */ |
249 | wlen = 16; | ||
247 | regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); | 250 | regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); |
248 | regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); | 251 | regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); |
249 | regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); | 252 | regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); |
250 | regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); | 253 | regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); |
251 | /* Set FS period and length in terms of bit clock periods */ | ||
252 | regs->srgr2 |= FPER(16 * 2 - 1); | ||
253 | regs->srgr1 |= FWID(16 - 1); | ||
254 | break; | 254 | break; |
255 | default: | 255 | default: |
256 | /* Unsupported PCM format */ | 256 | /* Unsupported PCM format */ |
257 | return -EINVAL; | 257 | return -EINVAL; |
258 | } | 258 | } |
259 | 259 | ||
260 | /* Set FS period and length in terms of bit clock periods */ | ||
261 | switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
262 | case SND_SOC_DAIFMT_I2S: | ||
263 | regs->srgr2 |= FPER(wlen * 2 - 1); | ||
264 | regs->srgr1 |= FWID(wlen - 1); | ||
265 | break; | ||
266 | case SND_SOC_DAIFMT_DSP_A: | ||
267 | regs->srgr2 |= FPER(wlen * 2 - 1); | ||
268 | regs->srgr1 |= FWID(0); | ||
269 | break; | ||
270 | } | ||
271 | |||
260 | omap_mcbsp_config(bus_id, &mcbsp_data->regs); | 272 | omap_mcbsp_config(bus_id, &mcbsp_data->regs); |
261 | mcbsp_data->configured = 1; | 273 | mcbsp_data->configured = 1; |
262 | 274 | ||
@@ -272,10 +284,12 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
272 | { | 284 | { |
273 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 285 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); |
274 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 286 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
287 | unsigned int temp_fmt = fmt; | ||
275 | 288 | ||
276 | if (mcbsp_data->configured) | 289 | if (mcbsp_data->configured) |
277 | return 0; | 290 | return 0; |
278 | 291 | ||
292 | mcbsp_data->fmt = fmt; | ||
279 | memset(regs, 0, sizeof(*regs)); | 293 | memset(regs, 0, sizeof(*regs)); |
280 | /* Generic McBSP register settings */ | 294 | /* Generic McBSP register settings */ |
281 | regs->spcr2 |= XINTM(3) | FREE; | 295 | regs->spcr2 |= XINTM(3) | FREE; |
@@ -293,6 +307,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
293 | /* 0-bit data delay */ | 307 | /* 0-bit data delay */ |
294 | regs->rcr2 |= RDATDLY(0); | 308 | regs->rcr2 |= RDATDLY(0); |
295 | regs->xcr2 |= XDATDLY(0); | 309 | regs->xcr2 |= XDATDLY(0); |
310 | /* Invert bit clock and FS polarity configuration for DSP_A */ | ||
311 | temp_fmt ^= SND_SOC_DAIFMT_IB_IF; | ||
296 | break; | 312 | break; |
297 | default: | 313 | default: |
298 | /* Unsupported data format */ | 314 | /* Unsupported data format */ |
@@ -316,7 +332,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
316 | } | 332 | } |
317 | 333 | ||
318 | /* Set bit clock (CLKX/CLKR) and FS polarities */ | 334 | /* Set bit clock (CLKX/CLKR) and FS polarities */ |
319 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 335 | switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) { |
320 | case SND_SOC_DAIFMT_NB_NF: | 336 | case SND_SOC_DAIFMT_NB_NF: |
321 | /* | 337 | /* |
322 | * Normal BCLK + FS. | 338 | * Normal BCLK + FS. |