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.

TLV320AIC3106: How do i enable and use the digital Mic in linux?

Part Number: TLV320AIC3106
Other Parts Discussed in Thread: SYSBIOS

we have a design that is using a digital mic but i am not seeing anywhere in the DTS documentation anything that indicates the use of digital mic

https://www.kernel.org/doc/Documentation/devicetree/bindings/sound/tlv320aic3x.txt

how does one set up the digital mic in the device tree file and then how do i switch to that input inside my program (we have been using ALSA for audio previously)

  • There're two ways, one is the asound,cof, the other is the DTS

    In order to save time, kindly offer me what you previously set the audio route for digital mic. Thanks.

  • how do you do it in the DTS and how do you switch to it in code/application is my question. is ALSA not capable of doing it? we will need to switch between microphones for our application so i need to know how to do it in code, not from the terminal (unless that's the only way, in which case i know i'll have to do system())

  • since i don't have a response i guess maybe i didn't answer your question. what does "kindly offer me what you previously set the audio route for digital mic" mean? we have no previous route for digital mic. this is a new design.

  • Hi Guy

    Sorry for late response. I'm in Spring Festival holiday. I will feedback you Feb 19. Thanks for understanding.

    Happy Spring Festival

    Shengdao Ding

  • Hi,

    May I understand your Digital Mic is PDM? AIC3106 is not supporting Digital mic (PDM), so our Linux driver cannot complete it in DTS level.

    But if you have another sound card for Digital Mic, you can switch it by switch sound card in application.

    Thanks

    Kevin

  • the 3106 does support digital mic, it states that it does in the datasheet and we have it working just fine in a sysbios project. we are trying to figure out how to make it work in the linux world

    in the first reply shen stated: 

    "There're two ways, one is the asound,cof, the other is the DTS"

    which means there ARE ways to do it. why the reversal? was Shen wrong?

  • Sorry, my misunderstanding for the DMIC of AIC3106, you should set GPIO, you should add ai3x-gpio-func in DTS, and you should enable the routing for "Left ADC" or "Right ADC"

    Thanks

  • please provide an example of what you're talking about. i am not an expert enough to know specifically what you means for me to do in the dts file

  • Hi,

    I found that the code of tlv320aic3x.c is not complete for DMIC, I recommend to set registers manually to enable Digital Mic, you can put that into a default array.

    Thanks 

  • so when i want to switch from a normal analog mic to the digital mic do i also have to do that via direct register writes? i assume that means i will have to make i2c system calls to accomplish this?

  • We will improve this part later, but not very soon. maybe you can utilize i2c system first.

  • this sparked a question in my head - can the drivers manipulate the registers for the output effects and de-emphasis filters (page 1 registers)?

  • Hi,

    Yes, but you can comment out this part in the driver.

    BTW, I have made some modifications to the code and need to verify it. I can give you feedback maybe tomorrow.

    Thanks

  • the thing is i want it to be able to access page 1 registers. is there an example where it shows how to access those registers via some API?

    i look forward to any support with the DMIC

  • If you want to access page 1, you need a step to switch page, write reg 0x00 to switch page, for example, if you write reg0x00 to be 0x01, you can get all the registers in page 1.

    I have modified the driver code from kernel 6.7, you can try to verify it (as below), and see if it can work, if it's not, kindly share me the RegDump contents before and after recording.

    /* SPDX-License-Identifier: GPL-2.0-only
     *
     * ALSA SoC TLV320AIC3x codec driver I2C interface
     *
     * Author:      Arun KS, <arunks@mistralsolutions.com>
     * Copyright:   (C) 2008 Mistral Solutions Pvt Ltd.,
     *
     * Based on sound/soc/codecs/wm8731.c by Richard Purdie
     *
     */
    
    #include <linux/i2c.h>
    #include <linux/module.h>
    #include <linux/of.h>
    #include <linux/regmap.h>
    #include <sound/soc.h>
    
    #include "tlv320aic3x.h"
    
    static const struct i2c_device_id aic3x_i2c_id[] = {
    	{ "tlv320aic3x", AIC3X_MODEL_3X },
    	{ "tlv320aic33", AIC3X_MODEL_33 },
    	{ "tlv320aic3007", AIC3X_MODEL_3007 },
    	{ "tlv320aic3104", AIC3X_MODEL_3104 },
    	{ "tlv320aic3106", AIC3X_MODEL_3106 },
    	{ }
    };
    MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
    
    static int aic3x_i2c_probe(struct i2c_client *i2c)
    {
    	struct regmap *regmap;
    	struct regmap_config config;
    	const struct i2c_device_id *id = i2c_match_id(aic3x_i2c_id, i2c);
    
    	config = aic3x_regmap;
    	config.reg_bits = 8;
    	config.val_bits = 8;
    	regmap = devm_regmap_init_i2c(i2c, &config);
    	return aic3x_probe(&i2c->dev, regmap, id->driver_data);
    }
    
    static void aic3x_i2c_remove(struct i2c_client *i2c)
    {
    	aic3x_remove(&i2c->dev);
    }
    
    static const struct of_device_id aic3x_of_id[] = {
    	{ .compatible = "ti,tlv320aic3x", },
    	{ .compatible = "ti,tlv320aic33" },
    	{ .compatible = "ti,tlv320aic3007" },
    	{ .compatible = "ti,tlv320aic3104" },
    	{ .compatible = "ti,tlv320aic3106" },
    	{},
    };
    MODULE_DEVICE_TABLE(of, aic3x_of_id);
    
    static struct i2c_driver aic3x_i2c_driver = {
    	.driver = {
    		.name = "tlv320aic3x",
    		.of_match_table = aic3x_of_id,
    	},
    	.probe = aic3x_i2c_probe,
    	.remove = aic3x_i2c_remove,
    	.id_table = aic3x_i2c_id,
    };
    
    module_i2c_driver(aic3x_i2c_driver);
    
    MODULE_DESCRIPTION("ASoC TLV320AIC3x codec driver I2C");
    MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
    MODULE_LICENSE("GPL");
    

    8054.tlv320aic3x.c

    3678.tlv320aic3x.h

    BTW, for DTS configuration, if you want to enable DMIC, you will need to config GPIOs, add

                                    ai3x-gpio-func = <
                                            10 /* AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK */
                                            5 /* AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT */
                                    >;
    Also, The route is also needed to be change in simple-audio-card:
                simple-audio-card,widgets =
                    "Line", "Line In",
                    "Line", "Line Out";

                simple-audio-card,routing =
                    "DMICL", "Line In",
                    "DMICR", "Line In",
                    "Line Out", "LLOUT",
                    "Line Out", "RLOUT";
  • i know how to write to the page 1 registers. we already do it in sysbios. i wanted to know if there were API's available to be able to do it in linux or does it require direct i2c writes to be able to alter them?

    unfortunately we won't have hardware for at least a couple of weeks that i could test this on. my goal for making this post is to be ready when the hardware comes

    my DTS will look like this:

    simple-audio-card,widgets =
    /* 1 */ "Speaker", "POTS Line Out",
    /* 2 */ "Speaker", "Handset Speaker", /* (2) */
    /* 3 */ "Speaker", "External Speaker", /* (3) */
    /* 5 */ "Line", "POTS Line In",
    /* 6 */ "Microphone", "Handset Mic", /* (7) */
    /* 7 */ "Line", "External Mic"; // /* (8) */
    simple-audio-card,routing =
    /* 1 */ "POTS Line Out", "MONO_LOUT",
    /* 2 */ "Handset Speaker", "LLOUT", /* pin 29, 30 */
    /* 3 */ "External Speaker", "RLOUT", /* pin 31, 32 */
    /* 6 */ "LINE2R", "POTS Line In",
    /* 7 */ "LINE1L", "Handset Mic", /* pin 3, 4 */
    /* 8 */ "DMICR", "External Mic", /* pin 7, 8 */
    /* 9 */ "LINE1R", "Headset Mic",
    /* 10 */ "Handset Mic", "Mic Bias"; /* pin 13 */

    and when i need to switch to dmic i can use asla to issue:

    "Right PGA Mixer DMICR Switch"  right? or do i need to do i2c writes to switch to the dmic routine?

  • Hi, no need to do i2c writes, the driver will do the same thing. kindly share me the logs if issues.

    Thanks

  • i assume you are talking about switching between DMIC and an analog MIC

    how about this part of my last reply:

    i know how to write to the page 1 registers. we already do it in sysbios. i wanted to know if there were API's available to be able to do it in linux/code or does it require direct i2c writes to be able to alter them?

  • You can utilize snd_soc_component_update_bits and snd_soc_component_write in code to do the i2c write, these functions have the feature of automatic page switching.

    In alsa, we use amixer controls to switch the input and output routing paths, you can check your amixer contents on the terminal device and look into driver code.

    Thanks