Skip to content

Commit

Permalink
ALSA: ASoC: OMAP: Fix DSP DAI format in McBSP DAI driver
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jarkko Nikula authored and Takashi Iwai committed Oct 20, 2008
1 parent 7c2dfee commit ba9d0fd
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions sound/soc/omap/omap-mcbsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
struct omap_mcbsp_data {
unsigned int bus_id;
struct omap_mcbsp_reg_cfg regs;
unsigned int fmt;
/*
* Flags indicating is the bus already activated and configured by
* another substream
Expand Down Expand Up @@ -200,6 +201,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
int wlen;
unsigned long port;

if (cpu_class_is_omap1()) {
Expand Down Expand Up @@ -244,19 +246,29 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
/* Set word lengths */
wlen = 16;
regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16);
regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16);
regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16);
regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16);
/* Set FS period and length in terms of bit clock periods */
regs->srgr2 |= FPER(16 * 2 - 1);
regs->srgr1 |= FWID(16 - 1);
break;
default:
/* Unsupported PCM format */
return -EINVAL;
}

/* Set FS period and length in terms of bit clock periods */
switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
regs->srgr2 |= FPER(wlen * 2 - 1);
regs->srgr1 |= FWID(wlen - 1);
break;
case SND_SOC_DAIFMT_DSP_A:
regs->srgr2 |= FPER(wlen * 2 - 1);
regs->srgr1 |= FWID(0);
break;
}

omap_mcbsp_config(bus_id, &mcbsp_data->regs);
mcbsp_data->configured = 1;

Expand All @@ -272,10 +284,12 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
{
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
unsigned int temp_fmt = fmt;

if (mcbsp_data->configured)
return 0;

mcbsp_data->fmt = fmt;
memset(regs, 0, sizeof(*regs));
/* Generic McBSP register settings */
regs->spcr2 |= XINTM(3) | FREE;
Expand All @@ -293,6 +307,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
/* 0-bit data delay */
regs->rcr2 |= RDATDLY(0);
regs->xcr2 |= XDATDLY(0);
/* Invert bit clock and FS polarity configuration for DSP_A */
temp_fmt ^= SND_SOC_DAIFMT_IB_IF;
break;
default:
/* Unsupported data format */
Expand All @@ -316,7 +332,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
}

/* Set bit clock (CLKX/CLKR) and FS polarities */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
/*
* Normal BCLK + FS.
Expand Down

0 comments on commit ba9d0fd

Please sign in to comment.