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.

Issues with MCASP on Linux/DM8168

I'm having similar issues to the user who posted here http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/717/t/229575.aspx

 After reading through that thread and following suggestions, I'm still having issues.

I'm getting input/output error from arecord and 'ALSA sound/core/pcm_lib.c:1765: capture write error (DMA or IRQ trouble?)' shows up in dmesg

I have only one serializer enabled in RX Mode

static u8 mcasp_iis_serializer_direction[] = {
     RX_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE,
      INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE,
      INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE,
      INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE, INACTIVE_MODE,
};

static struct snd_platform_data vhe022_snd_data1 = {
      .tx_dma_offset = 0x46400000,
      .rx_dma_offset = 0x46400000,
      .asp_chan_q = EVENTQ_1,
      .tdm_slots = 2, /* number of channels */
      .op_mode = DAVINCI_MCASP_IIS_MODE,
      .num_serializer = ARRAY_SIZE(mcasp_iis_serializer_direction),
      .serial_dir = mcasp_iis_serializer_direction,
      .version = MCASP_VERSION_2,
      .txnumevt = 0,
      .rxnumevt = 1,
};


Yet if I look at the registers for MCASP1 (the one this is being mapped to), it seems that serailizers 6-15 are also in RX Mode before and after running arecord. I also paused it in gdb right before the actual read call, and found the registers have the same contents.

Physical (Virtual) : Value
0x4803C180 (0x2ab1e180): 0x00000002
0x4803C184 (0x2ad35184): 0x00000000
0x4803C188 (0x2acc2188): 0x00000000
0x4803C18C (0x2acd018c): 0x00000000
0x4803C190 (0x2aba2190): 0x00000000
0x4803C194 (0x2aba6194): 0x00000000
0x4803C198 (0x2ad17198): 0x00000002
0x4803C19C (0x2ad0a19c): 0x00000002
0x4803C1A0 (0x2abac1a0): 0x00000002
0x4803C1A4 (0x2ab0f1a4): 0x00000002
0x4803C1A8 (0x2ab2c1a8): 0x00000002
0x4803C1AC (0x2ab901ac): 0x00000002
0x4803C1B0 (0x2acd61b0): 0x00000002
0x4803C1B4 (0x2abb01b4): 0x00000002
0x4803C1B8 (0x2ab4e1b8): 0x00000002
0x4803C1BC (0x2acf31bc): 0x00000002


I also added a quick log to davinci-mcasp.c in the function davinci_hw_common_param (around line 630)

for (i = 0; i < dev->num_serializer; i++) {
      mcasp_clr_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), 0x3);       //Addition: attempt to force clear bits
      mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
            dev->serial_dir[i]);

      printk("serial_dir[%d] = %d\n", i, dev->serial_dir[i]);       //Addition: print assigned serial dir 
      printk("Serial mode at 0x%08X set to %d\n",                   //Addition: print value after assignment
            dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
            mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i)));

Which then prints:

serial_dir[0] = 2
Serial mode at 0xFA03C180 set to 2
serial_dir[1] = 0
Serial mode at 0xFA03C184 set to 0
serial_dir[2] = 0
Serial mode at 0xFA03C188 set to 0
serial_dir[3] = 0
Serial mode at 0xFA03C18C set to 0
serial_dir[4] = 0
Serial mode at 0xFA03C190 set to 0
serial_dir[5] = 0
Serial mode at 0xFA03C194 set to 0
serial_dir[6] = 0
Serial mode at 0xFA03C198 set to 2
serial_dir[7] = 0
Serial mode at 0xFA03C19C set to 2
serial_dir[8] = 0
Serial mode at 0xFA03C1A0 set to 2
serial_dir[9] = 0
Serial mode at 0xFA03C1A4 set to 2
serial_dir[10] = 0
Serial mode at 0xFA03C1A8 set to 2
serial_dir[11] = 0
Serial mode at 0xFA03C1AC set to 2
serial_dir[12] = 0
Serial mode at 0xFA03C1B0 set to 2
serial_dir[13] = 0
Serial mode at 0xFA03C1B4 set to 2
serial_dir[14] = 0
Serial mode at 0xFA03C1B8 set to 2
serial_dir[15] = 0
Serial mode at 0xFA03C1BC set to 2


When arecord is run.

