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: Sometimes the differential HPROUT output is not working after power up configuration.

Part Number: TLV320AIC3106

When my card powers up, it configures the codec once and the configuration is not modified thereafter. We have a thousand cards in the field and the bug occurs only a few times per week. And I can't reproduce it in my lab.

I guess that maybe the register write sequence is not right, I tried a few changes without success.

We use the SPI bus for configuration. I am careful to add a 6.25 usec between the write access to register 45 to 93.

I have enabled the soft stepping in registers 19, 22, & 40. And the pop reduction in register 42. Can it have any negative effect?

I have noted that bit2 or register 65 & 72 are always set (Not all programmed gains to HPROUT have been applied yet.) Is it important, can it be fix by proper configuration? Can it be an indication that the output might be muted?

In one test I did at a customer site, I was able to clear the bug by rewriting only two registers: 64 and 65. Before writing, I read the values in both registers and they were correct. Then I wrote back the registers values as the configuration normally does: write(64, 0x80), write(65,0x11), write(65,0x19). Why did it work?

The file attached is the configuration file for the codec. The data structure lists the register addresses and values in the sequence they are written in the device.

I hope you can help me find the bug.

Best regards,

DSP_init_simplified - codec1.c
// L138_aic3106_init.c

//
// ** Define a structure with CODEC configuration.
// ** Note the register must be written in the CODECs following the order of the structure (ex 0,8,9,10,98,etc.)
//
struct codec_init_table_t {
   uint8_t address, codec1_val;
} codec_init_table [] = {
/*
address ,codec1 		      Register Name                              Function/command configured
*/
	//GPIO, clock, misc. config
	//=========================
{0      ,0x00 }, //  Page select reg                            Always select page 0
{1      ,0x80 }, //  Software reset                             To clear potential bugs
{0      ,0x00 }, //  Page select reg                            re-select page 0
{8      ,0x20 }, //  Audio serial data I/F reg A                BCLK,WCLK=input, Dout=tri-state,Disable 3D, disable digital mic
{9      ,0x4F }, //  Audio serial data I/F reg B                serial data:dsp mode, 16bit timeslot, 256bit/frame,resync adc+dac, soft mute
{10     ,0x00 }, //  Audio serial data I/F reg C                Codec1:timeslot=0
{11     ,0x00 }, //  Audio codec OV flag                        Flags, PLL R = dont care
{98     ,0x94 }, //  GPIO1 Control Reg                          CODEC 1, GPIO 1 NOT USED, PROGRAM AS GENERAL OUTPUT = 0
{99     ,0x42 }, //  GPIO2 Control Reg                          CODEC 1. GPIO 2 future use, PROGRAM AS GENERAL OUTPUT = 0
{100    ,0x88 }, //  Additional GPIO Control reg A              SCL,SDA used as General output = 0volt
{101    ,0x01 }, //  Additional GPIO Control reg B              CODEC_CLKIN = CLKDIV_OUT, other GPIO don�t care in SPI mode
{102    ,0x00 }, //  Clock Generation Control                   CLKDIV_IN = MCLK, PLL bits = don�t care
{107    ,0x30 }, //  New Prgm ADC Digital Path and I2C Bus Cond HP filters L/R use default coef. L/R MIC are analog
{108    ,0x00 }, //  Passive Analog Signal Byp Sel in Powerdown No bypass on any analog signal during power down
{109    ,0x00 }, //  DAC Quiescent Current Adjust               default DAC reference current
{2      ,0xAA }, //  Codec sample rate sel                      Codec sample rate = 8Khz = 48KHz / 6
{7      ,0x0A }, //  Codec datapath setup                       dual rate off, L/R ADC on L/R play
{3      ,0x10 }, //  PLL prgm reg A                             PLL disabled, Q = CLKIN / (128 x fs(ref) = 12.288M / (128 x 48000) = 2, P= dont care
{12     ,0xA0 }, //  Audio codec digital filter ctl             HP filter=100Hz ADC L+R, effect filter=disable, de-emphasis filter=disable
{13     ,0x16 }, //  headset/button detect reg A                Codec1: disable headset detection.
{14     ,0xC0 }, //  headset/button detect reg B                Codec1:ac coupled, Diff out
	//Inputs to ADC config
	//====================
	//**init inputs step#1
{25     ,0x00 }, //  MICBIAS ctl                                codec1:MICBIAS=disabled
	//**init inputs step#2
{17     ,0xFF }, //  MIC3L/R to left ADC                        codec1:micL/R not connected  to left ADC
{18     ,0xFF }, //  MIC3L/R to right ADC                       codec:micL/R not connected  to right ADC.
{19     ,0x00 }, //@  LINE1L to L ADC ctl                        Line1L to L ADC= codec1: 0dB codec1=SE !! KEEP LEFT ADC POWER DOWN !!
{20     ,0x78 }, //  LINE2L to L ADC ctl                        Line2L to L ADC= codec1: n.c. Disable weakly biased on input L ADC
{21     ,0x78 }, //  LINE1R to L ADC ctl                        Line1R to L ADC= codec1: n.c. Line1R: codec1=SE, codec2=FD, codec3=FD
{22     ,0x00 }, //@  LINE1R to R ADC ctl                        Line1R to R ADC= codec1: 0dB. Enable R ADC. Line1R: codec1=SE, !! KEEP LEFT ADC POWER DOWN !!
{23     ,0x78 }, //  LINE2R to R ADC ctl                        Line2R to R ADC= codec1: n.c. Disable weakly biased on input R ADC
{24     ,0x78 }, //  LINE1L to R ADC ctl                        Line1L to R ADC= codec1: n.c. Line1L: codec1=SE, codec2=FD, codec3=SE
	//**init inputs step#3
{15     ,0x15 }, //  Left ADC PGA gain ctl                      Left ADC not muted, PGA Gain: codec1 HDT mouth1= 10.5dB
{16     ,0x15 }, //  Right ADC PGA gain ctl                     Right ADC not muted, PGA Gain: codec1 HDT mouth1= 10.5dB
	//**init inputs step#4
{27     ,0x00 }, //  L AGC ctl reg B                            disable L AGC
{30     ,0x00 }, //  R AGC ctl reg B                            disable R AGC
	//**init inputs step#5
{19     ,0x04 }, //@  LINE1L to L ADC ctl                        Line1L to L ADC= codec1: 0dB codec1=SE !! LEFT ADC POWER ON !!
{22     ,0x04 }, //@  LINE1R to R ADC ctl                        Line1R to R ADC= codec1: 0dB. Enable R ADC. Line1R: codec1=SE !! RIGHT ADC POWER ON !!

	//DAC to outputs config
	//=====================
	//**init outputs step #1
{43     ,0x01 }, //@  L DAC digital volume ctl                   L DAC is not Muted, L DAC volume = -0.5dB to compensate Oct 28,2019 new output audio path configuration
{44     ,0x01 }, //@  R DAC digital volume ctl                   R DAC is not Muted, R DAC volume = -0.5dB to compensate Oct 28,2019 new output audio path configuration
	//**init outputs step #2
{37     ,0xC0 }, //  AC pwr and output driver                   L/R ADC power up, codec1:HPLCOM=diff
{38     ,0x04 }, //  high power output driver ctl               codec1:HPRCOM=diff, Short circuit protection enabled
{40     ,0x40 }, //  high power output stage ctl                VCM = 1.5v, disable:LINE2L, LINE2R, soft stepping 1 per fs
	//**init outputs step #3
{41     ,0x00 }, //  DAC out switching ctl                      L DAC uses DAC_L1 path (less noise), R DAC use DAC_R1 path (less noise), L & R DAC volume have independent ctl
{42     ,0x8E }, //  Output driver pop reduction                drv power on time=400ms, ramp-up step=4ms, weakly CM from bandgap ref
	//**init outputs step #4 (HPLOUT)
{47     ,0x80 }, //@  DAC_L1 to HPLOUT volume                    DAC_L1 goes to HPLOUT with 0dB attenuation on codecs 1
{51     ,0x11 }, //@  HPLOUT output level ctl                    HPLOUT 0dB level, Muted!!, weak driver when disable, Full power-up. GAIN: codec1=1dB
{51     ,0x19 }, //@  HPLOUT output level ctl                    HPLOUT 0dB level, not Muted, weak driver when disable, Full power-up. GAIN: codec1=1dB
	//**init outputs step #5 (HPLCOM) 
{58     ,0x00 }, //  HPLCOM output level ctl                    HPLCOM disable. Overriden by register 37 bit5,4 in differential mode
	//**init outputs step #5 (HPROUT)
{64     ,0x80 }, //@  DAC_R1 to HPROUT volume                    DAC_R1 goes to HPROUT with 0dB attenuation on codecs 1	
{65     ,0x11 }, //@  HPROUT output level ctl                    HPROUT 0dB level, Muted!!, weak driver when disable, Full power-up. GAIN: codec1=1dB
{65     ,0x19 }, //@  HPROUT output level ctl                    HPROUT 0dB level, not Muted, weak driver when disable, Full power-up. GAIN: codec1=1dB
	//**init outputs step #6 (HPRCOM) 
{72     ,0x00 }  //  HPRCOM output level ctl                    HPRCOM disable. Overriden by register 38 bit5,4,3 in differential mode
	//**init outputs step #7 (all unused line out) 
	//nothing needed
};

  • Hi,

    The first thing is to ensure the driver power is up and stable prior to these HPOUT register writes.

    If power is stable then we look at the write sequence. Those soft stepping registers are there to avoid any artifact due to transient and should not cause the issue here.

    I recommend to change the following sequence:

    • Swap (//**init outputs step #2) with (//**init outputs step #3)
    • Move address 14 to after step 2 above; after register 41 and 42 and before register 37 and 38
    • Move address 51 and 65 to the end after all other settings are configured.

    Regards.

  • Hi Pdjuandi,

    If the driver power must be stable. If we consider the value I wrote in reg 42 which sets a delay of 400ms and ramp-up of 4ms on the driver power. Does it means I should pause the codec initialization for 400ms+4ms to make sure its power is stable? If, so I guess I will change the delay to 0ms to avoid this delay.

    About the register 14, I will do what you told me. But another application engineer told me the reg 14 was not important because it only configures the headset detection. You are saying that it actually affects the driver power ?

    After you answer the questions above, I will try your suggestions. It will take a couple of weeks before I get a feedback for you on the results at customer sites.

    Thank you,

  • Hi,

    This register 42 is also used to control any click and pop so consider this in your decision.

    My suggestion is move register 51 and 65 to the end first and see that helps contain the issue before changing the delays.

    Register 14 besides the headset detection also configures the output driver.

    Regards.

  • I am not sure I understand what you said about reg 42. If I keep my setting of 400ms delay + 4ms ramp-up, then after writing reg 42, should I wait 404ms before writing the remaining output registers ?

  • Hi,

    What I'm saying you can keep what you have for now and just move register 51 and 65 to the end, see if that contain the issue.

    Regards.

  • We found a way to reproduce the problem more quickly. We made an automatic test setup where the codec is initialized, the audio output is tested, then we loop like this continuously until the test fails. It takes about 1 hours for the problem to occur. We were able to test different changes and get reliable results in a few hours. 

    I made many changes in the initialization function. I put all your suggestions, I also reduced the power-up delay in reg 42, and changed sequence for other registers which I felt might benefit from it.

    The result is good, the bug is gone. The card runs flawlessly for 6 hours of continuous re-initialization.

    I think T.I. should write a detailed app notes for the register initialization sequence requirements. This is clearly a bug in the IC unless there is an app notes I have missed. Now the bug can be managed because we know the secret recipe of register sequence.  Hopefully, that was the last bug with this device.

    Here is the init code that fixed the problem.

    //
    // ** Define a structure with CODECs configuration.
    // ** Note the register must be written in the CODECs following the order of the structure (ex 0,8,9,10,98,etc.)
    //
    struct codec_init_table_t {
       uint8_t address, codec1_val, codec2_val, codec3_val;
    } codec_init_table [] = {
    /*
    address ,codec1 ,codec2 ,codec3      Register Name                              Function/command configured
    */
    	//GPIO, clock, misc. config
    	//=========================
    {0      ,0x00   ,0x00   ,0x00 }, //  Page select reg                            Always select page 0
    {1      ,0x80   ,0x80   ,0x80 }, //  Software reset                             To clear potential bugs
    {0      ,0x00   ,0x00   ,0x00 }, //  Page select reg                            re-select page 0
    {8      ,0x20   ,0x20   ,0x20 }, //  Audio serial data I/F reg A                BCLK,WCLK=input, Dout=tri-state,Disable 3D, disable digital mic
    {9      ,0x4F   ,0x4F   ,0x4F }, //  Audio serial data I/F reg B                serial data:dsp mode, 16bit timeslot, 256bit/frame,resync adc+dac, soft mute
    {10     ,0x00   ,0x40   ,0x80 }, //  Audio serial data I/F reg C                Codec1:timeslot=0, Codec2:timeslot=4 (64bit offset), Codec3:timeslot=8 (128bit offset)
    {11     ,0x00   ,0x00   ,0x00 }, //  Audio codec OV flag                        Flags, PLL R = dont care
    {98     ,0x94   ,0x94   ,0xD4 }, //  GPIO1 Control Reg                          CODEC 1,2. GPIO 1 NOT USED, PROGRAM AS GENERAL OUTPUT = 0, CODEC 3: GPIO1 = JACK/HEADSET DETECTION INTERRUPT
    {99     ,0x42   ,0x42   ,0x42 }, //  GPIO2 Control Reg                          CODEC 1,2,3. GPIO 2 future use, PROGRAM AS GENERAL OUTPUT = 0
    {100    ,0x88   ,0x88   ,0x88 }, //  Additional GPIO Control reg A              SCL,SDA used as General output = 0volt
    {101    ,0x01   ,0x01   ,0x01 }, //  Additional GPIO Control reg B              CODEC_CLKIN = CLKDIV_OUT, other GPIO don’t care in SPI mode
    {102    ,0x00   ,0x00   ,0x00 }, //  Clock Generation Control                   CLKDIV_IN = MCLK, PLL bits = don’t care
    {107    ,0x30   ,0x30   ,0x30 }, //  New Prgm ADC Digital Path and I2C Bus Cond HP filters L/R use default coef. L/R MIC are analog
    {108    ,0x00   ,0x00   ,0x00 }, //  Passive Analog Signal Byp Sel in Powerdown No bypass on any analog signal during power down
    {109    ,0x00   ,0x00   ,0x00 }, //  DAC Quiescent Current Adjust               default DAC reference current
    {4      ,0x04   ,0x04   ,0x04 }, //  PLL prgm reg B                             PLL J= 1 dont care
    {5      ,0x00   ,0x00   ,0x00 }, //  PLL prgm reg C                             PLL D (msb) = 0 dont care
    {6      ,0x00   ,0x00   ,0x00 }, //  PLL prgm reg D                             PLL D (lsb) = 0 dont care
    {2      ,0xAA   ,0xAA   ,0xAA }, //  Codec sample rate sel                      Codec sample rate = 8Khz = 48KHz / 6
    {7      ,0x0A   ,0x0A   ,0x0A }, //  Codec datapath setup                       dual rate off, L/R ADC on L/R play
    {3      ,0x10   ,0x10   ,0x10 }, //  PLL prgm reg A                             PLL disabled, Q = CLKIN / (128 x fs(ref) = 12.288M / (128 x 48000) = 2, P= dont care
    {12     ,0xA0   ,0xA0   ,0xA0 }, //  Audio codec digital filter ctl             HP filter=100Hz ADC L+R, effect filter=disable, de-emphasis filter=disable
    	//Inputs to ADC config
    	//====================
    	//**init inputs step#1
    {25     ,0x00   ,0x00   ,0x80 }, //  MICBIAS ctl                                codec1-2:MICBIAS=disabled, codec3:MINBIAS=2.5V
    	//**init inputs step#2
    {17     ,0xFF   ,0xFF   ,0x0F }, //  MIC3L/R to left ADC                        codec1-2:micL/R not connected  to left ADC. codec3 micL connected 0dB to left ADC
    {18     ,0xFF   ,0xFF   ,0xFF }, //  MIC3L/R to right ADC                       codec:micL/R not connected  to right ADC.
    {19     ,0x00   ,0x80   ,0x78 }, //  LINE1L to L ADC ctl                        Line1L to L ADC= codec1: 0dB, codec2: 0dB, codec3: n.c. Line1L: codec1=SE, codec2=FD, codec3=SE,!! KEEP LEFT ADC POWER DOWN !!
    {20     ,0x78   ,0x78   ,0x78 }, //  LINE2L to L ADC ctl                        Line2L to L ADC= codec1-2-3: n.c. Disable weakly biased on input L ADC
    {21     ,0x78   ,0xF8   ,0xF8 }, //  LINE1R to L ADC ctl                        Line1R to L ADC= codec1-2-3: n.c. Line1R: codec1=SE, codec2=FD, codec3=FD
    {22     ,0x00   ,0x80   ,0x80 }, //  LINE1R to R ADC ctl                        Line1R to R ADC= codec1: 0dB, codec2: 0dB, codec3: 0dB. Enable R ADC. Line1R: codec1=SE, codec2=FD, codec3=FD, !! KEEP LEFT ADC POWER DOWN !!
    {23     ,0x78   ,0x78   ,0x78 }, //  LINE2R to R ADC ctl                        Line2R to R ADC= codec1-2-3: n.c. Disable weakly biased on input R ADC
    {24     ,0x78   ,0xF8   ,0x78 }, //  LINE1L to R ADC ctl                        Line1L to R ADC= codec1-2-3: n.c. Line1L: codec1=SE, codec2=FD, codec3=SE
    	//**init inputs step#3
    {15     ,0x15   ,0x10   ,0x3C }, //  Left ADC PGA gain ctl                      Left ADC not muted, PGA Gain: codec1 HDT mouth1= 10.5dB, codec2 Radio in= 8dB, codec3 micro= 30dB
    {16     ,0x15   ,0x10   ,0x00 }, //  Right ADC PGA gain ctl                     Right ADC not muted, PGA Gain: codec1 HDT mouth1= 10.5dB, codec2 Radio in= 8dB, codec3 n.c.= 0dB
    	
    	//**init inputs step#5
    {19     ,0x04   ,0x84   ,0x7C }, //  LINE1L to L ADC ctl                        Line1L to L ADC= codec1: 0dB, codec2: 0dB, codec3: n.c. Line1L: codec1=SE, codec2=FD, codec3=SE !! LEFT ADC POWER ON !!
    {22     ,0x04   ,0x84   ,0x84 }, //  LINE1R to R ADC ctl                        Line1R to R ADC= codec1: 0dB, codec2: 0dB, codec3: 0dB. Enable R ADC. Line1R: codec1=SE, codec2=FD, codec3=FD !! RIGHT ADC POWER ON !!
    
    	//DAC to outputs config
    	//=====================
    	//**init outputs step #1
    {43     ,0x01   ,0x01   ,0x01 }, //  L DAC digital volume ctl                   L DAC is not Muted, L DAC volume = -0.5dB to compensate Oct 28,2019 new output audio path configuration (DAC_L1 instead of DAC_L2)
    {44     ,0x01   ,0x01   ,0x01 }, //  R DAC digital volume ctl                   R DAC is not Muted, R DAC volume = -0.5dB to compensate Oct 28,2019 new output audio path configuration (DAC_R1 instead of DAC_R2)
    	//**init outputs step #new 2 (old 3)
    {41     ,0x00   ,0x00   ,0x00 }, //  DAC out switching ctl                      L DAC uses DAC_L1 path (less noise), R DAC use DAC_R1 path (less noise), L & R DAC volume have independent ctl
    {42     ,0x16   ,0x16   ,0x16 }, //  Output driver pop reduction                drv power on time=10us, ramp-up step=1ms, weakly CM from bandgap ref
    	//**init outputs step #3-a  (old2)
    {37     ,0xC0   ,0xC0   ,0xD0 }, //  AC pwr and output driver                   L/R ADC power up, codec1-2:HPLCOM=diff, codec3:HPLCOM=VCM
    {38     ,0x04   ,0x04   ,0x0C }, //  high power output driver ctl               codec1-2:HPRCOM=diff, codec3:HPRCOM=VCM. Short circuit protection enabled
    {40     ,0x40   ,0x40   ,0x40 }, //  high power output stage ctl                VCM = 1.5v, disable:LINE2L, LINE2R, soft stepping 1 per fs
    	//**init outputs step #3-b
    {13     ,0x16   ,0x16   ,0x96 }, //  headset/button detect reg A                Codec1-2: disable headset detection. Codec3: enable headset detection, jack det=512ms, button=16ms
    {14     ,0xC0   ,0xC0   ,0x80 }, //  headset/button detect reg B                Codec1-2:ac coupled, Diff out, Codec3 ac coupled, single ended out.
    
    	//**init outputs step #4 (HPLOUT)
    {47     ,0x80   ,0x80   ,0x80 }, //  DAC_L1 to HPLOUT volume                    DAC_L1 goes to HPLOUT with 0dB attenuation on codecs 1,2,3
    
    	//**init outputs step #5 (HPROUT)
    {64     ,0x80   ,0x80   ,0x80 }, //  DAC_R1 to HPROUT volume                    DAC_R1 goes to HPROUT with 0dB attenuation on codecs 1,2,3
    
    	//** outputs FINAL step: Texas Inst. says that reg 58, 72, 51 then 65 should be written at the end
    {58     ,0x00   ,0x00   ,0x00 }, //  HPLCOM output level ctl                    HPLCOM disable. Overriden by register 37 bit5,4 in differential mode
    {72     ,0x00   ,0x00   ,0x00 }, //  HPRCOM output level ctl                    HPRCOM disable. Overriden by register 38 bit5,4,3 in differential mode
    {51     ,0x11   ,0x31   ,0x71 }, //  HPLOUT output level ctl                    HPLOUT 0dB level, Muted!!, weak driver when disable, Full power-up. GAIN: codec1=1dB, codec2=3dB, codec3=7dB
    {51     ,0x19   ,0x39   ,0x79 }, //  HPLOUT output level ctl                    HPLOUT 0dB level, not Muted, weak driver when disable, Full power-up. GAIN: codec1=1dB, codec2=3dB, codec3=7dB
    {65     ,0x11   ,0x31   ,0x71 }, //  HPROUT output level ctl                    HPROUT 0dB level, Muted!!, weak driver when disable, Full power-up. GAIN: codec1=1dB, codec2=3dB, codec3=7dB
    {65     ,0x19   ,0x39   ,0x79 }  //  HPROUT output level ctl                    HPROUT 0dB level, not Muted, weak driver when disable, Full power-up. GAIN: codec1=1dB, codec2=3dB, codec3=7dB
    
    };