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.

AM3352: McASP DISMOD not working

Part Number: AM3352
Other Parts Discussed in Thread: TLV320AIC3106

Hi Processor Team,

My customer is using the AM3352 and is running into issues programming the DISMOD in the McASP. From the customer:

We have an application where we're talking to a ulaw codec.  As such, when the McASP transmitter is not actively transmitting something, I need the line pulled high because "zero" in ulaw is actually 0xFF.

According to the TRM, there are a few bits that can alter the behaviour, namely DISMOD:

Serializer pin drive mode bit.

Drive on pin when in inactive TDM slot of transmit mode or when serializer is inactive.

This field only applies if the pin is configured as a McASP pin (PFUNC = 0).

0h = Drive on pin is 3-state.

1h = Reserved.

2h = Drive on pin is logic low.

3h = Drive on pin is logic high.

I've tried changing this line in the kernel driver davinci-mcasp.c

from:

mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),

                                    DISMOD_LOW, DISMOD_MASK);

to:

mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),

                                    DISMOD_HIGH, DISMOD_MASK);

And I can see the bit change in the register with this print:

printk("[customer] %s: %p=%08x\n", __func__,

              mcasp->base + DAVINCI_MCASP_XRSRCTL_REG(i),

              __raw_readl((void *)(mcasp->base +

DAVINCI_MCASP_XRSRCTL_REG(i))));

from:

[   62.521870] [customer] mcasp_common_hw_param: fa03818c=00000019

to:

[   63.190781] [customer] mcasp_common_hw_param: fa03818c=0000001d

suggesting that the change has been applied, but the behaviour on the line doesn't actually change.

The pin is actually being driven low all the time because I can't pull it up with a resistor even when I've set the serialiser to tri-state:

[   53.521545] [customer] mcasp_common_hw_param: fa03818c=00000011

 

Can anyone at TI confirm that this features does, in fact, work?

Please let me know if there are any questions.

Regards,

