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.

dm385 mcasp异步模式环出播放不正常的问题

Other Parts Discussed in Thread: PCM1808, PCM1754

1、时钟配置

aux_osc引脚输入24.576M时钟,并提供mcasp模块的内部时钟auxclk(24.576M),同时AHCLKX_OUT(24.576M)输出,作为A/D芯片(PCM1808)、D/A芯片(PCM1754)的系统时钟;采样率为48K,bit时钟为3.072M

2、模式

发送与接收是异步模式

3、部分硬件图

4、问题

1)环出demo程序中,每次采集1152个样点的数据存在buffer中,然后将此buffer中的数据播放,此过程循环往复,通过音箱播放时候,没有声音出来;该环出demo程序在其他平台(如dm368平台)测试Ok;

示波器量的信号状态为:程序运行起来后,发送及接收bit时钟均由24.576M变为3.072M,但很快,发送的bit时钟又变为24.576M,而接收的bit时钟(3.072M)及采样时钟(48K)均正常

2)换一种方式播放,通过arecord程序采集数据并保存在文件中,然后通过aplay程序播放该文件,音箱播放声音正常

./arecord -Dhw:0,0 -f S32_LE -r 48000 -c 2 voice &
sleep 2
./aplay -Dhw:0,1 -f S32_LE -r 48000 -c 2 voice &

  • Sang Weisong,

    DM385的mcasp有fifo,但是DM36x没有。

    不知道你的自己的demo是否有使用edma?建议你对比默认aplay/arecord时候的mcasp的寄存器配置,和你demo时候的寄存器配置,

  • Chris,

    1、demo程序很简单,现附上部分源码:

    #define WORD_LEN 8 #define READ_SAMPLE 1152//2560//5120 long long device_capture( snd_pcm_t *c, snd_pcm_t *p, int rate, int secs, int port, int idx) { int frames = rate/25; int channels = port*2; char *data = buff0; long long total_len = 0; long long wave_buf_len = rate*WORD_LEN*secs; int frame_len = 2*channels; int r_frames = 0; int w_frames = 0; int err, i = 0,j=0; int try = 0; audio_frame_l_t *lframe; audio_frame_s_t *sframe; FILE *fpcapture=NULL; int count = 0; signed char *singlebuf=(signed char*)malloc(BS); signed char *singlebuf1=(signed char*)malloc(BS); printf("audio_frame_l_t=%d, audio_frame_s_t=%d\n", sizeof(audio_frame_l_t), sizeof(audio_frame_s_t)); fpcapture = fopen("/home/buffer/48k","wb+"); if(fpcapture == NULL){ printf("fopen file failed\n"); return -1; } while ( total_len < wave_buf_len ){ struct timeval birthsec,birthsec1; gettimeofday(&birthsec, NULL); try_again: //printf("1-------------\n"); memset(buff0,0,sizeof(buff0)); memset(singlebuf,0,sizeof(singlebuf)); memset(singlebuf1,0,sizeof(singlebuf1)); r_frames = snd_pcm_readi(c, (void*)buff0, READ_SAMPLE); printf(" snd_pcm_readi (%d) frames=%d, birthsec.tv_sec(%lu.%06lu)\n", i, r_frames, birthsec.tv_sec, birthsec.tv_usec); if(r_frames > 0) { total_len += r_frames * 8;//frame_len; #if defined(SAMPLE_48K)||defined(SAMPLE_8K)||defined(SAMPLE_16K) for(j=0;j<r_frames;j++){ #ifdef SAVE_FILE memcpy(singlebuf+j*2,(void*)(buff0+j*8+2),2); #endif #ifdef LOOP memcpy(singlebuf1+j*8,buff0+j*8,4); memcpy(singlebuf1+j*8+4,buff0+j*8,4); #endif } #endif #ifdef SAMPLE_64K for(j=0;j<r_frames;j++){ #ifdef SAVE_FILE memcpy(singlebuf+j*2,(void*)(buff0+j*8+1),2); #endif #ifdef LOOP memcpy(singlebuf1+j*8,buff0+j*8,4); memcpy(singlebuf1+j*8+4,buff0+j*8,4); #endif } #endif #ifdef SAVE_FILE count = fwrite(singlebuf, 1, r_frames*2, fpcapture); //printf("fwrite file %d bytes count %d==========>\n",r_frames*WORD_LEN,count); if(count != 2*r_frames){ printf("fwrite file failed\n"); fclose(fpcapture); free(singlebuf); free(singlebuf1); singlebuf = NULL; singlebuf1 = NULL; } #endif #ifdef LOOP try = 0; do{ usleep(100); printf(" snd_pcm_writei (%d) frames=%d\n", i, r_frames); if((w_frames = snd_pcm_writei(p, singlebuf1, r_frames) < 0)) { printf("2-------------\n"); err = w_frames; printf("w_frames %d========\n",err); if(err == -EPIPE) { try++; snd_pcm_prepare (p); fprintf (stderr, "snd_pcm_writei(%d) error, and try(%d)\n", i, try); } else { try = 0; } } else { printf("3-------------\n"); try = 0; } } while(try); #endif } else { printf("4-------------\n"); err = r_frames; if(err == -EPIPE) { snd_pcm_prepare (c); fprintf (stderr, "snd_pcm_readi error(%s)\n", snd_strerror(err)); goto try_again; } break; } i++; usleep(1000); } if(fpcapture != NULL) fclose(fpcapture); if(singlebuf != NULL){ free(singlebuf); singlebuf = NULL; } if(singlebuf1 != NULL){ free(singlebuf1); singlebuf1 = NULL; } return total_len; } int init_snd_pcm_hw_params(snd_pcm_t *handle, snd_pcm_hw_params_t *hw_params, int channels, int rate, int period_frames) { int err,dir,val; if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); return -1; } if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); return -2; } if ((err = snd_pcm_hw_params_set_format (handle, hw_params, SND_PCM_FORMAT_S32_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); return -3; } if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &rate, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); return -4; } printf("snd_pcm_hw_params_set_rate_near rate=%d\n", rate); #if 1 if ((err = snd_pcm_hw_params_set_period_size_near (handle, hw_params, &period_frames, 0)) < 0) { fprintf (stderr, "cannot set sample period_size (%s)\n", snd_strerror (err)); return -6; } printf("snd_pcm_hw_params_set_period_frames_near frames=%d\n", period_frames); #endif if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); return -5; } #if 1 if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); return -6; } #endif snd_pcm_hw_params_get_channels(hw_params, &val); printf("AUDIO : channels = %d\n", val); snd_pcm_hw_params_get_period_size(hw_params, &period_frames, &dir); snd_pcm_hw_params_get_period_time(hw_params, &val, &dir); printf("AUDIO : period size = %d frames, dir = %d\n", (int)period_frames, dir); printf("AUDIO : period time = %d us, dir = %d\n", val, dir); snd_pcm_hw_params_get_buffer_size(hw_params, &val); snd_pcm_hw_params_get_buffer_time(hw_params, &val, &dir); printf("AUDIO : buffer size = %d frames, dir = %d\n", val, dir); printf("AUDIO : buffer time = %d us, dir = %d\n", val, dir); snd_pcm_hw_params_get_rate(hw_params, &val, 0); printf("AUDIO : rate = %d \n", val); return 0; } //#define FRAME_SIZE 1240//256 #define FRAME_SIZE 5120//256 int main(int argc, char *argv[]) { snd_pcm_sframes_t frames; snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; unsigned int channel = 2; //2 unsigned int c_rate = 48000; int loop_secs = 20; //char pcm_player[32] = "plughw:0,1"; char pcm_player[32] = "hw:0,1"; snd_pcm_t *player_handle = NULL; //char pcm_capture[32] = "plughw:0,3"; //char pcm_capture[32] = "plughw:0";//"default"; char pcm_capture[32] = "hw:0,0";//"default"; snd_pcm_t *capture_handle = NULL; snd_pcm_hw_params_t *hw_params0 = NULL, *hw_params1 = NULL; char file_name[50] = "alarm_1_16K.wav"; int i, ret, err; int port = 1, channels = 2, c_idx = 0; int ch; int buffer_time=0; while ((ch = getopt(argc, argv, "c:r:j:p:l:")) != -1) { switch(ch) { case 'c': snprintf(pcm_capture, sizeof(pcm_capture), "plughw:%s", optarg); break; case 'r': c_rate = atoi(optarg); break; case 'p': snprintf(pcm_player, sizeof(pcm_player), "plughw:%s", optarg); break; case 'j': c_idx = atoi(optarg); break; case 'l': loop_secs = atoi(optarg); break; case '?': printf("Unknown option: %c\n",(char)optopt); break; } } buff0 = (signed char *)malloc(BS); buff1 = (signed char *)malloc(BS); if(buff0 == NULL || buff1 == NULL) { goto out_err; } if ((err = snd_pcm_open (&capture_handle, pcm_capture, SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf (stderr, "cannot open audio capture device %s (%s)\n", pcm_capture, snd_strerror(err)); goto out_err; } #ifdef LOOP if ((err = snd_pcm_open (&player_handle, pcm_player, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "cannot open audio playback device %s (%s)\n", pcm_player, snd_strerror(err)); goto out_err; } fprintf (stdout, "Step1: Open audio capture device[%s] and play device[%s] Success\n", pcm_capture, pcm_player); #endif snd_pcm_hw_params_malloc(&hw_params0); snd_pcm_hw_params_malloc(&hw_params1); if(strcmp(pcm_capture, "plughw:0,3") == 0) { port = 4; channels = 8; } else { port = 1; channels =2; } //printf("port =%d, channels =%d\n", port, channels); ret = init_snd_pcm_hw_params(capture_handle, hw_params0, channels, c_rate, FRAME_SIZE); //printf("ret1 = %d, c_rate = %d\n", ret, c_rate); sleep(1); #ifdef LOOP ret = init_snd_pcm_hw_params(player_handle, hw_params1, channels, c_rate, FRAME_SIZE); snd_pcm_hw_params_get_rate(hw_params1, &c_rate, 0); printf("ret2 = %d, c_rate set = %d\n", ret, c_rate); #endif snd_pcm_hw_params_get_buffer_time_max(hw_params0, &buffer_time, 0); //printf("buffer_time is %d========>\n",buffer_time); #ifdef LOOP if ((err = snd_pcm_prepare (capture_handle)) < 0 || (err = snd_pcm_prepare (player_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); goto out_err; } #endif #ifdef SAVE_FILE if ((err = snd_pcm_prepare (capture_handle)) < 0 ) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); goto out_err; } #endif sleep(1); //fprintf (stdout, "Start Capture(%s) => Player(%s) loop_secs=%d\n", pcm_capture, pcm_player, loop_secs); //device_capture_loop_2_play(capture_handle, player_handle, c_rate, loop_secs, port, c_idx); device_capture(capture_handle, player_handle, c_rate, loop_secs, port, c_idx); #ifdef LOOP snd_pcm_drain(player_handle); snd_pcm_close(player_handle); #endif snd_pcm_drain(capture_handle); snd_pcm_close(capture_handle); //fprintf (stdout, "End OK\n"); out_err: if(buff0) free(buff0); if(buff1) free(buff1); if(hw_params0) snd_pcm_hw_params_free(hw_params0); if(hw_params1) snd_pcm_hw_params_free(hw_params1); return 0; }
    2、我对比了下寄存器,状态寄存器、全局控制寄存器在发送出错的时候两者不一致,但是还是看不出到底哪里出了问题?
    1)运行arecord/aplay时候mcasp寄存器状态:
     
    2)运行demo程序出错前后寄存器状态:
     
    3)385mcasp寄存器列表:
     
    2、内核配置
    static u8 dm385_iis_serializer_direction[] = {
    	TX_MODE,	INACTIVE_MODE,	INACTIVE_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,
    };
    
    static struct snd_platform_data dm385_evm_snd_data = {
    	.tx_dma_offset	= 0x46000000,//0x46400000,
    	.rx_dma_offset	= 0x46000000,//0x46400000,
    	.op_mode	= DAVINCI_MCASP_IIS_MODE,
    	.num_serializer = ARRAY_SIZE(dm385_iis_serializer_direction),
    	.tdm_slots	= 2,
    	.serial_dir	= dm385_iis_serializer_direction,
    	.asp_chan_q	= EVENTQ_2,
    	.version	= MCASP_VERSION_2,
    	.txnumevt	= 2,
    	.rxnumevt	= 2,
    };
    
    static struct resource dm385_mcasp_resource[] = {
    	{
    		.name = "mcasp",
    		.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 platform_device ti81xx_mcasp_device = {
    	.name = "davinci-mcasp",
    };
    
    static struct platform_device pcm1808_device = {
    	.name = "pcm1808-codec",
    	.id = -1,
    };
    
    static struct platform_device pcm1754_device = {
    	.name = "pcm1754-codec",
    	.id = -1,
    };
    
    void __init ti81xx_register_mcasp(int id, struct snd_platform_data *pdata)
    {
    	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() || machine_is_dmipc385hdsdi()) {
    		ti81xx_mcasp_device.id = 0;
    		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);
    	omap_mux_init_signal("xref_clk0.mcasp0_ahclkx", 0);
    	ti81xx_mcasp_device.dev.platform_data = pdata;
    	platform_device_register(&ti81xx_mcasp_device);
    	//added for audio ADC/DAC device
    	omap_mux_init_signal("mmc2_dat7.gpio1_19", 0);
    	omap_mux_init_signal("mmc0_cmd.gpio0_2", 0);
    	platform_device_register(&pcm1808_device);
    	platform_device_register(&pcm1754_device);
    }
    
    
    davinci_mcasp.c文件部分代码
    static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
    {
    	int i, active_slots;
    	u32 mask = 0;
    
    	active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
    	for (i = 0; i < active_slots; i++)
    		mask |= (1 << i);
    
    #if 0
    	mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
    	//added for 48K, 64bit clkdiv value in SYNC mode
    	mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXDIV(7));
    	//mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRDIV(7));
    #else
    	mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
    	//added for 48K, 64bit clkdiv value in ASYNC mode
    	//mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRDIV(7));
    	//mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXDIV(7));
    	//printk("%s %x=============>>>>>>>>>>>>>>\n",__func__,__raw_readl(dev->base + DAVINCI_MCASP_ACLKRCTL_REG));
    #endif
    
    	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
    		/* bit stream is MSB first  with no delay */
    		/* DSP_B mode */
    		mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXDIV(7));	
    		mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
    				AHCLKXE);
    		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
    		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
    
    		if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
    			mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
    					FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
    		else
    			printk(KERN_ERR "playback tdm slot %d not supported\n",
    				dev->tdm_slots);
    
    		//mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
    		mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1), FSXDLY(0x3));
    		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
    	} else {
    		/* bit stream is MSB first with no delay */
    		/* DSP_B mode */
    		if(mcasp_get_reg(dev->base + DAVINCI_MCASP_ACLKXCTL_REG)&BIT(6)){	//ASYNC mode
    			mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRDIV(7));
    			mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,	AHCLKRE);
    			printk("%s %d -------->\n",__func__,__LINE__);
    		}else{									//SYNC mode
    			mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXDIV(7));
    			mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,	AHCLKRE);
    			mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,	AHCLKXE);
    			mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
    			mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
    			printk("%s %d -------->\n",__func__,__LINE__);
    
    			if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
    				mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
    						FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
    			else
    				printk(KERN_ERR "playback tdm slot %d not supported\n",
    					dev->tdm_slots);
    		}
    	
    		mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
    		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
    
    		if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
    			mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
    					FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
    		else
    			printk(KERN_ERR "capture tdm slot %d not supported\n",
    				dev->tdm_slots);
    
    		if(mcasp_get_reg(dev->base + DAVINCI_MCASP_ACLKXCTL_REG)&BIT(6)){	//ASYNC mode
    			//added by andy 20160825 for 1 bit delay
    			mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1), FSRDLY(0x3));
    			//mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
    			mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
    		}else{
    			mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1), FSXDLY(0x3));
    			mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
    		}
    	}
    }
    
    static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
    					struct snd_pcm_hw_params *params,
    					struct snd_soc_dai *cpu_dai)
    {
    	struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
    	struct davinci_pcm_dma_params *dma_params =
    					&dev->dma_params[substream->stream];
    	int word_length;
    	u8 fifo_level;
    	void __iomem *base = dev->base;
    
    	davinci_hw_common_param(dev, substream->stream);
    	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    		fifo_level = dev->txnumevt;
    	else
    		fifo_level = dev->rxnumevt;
    
    	if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
    		davinci_hw_dit_param(dev);
    	else
    		davinci_hw_param(dev, substream->stream);
    
    	switch (params_format(params)) {
    	case SNDRV_PCM_FORMAT_S8:
    		dma_params->data_type = 1;
    		word_length = DAVINCI_AUDIO_WORD_8;
    		break;
    
    	case SNDRV_PCM_FORMAT_S16_LE:
    		dma_params->data_type = 2;
    		word_length = DAVINCI_AUDIO_WORD_16;
    		break;
    
    	case SNDRV_PCM_FORMAT_S24_LE:
    		dma_params->data_type = 4;
    		word_length = DAVINCI_AUDIO_WORD_24;
    		break;
    
    	case SNDRV_PCM_FORMAT_S32_LE:
    		dma_params->data_type = 4;
    		word_length = DAVINCI_AUDIO_WORD_32;
    		break;
    
    	default:
    		printk(KERN_WARNING "davinci-mcasp: unsupported PCM format");
    		return -EINVAL;
    	}
    
    	if (dev->version == MCASP_VERSION_2 && !fifo_level)
    		dma_params->acnt = 4;
    	else
    		dma_params->acnt = dma_params->data_type;
    
    	dma_params->fifo_level = fifo_level;
    	//davinci_config_channel_size(dev, word_length);
    	davinci_config_channel_size(dev, word_length, substream->stream);
    	printk("%s %d=========>\n",__func__,__LINE__);
    
    #if 0
    	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
    		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
    		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
    		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));
    	}else{
    		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
    		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
    		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 29));
    	}
    #endif
    	return 0;
    }
    
    static void mcasp_start_rx(struct davinci_audio_dev *dev)
    {
    	//added by andy for sync mode start
    	if(!(mcasp_get_reg(dev->base + DAVINCI_MCASP_ACLKXCTL_REG)&BIT(6))){	//SYNC mode
    		
    		//added by andy for sync mode end
    
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
    		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
    
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
    		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
    
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
    
    #if 1
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
    		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
    
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
    		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
    #endif
    	}//added by andy for sync mode end
    	else{
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
    		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
    
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
    		mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
    
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
    		mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
    	}
    }
    
    static void mcasp_start_tx(struct davinci_audio_dev *dev)
    {
    	u8 offset = 0, i;
    	u32 cnt;
    
    	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
    	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
    	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
    	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
    
    	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
    	mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
    	mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
    	for (i = 0; i < dev->num_serializer; i++) {
    		if (dev->serial_dir[i] == TX_MODE) {
    			offset = i;
    			break;
    		}
    	}
    
    	/* wait for TX ready */
    	cnt = 0;
    	while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) &
    		 TXSTATE) && (cnt < 100000)){
    		cnt++;
    	}
    }

    不知道驱动的配置是不是有什么问题呢?还有一点,如果arecord、aplay程序同时运行,音箱也一直没有声音,接收bit时钟、采样时钟也都正常,发送时钟不正常,跟环出demo问题一样。

  • Chirs,

    不好意思,demo代码编辑的有问题。。。。

    #define WORD_LEN	8
    #define	READ_SAMPLE	1152//2560//5120
    
    long long device_capture( snd_pcm_t *c, snd_pcm_t *p, int rate, int secs, int port, int idx)
    { 
    	int frames = rate/25;
    	int channels = port*2;
    	char *data = buff0;
    	long long total_len = 0;
    	long long wave_buf_len = rate*WORD_LEN*secs;
    	int frame_len = 2*channels;
    	int r_frames = 0;
    	int w_frames = 0;
    	int err, i = 0,j=0;
    	int try = 0;
    	audio_frame_l_t *lframe;
    	audio_frame_s_t *sframe;
    	FILE *fpcapture=NULL;
    	int count = 0;
    
    	signed char *singlebuf=(signed char*)malloc(BS);
    	signed char *singlebuf1=(signed char*)malloc(BS);
    
    	printf("audio_frame_l_t=%d, audio_frame_s_t=%d\n", sizeof(audio_frame_l_t), sizeof(audio_frame_s_t));
    
    	fpcapture = fopen("/home/buffer/48k","wb+");
    	if(fpcapture == NULL){
    		printf("fopen file failed\n");
    		return -1;
    	}
    
    	while ( total_len < wave_buf_len ){
    		struct timeval birthsec,birthsec1;
    
    		gettimeofday(&birthsec, NULL);
    
    try_again:
    		//printf("1-------------\n");
    		memset(buff0,0,sizeof(buff0));
    		memset(singlebuf,0,sizeof(singlebuf));
    		memset(singlebuf1,0,sizeof(singlebuf1));
    		r_frames = snd_pcm_readi(c, (void*)buff0, READ_SAMPLE);
    
    		printf("  snd_pcm_readi (%d) frames=%d, birthsec.tv_sec(%lu.%06lu)\n", i, r_frames, birthsec.tv_sec, birthsec.tv_usec);
    		if(r_frames > 0) {
    		    total_len += r_frames * 8;//frame_len;
    
    #if  defined(SAMPLE_48K)||defined(SAMPLE_8K)||defined(SAMPLE_16K)
    			for(j=0;j<r_frames;j++){
    #ifdef SAVE_FILE
    				memcpy(singlebuf+j*2,(void*)(buff0+j*8+2),2);
    #endif
    #ifdef LOOP
    				memcpy(singlebuf1+j*8,buff0+j*8,4);
    				memcpy(singlebuf1+j*8+4,buff0+j*8,4);
    #endif
    			    }
    #endif
    #ifdef SAMPLE_64K
    			for(j=0;j<r_frames;j++){
    #ifdef SAVE_FILE
    				memcpy(singlebuf+j*2,(void*)(buff0+j*8+1),2);
    #endif
    #ifdef LOOP
    				memcpy(singlebuf1+j*8,buff0+j*8,4);
    				memcpy(singlebuf1+j*8+4,buff0+j*8,4);
    #endif
    			    }
    #endif
    #ifdef SAVE_FILE
    		    count = fwrite(singlebuf, 1, r_frames*2, fpcapture);
    		    //printf("fwrite file %d bytes count %d==========>\n",r_frames*WORD_LEN,count);
    		    if(count != 2*r_frames){
    		    	printf("fwrite file failed\n");
    			fclose(fpcapture);
    			free(singlebuf);
    			free(singlebuf1);
    			singlebuf = NULL;
    			singlebuf1 = NULL;
    		    }
    #endif
    #ifdef LOOP
    		try = 0;
    		do{
    			usleep(100);
    			printf("  snd_pcm_writei (%d) frames=%d\n", i, r_frames);
    			if((w_frames = snd_pcm_writei(p, singlebuf1, r_frames) < 0))
    			//if((w_frames = snd_pcm_writei(p, buff0, r_frames) < 0))
    			{
    				printf("2-------------\n");
    			    err = w_frames;
    			    printf("w_frames %d========\n",err);
    			    if(err == -EPIPE) {
    				 try++;
    				 snd_pcm_prepare (p);  
    				 fprintf (stderr, "snd_pcm_writei(%d) error, and try(%d)\n", i, try);
    			    }
    			    else {
    				 try = 0;
    			    }
    			 }
    			 else {
    				printf("3-------------\n");
    			    try = 0;
    			 }
    		     } while(try);
    #endif
    		} 
    		else {
    			printf("4-------------\n");
    		    err = r_frames;
    		    if(err == -EPIPE) {
    			 snd_pcm_prepare (c);
    			 fprintf (stderr, "snd_pcm_readi error(%s)\n", snd_strerror(err));
    			 goto try_again;
    		    }
    		    break;
    		}
    		i++;
    		usleep(1000); 
    	}
    	if(fpcapture != NULL)
    		fclose(fpcapture);
    	if(singlebuf != NULL){
    		free(singlebuf);
    		singlebuf = NULL;
    	}
    	if(singlebuf1 != NULL){
    		free(singlebuf1);
    		singlebuf1 = NULL;
    	}
    
    	return total_len;
    }
    
    
    int init_snd_pcm_hw_params(snd_pcm_t *handle, snd_pcm_hw_params_t *hw_params, int channels, int rate, int period_frames)
    {
            int err,dir,val;
    
            if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {  
               fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",  
                    snd_strerror (err));  
               return -1;  
           }  
      
            if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {  
                fprintf (stderr, "cannot set access type (%s)\n",  
                     snd_strerror (err));  
                return -2;  
            }  
    
            if ((err = snd_pcm_hw_params_set_format (handle, hw_params, SND_PCM_FORMAT_S32_LE)) < 0) {  
                fprintf (stderr, "cannot set sample format (%s)\n",  
                     snd_strerror (err));  
                return -3;  
            }  
     
            if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &rate, 0)) < 0) {  
                fprintf (stderr, "cannot set sample rate (%s)\n",  
                     snd_strerror (err));  
                return -4;  
            }
            printf("snd_pcm_hw_params_set_rate_near rate=%d\n", rate);
    
            #if 1
            if ((err = snd_pcm_hw_params_set_period_size_near (handle, hw_params, &period_frames, 0)) < 0) {
                fprintf (stderr, "cannot set sample period_size (%s)\n",
                     snd_strerror (err));
                return -6;
            }
            printf("snd_pcm_hw_params_set_period_frames_near frames=%d\n", period_frames);
            #endif
    
            if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, channels)) < 0) {  
                fprintf (stderr, "cannot set channel count (%s)\n",  
                     snd_strerror (err));  
                return -5;  
            }  
    
            #if 1
            if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) {  
                fprintf (stderr, "cannot set parameters (%s)\n",  
                     snd_strerror (err));  
               return -6;  
            }  
            #endif
    
    	snd_pcm_hw_params_get_channels(hw_params, &val);
    	printf("AUDIO : channels = %d\n", val);
    
    	snd_pcm_hw_params_get_period_size(hw_params, &period_frames, &dir);
    	snd_pcm_hw_params_get_period_time(hw_params, &val, &dir);
    	printf("AUDIO : period size = %d frames, dir = %d\n", (int)period_frames, dir);
    	printf("AUDIO : period time = %d us, dir = %d\n", val, dir);
    
    	snd_pcm_hw_params_get_buffer_size(hw_params, &val);
    	snd_pcm_hw_params_get_buffer_time(hw_params, &val, &dir);
    	printf("AUDIO : buffer size = %d frames, dir = %d\n", val, dir);
    	printf("AUDIO : buffer time = %d us, dir = %d\n", val, dir);
    
    	snd_pcm_hw_params_get_rate(hw_params, &val, 0); 
    	printf("AUDIO : rate = %d \n", val);
     
            return 0;
    }
    //#define	FRAME_SIZE	1240//256
    #define	FRAME_SIZE	5120//256
    
    int main(int argc, char *argv[]) 
    {
    	snd_pcm_sframes_t frames;      
    	snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE;
    	unsigned int channel = 2; //2 
    	unsigned int c_rate = 48000; 
            int loop_secs = 20;    
    
            //char pcm_player[32] = "plughw:0,1";
    	char pcm_player[32] = "hw:0,1";
            snd_pcm_t *player_handle = NULL;
            //char pcm_capture[32] = "plughw:0,3";
    	//char pcm_capture[32] = "plughw:0";//"default";
    	char pcm_capture[32] = "hw:0,0";//"default";
            snd_pcm_t *capture_handle = NULL;
            snd_pcm_hw_params_t *hw_params0 = NULL, *hw_params1 = NULL;
    	char file_name[50] = "alarm_1_16K.wav";
            int i, ret, err;
            int port = 1, channels = 2, c_idx = 0;
            int ch; 
    	int buffer_time=0;
    
            while ((ch = getopt(argc, argv, "c:r:j:p:l:")) != -1)
            {
               switch(ch) {
               case 'c':
                       snprintf(pcm_capture, sizeof(pcm_capture), "plughw:%s", optarg);
                       break;
               case 'r':
                       c_rate = atoi(optarg);
                       break;
               case 'p':
                       snprintf(pcm_player, sizeof(pcm_player), "plughw:%s", optarg);
                       break;
               case 'j':
                       c_idx = atoi(optarg);
                       break;
               case 'l':
                       loop_secs = atoi(optarg);
                       break;
               case '?':
                       printf("Unknown option: %c\n",(char)optopt);  
                       break;
               }
            }
    
    	buff0 = (signed char *)malloc(BS);
            buff1 = (signed char *)malloc(BS);
            if(buff0 == NULL || buff1 == NULL) 
            {
               goto out_err;
            }      
           
           if ((err = snd_pcm_open (&capture_handle, pcm_capture, SND_PCM_STREAM_CAPTURE, 0)) < 0) {  
               fprintf (stderr, "cannot open audio capture device %s (%s)\n", pcm_capture, snd_strerror(err));  
               goto out_err;  
           }  
        
    #ifdef LOOP
           if ((err = snd_pcm_open (&player_handle, pcm_player, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
               fprintf (stderr, "cannot open audio playback device %s (%s)\n", pcm_player, snd_strerror(err));
               goto out_err;
           } 
           fprintf (stdout, "Step1: Open audio capture device[%s] and play device[%s] Success\n", pcm_capture, pcm_player);
    #endif
    
           snd_pcm_hw_params_malloc(&hw_params0);
           snd_pcm_hw_params_malloc(&hw_params1);
          
           if(strcmp(pcm_capture, "plughw:0,3") == 0) {
                           port = 4;
                           channels = 8;
           }
           else {
                port = 1;
                channels =2;
           }
           
           //printf("port =%d, channels =%d\n", port, channels);          
           ret = init_snd_pcm_hw_params(capture_handle, hw_params0, channels, c_rate, FRAME_SIZE);
           //printf("ret1 = %d, c_rate = %d\n", ret, c_rate);
           sleep(1);
    #ifdef LOOP
           ret = init_snd_pcm_hw_params(player_handle, hw_params1, channels, c_rate, FRAME_SIZE);
           snd_pcm_hw_params_get_rate(hw_params1, &c_rate, 0); 
           printf("ret2 = %d, c_rate set = %d\n", ret, c_rate);    
    #endif
    
           snd_pcm_hw_params_get_buffer_time_max(hw_params0, &buffer_time, 0);
           //printf("buffer_time is %d========>\n",buffer_time);
     
    #ifdef LOOP
            if ((err = snd_pcm_prepare (capture_handle)) < 0 || (err = snd_pcm_prepare (player_handle)) < 0) {  
                fprintf (stderr, "cannot prepare audio interface for use (%s)\n",  
                     snd_strerror (err));  
                goto out_err;  
            } 
    #endif
    #ifdef SAVE_FILE
    	if ((err = snd_pcm_prepare (capture_handle)) < 0 ) {  
                fprintf (stderr, "cannot prepare audio interface for use (%s)\n",  
                     snd_strerror (err));  
                goto out_err;  
            } 
    #endif
    
           sleep(1); 
    
           //fprintf (stdout, "Start Capture(%s) => Player(%s) loop_secs=%d\n", pcm_capture, pcm_player, loop_secs);
    
           //device_capture_loop_2_play(capture_handle, player_handle, c_rate, loop_secs, port, c_idx);
           device_capture(capture_handle, player_handle, c_rate, loop_secs, port, c_idx);
    
    #ifdef LOOP
           snd_pcm_drain(player_handle);
           snd_pcm_close(player_handle); 
    #endif
           snd_pcm_drain(capture_handle);
           snd_pcm_close(capture_handle); 
    
           //fprintf (stdout, "End OK\n"); 
       
    out_err:
           if(buff0) free(buff0);
           if(buff1) free(buff1);
           if(hw_params0) 
                   snd_pcm_hw_params_free(hw_params0);
           if(hw_params1)
                   snd_pcm_hw_params_free(hw_params1);
     
           return 0;  
       }
  • 你好;

          你通过arecord 采集的 voice 文件,你后期到pc上面播放声音是正常的吗?

          环出不是你上面那样测试的。

  • ternence hsu,

    1、通过arecord采集的voice文件,由于采集的数据一帧是64bit,左右两个声道,所以在pc上是直接播放不了的;保存的voice文件,可以通过aplay直接通过音箱播放出来

    2、我这里的环出指的是从音频输入电路采集到的数据直接送到音频输出电路,然后接到音箱上播放。

  • 你好;

            你可以用 GoldWave 播放采集数据,32bit 立体声是可以播放的,确认一下采集数据也是正常的。

  • ternence hsu,

    我试过在pc上播放,方式是将采集到的一个声道的32bit数据低16bit数据丢弃,只保存高16bit,保存的文件在cooledit播放是没有问题的,音频输入信号是标准的正弦波,在cooledit软件上播放,是同样频率的正弦波,所以数据是OK的

  • 问题已解决,解决方法:

    davinci_mcasp.c文件中mcasp_start_tx函数在设置全局控制寄存器之前加ms级延时

    采集和播放异步、同步两种方式都验证OK。