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.

TLV320AIC3100: Biquad filter / DAC

Part Number: TLV320AIC3100

Dear Team,

our customer has challenges setting up the Biquad filter of the device's DAC via the tlv320aic31xx.c

We sent via e-mail first data and register dumps for page 0 and page 8.

This E2E post as direct communication between customer (Tim) <> product line (Pedro/Aaron) as I will be on vacation.

Best Regards
Martin

  • Hi Tim,

    It seems as though you are correctly writing to page 8. I would like to try see how the device is getting configured but only have a register dump for page 0 and 8. Can you please send a register dump for page 1?

    I will attempt to copy your configuration on an EVM to see if I can replicate the issue. A question I had is if you are passing data through the device when polling for bit D0 on page 8, register 1?

    Regards,

    Aaron

  • Hi Aaron,

    Thank you for your answer. The chip is "just there", and I'm not playing music when setting register values.

    Should I turn off additional stuff?

    # i2cset -f -y 1 0x18 0 1
    # i2cdump -f -y 1 0x18
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
    00: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ?...............
    10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c4    ...............?
    20: 86 3e 00 76 80 80 80 7f 4f 4f 1d 00 20 86 00 80    ?>.v????OO?. ?.?
    30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
    f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

    With kind regards,
    Tim

  • Hi Tim,

    Apologies on the delay here as we were out due to the holidays. 

    I would make sure the BCLK and WCLK are connected and also try to pass through some data when adaptive mode is enabled. When Bit D0 is set = 1, the coefficients will switch on the next WCLK frame while the device is running. Can you try this?

    Regards,

    Aaron

  • Hi Aaron,

    I've tried to measure the BCLK and WCLK on my (old, analog) oscilloscope. Tomorrow I will discuss it with the hardware engineer.
    WCLK (I2S_SCLK) = ~3 Volt, ~1.6us (625.0kHz)
    BCLK (I2S_FCLK) = ~3 Volt, ~50.2us (19.92kHz)

    I've played a a sweep from 20Hz to 20kHz and then run the "setbiquad.sh" script. The only difference I notice is the sound. It seems that an extra sine is being played.

  • Hi Tim,

    Is it possible that you have the WCLK and BCLK frequencies above swapped? A 600kHz WCLK is excessively high and a 19kHz BCLK frequency is too low. WCLK frequency should equal the sampling rate so if swapped, I would think you are funning at a 20kHz sample rate. Is this correct? 

    Regards,

    Aaron

  • In my comment above I indeed switched the two, sorry. The WCLK is connected to I2S_FCLK and BCLK to I2S_SCLK.

    In the discussion with "my" hardware engineer we found out that somehow the MCLK isn't working (at least no signal on the pad). I find it kind of strange that I'm able to play a tone. I'm fixing this ATM and I will come back to you tomorrow.

  • Tim,

    Thanks for the clarification. I will be awaiting your response.

    Regards,

    Aaron Estrada

  • Hello Aaron,

    I've enabled a 12.5Mhz and the bit still seems to hang. Should I change something in the tlv320aic31xx driver to get the DAC working or should it be working as-is? What are the prerequisites enable the DAC?

    Thanks.

    With kind regards,
    Tim

  • Hi Tim,

    From the register configuration I have received for Page 0, It looks like the DAC's are powered down. Can you enable the DACs in Page 0, Register 0x3F?

    Regards,
    Aaron Estrada

  • Hi Tim,

    I went ahead and tested the adaptive mode on an EVM and see both bits D0 and D1 toggle. I do find it odd that if your last register dump on P0, the DAC was disabled. I would make sure that when you are checking for the bit to toggle, that the device is ready for playback with the DACs enabled and the CODEC is receiving BCLK and WCLK. 

    Regards,

    Aaron Estrada

  • Hi Aaron,

    I have it working on a device. Somehow during multiple tries I accidentally removed enabling the DAC.

    Thanks.

    With kind regards,
    Tim Gruijters

  • Hi Tim,

    Great to hear. Is your system now running as intended? If so, I can close this thread. 

    Regards,

    Aaron Estrada

  • Hello Aaron,

    Unfortunately, adding it in the default setup doesn't work. The error:
    [    3.588296] asoc-simple-card sound0: tlv320aic31xx-hifi <-> 202c000.ssi mapping ok
    [    4.620986] tlv320aic31xx-codec 1-0018: aic31xx_wait_bits: Failed! 0x25 was 0x88 expected 0x0 (0, 0x80, 500000 us)
    [    4.632078] tlv320aic31xx-codec 1-0018: ASoC: POST_PMD: DAC Left event failed: -1

    Address 0x25 is the DAC flag register. According to the datasheet, the "Mono class-D driver powered up" and "Left-channel DAC powered up". My best guess is that this is correct :-)

    static const struct reg_default aic31xx_reg_defaults[] = {
        { AIC31XX_RESET, 0x1 },
        { AIC31XX_RESET, 0x0 },
        { AIC31XX_CLKMUX, 0x00 },
        { AIC31XX_PLLPR, 0x11 },
        { AIC31XX_PLLJ, 0x04 },
        { AIC31XX_PLLDMSB, 0x00 },
        { AIC31XX_PLLDLSB, 0x00 },
        { AIC31XX_NDAC, 0x01 },
        { AIC31XX_MDAC, 0x01 },
        { AIC31XX_DOSRMSB, 0x00 },
        { AIC31XX_DOSRLSB, 0x80 },
        { AIC31XX_NADC, 0x01 },
        { AIC31XX_MADC, 0x01 },
        { AIC31XX_AOSR, 0x80 },
        { AIC31XX_IFACE1, 0x00 },
        { AIC31XX_DATA_OFFSET, 0x00 },
        { AIC31XX_IFACE2, 0x00 },
        { AIC31XX_BCLKN, 0x01 },
        { AIC31XX_DACSETUP, 0x14 },
        { AIC31XX_DACMUTE, 0x0c },
        { AIC31XX_LDACVOL, 0x00 },
        { AIC31XX_RDACVOL, 0x00 },
        { AIC31XX_ADCSETUP, 0x00 },
        { AIC31XX_ADCFGA, 0x80 },
        { AIC31XX_ADCVOL, 0x00 },
        { AIC31XX_HPDRIVER, 0x04 },
        { AIC31XX_SPKAMP, 0x06 },
        { AIC31XX_DACMIXERROUTE, 0x00 },
        { AIC31XX_LANALOGHPL, 0x7f },
        { AIC31XX_RANALOGHPR, 0x7f },
        { AIC31XX_LANALOGSPL, 0x7f },
        { AIC31XX_RANALOGSPR, 0x7f },
        { AIC31XX_HPLGAIN, 0x02 },
        { AIC31XX_HPRGAIN, 0x02 },
        { AIC31XX_SPLGAIN, 0x00 },
        { AIC31XX_SPRGAIN, 0x00 },
        { AIC31XX_MICBIAS, 0x00 },
        { AIC31XX_MICPGA, 0x80 },
        { AIC31XX_MICPGAPI, 0x00 },
        { AIC31XX_MICPGAMI, 0x00 },
            /* added */
        { AIC31XX_DACSETUP, 0xb0 },
        { AIC31XX_DACMUTE, 0x00 },
        { AIC31XX_REG(8,  2), (TLV320AIC3XXX_FILTER_N0 & 0xFF00) >> 8}, /* N0 MSB: 0x7d */
        { AIC31XX_REG(8,  3), (TLV320AIC3XXX_FILTER_N0 & 0xFF)},        /* N0 LSB: 0x00 */
        { AIC31XX_REG(8,  4), (TLV320AIC3XXX_FILTER_N1 & 0xFF00) >> 8}, /* N1 MSB: 0x82 */
        { AIC31XX_REG(8,  5), (TLV320AIC3XXX_FILTER_N1 & 0xFF)},        /* N1 LSB: 0xff */
        { AIC31XX_REG(8,  6), (TLV320AIC3XXX_FILTER_N2 & 0xFF00) >> 8}, /* N2 MSB: 0x7d */
        { AIC31XX_REG(8,  7), (TLV320AIC3XXX_FILTER_N2 & 0xFF)},        /* N2 LSB: 0x00 */
        { AIC31XX_REG(8,  8), (TLV320AIC3XXX_FILTER_D1 & 0xFF00) >> 8}, /* D1 MSB: 0x7c */
        { AIC31XX_REG(8,  9), (TLV320AIC3XXX_FILTER_D1 & 0xFF)},        /* D1 LSB: 0xf7 */
        { AIC31XX_REG(8, 10), (TLV320AIC3XXX_FILTER_D2 & 0xFF00) >> 8}, /* D2 MSB: 0x85 */
        { AIC31XX_REG(8, 11), (TLV320AIC3XXX_FILTER_D2 & 0xFF)},        /* D2 LSB: 0xec */
    };

    Thanks,
    Tim

  • Changing 0x00 to 0x88 does not solve the problem:

    tlv320aic31xx-codec 1-0018: aic31xx_wait_bits: Failed! 0x25 was 0x88 expected 0x88 (0, 0x80, 500000 us)

  • Hi Tim,

    It looks like the DACs are still powered down. The error looks to be thrown because it is reading register 0x25 and not seeing 0x88 (When register 0x25 reads 0x88, the DACs are powered on). 

    The AIC31XX_DACSETUP is where the DACs can be powered on. 

    Regards,

    Aaron Estrada

  • Hallo Aaron,

    I think that's is not true because it's being triggered in aic31xx_dapm_power_event under the SND_SOC_DAPM_POST_PMD event. The value is masked and both must be 0, but it does not take into account that another DAC could be enabled).

        case SND_SOC_DAPM_POST_PMD:
            return aic31xx_wait_bits(aic31xx, reg, mask, 0, 5000, 100);

    I still get the error:

    [    2.621239] tlv320aic31xx-codec 1-0018: aic31xx_wait_bits: Failed! 0x25 was 0x88 expected 0x0 (0, 0x80, 500000 us) ((bits & mask) = 0x80)
    [    2.632370] tlv320aic31xx-codec 1-0018: ASoC: POST_PMD: DAC Left event failed: -1

    After debugging it seems that I'm not allowed to enable the DAC in aic31xx_codec_probe. Ive added the following:

    static const struct reg_default aic31xx_biquad_a[] = {
        /*  DAC Biquad A */
        { 0x0, 0x0}, // page
        { AIC31XX_DACMUTE, 0x00 },
        { AIC31XX_DACSETUP, 0xb0 },
        { 0x0, 0x8}, // page
        { AIC31XX_REG(8,  2), (TLV320AIC3XXX_FILTER_N0 & 0xFF00) >> 8}, /* N0 MSB: 0x7d */
        { AIC31XX_REG(8,  3), (TLV320AIC3XXX_FILTER_N0 & 0xFF)},        /* N0 LSB: 0x00 */
        { AIC31XX_REG(8,  4), (TLV320AIC3XXX_FILTER_N1 & 0xFF00) >> 8}, /* N1 MSB: 0x82 */
        { AIC31XX_REG(8,  5), (TLV320AIC3XXX_FILTER_N1 & 0xFF)},        /* N1 LSB: 0xff */
        { AIC31XX_REG(8,  6), (TLV320AIC3XXX_FILTER_N2 & 0xFF00) >> 8}, /* N2 MSB: 0x7d */
        { AIC31XX_REG(8,  7), (TLV320AIC3XXX_FILTER_N2 & 0xFF)},        /* N2 LSB: 0x00 */
        { AIC31XX_REG(8,  8), (TLV320AIC3XXX_FILTER_D1 & 0xFF00) >> 8}, /* D1 MSB: 0x7c */
        { AIC31XX_REG(8,  9), (TLV320AIC3XXX_FILTER_D1 & 0xFF)},        /* D1 LSB: 0xf7 */
        { AIC31XX_REG(8, 10), (TLV320AIC3XXX_FILTER_D2 & 0xFF00) >> 8}, /* D2 MSB: 0x85 */
        { AIC31XX_REG(8, 11), (TLV320AIC3XXX_FILTER_D2 & 0xFF)},        /* D2 LSB: 0xec */

    };

    static int aic31xx_codec_probe(struct snd_soc_codec *codec) {
        /* Original init code..  */
        ret = aic31xx_add_controls(codec);
        if (ret) {
            printk(KERN_ERR "Error aic31xx_add_controls\n");
            return ret;
        }

        ret = aic31xx_add_widgets(codec);
        if (ret) {
            printk(KERN_ERR "Error aic31xx_add_widgets\n");
            return ret;
        }
        for (i = 0; i < ARRAY_SIZE(aic31xx_biquad_a); i++) {
            printk(KERN_ERR "iteration %d\n", i);
            snd_soc_write(codec, aic31xx_biquad_a[i].reg, aic31xx_biquad_a[i].def);
        }
        return ret;
    }

    How should I enable the DAC in the driver if I can't add it to aic31xx_reg_defaults? Do you have an example that shows how the DAC is enabled in the tlv320aic31xx driver?

  • Hello Tim,

    I think you can use the amixer command to enable the DAC. I don't have a specific example where the DAC is enabled but I have included a E2E post here that shows some linux commands and available controls. Let me know if this helps. 

    Regards,

    Aaron Estrada

  • Hello Aaron,

    I'm using the kernel on an Android device, thus I only have tinymix.

    tinymix -D 0 4 1                # Enable        Speaker Driver Playback Switch
    tinymix -D 0 5 2                # Set           Speaker Driver Playback Volume  2
    tinymix -D 0 6 115              # Set           Speaker Analog Playback Volume  115
    tinymix -D 0 7 131 131          # Set           DAC Playback Volume             131 131
    tinymix -D 0 11 Mono            # Set           DAC Left Input                  Mono
    tinymix -D 0 19 1               # Enable        Output Left From Left DAC
    tinymix -D 0 24 1               # Enable        Speaker Switch

    So what you're saying is that I can't enable the DAC in the driver itself?

  • Tim,

    Let me jump and see if I can help. To give a little background, the driver first probes the AIC31xx with the aic31xx_i2C_probe.  Then while loading the driver it executes aic31xx_codec_probe. However other ALSA commands could execute any of the other parts fo the driver: aic31xx_set_jack, aic31xx_set_bias_level, or common31xx_snd_controls. The driver was written so that ALSA widgets (common31xx_dapm_widgets) would call the aic31xx_dapm_power_event to turn on DAC channels.

    We do not have an Android system here to try this out, but seems the alsamixer controls are in the tiny mixer. Enabling DAC Left or DAC right call the aic31xx_dapm_power_event that enables the DAC channels 

    You could also code at the end of aic31xx_codec_probe to enable the DAC channels similar to how aic31xx_dapm_power_event sets the AIC31XX_DACFLAG registers.

    Best regards,
    Pedro