So... I'm a bit puzzled as to why these registers aren't being set, and I think this may at least be part of the cause of my issue. 

  • Hi Shawn,

    Did you tried num_serializer to 1 ? (Although I tried with no effect)


    I'm working on DM8168 McASP with AIC23, base on DVRRDK3.50.00.05.

    Problems were found at capture and playback:

    1. playback program halt at snd_pcm_mmap_writei after several writes. No signal at AXR pin but also found "ALSA sound/core/pcm_lib.c:1765: playback write error (DMA or IRQ trouble?)" in dmesg.

    2. arecord has no input.

    Hardware measured AHCLK and AFSR /AFSX are normal.

    DAVINCI_MCASP_TXSTAT_REG have error when first run, then no errors.

    DAVINCI_MCASP_TXCLKCHK_REG counting ok

    Any idea? Thanks.

    Mike

  •  Tried setting num_serializer to 1, also to no effect.  

     I also just realized that each McASP on the 8168 has only 6 serializers, despite there being 16 control registers, so I guess not being able to set serializers 6-15 is a non-issue, but I changed the array size to 6, still to no positive effect.

     I'm still looking into this issue.  Thank you for any help.

     

     




  • I've made a bit of progress here. The GBLCTRL register is not being set.  According to section 14.3.8 of the technical manual, this is likely because there's no active clock to latch it.  I have however not been succesful in enabling the internal clock source - they seem to be getting reset to the external source before the attempted set of GBLCTL.

    Also I should mention, the function in davinci-mcasp.c:

    static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
    {
          int i = 0;

          mcasp_set_bits(regs, val);

          /* programming GBLCTL needs to read back from GBLCTL and verfiy */
          /* loop count is to avoid the lock-up */
          for (i = 0; i < 1000; i++) {
                if ((mcasp_get_reg(regs) & val) == val)
                      break;
          }

          if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
                printk(KERN_ERR "GBLCTL write error\n");
    }

    appears either not exaclty right, or appears to be used improperly in the driver I'm looking at.  The driver code (found in linux-04.04.00.01) calls it with the alias register GBLCTLR, which does not appear to be subject to the same latching issue as GBLCTL, negating any usefulness of verifying the write..  i.e. it's verifying the write to the alias register and not to the actual register.

     

    Edit: got the GBLCTL bits so set by setting/clearing the clock source bits around the GBLCTL sets.  Still getting read errors.

     

  • Which clock are you using ? ACLK or AHCLK ?

    if you use AHCLK, you'll need to enable it before setting GBLCTL using mcasp_ahclkx_enable.

    I could set it but still getting error

  • I'm not sure I understand what you mean by which clock am I using?  I was under the impression that both clocks are needed.  Both are externally generated, with AHCLKR always being on.

    I think I'm to the point where I'm pretty happy with what I'm seeing in the register dumps of the MCASP1 region of memory, but I'm still getting read errors.  I don't really know where to look next.

  • Finally found at least the issue that's causing the timeout.

    Our board does not have any transmit signals, so the tx clocks are all disabled, but the ASYNC bit of ACLKXCTL was not being set.  

    Setting the bit got rid of the timeout.

     

     

     

     

  • I am working on DM8148 and use McAsp3 to connect AIC3106. I made it running. 

    I want to share for everybody.

    in the board-ti8148ipnc.c

    //panda
    static u8 ti8148_iis_serializer_direction_1[] = {
    	TX_MODE,	RX_MODE,	INACTIVE_MODE,	INACTIVE_MODE,
    	INACTIVE_MODE,	INACTIVE_MODE,	INACTIVE_MODE,	INACTIVE_MODE,
    	INACTIVE_MODE,	INACTIVE_MODE,	INACTIVE_MODE,	INACTIVE_MODE,
    	INACTIVE_MODE,	INACTIVE_MODE,	INACTIVE_MODE,	INACTIVE_MODE,
    };
    static struct snd_platform_data ti8148_evm_snd_data[] = {
    		{
    			.tx_dma_offset	= 0x46800000,
    			.rx_dma_offset	= 0x46800000,
    			.op_mode	= DAVINCI_MCASP_IIS_MODE,
    			.num_serializer = ARRAY_SIZE(ti8148_iis_serializer_direction),
    			.tdm_slots	= 2,
    			.serial_dir	= ti8148_iis_serializer_direction,
    			.asp_chan_q	= EVENTQ_2,
    			.version	= MCASP_VERSION_2,
    			.txnumevt	= 64,
    			.rxnumevt	= 64,
    		},
    		{
    			.tx_dma_offset	= 0x4A1A5000,
    			.rx_dma_offset	= 0x4A1A5000,
    			.op_mode	= DAVINCI_MCASP_IIS_MODE,
    			.num_serializer = ARRAY_SIZE(ti8148_iis_serializer_direction_1),
    			.tdm_slots	= 2,
    			.serial_dir	= ti8148_iis_serializer_direction_1,
    			.asp_chan_q	= EVENTQ_2,//??
    			.version	= MCASP_VERSION_2,
    			.txnumevt	= 1,//?
    			.rxnumevt	= 1,//?
    		}
    
    };
    

    also add a register line in function ti8148_ipnc_init

    ti81xx_register_mcasp(3, &ti8148_evm_snd_data[1]);

    in the devices.c

    static struct resource ti81xx_mcasp3_resource[] = {
    	{
    		.name = "mcasp",
    		.start = TI81XX_ASP3_BASE,
    		.end = TI81XX_ASP3_BASE + (SZ_1K * 12) - 1,
    		.flags = IORESOURCE_MEM,
    	},
    	/* TX event */
    	{
    		.start = TI81XX_DMA_MCASP3_AXEVT,
    		.end = TI81XX_DMA_MCASP3_AXEVT,
    		.flags = IORESOURCE_DMA,
    	},
    	/* RX event */
    	{
    		.start = TI81XX_DMA_MCASP3_AREVT,
    		.end = TI81XX_DMA_MCASP3_AREVT,
    		.flags = IORESOURCE_DMA,
    	},
    };
    static struct platform_device ti81xx_mcasp3_device = {
    	.name = "davinci-mcasp",
    };

    with some defination in the asp.h

    //panda
    /* EDMA channels of ti81xx McASP3 */
    #define TI81XX_DMA_MCASP3_AXEVT 56
    #define TI81XX_DMA_MCASP3_AREVT 57
    //~panda

    //panda
    #define TI81XX_ASP3_BASE 0x4A1A2000
    //~panda

    modify ti81xx_register_mcasp function in devices.c like that:

    void __init ti81xx_register_mcasp(int id, struct snd_platform_data *pdata)
    {
    	if (id==2)
    	{
    	if (machine_is_ti8168evm() || machine_is_ti8148evm() || machine_is_ti811xevm() || machine_is_ti8148ipnc()) {
    		ti81xx_mcasp_device.id = 2;
    		ti81xx_mcasp_device.resource = ti81xx_mcasp_resource;
    		ti81xx_mcasp_device.num_resources = ARRAY_SIZE(ti81xx_mcasp_resource);
    	} else if (machine_is_dm385evm() || machine_is_dm385ipnc()) {
    		ti81xx_mcasp_device.id = 1;
    		ti81xx_mcasp_device.resource = dm385_mcasp_resource;
    		ti81xx_mcasp_device.num_resources = ARRAY_SIZE(dm385_mcasp_resource);
    	} else {
    		pr_err("%s: platform not supported\n", __func__);
    		return;
    	}
    
    	/* TI811x AIC_MCLK is connected to SoC pin MCA2_AHCLKX */
    	//omap_mux_init_signal("xref_clk2.mcasp2_ahclkx", 0);
    	ti81xx_mcasp_device.dev.platform_data = pdata;
    	platform_device_register(&ti81xx_mcasp_device);
    }
    	if (id==3)
    	{
    		if (machine_is_ti8168evm() || machine_is_ti8148evm() || machine_is_ti811xevm() || machine_is_ti8148ipnc()) {
    			ti81xx_mcasp3_device.id = 3;
    			ti81xx_mcasp3_device.resource = ti81xx_mcasp3_resource;
    			ti81xx_mcasp3_device.num_resources = ARRAY_SIZE(ti81xx_mcasp3_resource);
    		} else if (machine_is_dm385evm() || machine_is_dm385ipnc()) {
    			ti81xx_mcasp3_device.id = 3;
    			ti81xx_mcasp3_device.resource = dm385_mcasp_resource;
    			ti81xx_mcasp3_device.num_resources = ARRAY_SIZE(dm385_mcasp_resource);
    		} else {
    			pr_err("%s: platform not supported\n", __func__);
    			return;
    		}
    
    		/* TI811x AIC_MCLK is connected to SoC pin MCA2_AHCLKX */
    		//omap_mux_init_signal("xref_clk2.mcasp2_ahclkx", 0);
    		ti81xx_mcasp3_device.dev.platform_data = pdata;
    		platform_device_register(&ti81xx_mcasp3_device);
    	}
    }

    finally , due to dma for mcasp 345 work on dsp so We have modify on devices.c dma slot and dma channel rsv :

    static const s16 ti814x_dma_rsv_chans[][2] = {
    /* (offset, number) */
    {0, 2},
    {14, 2},
    {26, 6},
    {48, 4},
    {58, 6},//panda {56,8}
    {-1, -1}
    };

    static const s16 ti814x_dma_rsv_slots[][2] = {
    /* (offset, number) */
    {0, 2},
    {14, 2},
    {26, 6},
    {48, 4},
    {58, 6},//panda {56,8}
    {64, 127},
    {-1, -1}
    };

    (for this one, please read http://processors.wiki.ti.com/index.php/TI81XX_EDMA_Driver_User_Guide )

    finally, mcasp3 work on the A8.

    i am amateur, i just want share what i done, forgive me if i have mistake.

    thank you

    (I spent alot of time to fix bug "davinci_pcm: Failed to get dma channels" . So i want to help who have same situation)