⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wtaudioout.c

📁 MCF5249的音频驱动程序,可以实现PCM的实时播放和采集
💻 C
📖 第 1 页 / 共 2 页
字号:
     /* INTPUTCLK, PDOR3, SCLKINVERT*/     *mcf2Reg32p(MCFA_IIS1CONFIG) |=  0x00000800;     *mcf2Reg32p(MCFA_IIS1CONFIG) = MCFA_IIS_CLKINPUT | MCFA_IIS_TXSRC_PDOR3 |           	MCFA_IIS_16BIT | MCFA_IIS_MODE_IIS | MCFA_IIS_LRCK64BIT;// |MCFA_IIS_SCLKINV;     *mcf2Reg32p(MCFA_DATAINCTRL) = 0;}//*************************************************************/* *	Configure and start DMA engine. */void __inline__ WTAudio_tx_dmarun(void){#if DEBUG    printk("WTAudio_tx_dmarun(): dma=%d count=%d\n",	   AudioDev.tx_nDmaStart, AudioDev.tx_nDmaCount);#endif	    set_dma_mode(WTAUDIO_TXDMA, DMA_MODE_WRITE | DMA_MODE_LONG_BIT);    //set_dma_mode(WTAUDIO_TXDMA, DMA_MODE_WRITE);    set_dma_device_addr(WTAUDIO_TXDMA, (MCF_MBAR2 + MCFA_PDOR3));    set_dma_addr(WTAUDIO_TXDMA,(int) &WTAudio_buf[AudioDev.tx_nDmaStart*AudioDev.packsize]);    set_dma_count(WTAUDIO_TXDMA, AudioDev.tx_nDmaCount*AudioDev.packsize);    WTAudio_txdmaing = 1;    WTAudio_txbusy = 1;        KDEBUG("CTL 0[%x] 1[%x]\n",DMA0_CTL,DMA1_CTL);    KDEBUG("SA   0[%x] 1[%x]\n",DMA0_SA,DMA1_SA);    KDEBUG("DA  0[%x] 1[%x]\n",DMA0_DA,DMA1_DA);    KDEBUG("BC  0[%x] 1[%x]\n",DMA0_BC,DMA1_BC);        enable_dma(WTAUDIO_TXDMA);      }/* *	Start DMA'ing a new buffer of data if any available. */void WTAudio_tx_dmabuf(void){#if DEBUG    printk("WTAudio_tx_dmabuf()\n");#endif	KDEBUG("DMA        [%d]\n",WTAudio_txdmaing);    /* If already running then nothing to do... */    if (WTAudio_txdmaing)	return;		/* 设置这次DMA需要传送的包个数*/	    AudioDev.tx_nDmaCount = (AudioDev.tx_nBufT>= AudioDev.tx_nDmaStart) ?	(AudioDev.tx_nBufT-AudioDev.tx_nDmaStart) :(PACKCOUNT - AudioDev.tx_nDmaStart);    if (AudioDev.tx_nDmaCount > DMACOUNT)	AudioDev.tx_nDmaCount = DMACOUNT;    /* 调整nBufB指针 */ /*   AudioDev.tx_nBufB += AudioDev.tx_nDmaCount;    if (AudioDev.tx_nBufB >= PACKCOUNT)	AudioDev.tx_nBufB = 0;*/	printk("nDmaCount =%d\n",AudioDev.tx_nDmaCount);     if (AudioDev.tx_nDmaCount > 0){		WTAudio_tx_dmarun();    	}  else{			WTAudio_txbusy = 0;    } 			}/* *	Interrupt from DMA engine. */void WTAudio_tx_dmaisr(int irq, void *dev_id, struct pt_regs *regs){#if DEBUG    printk("WTAudio_tx_dmaisr(irq=%d)\n", irq);#endif    printk("t isr statue[%x]\n",DMA0_STATUE);     /* Clear DMA interrupt */	    disable_dma(WTAUDIO_TXDMA);    WTAudio_txdmaing = 0;    printk("statue[%x]\n",DMA0_STATUE);     /* 修改DMA读写头指示(以包为单位)*/    AudioDev.tx_nDmaStart += AudioDev.tx_nDmaCount;   if (AudioDev.tx_nDmaStart >= PACKCOUNT)AudioDev.tx_nDmaStart = 0;    AudioDev.tx_nDmaCount = 0;    /* Start new DMA buffer if we can */    WTAudio_tx_dmabuf();}/****************************************************************************/void WTAudio_txdrain(void){#ifdef DEBUG    printk("WTAudio_txdrain()\n");#endif	WTAudio_txbusy=0;	current->state = TASK_INTERRUPTIBLE;	schedule_timeout(1);	return;    while (!signal_pending(current)) {	if (WTAudio_txbusy == 0)	    break;    }}/****************************************************************************/int WTAudio_open(struct inode *inode, struct file *filp){#if DEBUG    printk("WTAudio_open()\n");#endif#ifdef MODULE	MOD_INC_USE_COUNT;#endif	if (WTAudio_isopen)		return (-EBUSY);	WTAudio_isopen = 1;    	WTAudio_txdmaing = 0;	    return (0);}int WTAudio_release(struct inode *inode, struct file *filp){#if DEBUG       	    printk("WTAudio_release()\n");#endif#ifdef MODULE       	    MOD_DEC_USE_COUNT;#endif       	    WTAudio_txdrain();	    disable_dma(WTAUDIO_TXDMA);	    WTAudio_txdmaing = 0;	   *mcf2Reg32p(MCFA_PDOR3) = 0;	    WTAudio_txbusy = 0;	    AudioDev.tx_nDmaStart= 0;	    AudioDev.tx_nDmaCount= 0;	 //   AudioDev.tx_nBufB= 0;	    AudioDev.tx_nBufT= 0;	    WTAudio_isopen = 0;    return (0);}/****************************************************************************/ssize_tWTAudio_write(struct file * filp, const char *buf, size_t count,		 loff_t * ppos){	unsigned int start,end,packcount,ret;#ifdef DEBUG    	printk("m5249_write(buf=%x,count=%d)\n", (int) buf, count);#endif	packcount = (count/AudioDev.packsize);    //计算当前用户写了多少包到缓冲区tryagain:          	start = AudioDev.tx_nDmaStart;        	end = AudioDev.tx_nBufT;			if((end+packcount)%PACKCOUNT == start){		KDEBUG("FULL\n");		if (signal_pending(current))	  	  return (-ERESTARTSYS);		set_current_state(TASK_INTERRUPTIBLE);		schedule_timeout(1);		goto tryagain;	  }    	end += packcount;	if(end>=PACKCOUNT) 		end=0;		AudioDev.tx_nBufT = end;			ret = end;	KDEBUG("T[%d] START[%d]\n ", AudioDev.tx_nBufT, AudioDev.tx_nDmaStart);    	//KDEBUG("DMA Method of write.\n");	    	WTAudio_tx_dmabuf();	return (ret);}int WTAudio_map(struct file *filp, struct vm_area_struct *vma){		KDEBUG("mmap()\n");	//if(offset >= _pa(high_memory) || (file->f_flags & O_SYNC))	//	vma->vm_flags |= VM_IO;	vma->vm_flags |= VM_RESERVED;	//if((WTAudio_buf == NULL) || remap_page_range(vma->vm_start,__pa(WTAudio_buf),BUFSIZE,PAGE_SHARED))	vma->vm_start = vma->vm_offset + AudioDev.mmstart;	//return -EAGAIN;		return 0;}int WTAudio_ioctl(struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg){	int err =0;	int ret = 0;	int val;	WTDevBufStatus BufStatus;	if(_IOC_DIR(cmd) & _IOC_READ)		err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));	else if (_IOC_DIR(cmd) & _IOC_WRITE)       	err =  !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));	    	if (err) return -EFAULT;			switch(cmd){	case IOCASTOP:		WTAudio_txdrain();		disable_dma(WTAUDIO_TXDMA);		*mcf2Reg32p(MCFA_PDOR3) = 0;		//AudioDev.tx_nBufB = 0;		AudioDev.tx_nBufT = 0;		AudioDev.tx_nDmaStart =0;		AudioDev.tx_nDmaCount =0;		KDEBUG("Stop!\n");		break;			case IOCASTART:		*mcf2Reg32p(MCFA_PDOR3) = 0;		WTAudio_tx_dmabuf();		KDEBUG("Start!\n");		break;			case IOCASPACKSIZE:		KDEBUG("Reset pack size\n");		ret = get_user(val, (int*)arg);		if(val == AudioDev.packsize){			//printk("k [%x %x]\n",AudioDev.rxmmstart,AudioDev.mmstart);			break;		}			WTAudio_txdrain();		disable_dma(WTAUDIO_TXDMA);		*mcf2Reg32p(MCFA_PDOR3) = 0;		//AudioDev.tx_nBufB = 0;		AudioDev.tx_nBufT = 0;		AudioDev.tx_nDmaStart =0;		AudioDev.tx_nDmaCount =0;		kfree(WTAudio_buf);		AudioDev.packsize = val;		AudioDev.mmsize = (val*AudioDev.mmcount);		AudioDev.dmasize = (val*AudioDev.dmacount);			WTAudio_buf = kmalloc(AudioDev.mmsize, GFP_KERNEL);		AudioDev.mmstart = (unsigned long)WTAudio_buf;				break;			case IOCAGDEVBUFSTATUS:		//BufStatus.tx_nBufB = AudioDev.tx_nBufB;		BufStatus.tx_nBufT = AudioDev.tx_nBufT;		BufStatus.tx_nDmaStart = AudioDev.tx_nDmaStart;		//WTAudio_txdrain();		ret = copy_to_user((WTDevBufStatus*)arg, &BufStatus, sizeof(struct WTDevBufStatus) );		break;	case IOCAGDEVSTATUS:		ret = copy_to_user((WTAudio_dev *)arg, &AudioDev, sizeof(struct WTAudio_dev));		break;		default :		return -ENOTTY;			}	return ret;	}/****************************************************************************//****************************************************************************/struct file_operations WTAudio_fops = {  open:WTAudio_open,	/* open */  release:WTAudio_release,	/* release */  write:WTAudio_write,	/* write */  ioctl:WTAudio_ioctl,	/* ioctl */  mmap:WTAudio_map,    /* map */};/****************************************************************************/int __init WTAudio_init(void){     if (register_chrdev(AudioDev.major, "WTAUDIO", &WTAudio_fops) < 0) {	printk(KERN_WARNING "WTAUDIO: failed to register major %d\n",	       AudioDev.major);	return (0);    }	        WTAudio_buf = kmalloc(AudioDev.mmsize, GFP_KERNEL);        if (WTAudio_buf == NULL) {	printk("WTAUDIO: failed to allocate DMA[%d] buffer\n", BUFSIZE);    }	AudioDev.mmstart = (unsigned long)WTAudio_buf;#ifdef MOUDLE		SET_MODULE_OWNER(&WTAudio_fops);#endif	printk("WTAUDIO: DMA channel=%d, irq=%d\n",	       WTAUDIO_TXDMA, WTAUDIO_TXDMAIRQ);	if (request_irq(WTAUDIO_TXDMAIRQ, WTAudio_tx_dmaisr,			(SA_INTERRUPT | IRQ_FLG_FAST), "AUDIO_OUT(DMA)", NULL))	{	    printk("WTAUDIO: DMA IRQ %d already in use?\n",		   WTAUDIO_TXDMAIRQ);	}	//dmap = (BYTE *) dma_base_addr[WTAUDIO_TXDMA]; //选择通道	//dmap[MCFDMA_DIVR] = WTAUDIO_TXDMAIRQ;  //设置DMA中断向量:120	*mcfReg8p(MCFDMA_INTVR0) = WTAUDIO_TXDMAIRQ;	/* Set interrupt level and priority */		//*mcfReg8p(MCFSIM_ICRDMA0) = MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3;	*mcfReg8p(MCFSIM_ICRDMA0) = MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI2;	//*((DWORD*) (MCF_MBAR + MCFSIM_IMR)) &=~MCFSIM_IMR_DMA0;	*mcfReg32p(MCFSIM_IMR) &=~MCFSIM_IMR_DMA0;		/* Set DMA to use channel 0 for audio */	*mcf2Reg8p(MCFA_DMACONF) |= MCFA_DMA_0REQ; //	*mcf2Reg32p(MCFSIM2_DMAROUTE) = 0x00000080; //dam0 audio source 1	if (request_dma(WTAUDIO_TXDMA, "AUDIO_OUT")) {	    printk("WTAUDIO: DMA channel %d already in use?\n",		   WTAUDIO_TXDMA);	}     	WTAudio_chipinit();//	sema_init (&sem,1);//	memset((void *)DelayBuf,0,AudioDev.packsize);    /* Dummy write to start outputing */    	*mcf2Reg32p(MCFA_PDOR3) = 0;	return (0);}#ifdef MODULEvoid WTAudio_cleanup(void){      	kfree(WTAudio_buf);	free_dma(WTAUDIO_TXDMA);	unregister_chrdev(AUDIOMAJOR, "WTAUDIO");	printk("release WTAUDIO!!!\n");}module_init(WTAudio_init);module_exit(WTAudio_cleanup);MODULE_LICENSE("GPL");#endif/****************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -