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.

PCMD3140: How to configure Voice Activity Detection (VAD) on PCMD3140IRTER in Linux

Part Number: PCMD3140


I have a four-channel PDM-input codec, the PCMD3140IRTER, and I would like to enable Voice Activity Detection (VAD). I noticed that in the driver section of your website, the driver doesn’t seem to support it: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/sound/soc/codecs/tlv320adcx140.c

Reading through the datasheet, it references this document:
www.ti.com/.../sbaa490a.pdf
From which I tried to take inspiration to add VAD functionality to the driver, starting from Example 2 on page 10:

w 9C 00 00 # Go to Page 0
w 9C 02 81 # Wake-up device by I2C write into P0_R2, exit Sleep mode
d 10 # Wait 16 ms
w 9c 00 00 # go to page 9
w 9c 50 00 72 59 dc # -7dB threshold
w 9C 00 00 # Go to Page 0
w 9c 3c 40 # Ch1 configured as Digital microphone PDM input
w 9c 41 40 # Ch2 configured as Digital microphone PDM input
w 9c 73 C0 # Input channels 1 and 2 enabled
w 9c 74 C0 # ASI output channels 1 and 2 enabled
w 9c 21 21 # GPIO1 as IRQ
w 9c 22 41 # GPO1 as PDM CLK
w 9c 2b 45 # GPI1 as Ch1/2 DMIC data
w 9c 20 00 # GPI1 negative edge as Ch1
w 9c 00 01 # go to page 1
w 9c 1e 00 # Channel 1 as VAD input, user mode, internal clock
w 9c 1f 00 # VAD disabled in recording mode
w 9c 00 00 # go to page 0
w 9c 75 21 # Enable VAD

However, I noticed an inconsistency: the script says to go to page 9, but in the datasheet I cannot find any user-accessible registers on page 9, and there is an error in the command w 9c 00 00 # go to page 9 (00 != 09). I tried on both pages 9 and 0, but in both cases I don’t get the desired result.

Even after using an oscilloscope and adding these commands to the driver, I don’t see any interrupt activity on GPIO1, even though I’ve included the following in the device tree:

pcmd3140_codec: pcmd3140_codec@4e {
    compatible = "ti,tlv320adc3140";
    reg = <0x4e>;
    ti,pdm-edge-select = <1 1 1 1>;
    ti,gpi-config = <4 5 0 0>;
    ti,gpio-config = <2 1>;
    ti,gpo-config-1 = <4 1>;
    
    pcmd3140_port: port {
        #address-cells = <1>;
        #size-cells = <0>;

        pcmd3140_tx_endpoint: endpoint@0 {
            reg = <0>;
            remote-endpoint = <&sai1a_endpoint>;
        };
    };
};

Even when bypassing the driver and manually issuing the commands using the i2cset tool, I get the same result:

i2cset -y 0 0x4e 0x00 0x00 # Go to Page 0
i2cset -y 0 0x4e 0x02 0x81 # Wake-up device
sleep 0.016 # Wait 16 ms
i2cset -y 0 0x4e 0x00 0x09 # Go to Page 9 (corrected from 0x00) 
i2cset -y 0 0x4e 0x50 0x00 0x72 0x59 0xDC i # -7dB threshold
i2cset -y 0 0x4e 0x00 0x00 # Go to Page 0
i2cset -y 0 0x4e 0x3C 0x40 # Ch1 configured as Digital microphone PDM input
i2cset -y 0 0x4e 0x41 0x40 # Ch2 configured as Digital microphone PDM input
i2cset -y 0 0x4e 0x73 0xC0 # Input channels 1 and 2 enabled
i2cset -y 0 0x4e 0x74 0xC0 # ASI output channels 1 and 2 enabled
i2cset -y 0 0x4e 0x21 0x21 # GPIO1 as IRQ
i2cset -y 0 0x4e 0x22 0x41 # GPO1 as PDM CLK
i2cset -y 0 0x4e 0x2B 0x45 # GPI1 as Ch1/2 DMIC data
i2cset -y 0 0x4e 0x20 0x00 # GPI1 negative edge as Ch1
i2cset -y 0 0x4e 0x00 0x01 # Go to Page 1
i2cset -y 0 0x4e 0x1E 0x00 # Channel 1 as VAD input, user mode, internal clock
i2cset -y 0 0x4e 0x1F 0x00 # VAD disabled in recording mode
i2cset -y 0 0x4e 0x00 0x00 # Go to Page 0
i2cset -y 0 0x4e 0x75 0x21 # Enable VAD

Could you please provide any guidance or share a driver implementation that already includes VAD support?

Thanks in advance.

  • Hi Mattia,

    You will need to also write to register 0x33 to unmask the interrupt so it can assert.

    Best,

    Garret

  • I tried adding i2cset -y 0 0x4e 0x33 0xE7 # INT_MASK0 Do not mask bit 4 and 3
    to the sequence of commands, which becomes:

    i2cset -y 0 0x4e 0x00 0x00 # Go to Page 0
    i2cset -y 0 0x4e 0x02 0x81 # Wake-up device
    ...
    ...
    ...
    i2cset -y 0 0x4e 0x1F 0x00 # VAD disabled in recording mode
    i2cset -y 0 0x4e 0x00 0x00 # Go to Page 0
    i2cset -y 0 0x4e 0x33 0xE7 # INT_MASK0 Do not mask bit 4 and 3
    i2cset -y 0 0x4e 0x75 0x21 # Enable VAD

    However, I still don’t see any interrupt on GPIO1 when checking with the oscilloscope. The only difference is that the GPIO1 line goes from high (with the register set to 0xFF) to low (with the register set to 0xE7), but the line seems to remain constantly low without showing any interrupts.

  • Thank you, Garret Godfrey, for your support. I finally solved the problem by reading the value of the INT_LTCH0 Register (Address = 0x36). It does not generate a new interrupt until there is a 0 in the bit representing the source that generated the interrupt. After reading the register, it automatically returns to the reset value [Reset = 0x0].