~John

  • Hi John,

    From what I was able to find, yes, this DISMOD feature should work.

    DISMOD is documented as not applicable for "Burst Transfer Mode", make sure you are not in this mode. Check AM335x TRM, section 22.3.8.1 Burst Transfer Mode.

    In TDM mode, if the transmit/receive bit is active, the McASP functions normally during that time slot; otherwise, the McASP is inactive during that time slot; no update to the buffer occurs, and no event is generated. Transmit pins are automatically set to a high-impedance state, 0, or 1 during that slot, as determined by bit DISMOD in SRCTL[n].

    GBLCTL[11] XSMRST = 0 - Transmit state machine is held in reset. AXRn pin state: If PFUNC[n] = 0 and PDIR[n] = 1; then the serializer drives the AXRn pin to the state specified for inactive time slot (as determined by DISMOD bits in SRCTL)

    DISMOD - Drive on pin when in inactive TDM slot of transmit mode or when serializer is inactive.

    Regards,
    Pavel

  • Hi Pavel,

    John's customer here.

    We're not using burst mode.  We're using AXR3 as transmit in 2 slot TDM mode and this works (ie. I can send audio to the codec).  The codec is the master, the mcasp is in slave mode if that makes any difference.

    For some reason /dev/mem2 is giving me bus errors when trying to access mcasp0 registers:

    ~# devmem2 0x48038000 w
    /dev/mem opened.
    Memory mapped at address 0xb6f9d000.
    Bus error

    Do you happen to know why?

    Instead I printed the register values from within davinci-mcasp.c.   There were some issues with the driver, but now I believe that the register settings are correct  per your reply and DISMOD still doesn't seem to be working.

    After boot, the pin reads 3.3V.  After aplay:

    [   52.189733] [-] mcasp_common_hw_param: (DISMOD tx_ser 3) 0xfa03818c=0x00000000
    [   52.197725] [+] mcasp_common_hw_param: (DISMOD tx_ser 3) 0xfa03818c=0x0000001d
    [   52.213318] [] davinci_mcasp_hw_params: (VER) 0xfa038000=0x44307b02
    [   52.220354] [] davinci_mcasp_hw_params: (PFUNC) 0xfa038010=0x00000000
    [   52.227506] [] davinci_mcasp_hw_params: (PDIR) 0xfa038014=0x00000008
    [   52.234536] [] davinci_mcasp_hw_params: (AFSRCTL) 0xfa03806c=0x00000111
    [   52.241898] [] davinci_mcasp_hw_params: (AFSXCTL) 0xfa0380ac=0x00000111
    

    the pin reads 0V.  The first two lines show before (-) and after (+) DISMOD bits are modified.  After aplay a second time

    [  323.019640] [-] mcasp_common_hw_param: (DISMOD tx_ser 3) 0xfa03818c=0x0000001d
    [  323.027662] [+] mcasp_common_hw_param: (DISMOD tx_ser 3) 0xfa03818c=0x0000001d
    [  323.107161] [] davinci_mcasp_hw_params: (VER) 0xfa038000=0x44307b02
    [  323.114255] [] davinci_mcasp_hw_params: (PFUNC) 0xfa038010=0x00000000
    [  323.121474] [] davinci_mcasp_hw_params: (PDIR) 0xfa038014=0x00000008
    [  323.128533] [] davinci_mcasp_hw_params: (AFSRCTL) 0xfa03806c=0x00000011
    [  323.135925] [] davinci_mcasp_hw_params: (AFSXCTL) 0xfa0380ac=0x00000111

    The pin still reads 0V.  As far as I can tell there's nothing wrong with the register settings.

    Thanks,
    Stef

  • Stefano Antonelli said:

    For some reason /dev/mem2 is giving me bus errors when trying to access mcasp0 registers:

    ~# devmem2 0x48038000 w
    /dev/mem opened.
    Memory mapped at address 0xb6f9d000.
    Bus error

    Do you happen to know why?

    Because McASP0 is not enabled in device PRCM at that time. Check value of register CM_PER_MCASP0_CLKCTRL. McASP0 is enabled after aplay command is executed.

    Stefano Antonelli said:
    [ 323.027662] [+] mcasp_common_hw_param: (DISMOD tx_ser 3) 0xfa03818c=0x0000001d

    The value of SRCTL_3 (0x4803808C) [1:0] SRMOD is 0x1 (serializer is transmitter), while should be 0x0 (serializer is inactive).

    Please check with SRMOD = 0. If that doesn't work, try also with GBLCTL[11] XSMRST = 0. Check also if conf_<module>_<pin> [4] putypesel bit has the correct value.

    Regards,
    Pavel

  • Can use devmem2 now, thanks.  Speeds things up.

    If I make the serialiser inactive (devmem2 0x4803818c w 0xC) then the pin changes from 0V to 3.3V which is good.  However, the original issue remains.

    Please refer to the following scope captures.  Pink is frame sync. purple is axr3.

    On the left of the screen, the axr3 pin is high.  This is because I have executed the following commands:

    devmem2 0x44E00034 w 0x2
    devmem2 0x4803818c w 0xC

    and the serializer is inactive.  The axr3 pin goes low when I aplay.  It stays low for approx 52ms.  This is not audio data.  The axr3 pin then becomes active after that 52ms.  Here is a close up of what's happening at the transition.

    The format is not quite I2S (there is no delay), but the axr3 pin should be transmitting when framesync is low.  To achieve this I'm using inverted framesync and time slot 0 (least amount of driver changes).  You can see axr3 goes high again in the 4th grid.  In this capture it's doing this in an inactive slot, but sometimes it happens in an active slot.  Either way the transition from FF to 00 creates a tick as does the transition from 00 to FF.  The real audio data begins in the 5th slot.  The data in the capture is 0xFF, 0x80, 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0x00, 0xFF, 0x80.  The first byte of data in my file is 0xFF (ie. zero in ulaw).

    I don't yet understand what's going on in that 52ms.  Do you have any insights?

    Maybe I misunderstand how it's supposed to work, but:

    DISMOD says "when in inactive TDM slot of transmit mode or when serializer is inactive".

    XSMRST says "serializer drives the AXRn pin to the state specified for inactive time slot".

    Nowhere does it say that the serializer must be inactive when the transmit state machine is in reset?

    Thanks,
    Stef

  • Hi Stef,

    Pavel will be back on Monday. Hopefully he can help you with this issue.

    Customers have used this feature.

    Stefano Antonelli said:

    Nowhere does it say that the serializer must be inactive when the transmit state machine is in reset?

    Can you confirm that during the init you take the serializers out of reset before you take the state machine out of reset?

    Regards,
    Mark

  • Hi Mark,

    I'm using the drivers available on the 4.4.113 linux kernel.  In other words, all I've been doing is patching code that someone else wrote.

    Can you confirm that this feature works on any linux kernel version?

    Here's the code in mcasp_start_rx:

    	/* Activate serializer(s) */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
    	/* Release RX state machine */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
    	/* Release Frame Sync generator */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
    	if (mcasp_is_synchronous(mcasp))
    		mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
    

    And here's the code in mcasp_start_tx:

    	/* Activate serializer(s) */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
    
    	/* wait for XDATA to be cleared */
    	cnt = 0;
    	while ((mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) & XRDATA) &&
    	       (cnt < 100000))
    		cnt++;
    
    	/* Release TX state machine */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
    	/* Release Frame Sync generator */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
    
    	/* enable transmit IRQs */
    	mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
    		       mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);

    Thanks,
    Stef

  • Pavel Botev said:
    Stefano Antonelli

    For some reason /dev/mem2 is giving me bus errors when trying to access mcasp0 registers

    Check value of register CM_PER_MCASP0_CLKCTRL. McASP0 is enabled after aplay command is executed.

    Note that you can easily force the kernel to keep the peripheral clock enabled by adding a devicetree property:

    &mcasp0 {
    	ti,no-idle;
    };
    

  • Stef,

    Stefano Antonelli said:

    Maybe I misunderstand how it's supposed to work, but:

    DISMOD says "when in inactive TDM slot of transmit mode or when serializer is inactive".

    XSMRST says "serializer drives the AXRn pin to the state specified for inactive time slot".

    Nowhere does it say that the serializer must be inactive when the transmit state machine is in reset?

    I am checking with the McASP module expert regarding DISMOD, if inactive TDM slot is enough or we need also setup bits SRCTL[1:0] SRMOD and GBLCTL [11] XSMRST. I will come back to you when I have something.

    Meanwhile, you can check and verify that you have bit XTDM[x] XTDMS = 0 for the time slot you consider as inactive.

    Regards,
    Pavel

  • Stefano Antonelli said:
    I'm using the drivers available on the 4.4.113 linux kernel.

    Stef,

    This kernel version (4.4.113) is not supported in our AM335x PSDKs. Can you check if you have this issue with AM335x TI PSDK 3.03 (link below), which comes with kernel 4.4.41.

    This requirement (1st activate serializers, then TX state machine) is available in the McASP driver from PSDK 3.03:

    PSDK/board-support/linux-4.4.x/sound/soc/davinci/davinci-mcasp.c
     
    static void mcasp_start_tx(struct davinci_mcasp *mcasp)
    {
    ......
    /* Activate serializer(s) */
        mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
    ......
    /* Release TX state machine */
        mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
    .....
    }

    Regards,
    Pavel
  • Hi Pavel,

    If you read my reply to Mark further up:

    https://e2e.ti.com/support/processors/f/791/p/737730/2736539#2736539

    You'll see that the the serializer is activated before the state machine for both tx and rx.

    Also I downloaded the PSDK 3.03 and diffed the file davinci-mcasp.c against the kernel I'm using and there was only one line of change

    --- board-support/linux-4.4.41+gitAUTOINC+f9f6f0db2d-gf9f6f0db2d/sound/soc/davinci/davinci-mcasp.c	2017-03-29 14:09:59.000000000 -0700
    +++ linux-4.4.113-ti-rt-r149/sound/soc/davinci/davinci-mcasp.c	2018-04-06 13:25:09.000000000 -0700
    @@ -925,7 +925,7 @@
     		for (i = 0; i < active_slots; i++)
     			mask |= (1 << i);
     	}
    -	mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
    +	mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
     
     	if (!mcasp->dat_port)
     		busel = TXSEL;
    

    And I don't think this has any impact on DISMOD.  If I can find some time I will test this kernel.

    Thanks,
    Stef

  • Stef,

    Stefano Antonelli said:
    You'll see that the the serializer is activated before the state machine for both tx and rx.

    Yes, I see. This should be correct.

    You can check and verify that you have bit XTDM[x] XTDMS = 0 for the time slot you consider as inactive.

    Regards,
    Pavel

  • Hi Pavel,

    I have some new information.  I added some code to toggle a gpio during certain sections of code to zero in where axr3 was going unexpectedly low in post http://e2e.ti.com/support/processors/f/791/p/737730/2726383#2726383.

    This section of code is in davinci-mcasp.c in the function mcasp_common_hw_param():

    /* axr3 is high */
    	for (i = 0; i < mcasp->num_serializer; i++) {
    printk("[stef-] %s: (DISMOD tx_ser %d) 0x%08x\n", __func__, i,
    	mcasp_get_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i)));
    
    		mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
    			       mcasp->serial_dir[i]);
    		if (mcasp->serial_dir[i] == TX_MODE &&
    					tx_ser < max_active_serializers) {
    			mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
    			mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
    				       DISMOD_HIGH, DISMOD_MASK);
    /************** axr3 goes low here. *****************/
    			tx_ser++;
    		} else if (mcasp->serial_dir[i] == RX_MODE &&
    					rx_ser < max_active_serializers) {
    			mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
    			rx_ser++;
    		} else {
    			mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
    				       SRMOD_INACTIVE, SRMOD_MASK);
    		}
    
    printk("[stef+] %s: (DISMOD tx_ser %d) 0x%08x\n", __func__, i,
    	mcasp_get_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i)));
    printk("[stef+] %s: (GBLCTLX_REG) 0x%08x\n", __func__,
    	mcasp_get_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG));
    	}

    First I enabled the mcasp peripheral, then set the DISMOD bits for DISMOD=drive high and SRMOD=serializer inactive:

    devmem2 0x44E00034 w 0x2
    devmem2 0x4803818c w 0xC

    This is why the comment says axr3 is high before entering the for loop.

    When this function gets called, axr3 goes low when i=3 and stays low until the first inactive time *after* the first sample gets shifted out.  After that first sample gets shifted out, axr3 stays high during inactive time slots.

    Here are the prints:

    [  199.362544] [stef-] mcasp_common_hw_param: (DISMOD tx_ser 0) 0x00000000
    [  199.370132] [stef+] mcasp_common_hw_param: (DISMOD tx_ser 0) 0x00000000
    [  199.377164] [stef+] mcasp_common_hw_param: (GBLCTLX_REG) 0x00000000
    [  199.383758] [stef-] mcasp_common_hw_param: (DISMOD tx_ser 1) 0x00000000
    [  199.390828] [stef+] mcasp_common_hw_param: (DISMOD tx_ser 1) 0x00000000
    [  199.397841] [stef+] mcasp_common_hw_param: (GBLCTLX_REG) 0x00000000
    [  199.404438] [stef-] mcasp_common_hw_param: (DISMOD tx_ser 2) 0x00000000
    [  199.411448] [stef+] mcasp_common_hw_param: (DISMOD tx_ser 2) 0x00000002
    [  199.418480] [stef+] mcasp_common_hw_param: (GBLCTLX_REG) 0x00000000
    [  199.425325] [stef-] mcasp_common_hw_param: (DISMOD tx_ser 3) 0x0000000c
    [  199.432392] [stef+] mcasp_common_hw_param: (DISMOD tx_ser 3) 0x0000001d
    [  199.439383] [stef+] mcasp_common_hw_param: (GBLCTLX_REG) 0x00000000

    So we seem to have the case where the serializer is no longer inactive (ie. it's set to transmit), the serializers are disabled,  the state machine is not running, and DISMOD is not working...

    Thanks,
    Stef

  • Stef,

    I have check with our McASP experts. We think McASP DISMOD feature should work fine, axr3 pin should change to high during inactive slots. Which means that there is no need to keep state machine in reset (GBLCTL[11] XSMRST = 0) or make serializer inactive (SRCTL_3 [1:0] SRMOD = 0), inactive slot (XTDM[x] XTDMS = 0) should be enough.

    Make sure also that the corresponding axr3 pin control register has the correct value for pull register, conf_<module>_<pin>[4] putypesel

    Regards,
    Pavel
  • Hi Pavel,

    Here's what I have in the device tree:

    0x1ac 0x12    /* mcasp0_ahclkx.mcasp0_axr3 */

    And here's what devmem2 reads back:

    ~# devmem2 0x44e109ac w
    /dev/mem opened.
    Memory mapped at address 0xb6f96000.
    Value at address 0x44E109AC (0xb6f969ac): 0x12

    Just to be clear, the DISMOD feature works fine once data starts shifting out of the serializer during inactive time slots.  The DISMOD features seems broken when the serializer is in an "armed" state (without data flow) when clocks are active on the bus.

    Thanks,
    Stef

  • Stef,

    Stefano Antonelli said:
    The DISMOD features seems broken when the serializer is in an "armed" state (without data flow) when clocks are active on the bus.

    Can you provide more details regarding this state? What value you have there for XTDM[x] XTDMS bit?

    Regards,
    Pavel

  • Hi Pavel,

    At the point where DISMOD is "failing" in mcasp_common_hw_param(), the DAVINCI_MCASP_TXTDM_REG contains all zeros.  Nothing gets set until later in mcasp_i2s_hw_param() where DAVINCI_MCASP_TXTDM_REG = 0x00000001.

    I take it that's the problem?

    Thanks,
    Stef

  • Stef,

    Please double check that you are NOT in burst mode (XMOD/RMOD = 0) or DIT mode (DITEN = 1). In this cases DISMOD is not applicable.

    Another thing to try is to:

    if (mcasp->serial_dir[i] == TX_MODE &&
    tx_ser < max_active_serializers) {
    - mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
    mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i), DISMOD_LOW, DISMOD_MASK);
    + mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
    tx_ser++;
    } else ...

    So, first configure the DISMOD _then_ set the PDIR to output. It could be that the inactive state is configured based on the DISMOD at the time we switch the PDIR to 1.

    Regards,
    Pavel

  • Hi Pavel,

    Where DISMOD breaks, the XMOD bits are indeed 0.  They don't get set until later in mcasp_i2s_hw_param().  However, even if I set XMOD=2 before entering the for loop, the behaviour on the wire is still the same. I also tried your patch and it had no effect.

    Here some prints,  before the loop:

    [   52.899948] [stef-] DAVINCI_MCASP_TXTDM_REG: 0x00000000
    [ 52.905474] [stef-] DAVINCI_MCASP_TXFMCTL_REG: 0x00000011
    [ 52.911211] [stef-] DAVINCI_MCASP_RXFMCTL_REG: 0x00000011
    [ 52.916958] [stef-] DAVINCI_MCASP_TXDITCTL_REG: 0x00000000
    [ 52.922758] [stef=] DAVINCI_MCASP_TXFMCTL_REG: 0x00000111

    prints from the loop

    [   52.928582] [stef-] mcasp_common_hw_param: (DISMOD tx_ser 0) 0x00000000
    [ 52.935572] [stef+] mcasp_common_hw_param: (DISMOD tx_ser 0) 0x00000000
    [ 52.943212] [stef+] DAVINCI_MCASP_GBLCTLX_REG: 0x00000000
    [ 52.948978] [stef-] mcasp_common_hw_param: (DISMOD tx_ser 1) 0x00000000
    [ 52.956016] [stef+] mcasp_common_hw_param: (DISMOD tx_ser 1) 0x00000000
    [ 52.962972] [stef+] DAVINCI_MCASP_GBLCTLX_REG: 0x00000000
    [ 52.968688] [stef-] mcasp_common_hw_param: (DISMOD tx_ser 2) 0x00000000
    [ 52.975674] [stef+] mcasp_common_hw_param: (DISMOD tx_ser 2) 0x00000002
    [ 52.982612] [stef+] DAVINCI_MCASP_GBLCTLX_REG: 0x00000000
    [ 52.988338] [stef-] mcasp_common_hw_param: (DISMOD tx_ser 3) 0x0000000c
    [ 52.995390] [stef+] mcasp_common_hw_param: (DISMOD tx_ser 3) 0x0000001d

    prints from after the loop

    [   53.002336] [stef+] DAVINCI_MCASP_GBLCTLX_REG: 0x00000000
    [ 53.008061] [stef+] DAVINCI_MCASP_TXTDM_REG: 0x00000000
    [ 53.013587] [stef+] DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [ 53.019340] [stef+] DAVINCI_MCASP_RXFMCTL_REG: 0x00000011
    [ 53.025037] [stef+] DAVINCI_MCASP_TXDITCTL_REG: 0x00000000

    and later in mcasp_i2s_hw_param():

    [   53.034768] [stef] total_slots = 2
    [ 53.038383] [stef] DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [ 53.045660] [stef] DAVINCI_MCASP_TXTDM_REG: 0x00000001

    Did I miss anything?

    Thanks,
    Stef

  • I ran another test.  I moved the DISMOD enable to after the transmitter is out of reset.  Per this snippet in mcasp_start_tx():

    	/* Release TX state machine */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
    	/* Release Frame Sync generator */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
    
    	/* enable transmit IRQs */
    	mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
    		       mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);
    
    	/* enable tx serializers */
    	for (i = 0; i < mcasp->num_serializer; i++) {
    		mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
    			       mcasp->serial_dir[i]);
    		if (mcasp->serial_dir[i] == TX_MODE) {
    			mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
    			mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
    				       DISMOD_HIGH, DISMOD_MASK);
    		}
    	}
    	/* Activate serializer(s) */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);

    And the result:

    Pink is frame sync.  Green is a gpio that goes low just before davinci_mcasp_start() returns.  The purple trace is axr3.

    Note that DISMOD is working well up until the serializers are enabled in grid 5.  The first valid data doesn't come out until grid 7.

    Thanks,
    Stef

  • Stef,

    Stefano Antonelli said:
    Note that DISMOD is working well up until the serializers are enabled in grid 5. 

    You should make McASP registers and pinmux dump for the working well DISMOD case and for the non-working case and compare the differences.

    Can you also provide more details regarding your use case - do you use aplay tool or you are using playback application of your own? If you are using playback application of your own, can you reproduce the issue with the generic/minimal playback application (available at below link)?

    Regards,
    Pavel

  • Hi Pavel,

    I did a register dump of the registers we've been talking about.  If I missed any please tell me which registers you'd like to see.  I don't know how to get at the pinmux registers from within the mcasp driver.  If that's important please provide directions.

    before DISMOD breaks:
    [  268.680416] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXTDM_REG: 0x00000001
    [  268.687371] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [  268.694466] [stefd-]mcasp_start_tx DAVINCI_MCASP_RXFMCTL_REG: 0x00000111
    [  268.701509] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXDITCTL_REG: 0x00000000
    [  268.708696] [stefd-]mcasp_start_tx DAVINCI_MCASP_PDIR_REG: 0x00000000
    [  268.715486] [stefd-]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(0): 0x00000000
    [  268.722878] [stefd-]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(1): 0x00000000
    [  268.730240] [stefd-]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(2): 0x00000000
    [  268.737626] [stefd-]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(3): 0x0000000c
    
    after DISMOD breaks:
    [  268.745008] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXTDM_REG: 0x00000001
    [  268.758399] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [  268.765410] [stefd+]mcasp_start_tx DAVINCI_MCASP_RXFMCTL_REG: 0x00000111
    [  268.772442] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXDITCTL_REG: 0x00000000
    [  268.779545] [stefd+]mcasp_start_tx DAVINCI_MCASP_PDIR_REG: 0x00000008
    [  268.786283] [stefd+]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(0): 0x00000000
    [  268.793565] [stefd+]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(1): 0x00000000
    [  268.800850] [stefd+]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(2): 0x00000002
    [  268.808133] [stefd+]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(3): 0x0000000d

    I don't see anything unexpected.

    And I'm using aplay.

    Thanks,
    Stef

  • Stef,

    Stefano Antonelli said:
    I did a register dump of the registers we've been talking about.  If I missed any please tell me which registers you'd like to see. 

    I would like to see also: PFUNC, GBLCTL, XGBLCTL, ACLKXCTL, AHCLKXCTL, XINTCTL, XSTAT, XSLOT, XCLKCHK, XBUF_3, WFIFOCTL, WFIFOSTS

    Stefano Antonelli said:
    before DISMOD breaks:

    Stefano Antonelli said:
    [ 268.708696] [stefd-]mcasp_start_tx DAVINCI_MCASP_PDIR_REG: 0x00000000

    Stefano Antonelli said:
    [ 268.737626] [stefd-]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(3): 0x0000000c

    In this case "before DISMOD breaks", per mine understanding you are able to provide high level output on axr3 pin during aplay, is that correct? Because I see AXR3 is configured as input and serializer is inactive.

    Regards,
    Pavel

  • Hi Pavel,

    Before DISMOD breaks:
    [  218.866225] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXTDM_REG: 0x00000001
    [  218.873148] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [  218.880201] [stefd-]mcasp_start_tx DAVINCI_MCASP_RXFMCTL_REG: 0x00000111
    [  218.887387] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXDITCTL_REG: 0x00000000
    [  218.894627] [stefd-]mcasp_start_tx DAVINCI_MCASP_PDIR_REG: 0x00000000
    [  218.901429] [stefd-]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(3): 0x0000000c
    [  218.908747] [stefd-]mcasp_start_tx DAVINCI_MCASP_PFUNC_REG: 0x00000000
    [  218.915902] [stefd-]mcasp_start_tx DAVINCI_MCASP_GBLCTL_REG: 0x00001b00
    [  218.922899] [stefd-]mcasp_start_tx DAVINCI_MCASP_GBLCTLX_REG: 0x00001b00
    [  218.930015] [stefd-]mcasp_start_tx DAVINCI_MCASP_ACLKXCTL_REG: 0x00000080
    [  218.937177] [stefd-]mcasp_start_tx DAVINCI_MCASP_AHCLKXCTL_REG: 0x00008000
    [  218.944445] [stefd-]mcasp_start_tx DAVINCI_MCASP_EVTCTLX_REG: 0x00000001
    [  218.951570] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXSTAT_REG: 0x00000154
    [  218.958652] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXTDMSLOT_REG: 0x00000001
    [  218.965905] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXCLKCHK_REG: 0x00000000
    [  218.973131] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXBUF_REG(3): 0x00000000
    [  218.980284] [stefd-]mcasp_start_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOCTL_OFFSET: 0x00010101
    [  218.989530] [stefd-]mcasp_start_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOSTS_OFFSET: 0x00000040
    
    After DISMOD breaks:
    [  218.998851] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXTDM_REG: 0x00000001
    [  219.005804] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [  219.012848] [stefd+]mcasp_start_tx DAVINCI_MCASP_RXFMCTL_REG: 0x00000111
    [  219.019939] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXDITCTL_REG: 0x00000000
    [  219.027099] [stefd+]mcasp_start_tx DAVINCI_MCASP_PDIR_REG: 0x00000008
    [  219.033853] [stefd+]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(3): 0x0000001d
    [  219.041207] [stefd+]mcasp_start_tx DAVINCI_MCASP_PFUNC_REG: 0x00000000
    [  219.048096] [stefd+]mcasp_start_tx DAVINCI_MCASP_GBLCTL_REG: 0x00001f00
    [  219.055082] [stefd+]mcasp_start_tx DAVINCI_MCASP_GBLCTLX_REG: 0x00001f00
    [  219.062206] [stefd+]mcasp_start_tx DAVINCI_MCASP_ACLKXCTL_REG: 0x00000080
    [  219.069446] [stefd+]mcasp_start_tx DAVINCI_MCASP_AHCLKXCTL_REG: 0x00008000
    [  219.076717] [stefd+]mcasp_start_tx DAVINCI_MCASP_EVTCTLX_REG: 0x00000001
    [  219.083896] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXSTAT_REG: 0x0000015c
    [  219.090893] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXTDMSLOT_REG: 0x00000001
    [  219.098165] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXCLKCHK_REG: 0x00000000
    [  219.105384] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXBUF_REG(3): 0x00000000
    [  219.112563] [stefd+]mcasp_start_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOCTL_OFFSET: 0x00010101
    [  219.121827] [stefd+]mcasp_start_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOSTS_OFFSET: 0x00000040

    The register called DAVINCI_MCASP_EVTCTLX is XINTCTL according to the register offset.

    Pavel Botev said:

    In this case "before DISMOD breaks", per mine understanding you are able to provide high level output on axr3 pin during aplay, is that correct? Because I see AXR3 is configured as input and serializer is inactive.

    Yes AXR3 is high because I issue the following commands before aplay:

    devmem2 0x44E00034 w 0x2
    devmem2 0x4803818c w 0xC

    Otherwise AXR3 would be low.

    Thanks,
    Stef

  • Stef,

    Stefano Antonelli said:

    Yes AXR3 is high because I issue the following commands before aplay:

    devmem2 0x44E00034 w 0x2
    devmem2 0x4803818c w 0xC

    In this case DISMOD is working because serializer is inactive. But from what I understand, you need DISMOD feature to work fine when serializer is in transmit mode, and during inactive slots.

    So can you do the below steps and provide me the result:

    1. print conf_mcasp0_ahclkx with devmem2 tool

    2. run aplay tool

    3. provide me the McASP0 register dump

    Regards,
    Pavel

  • Hi Pavel,

    Pavel Botev said:

    In this case DISMOD is working because serializer is inactive. But from what I understand, you need DISMOD feature to work fine when serializer is in transmit mode, and during inactive slots.

    Correct, but it's worth pointing out that there are three conditions:

    1. DISMOD works when serializer is inactive prior to data shifting out onto the bus.
    2. DISMOD breaks when serializer is in transmit mode prior to data shifting out onto the bus.
    3. DISMOD works again during inactive time slots after data is shifting onto the bus.

    Pavel Botev said:

    So can you do the below steps and provide me the result:

    1. print conf_mcasp0_ahclkx with devmem2 tool

    2. run aplay tool

    3. provide me the McASP0 register dump

    I'm confused as to what you want.  Aside from printing conf_mcasp0_ahclkx, there will be no new information dumping the same MCASP0 register dump (ie. conditions 1 and 2).

    Are you looking for a register dump during condition 3 above?  If so, will the register cache under debugfs be good enough?  I can cat this while aplay has the device open.

    Thanks,
    Stef

  • Stefano Antonelli said:
    DISMOD works again during inactive time slots after data is shifting onto the bus.

    I am not sure I understand this case. In this case, is the serializer active (configured as tx)? Can you provide register dump for this case only?

    Stefano Antonelli said:
    Pavel Botev

    So can you do the below steps and provide me the result:

    1. print conf_mcasp0_ahclkx with devmem2 tool

    2. run aplay tool

    3. provide me the McASP0 register dump

    I'm confused as to what you want.  Aside from printing conf_mcasp0_ahclkx, there will be no new information dumping the same MCASP0 register dump (ie. conditions 1 and 2).

    Regarding step 3, you need to print the McASP0 register inside the mcasp linux kernel driver.

    Regards,
    Pavel

  • Hi Pavel,

    I'm not sure we're on the same page here (plus this forum layout is absolutely stupid).  Here's a picture I posted before with some markup so we can be sure we're talking about the same things.

    Two posts up I mentioned 3 conditions.  They are labelled on the above image.  The line marked end of mcasp_start_tx actually marks the end of davinci_mcasp_start().  Here is the code that belongs to the above image:

    static void mcasp_start_tx(struct davinci_mcasp *mcasp)
    {
    	u32 cnt;
    	int i;
    
    	if (mcasp->txnumevt) {	/* enable FIFO */
    		u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
    
    		mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
    		mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
    	}
    
    	/* Start clocks */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
    
    
    	/* wait for XDATA to be cleared */
    	cnt = 0;
    	while ((mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) & XRDATA) &&
    	       (cnt < 100000))
    		cnt++;
    
    	/* Release TX state machine */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
    	/* Release Frame Sync generator */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
    
    	/* enable transmit IRQs */
    	mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
    		       mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);
    
    stef_dump_reg(mcasp, "d-", __func__);
    	/* enable tx serializers */
    	/* Todo fix missing max_active_serializers */
    	for (i = 0; i < mcasp->num_serializer; i++) {
    		mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
    			       mcasp->serial_dir[i]);
    		if (mcasp->serial_dir[i] == TX_MODE) {
    			mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, AXR(i));
    			mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
    				       DISMOD_HIGH, DISMOD_MASK);
    		}
    	}
    	/* Activate serializer(s) */
    	mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
    stef_dump_reg(mcasp, "d+", __func__);
    }
    
    static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
    {
    	mcasp->streams++;
    
    	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
    		mcasp_start_tx(mcasp);
    	else
    		mcasp_start_rx(mcasp);
    
    	gpio_set_value(mcasp->debugio, 0);
    }

    At the end of davinci_mcasp_start, I'm not sure where control goes.  I think, but can't confirm, that there is no more configuration code.  The dmas have been started and the rest is up to hardware.

    I tried to print a register dump in davinci_mcasp_tx_irq_handler, but the prints didn't reliably come out.  The only other place I could think of to get at the register dump was in mcasp_stop_tx.  Hopefully that's representative.

    # this is conf_mcasp0_ahclkx, I think
    root:~# devmem2 0x44e109ac w
    /dev/mem opened.
    Memory mapped at address 0xb6feb000.
    Value at address 0x44E109AC (0xb6feb9ac): 0x12
    
    Condition 1:
    [   89.986047] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXTDM_REG: 0x00000001
    [   89.993590] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [   90.000684] [stefd-]mcasp_start_tx DAVINCI_MCASP_RXFMCTL_REG: 0x00000111
    [   90.007836] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXDITCTL_REG: 0x00000000
    [   90.015005] [stefd-]mcasp_start_tx DAVINCI_MCASP_PDIR_REG: 0x00000000
    [   90.021840] [stefd-]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(3): 0x0000000c
    [   90.029274] [stefd-]mcasp_start_tx DAVINCI_MCASP_PFUNC_REG: 0x00000000
    [   90.036185] [stefd-]mcasp_start_tx DAVINCI_MCASP_GBLCTL_REG: 0x00001b00
    [   90.043201] [stefd-]mcasp_start_tx DAVINCI_MCASP_GBLCTLX_REG: 0x00001b00
    [   90.050279] [stefd-]mcasp_start_tx DAVINCI_MCASP_ACLKXCTL_REG: 0x00000080
    [   90.057461] [stefd-]mcasp_start_tx DAVINCI_MCASP_AHCLKXCTL_REG: 0x00008000
    [   90.064765] [stefd-]mcasp_start_tx DAVINCI_MCASP_EVTCTLX_REG: 0x00000001
    [   90.071857] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXSTAT_REG: 0x0000015c
    [   90.078857] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXTDMSLOT_REG: 0x00000001
    [   90.086217] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXCLKCHK_REG: 0x00000000
    [   90.093401] [stefd-]mcasp_start_tx DAVINCI_MCASP_TXBUF_REG(3): 0x00000000
    [   90.100549] [stefd-]mcasp_start_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOCTL_OFFSET: 0x00010101
    [   90.109814] [stefd-]mcasp_start_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOSTS_OFFSET: 0x00000040
    
    Condition 2:
    [   90.119128] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXTDM_REG: 0x00000001
    [   90.132615] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [   90.139642] [stefd+]mcasp_start_tx DAVINCI_MCASP_RXFMCTL_REG: 0x00000111
    [   90.146669] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXDITCTL_REG: 0x00000000
    [   90.153796] [stefd+]mcasp_start_tx DAVINCI_MCASP_PDIR_REG: 0x00000008
    [   90.160542] [stefd+]mcasp_start_tx DAVINCI_MCASP_XRSRCTL_REG(3): 0x0000000d
    [   90.167827] [stefd+]mcasp_start_tx DAVINCI_MCASP_PFUNC_REG: 0x00000000
    [   90.174659] [stefd+]mcasp_start_tx DAVINCI_MCASP_GBLCTL_REG: 0x00001f00
    [   90.181605] [stefd+]mcasp_start_tx DAVINCI_MCASP_GBLCTLX_REG: 0x00001f00
    [   90.188618] [stefd+]mcasp_start_tx DAVINCI_MCASP_ACLKXCTL_REG: 0x00000080
    [   90.195720] [stefd+]mcasp_start_tx DAVINCI_MCASP_AHCLKXCTL_REG: 0x00008000
    [   90.202912] [stefd+]mcasp_start_tx DAVINCI_MCASP_EVTCTLX_REG: 0x00000001
    [   90.209924] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXSTAT_REG: 0x00000155
    [   90.216845] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXTDMSLOT_REG: 0x00000001
    [   90.224057] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXCLKCHK_REG: 0x00000000
    [   90.231159] [stefd+]mcasp_start_tx DAVINCI_MCASP_TXBUF_REG(3): 0x00000000
    [   90.238261] [stefd+]mcasp_start_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOCTL_OFFSET: 0x00010101
    [   90.247452] [stefd+]mcasp_start_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOSTS_OFFSET: 0x00000040
    
    Condition 3:
    [   90.256708] [stefd*]mcasp_stop_tx DAVINCI_MCASP_TXTDM_REG: 0x00000001
    [   90.263448] [stefd*]mcasp_stop_tx DAVINCI_MCASP_TXFMCTL_REG: 0x00000111
    [   90.270370] [stefd*]mcasp_stop_tx DAVINCI_MCASP_RXFMCTL_REG: 0x00000111
    [   90.277292] [stefd*]mcasp_stop_tx DAVINCI_MCASP_TXDITCTL_REG: 0x00000000
    [   90.284326] [stefd*]mcasp_stop_tx DAVINCI_MCASP_PDIR_REG: 0x00000008
    [   90.290975] [stefd*]mcasp_stop_tx DAVINCI_MCASP_XRSRCTL_REG(3): 0x0000000d
    [   90.298169] [stefd*]mcasp_stop_tx DAVINCI_MCASP_PFUNC_REG: 0x00000000
    [   90.304909] [stefd*]mcasp_stop_tx DAVINCI_MCASP_GBLCTL_REG: 0x00001f00
    [   90.311740] [stefd*]mcasp_stop_tx DAVINCI_MCASP_GBLCTLX_REG: 0x00001f00
    [   90.318660] [stefd*]mcasp_stop_tx DAVINCI_MCASP_ACLKXCTL_REG: 0x00000080
    [   90.325690] [stefd*]mcasp_stop_tx DAVINCI_MCASP_AHCLKXCTL_REG: 0x00008000
    [   90.332792] [stefd*]mcasp_stop_tx DAVINCI_MCASP_EVTCTLX_REG: 0x00000001
    [   90.339715] [stefd*]mcasp_stop_tx DAVINCI_MCASP_TXSTAT_REG: 0x0000015d
    [   90.346545] [stefd*]mcasp_stop_tx DAVINCI_MCASP_TXTDMSLOT_REG: 0x00000000
    [   90.353647] [stefd*]mcasp_stop_tx DAVINCI_MCASP_TXCLKCHK_REG: 0x00000000
    [   90.360658] [stefd*]mcasp_stop_tx DAVINCI_MCASP_TXBUF_REG(3): 0x00000000
    [   90.367687] [stefd*]mcasp_stop_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOCTL_OFFSET: 0x00010101
    [   90.376786] [stefd*]mcasp_stop_tx DAVINCI_MCASP_V3_AFIFO_BASE+MCASP_WFIFOSTS_OFFSET: 0x00000040
    
    
    Thanks,
    Stef

  • Stef,

    Let me summarize what we have so far:

    - you are using AM335x custom board with TI PSDK 3.03

    - you have modified davinci-mcasp.c and DTS file. Can you attach your DTS file also?

    - you are using aplay tool. Can you provide the console log output of the aplay command execution?

    - you need to use DISMOD feature (logic high) when serializer is transmitter and Transmit state machine is released from reset

    - "DISMOD breaks when serializer is in transmit mode prior to data shifting out onto the bus." - does this happen during inactive time slot? Can you provide more details for that case? If you have JTAG, you might put breakpoint and explore the McASP module registers.

    Regards,
    Pavel
  • Hi Pavel,


    Pavel Botev said:

    - you are using AM335x custom board with TI PSDK 3.03

    Just the kernel.  I have made modifications in order to send 8-bit ulaw.  But you should be able to see that from the registers.  If I can change the clocks to do 2 timeslots at 16-bit I will try that next.

    Pavel Botev said:

    - you have modified davinci-mcasp.c and DTS file. Can you attach your DTS file also?

    Probably not in its entirety.  Can you tell me which parts you need to see?

    Pavel Botev said:

    - you are using aplay tool. Can you provide the console log output of the aplay command execution?

    There is no output aside from:

    root:~# aplay -t raw -f MU_LAW test.ulaw
    Playing raw data 'test.ulaw' : Mu-Law, Rate 8000 Hz, Mono
    

    Was there something else you wanted to see?

    Pavel Botev said:

    - you need to use DISMOD feature (logic high) when serializer is transmitter and Transmit state machine is released from reset

    The serialiser must be high (or even high impedance) whenever there isn't an active timeslot.  The mcasp is bit clock and frame clock slave so the clocks are always running.  I need DISMOD to not be broken when "serializer is transmitter and Transmit state machine is released from reset".

    Pavel Botev said:

    - "DISMOD breaks when serializer is in transmit mode prior to data shifting out onto the bus." - does this happen during inactive time slot? Can you provide more details for that case? If you have JTAG, you might put breakpoint and explore the McASP module registers.

    Once it starts working again it works fine.  No JTAG header on this board.  Have another look at the scope capture 2 posts back.  Err wait a sec.  It seems to have disappeared?  I'll attach it again, but you may want to go back and read 2 post back where I describe this scope capture in relation to the code snippets.

    Have a look at the area marked first valid frame and you can see that DISMOD is working properly for each valid data sample.  What you see after the second orange line are two timeslots.  Timeslot 0 is unused and timeslot 1 is active.  However, there's a bit of trickery here.  The linux driver doesn't allow you to pick which timeslot you want to use.  I can't change how the codec works and it wants to exchange data when framesync is low; in timeslot 1.  To avoid having to make a bunch of patches to have the serializer transmit in timeslot 1 instead of timeslot 0, I've told the mcasp to use an inverted frame sync.  So the mcasp thinks it's transmitting in timeslot 0 when framesync is low, but this is actually timeslot 1 on the bus.

    From the mcasp perspective, the start of valid data actually happens on the falling edge of framesync before the second orange line that marks the first valid frame.  But region #2 appears to be some kind of no man's land where the serializer is behaving is an unexpected manner.  Due to the inverted frame sync, the serializer could have written zero to the bus in the "timeslot 0" (wrt to the serializer) which occurs on the left side of the second orange line.  However, if the serializer did write zero, that zero did not come from the dma.    I've put prints in the dma handler and I know my data buffer begins with 0x00, 0x01, 0x02.

    In region 3 I can see my data come out: 0x00, 0x01, 0x02 in timeslot 1.  Meanwhile the serializer is behaving properly during timeslot 0 (timeslot 1 wrt to the serializer).

    -Stef

  • Stefano Antonelli said:
    Just the kernel.  I have made modifications in order to send 8-bit ulaw.  But you should be able to see that from the registers.  If I can change the clocks to do 2 timeslots at 16-bit I will try that next.

    Do you mean that you have made additional modifications to davinci-mcasp.c driver, in order to match your system requirements?

    Stefano Antonelli said:
    - you have modified davinci-mcasp.c and DTS file. Can you attach your DTS file also?

    Probably not in its entirety.  Can you tell me which parts you need to see?

    The McASP related stuff. On AM335x EVM we have:

    sound {
            compatible = "simple-audio-card";
            simple-audio-card,name = "AM335x-EVM";
            simple-audio-card,widgets =
                "Headphone", "Headphone Jack",
                "Line", "Line In";
            simple-audio-card,routing =
                "Headphone Jack",    "HPLOUT",
                "Headphone Jack",    "HPROUT",
                "LINE1L",        "Line In",
                "LINE1R",        "Line In";
            simple-audio-card,format = "dsp_b";
            simple-audio-card,bitclock-master = <&sound_master>;
            simple-audio-card,frame-master = <&sound_master>;
            simple-audio-card,bitclock-inversion;

            simple-audio-card,cpu {
                sound-dai = <&mcasp1>;
            };

            sound_master: simple-audio-card,codec {
                sound-dai = <&tlv320aic3106>;
                system-clock-frequency = <12000000>;
            };
        };

    mcasp1_pins: mcasp1_pins {
            pinctrl-single,pins = <
                AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
                AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
                AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
                AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
            >;
        };

        mcasp1_pins_sleep: mcasp1_pins_sleep {
            pinctrl-single,pins = <
                AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
                AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
                AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)
                AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
            >;
        };

    &mcasp1 {
        #sound-dai-cells = <0>;
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&mcasp1_pins>;
        pinctrl-1 = <&mcasp1_pins_sleep>;

        status = "okay";

        op-mode = <0>;          /* MCASP_IIS_MODE */
        tdm-slots = <2>;
        /* 4 serializers */
        serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
            0 0 1 2
        >;
        tx-num-evt = <32>;
        rx-num-evt = <32>;
    };

    &i2c1 {

    ...

    tlv320aic3106: tlv320aic3106@1b {
            #sound-dai-cells = <0>;
            compatible = "ti,tlv320aic3106";
            reg = <0x1b>;
            status = "okay";

            /* Regulators */
            AVDD-supply = <&vaux2_reg>;
            IOVDD-supply = <&vaux2_reg>;
            DRVDD-supply = <&vaux2_reg>;
            DVDD-supply = <&vbat>;
        };

    Regards,
    Pavel

  • Hi Stefano,

    I was able to reproduce the issue with the following setup:

    BeagleBone White + audio cape (aic3106 codec).

    I have the following series: http://mailman.alsa-project.org/pipermail/alsa-devel/2018-November/141935.html

    I configured the AXR3 (tx serializer) in DT to pull up.

    Due to the codec on the cape, my setup for 8bit audio is to have 4 TDM slots, DISMOD is set to high.

    Codec as clock master:

    Codec as clock slave:

    The gpio3_19 is going low just before the PDIR for the AXR3 is set to output. In both capture we can see that as soon as we set PDIR to 1 (output) the line immediately pulled down for some reason.

    In my experimentation however I have seen other pattern as well: if I set the PDIR to 1, but the bitclk is _not_ running the AXR3 stays high till the point when the bclk starts to run.

    The command I use for playback:

    aplay -Dplughw:0,0 -c1 -r44100 -fS8-v /dev/zero

    From the first FS after the serializer is enabled the AXR3 pin looks OK: 8bit 0, 3x8bit 1 (DISMOD is high) as I only have timeslot 0 as active, the rest is inactive.

    When the codec is generating the clocks we have bclk and FS already on the bus when the McASP is enabled so the codec will interpret at least one sample with 'garbage'.

    When the codec is slave the misbehaving AXR3 is not an issue as the codec will only going to look at the AXR3 line after the first FS and from that point the line behaves correctly.

    After this experiment my conclusion is that DISMOD (high) is not behaving how it should based on the documentation and DISMOD_HIGH in codec master mode will generate at least one corrupted sample for the codec. The codec slave mode on the other hand can be safely used with DISMOD_HIGH.

    Is it possible for you to run McASP as master?

    If I recall correctly you have mentioned in this thread that you see issues with 8bit sample size. That you see 0x7f on the bus for a period of time?

    I created my setup to verify the 8bit as well (initially I was using 16bit samples as it is supported by the codec) and I don't see any corruption in the data.I believe you have modified the McASP driver to include SNDRV_PCM_FMTBIT_MU_LAW and I believe you cased it along with the U8/S8 so 8bit word length, is this correct?

    If so it is a possibility that the ALSA layer (or application) is playing 'silence' for a period of time and this is what you are seeing on the bus. Silence is defined for MU_LAW as 0x7f (sound/core/pcm_misc.c)

    I have couple of questions:

    - is the codec you are using is a public one and if it is where can I find the data sheet so I can go through and see if there is anything we can do to make master mode working

    - is it possible to see the modifications you have done to the mcasp driver and the related DT sections?

    Note: From the upstream series I have omitted adding SNDRV_PCM_FMTBIT_MU_LAW as supported sample format at least for the time when we understand the issue and limitation better.

    At the moment I see two possibilities to make your setup working:

    1. McASP as clock master

    2. codec as clock master, but delay the bclk/fs clock from the codec _after_ the McASP start. This way we kind of simulate how the bclk/fs behaves in slave mode and the codec will not interpret invalid data due to the AXR3 going low unexpectedly.

    Kind regards,
    Peter

  • Hi Peter,

    Thanks for looking into this.

    Sorry I cannot give you details on the codec other than:

    1.  master only
    2. clocks are always active

    Is there a workaround by perhaps setting part of the McASP as master?  I don't need to send a transmit framesync to the codec.  As long as the receive side works in slave mode, can the transmit side somehow be synchronized to the receiver while still generating frame sync in master mode?

    Otherwise, I can put a transistor or something to pull up hard on the tx line until data first starts to flow.  Is there any signal I can get out from the McASP via gpio to tell me that the DMA has shifted data into the shift register?

    Thanks,
    Stef

  • Hi Stefano,

    Codec details: No problem, I understand. It is in my debug list to know what we are dealing with.

    You can configure McASP as BCLK slave and FS master by configuring the dai link to SND_SOC_DAIFMT_CBM_CFS. In this case your codec must not generate FS on the bus, but it is required to run the bitclock.

    There will be always a race if you try to manage the pull, imho
    It is one thing that the shift registers are loaded with data via the DMA (or the FIFO is filled). The most critical one is that for some unknown reason McASP will not honor the DISMOD _before_ the first start condition and it is pulling down the AXR line.
    So it does not matter (imo) when you will release the hard pull it is most likely not going to align with the last bclk of a previous time slot which should not contain any invalid 0 because of McASP pulling the line down.

    Kind regards,
    Peter
  • Hi Peter,

    Peter Ujfalusi said:
    You can configure McASP as BCLK slave and FS master by configuring the dai link to SND_SOC_DAIFMT_CBM_CFS. In this case your codec must not generate FS on the bus, but it is required to run the bitclock.

    This won't work.  The codec needs to see it's own frame sync for internal synchronization.

    The most critical one is that for some unknown reason McASP will not honor the DISMOD _before_ the first start condition and it is pulling down the AXR line.

    From what I've seen on the scope there is a point in time where AXR goes low when it should be staying high.  I can't recall if that's when PDIR is set or at some other line of code.  With the code modification I made to enable the AXR after that McASP has been started, this always occurs in the frame preceeding start of data.  So I think, all I  need is a little bit of hardware to start pulling up hard on AXR3 before DISMOD has a chance to pull the line low, and then release it on the rising edge of the next frame sync.

    So this piece of hardware would:

    1. arm via gpio (ie. pull up)
    2. disarm via rising edge of frame sync (ie. tristate)

    Do you see any issues with this approach?

    Thanks,
    Stef

  • Hi Stefano,

    Interesting, it could work.
    You would need DSP_A mode (1 bit delay after the FS edge), the pull hardware should trigger on the falling edge of the FS pulse, I think.

    Kind regards,
    Peter
  • Hi Peter,

    There is one thing that is bothering me.  We use the McASP in slave mode successfully with the aic3106 codec.  In that scenario, the codec generates bit clock and frame sync and I don't recalling seeing a problem with DISMOD being low when the slot width is 16-bit.

    However, even with DISMOD set to low with an 8-bit slot, I've seen the same behaviour with garbage data on the bus as soon as PDIR=1.  Though in this case AXR3 drives high when it should be low.

    Is this DISMOD problem only related to an 8-bit slot width, or is the problem there with a 16-bit slot width?

    -Stef

  • Hi Stefano,

    I have tested the DISMOD with McASP slave/master mode and with 8/16bit sample sizes and I can not recall anything which would be inconsistent. The AXR line went down as soon as I switched the PDIR.
    To be precise: the AXR went low _if_ there were bitclk running _and_ the PDIR was set to output. So if there were no bitclock and I set the PDIR the AXR was still high, but as soon as the BCLK started to run it went down.

    I can try to resurrect my setup on Monday to confirm.

    Kind regards,
    Peter
  • Peter Ujfalusi said:

    To be precise: the AXR went low _if_ there were bitclk running _and_ the PDIR was set to output. So if there were no bitclock and I set the PDIR the AXR was still high, but as soon as the BCLK started to run it went down.

    I assume you only tested this with DISMOD=HIGH.  Does DISMOD=LOW or DISMOD=HIGHZ have the same problem?


    I can try to resurrect my setup on Monday to confirm.

    If you could that would help me choose my next steps.

    -Stef

  • Hi Peter,

    I'm re-reading your replies and have a question.

    Peter Ujfalusi said:

    When the codec is slave the misbehaving AXR3 is not an issue as the codec will only going to look at the AXR3 line after the first FS and from that point the line behaves correctly.

    Your scope capture showed AXR3 being low already when frame sync went low.  Did you test with any data values other than zero?  If you tested with a value such as 0xAA, is the first byte whole or corrupted in the first bit?  With data=0x00 I can't tell.

    If I recall correctly you have mentioned in this thread that you see issues with 8bit sample size. That you see 0x7f on the bus for a period of time?

    I created my setup to verify the 8bit as well (initially I was using 16bit samples as it is supported by the codec) and I don't see any corruption in the data.I believe you have modified the McASP driver to include SNDRV_PCM_FMTBIT_MU_LAW and I believe you cased it along with the U8/S8 so 8bit word length, is this correct?

    If so it is a possibility that the ALSA layer (or application) is playing 'silence' for a period of time and this is what you are seeing on the bus. Silence is defined for MU_LAW as 0x7f (sound/core/pcm_misc.c)

    interesting.  MU_LAW 0x7f is actually -1.  0xFF is 0 which is why a working DISMOD=HIGH is necessary for ulaw.

    https://en.wikipedia.org/wiki/%CE%9C-law_algorithm

    Thanks,
    Stef

  • Hi Stefano,

    Yes, the first byte is correct, tested with 0xaa and 0x55 as well.

    I think I have found some pattern in how the AXR3 line is behaving, but I need to investigate it more

    In the scope pic: aic3106 is master, I'm using i2s mode, 16bits, stereo, DISMOD is 3 and playing raw 0xaa:

    gpio1_17 is high while the PDIR is changed for the AXR3, gpio3_19 is high during the time the TX state machine is released and the Frame sync generator is released.

    As you can see the AXR3 line goes low when AXR3 is set to output, then it goes up after the McASP is released. The data (0xaa) will be on the bus on the first left (fs low) channel after the McASP is released.

    However, if in the same setup I play 0x55 then the AXR3 line would _not_ go high after the McASP is released. It looks to me that McASP will pull the AXR3 line to the level of the first bit in the data before the first start condition. In case of 0xaa it is high, in case of 0x55 it is low.

    As for the MU_LAW: it is in the sound/core/pcm_misc.c, the 0x7f  value predates the Linux move to git. A_LAW silence is 0x55.

    Kind regards,

    Peter

  • Hi Peter,

    Peter Ujfalusi said:

    Yes, the first byte is correct, tested with 0xaa and 0x55 as well.

    Thanks for this.  I have a circuit designed now that appears to work.

    Peter Ujfalusi said:

    As for the MU_LAW: it is in the sound/core/pcm_misc.c, the 0x7f  value predates the Linux move to git. A_LAW silence is 0x55.

    Indeed I saw that.  Only an issue with aplay though.  Our application will write 0xFF for silence.  According to wikipedia:

    Note that 0 is encoded as 0xFF, and −1 is encoded as 0x7F, but when decoded back the result is 0 in both cases.

    So if wikipedia is to be believed 0xFF is more correct.  But I have no interest in fixing alsalib.

    Thanks,
    Stef

  • Hi Stefano,

    I'm really interested to hear more about the circuit and how it performs!

    I have the following captures: aic3106 is master, i2s mode, 16bits, stereo, DISMOD is 3, gpio1_17 is high while the PDIR is changed for the AXR3, gpio3_19 is high during the time the TX state machine is released and the Frame sync generator is released.

    Playing raw 0xaa:

    Playing raw 0x55:

    AXR3 drops to low right after the pin is configured to output in both cases, but when the MSB bit is 1 it is going to be driven high after the frame sync generator/tx state machine is released.

    I think after the McASP is released the MSB bit of the first sample is pulling the line to either direction, depending if it is 0 or 1. Bit it does pull down the line between PDIR and McASP release by itself which I can not explain or understand.

    This issue also affects non MU law use cases when the codec is master as if the first sample's MSB is 1 then the line will be kept high until the first start condition appears on the FS line.

    Kind regards,

    Peter

  • Hi Peter,

    I appreciate all of your help, but I can't post details about this circuit in the forums.  I'd be happy to discuss it over the phone though if you wanted to give me a ring.

    It seems to me that you've proven rather conclusively that DISMOD is badly broken, despite assurances to the contrary earlier in this thread.  I someone at TI add this to the errata for this chip and add a big disclaimer somewhere in the datasheet.

    Since my clocks are always running, the broken DISMOD at least behaves consistently.  I have everything I need now to get this product working.  Thanks again for your help.

    Thanks,
    Stef

  • Hi Stefano,

    I did another experiment to mitigate the DISMOD issue, it has it's issue, but from SW this is the most I can think we can do:

    The setup is the same, but in case the McASP is slave I wait for the first FS start condition, then set the PDIR to output.

    gpio1_17 is high while the PDIR is changed to output, gpio3_19 is high while waiting for the first FS.

    Due to SW latency we loose some MSB bits from the first channel.. I have tried to wait for the XLAST, but then we will loose the entire first slot and part of the second slot.

    From SW this never going to work correctly due to unpredictability, not sure which is worst: having the line pulled up/down based on the MSB bit until the first FS or to loose bits from the very first time slot.

    This issue definitely warrants an ERRATA and I believe it might affect all SoC integrating McASP.

    If John could set up a short call to discuss your findings and solution, I would be happy to join.

    I'm glad that you managed to work around the issue!

    Kind regards,

    Peter