This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DM8148 EVM: ASoC: McASP seems to be I2S mode while AIC3106 is DSP mode

Hi,

We have captured MIC input using both ALSA and DSP/BIOS Audio Driver (via our CodecEngine Server).  We are observing that ALSA capture has 6dB higher noise level than that of DSP Audio Driver.  It appears that there is 1-bit shift on Rx and Tx due to incorrect dai fmt setting in ALSA.  Can anyone help me verify this?

My assumption is that McASP is set to I2S mode in the board-ti8148evm.c file.

board-ti8148evm.c:

static struct snd_platform_data ti8148_evm_snd_data = {
    .tx_dma_offset    = 0x46800000,
    .rx_dma_offset    = 0x46800000,
    .op_mode    = DAVINCI_MCASP_IIS_MODE,
    .num_serializer = ARRAY_SIZE(ti8148_iis_serializer_direction),
    .tdm_slots    = 2,
    .serial_dir    = ti8148_iis_serializer_direction,
    .asp_chan_q    = EVENTQ_2,
    .version    = MCASP_VERSION_2,
    .txnumevt    = 1,
    .rxnumevt    = 1,
};

However, AIC is set to DSP mode in the davinci-evm.c file.

davinci-evm.c:

#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
        SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)

static struct snd_soc_dai_link ti81xx_evm_dai[] = {
    {
        .name = "TLV320AIC3X",
        .stream_name = "AIC3X",
        .cpu_dai_name = "davinci-mcasp.2",
        .codec_dai_name = "tlv320aic3x-hifi",
        .codec_name = "tlv320aic3x-codec.1-0018",
        .platform_name = "davinci-pcm-audio",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
    },

The codec (AIC) driver does initialize the AIC to DSP mode (via Register 9) due to SND_SOC_DAIFMT_DSP_B.

    /*
     * match both interface format and signal polarities since they
     * are fixed
     */
    switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
               SND_SOC_DAIFMT_INV_MASK)) {
    case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF):
        break;
    case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF):
        delay = 1;
    case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF):
        iface_breg |= (0x01 << 6);
        break;
    case (SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF):
        iface_breg |= (0x02 << 6);
        break;
    case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF):
        iface_breg |= (0x03 << 6);
        break;
    default:
        return -EINVAL;
    }

    /* set iface */
    snd_soc_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg);
    snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg);
    snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, delay);

I have verified that AIC Register 9 is set to 0x40, which is DSP mode.

Looking at davinci-mcasp.c, the following code does not seem to be able to handle CPU dai fmt other than master/slave and polarity.  I think this is why McASP remains I2S mode while AIC is set to DSP mode.  Can anyone confirm or let me know how to verify McASP settings?

static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                     unsigned int fmt)
{
    struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
    void __iomem *base = dev->base;

    switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    case SND_SOC_DAIFMT_CBS_CFS:
        /* codec is clock and frame slave */
        mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
        mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

        mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
        mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

        mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));
        break;
    case SND_SOC_DAIFMT_CBM_CFS:
        /* codec is clock master and frame slave */
        mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
        mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

        mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
        mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

        mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x2d << 26));
        break;
    case SND_SOC_DAIFMT_CBM_CFM:
        /* codec is clock and frame master */
        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
        mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
        mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);

        mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26));
        break;

    default:
        return -EINVAL;
    }

    switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    case SND_SOC_DAIFMT_IB_NF:
        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
        mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

        mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
        mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
        break;

    case SND_SOC_DAIFMT_NB_IF:
        mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
        mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
        mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
        break;

    case SND_SOC_DAIFMT_IB_IF:
        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
        mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

        mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
        mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
        break;

    case SND_SOC_DAIFMT_NB_NF:
        mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
        mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);

        mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
        mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
        break;

    default:
        return -EINVAL;
    }

    return 0;
}

Regards,

Chan-Taek Park

Applications Engineer

Texas Instruments, Inc