aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@nokia.com>2008-10-20 08:29:59 -0400
committerTakashi Iwai <tiwai@suse.de>2008-10-20 11:03:21 -0400
commitba9d0fd0f0af3eb7ec463847b409dd88f8e5c031 (patch)
treec80d2d5712bba95af3fd08c01fe2c91c049bab23
parent7c2dfee84863628f9af109131edd4344ce567d16 (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>
-rw-r--r--sound/soc/omap/omap-mcbsp.c24
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 @@
43struct omap_mcbsp_data { 43struct 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.