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.

dm8168中mcasp0音频问题



1.音频采集是通过HDMI的接口芯片sii9233A,通过i2s连接到8168的mcasp0上。

2.内核ALSA驱动已经修改能支持sii9233A,

root@dm816x:~# arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: ETV [TI81XX ETV], device 0: AIC3X tlv320aic3x-hifi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: ETV [TI81XX ETV], device 2: HDMI sii9233a-hifi-2 []
Subdevices: 1/1
Subdevice #0: subdevice #0

3.现在通过arecord录音,录制的wmv文件发现录音文件只有4k大小,也就是根本没有采集到音频数据,在davinci-pcm.c文件中,无法进入davinci_pcm_dma_irq()

4.sii9233A上i2s格式跟mcasp0上i2s格式配置已经是一致的。

为什么在采集音频的时候进入不了davinci_pcm_dma_irq()????

  • 你好,

    PSP默认驱动使用的是McASP2,请问你是否有参考http://processors.wiki.ti.com/index.php/TI81xx_PSP_Porting_Guide#Audio_driver_.28McASP.29,做了相应的修改?

  • 已经做了修改了

    <kernel-src>/arch/arm/mach-omap2/board-ti8168evm.c修改如下:

    static u8 ti8168_iis_serializer_direction_mcasp0[] = {
    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 u8 ti8168_iis_serializer_direction_mcasp1[] = {
    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 u8 ti8168_iis_serializer_direction_mcasp2[] = {
    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 ti8168_evm_snd_data[] = {
    {
    .tx_dma_offset = 0x46000000,
    .rx_dma_offset = 0x46000000,
    .op_mode = DAVINCI_MCASP_IIS_MODE,
    .num_serializer = ARRAY_SIZE(ti8168_iis_serializer_direction_mcasp0),
    .tdm_slots = 2,
    .serial_dir = ti8168_iis_serializer_direction_mcasp0,
    .asp_chan_q = EVENTQ_2,
    .version = MCASP_VERSION_2,
    .txnumevt = 1,
    .rxnumevt = 1,
    },
    {
    .tx_dma_offset = 0x46400000,
    .rx_dma_offset = 0x46400000,
    .op_mode = DAVINCI_MCASP_IIS_MODE,
    .num_serializer = ARRAY_SIZE(ti8168_iis_serializer_direction_mcasp1),
    .tdm_slots = 2,
    .serial_dir = ti8168_iis_serializer_direction_mcasp1,
    .asp_chan_q = EVENTQ_2,
    .version = MCASP_VERSION_2,
    .txnumevt = 1,
    .rxnumevt = 1,
    },
    {
    .tx_dma_offset = 0x46800000,
    .rx_dma_offset = 0x46800000,
    .op_mode = DAVINCI_MCASP_IIS_MODE,
    .num_serializer = ARRAY_SIZE(ti8168_iis_serializer_direction_mcasp2),
    .tdm_slots = 2,
    .serial_dir = ti8168_iis_serializer_direction_mcasp2,
    .asp_chan_q = EVENTQ_2,
    .version = MCASP_VERSION_2,
    .txnumevt = 1,
    .rxnumevt = 1,
    },
    };

    ti81xx_register_mcasp(0, &ti8168_evm_snd_data[0]);
    ti81xx_register_mcasp(1, &ti8168_evm_snd_data[1]);
    ti81xx_register_mcasp(2, &ti8168_evm_snd_data[2]);

    arch/arm/mach-omap2/devices.c修改如下:

    static struct resource ti81xx_mcasp0_resource[] = {
    {
    .name = "mcasp0",
    .start = TI81XX_ASP0_BASE,
    .end = TI81XX_ASP0_BASE + (SZ_1K * 12) - 1,
    .flags = IORESOURCE_MEM,
    },
    /* TX event */
    {
    .start = TI81XX_DMA_MCASP0_AXEVT,
    .end = TI81XX_DMA_MCASP0_AXEVT,
    .flags = IORESOURCE_DMA,
    },
    /* RX event */
    {
    .start = TI81XX_DMA_MCASP0_AREVT,
    .end = TI81XX_DMA_MCASP0_AREVT,
    .flags = IORESOURCE_DMA,
    },
    };

    static struct resource ti81xx_mcasp1_resource[] = {
    {
    .name = "mcasp1",
    .start = TI81XX_ASP1_BASE,
    .end = TI81XX_ASP1_BASE + (SZ_1K * 12) - 1,
    .flags = IORESOURCE_MEM,
    },
    /* TX event */
    {
    .start = TI81XX_DMA_MCASP1_AXEVT,
    .end = TI81XX_DMA_MCASP1_AXEVT,
    .flags = IORESOURCE_DMA,
    },
    /* RX event */
    {
    .start = TI81XX_DMA_MCASP1_AREVT,
    .end = TI81XX_DMA_MCASP1_AREVT,
    .flags = IORESOURCE_DMA,
    },
    };

    static struct resource ti81xx_mcasp2_resource[] = {
    {
    .name = "mcasp2",
    .start = TI81XX_ASP2_BASE,
    .end = TI81XX_ASP2_BASE + (SZ_1K * 12) - 1,
    .flags = IORESOURCE_MEM,
    },
    /* TX event */
    {
    .start = TI81XX_DMA_MCASP2_AXEVT,
    .end = TI81XX_DMA_MCASP2_AXEVT,
    .flags = IORESOURCE_DMA,
    },
    /* RX event */
    {
    .start = TI81XX_DMA_MCASP2_AREVT,
    .end = TI81XX_DMA_MCASP2_AREVT,
    .flags = IORESOURCE_DMA,
    },
    };

  • 你好,

    PINMUX有正确配置么?

  • 你好,

         我只使用了mcasp0当中的MCA[0]_ACLKR、MCA[0]_AHCLKR、MCA[0]_AFSR、MCA[0]_AXR[0]这几个管脚,从芯片手册当中看这几个管脚没有被复用,所以我没有配置PINMUX

  • 你好,

    您能读取相关PINCTRLx确认一下么?最好也能读取默认驱动支持的Mcasp2看看上下拉配置是否配置一致。

  • 你好,

         mcasp2上下拉配置指的是?

  • 你好,

    你能否参考下面的讨论? .rxnumevt = 0,而不是1吧?你现在mcasp0的模式是slave?

    http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/717/p/219756/774326

  • 你好,

         我现在mcasp0模式是slave的。因为我现在在mcasp0上是接收数据,所以 .rxnumevt 应该要等于1的( .rxnumevt = 1

  • 我也曾遇到类似的问题。我也是将音频编码芯片回到McASP0口,只使用MCA[0]_AHCLKR, MCA[0]_ACLKR, MCA[0]_AFSR, MCA[0]_AXR[0],这几个管脚配置为音频接收方式。

    使用arecord 工具录音如下:

    arecord -D plughw:0,1 -d 20 -c 2 -t wav -r 16000 -f "Signed 16 bit Little Endian" /mnt/ti8168/test.wav
    Recording WAVE '/mnt/ti8168/test.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Stereo
    arecord: pcm_read:1801: read error: Input/output error

    内核报错如下:

    capture write error (DMA or IRQ trouble?)

    这很可能是McASP没有接收到管脚的数据,所以不同有产生中断。

    通过修改davinci-mcasp.c 代码读取 PDSET寄存器 确认对应管脚确实有变化的数据。

    printk("mcasp: PDSET=0x%08x\n", mcasp_get_reg(dev->base + DAVINCI_MCASP_PDSET_REG));

    但发现RXSTAT 寄存器的 RSTAFM和RDATA都没有被置位,这很可能是前端时钟有问题。

    看了相关资料发现如果McASP配置为收发同步时钟模式的话,ACLKR的时钟会被屏蔽掉而直接使用ACLKX作为它的时钟。(相关配置信息在ACLKXCTL中的ASYNC这个配置位)如果McASP接口仅仅配置为接收且未使能发送时钟ACLKX,则应该将时钟配置为异步方式,即将ASYSC=1。

    对davinci-mcasp.c 修改如下:

    static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
    unsigned int fmt)
    {
    struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
    void __iomem *base = dev->base;

    printk("mcasp: %s...\n", __FUNCTION__);
    printk("%s: %d, fmt=0x%x\n", cpu_dai->name, cpu_dai->id, fmt);
    switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
    case SND_SOC_DAIFMT_CBS_CFS:
    /* codec is clock and frame slave */
    mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
    mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);

    //mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
    mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);     // ACLKR使用外部时钟
    //mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
    mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);          // AFSR 使用外部时钟

    mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));
    break;

    。。。

    }

    static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
    {
    int i, active_slots;
    u32 mask = 0;

    printk("mcasp: %s...\n", __FUNCTION__);
    active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
    for (i = 0; i < active_slots; i++)
    mask |= (1 << i);

    //mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
    mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);   // 将ASYNC=1

    。。。

    }