TI dm365 ALSA audio question, configutation McBSP to I2S master mode, why the McBSP cannot produces EDMA events ?
1. Running environment
Hardware: TI tms320dm365
Software: Linux kernel 2.6.32.17
Audio framework: ALSA
Record data flow: Microphone --> (Echo cancel chip)ZL38012 --> McBSP I2S --> ALSA framework.
Playback data flow: ALSA framework --> McBSP I2S --> (Echo cancel chip) --> Speaker。
Remark:
(1) Configuration McBSP to I2S master mode, use McBSP internal clock(SCLKME=0, CLKSM=1). MCBSP_CLKX pin can output clock signal.
(2) (Echo cancel chip) ZL38012 was config to I2S slave mode, and it has ADC/DAC fuunctions.
(3) Register a dummy codec device (dummy-CQ93VC) that base on Voice Codec(CQ93VC) ALSA framework.
2. Modification source code
2.1 config pins to McBSP
/* file: arch/arm/mach-davinci/board-amico-i.c */
static struct snd_platform_data dm365_dingo_snd_data[] = {
{
},
{
.asp_chan_q = EVENTQ_3,
.ram_chan_q = EVENTQ_2,
.i2s_accurate_sck = 1,
.clk_input_pin = MCBSP_CLKS,
},
};
static __init void amico_init(void)
{
/* ... */
dm365_init_asp(&dm365_dingo_snd_data[1]); /* wenxy add */
}
/* file: arch/arm/mach-davinci/dm365.c */
void __init dm365_init_asp(struct snd_platform_data *pdata)
{
pr_debug("Audio: into %s, %s", __FILE__, __FUNCTION__); /* wenxy debug */
davinci_cfg_reg(DM365_MCBSP0_BDX);
davinci_cfg_reg(DM365_MCBSP0_X);
davinci_cfg_reg(DM365_MCBSP0_BFSX);
davinci_cfg_reg(DM365_MCBSP0_BDR);
if (pdata->clk_input_pin == MCBSP_CLKR)
{
pr_debug("Audio: into %s, %s, MCBSP_CLKR", __FILE__, __FUNCTION__); /* wenxy debug */
davinci_cfg_reg(DM365_MCBSP0_R);
}
else if (pdata->clk_input_pin == MCBSP_CLKS)
{
pr_debug("Audio: into %s, %s, MCBSP_CLKS", __FILE__, __FUNCTION__); /* wenxy debug */
davinci_cfg_reg(DM365_MCBSP0_CLKS);
}
davinci_cfg_reg(DM365_MCBSP0_BFSR);
davinci_cfg_reg(DM365_EVT2_ASP_TX);
davinci_cfg_reg(DM365_EVT3_ASP_RX);
dm365_asp_device.dev.platform_data = pdata;
platform_device_register(&dm365_asp_device);
}
2.2 Register a dummy codec device (dummy-CQ93VC) that base on Voice Codec(CQ93VC) ALSA framework.
Linux kernel boot log as blow:
asoc: dummy-CQ93VC <-> davinci-vcif mapping ok
ALSA device list:
#0: DaVinci AMICO_I VOICE (dummy-CQ93VC)
/* file: sound/soc/davinci/davinci-amico-i.c */
/* amico-i digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link dm365_amico_i_dai[] = {
{
.name = "Voice Codec - CQ93VC",
.stream_name = "CQ93",
.cpu_dai = &davinci_vcif_dai,
/*.codec_dai = &cq93vc_dai,*/
.codec_dai = &davinci_i2s_dai, /* wenxy modify */
.init = amico_i_cq93_init,
.ops = &amico_i_ops_cq93,
},
};
/* McBSP DMA events pins, config it to McBSP: REVT and McBSP: XEVT */
static int amico_i_hw_params_cq93(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
pr_debug("Audio: into %s, %s", __FILE__, __FUNCTION__); /* wenxy debug */
struct davinci_soc_info *soc_info = &davinci_soc_info;
void __iomem *base = soc_info->pinmux_base;
/*
* Even if this settings are done in
* dm365.c, it assures that they are
* correct.
*/
#if 0
/* wenxy comment */
davinci_cfg_reg(DM365_EVT2_VC_TX);
davinci_cfg_reg(DM365_EVT3_VC_RX);
#else
davinci_cfg_reg(DM365_EVT2_ASP_TX);
davinci_cfg_reg(DM365_EVT3_ASP_RX);
#endif
pr_debug("Audio: into %s, %s, EDMA_EVTMUX(0x%x) = 0x%x",
__FILE__, __FUNCTION__, io_v2p(base + 0x1c), readl(base + 0x1c)); /* wenxy debug */
return 0;
}
2.3 McBSP driver, modify some code for config McBSP to I2S master mode.
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-i2s.h
3. Questions
3.1 Quest 1: The McBSP cannot produces EDMA events when run aplay command to test playback, why and how modify ?
/* file: sound/soc/davinci/davinci-vcif.c */
static void davinci_vcif_start(struct snd_pcm_substream *substream)
{
if (dm365_mcbsp_vaddr != NULL)
{
pr_debug("Audio McBSP: into %s, %s, dm365_mcbsp_vaddr(paddr: 0x%x]) = 0x%x",
__FILE__, __FUNCTION__, io_v2p(dm365_mcbsp_vaddr), dm365_mcbsp_vaddr); /* wenxy debug */
/* Serial Port Control Register (SPCR) */
spcr = readl(dm365_mcbsp_vaddr + 0x08);
pr_debug("Audio: into %s, %s, read spcr = 0x%x", __FILE__, __FUNCTION__, spcr); /* wenxy debug */
spcr |= 0x1 << 15; /* DLB = 1 */
spcr |= 0x1 << 22; /* GRST = 1 */
spcr |= 0x1 << 23; /* FRST = 1 */
spcr |= 0x1 << 25; /* FREE = 1 */
writel(spcr, dm365_mcbsp_vaddr + 0x08);
/* XRST = 0 */
//spcr &= ~(0x1 << 16);
//writel(spcr, dm365_mcbsp_vaddr + 0x08);
/* XRDY = 0 */
//spcr &= ~(0x1 << 17);
//writel(spcr, dm365_mcbsp_vaddr + 0x08);
/* XRST = 1 */
spcr |= 0x1 << 16;
writel(spcr, dm365_mcbsp_vaddr + 0x08);
/* XRDY = 1 */
spcr |= 0x1 << 17;
//writel(spcr, dm365_mcbsp_vaddr + 0x08);
pr_debug("Audio: into %s, %s, write spcr = 0x%x", __FILE__, __FUNCTION__, spcr); /* wenxy debug */
}
}
static void davinci_vcif_stop(struct snd_pcm_substream *substream)
{
if (dm365_mcbsp_vaddr != NULL)
{
/* Serial Port Control Register (SPCR) */
spcr = readl(dm365_mcbsp_vaddr + 0x08);
pr_debug("Audio: into %s, %s, read spcr = 0x%x", __FILE__, __FUNCTION__, spcr); /* wenxy debug */
/* XRST = 0 */
spcr &= ~(0x1 << 16);
writel(spcr, dm365_mcbsp_vaddr + 0x08);
/* XRDY = 0 */
spcr &= ~(0x1 << 17);
writel(spcr, dm365_mcbsp_vaddr + 0x08);
pr_debug("Audio: into %s, %s, write spcr = 0x%x", __FILE__, __FUNCTION__, spcr); /* wenxy debug */
}
}
3.2 Quest 2: Register a dummy codec device (dummy-CQ93VC) that base on Voice Codec(CQ93VC) ALSA framework, is it right solution ?
Thanks for any help.
BTW, my Email: xiaoyong.wen@legrand.com.cn