?? wtaudioin.c
字號:
#define DMA1_CTL (*mcfReg32p(MCFDMA_DCR1))#define DMA0_SA (*mcfReg32p(MCFDMA_SAR0))#define DMA1_SA (*mcfReg32p(MCFDMA_SAR1))#define DMA0_DA (*mcfReg32p(MCFDMA_DAR0))#define DMA1_DA (*mcfReg32p(MCFDMA_DAR1))#define DMA0_BC (*mcfReg16p(MCFDMA_BCR0))#define DMA1_BC (*mcfReg16p(MCFDMA_BCR1))/* * General purpose IO registers (in MBAR2). */#define MCFSIM2_GPIOREAD 0x0 /* GPIO read values */#define MCFSIM2_GPIOWRITE 0x4 /* GPIO write values */#define MCFSIM2_GPIOENABLE 0x8 /* GPIO enabled */#define MCFSIM2_GPIOFUNC 0xc /* GPIO function */#define MCFSIM2_GPIO1READ 0xb0 /* GPIO1 read values */#define MCFSIM2_GPIO1WRITE 0xb4 /* GPIO1 write values */#define MCFSIM2_GPIO1ENABLE 0xb8 /* GPIO1 enabled */#define MCFSIM2_GPIO1FUNC 0xbc /* GPIO1 function */#define MCF_SDATAI3 0x00000200#define MCF_SDATAI4 0x00000400/****************************************************************************/// audio devicetypedef struct WTAudio_dev{ int major; unsigned char * rxbuf; // int rxBufSize; // max audio data count if buffer; = buffersize/4 int rxdmaStart; // unsigned int nDmaCount;}WTAudio_dev;WTAudio_dev AudioDev={AUDIOINMAJOR,0,BUFSIZE,0,0};#define BUFFERINC(x,y,z) ((x+y)%z) //z: num of package y: inc x: indicate/****************************************************************************/void WTAudio_chipinit(void){#if DEBUG printk("WTAudio_chipinit()\n");#endif //*mcf2Reg32p(MCFA_IIS2CONFIG) = MCFA_IIS_CLK8 | MCFA_IIS_TXSRC_IIS1 | // MCFA_IIS_16BIT | MCFA_IIS_MODE_IIS | MCFA_IIS_LRCK32BIT; //*mcf2Reg32p(MCFA_IIS1CONFIG) = MCFA_IIS_CLK8 | MCFA_IIS_TXSRC_PDOR3 | //MCFA_IIS_16BIT | MCFA_IIS_MODE_IIS | MCFA_IIS_LRCK32BIT; /* INTPUTCLK, PDOR3, SCLKINVERT*/ *mcf2Reg32p(MCFA_IIS1CONFIG) |= 0x00000800; *mcf2Reg32p(MCFA_IIS1CONFIG) |= MCFA_IIS_CLKINPUT | MCFA_IIS_16BIT | MCFA_IIS_MODE_IIS | MCFA_IIS_LRCK64BIT;// |MCFA_IIS_SCLKINV; /* *mcf2Reg32p(MCFSIM2_GPIO1FUNC) &= ~MCF_SDATAI3; *mcf2Reg32p(MCFA_IIS3CONFIG) |= 0x00000800; *mcf2Reg32p(MCFA_IIS3CONFIG) = MCFA_IIS_CLKIIS1 | MCFA_IIS_16BIT | MCFA_IIS_MODE_IIS | MCFA_IIS_LRCK64BIT; */ /* DataInControl, 1 Samples, PDIR2 */ *mcf2Reg32p(MCFA_DATAINCTRL) |= MCFA_DIC_PDIR2_IIS1 | MCFA_DIC_PDIR2_1SAMP;//MCFA_DIC_PDIR2_1SAMP;}/****************************************************************************//* **************************************** Divide the rx buffer into DMABCNT dma buffers, each time start dma to feed one of the dma buffers, and each dma buffer should be aligned by 4bytes, so the rx buffer should be aligned by 16bytes.*******************************************/static inline void WTAudio_rx_dmarun(){ if(WTAudio_rxdmaing) return; KDEBUG("rx_dmarun!\n"); /* Set DMA transfer count */ set_dma_mode(WTAUDIO_RXDMA, DMA_MODE_READ | DMA_MODE_LONG_BIT); set_dma_device_addr(WTAUDIO_RXDMA, (MCF_MBAR2 + MCFA_PDIR2)); set_dma_addr(WTAUDIO_RXDMA, (int)&AudioDev.rxbuf[AudioDev.rxdmaStart]); set_dma_count(WTAUDIO_RXDMA, nDmaCount); WTAudio_rxdmaing = 1; printk("rxbuf = %x\n",AudioDev.rxBufSize); printk("sa= %x da = %x\n",*mcfReg32p(0x340),*mcfReg32p(0x344)); printk("Dmactl = %x count = %x\n",*mcfReg32p(0x348),*mcfReg8p(0x34c)); printk("statue = %x vector = %x\n",*mcfReg8p(0x350),*mcfReg8p(0x354)); printk("dmaroute= %x\n",*mcf2Reg32p(0x188)); printk("bufA = %x\n", AudioDev.rxbuf); //WTAudio_rxbusy = 1; //data buffer is aligned by 4bytes enable_dma(WTAUDIO_RXDMA);}void WTAudio_rx_dmaisr(int irq, void *dev_id, struct pt_regs *regs){ KDEBUG("rx_dmaisr\n"); disable_dma(WTAUDIO_RXDMA); WTAudio_rxdmaing = 0; //adjust the data buffer //AudioDev.rxdmaStart = (AudioDev.rxdmaStart+(AudioDev.rxBufSize/DMABCNT)) % (AudioDev.rxBufSize); AudioDev.rxdmaStart = 0; AudioDev.nDmaCount = 0; WTAudio_rx_dmarun(); } ssize_tWTAudio_read(struct file *filp, char *buf, size_t count, loff_t * ppos){ unsigned long bufcnt,slen; KDEBUG("m5249_read(buf=%x,count=0x%d)\n", (int) buf, count); if (count <= 0)return 0; bufcnt = count ;tryagain: if(bufcnt <= BUFSIZE) { slen = bufcnt; AudioDev.nDmaCount = bufcnt; } else { slen = BUFSIZE; AudioDev.nDmaCount = BUFSIZE; } WTAudio_rx_dmarun(); while(1) { if(!WTAudio_rxdmaing) break; } copy_to_user(buf,(char *)AudioDev.rxbuf,slen); bufcnt -= slen; if(bufcnt > 0) goto tryagain; KDEBUG("WTAudio_read returned %d.\n", count); return count; }void WTAudio_txdrain(void){#ifdef DEBUG printk("WTAudio_txdrain()\n");#endif WTAudio_rxbusy =0; current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); return; while (!signal_pending(current)) { if (WTAudio_rxbusy == 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; 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_RXDMA); WTAudio_rxdmaing = 0; AudioDev.rxdmaStart = 0; AudioDev.nDmaCount = 0; WTAudio_isopen = 0; WTAudio_rxbusy = 0; 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; 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; return ret; }/****************************************************************************/struct file_operations WTAudio_fops = { open:WTAudio_open, /* open */ read:WTAudio_read, /*read */ release:WTAudio_release, /* release */ ioctl:WTAudio_ioctl, /* ioctl */};/****************************************************************************/int __init WTAudio_init(void){ if (register_chrdev(AUDIOINMAJOR, "WTAUDIOIN", &WTAudio_fops) < 0) { printk(KERN_WARNING "WTAUDIOIN: failed to register major %d\n", AUDIOINMAJOR); return (0); } AudioDev.rxbuf = (unsigned char *)kmalloc(AudioDev.rxBufSize, GFP_KERNEL); if (AudioDev.rxbuf == NULL) { printk("WTAUDIOIN: failed to allocate [%d] buffer\n",(AudioDev.rxBufSize)); } printk("mem = %x\n",AudioDev.rxbuf);#ifdef MODULE SET_MODULE_OWNER(&WTAudio_fops);#endif printk("WTAUDIOIN RX: DMA channel=%d, irq=%d\n", WTAUDIO_RXDMA, WTAUDIO_RXDMAIRQ); if (request_irq(WTAUDIO_RXDMAIRQ, WTAudio_rx_dmaisr, (SA_INTERRUPT | IRQ_FLG_FAST), "AUDIO_IN(DMA)", NULL)) { printk("WTAUDIOIN: RX DMA IRQ %d already in use?\n", WTAUDIO_RXDMAIRQ); } //dmap = (BYTE *) dma_base_addr[WTAUDIO_RXDMA]; //選擇通道 //dmap[MCFDMA_DIVR] = WTAUDIO_RXDMAIRQ; //設置DMA中斷向量:121 *mcfReg8p(MCFDAM_INTVR1) = WTAUDIO_RXDMAIRQ; //*mcfReg8p(MCFDMA_INTVR0) = WTAUDIO_RXDMAIRQ; /* Set interrupt level and priority */ *mcfReg8p(MCFSIM_ICRDMA1) = MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; //*mcfReg8p(MCFSIM_ICRDMA0) = MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; //*mcfReg8p(MCFSIM_ICRDMA1) = MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI1; //*((DWORD*) (MCF_MBAR + MCFSIM_IMR)) &=~MCFSIM_IMR_DMA0; *mcfReg32p(MCFSIM_IMR) &=~MCFSIM_IMR_DMA1; //*mcfReg32p(MCFSIM_IMR) &= ~MCFSIM_IMR_DMA0; /* Set DMA to use channel 1 for audio rx */ *mcf2Reg8p(MCFA_DMACONF) &= ~(MCFA_DMA_1REQ); //PDIR2 on dma1 *mcf2Reg32p(MCFSIM2_DMAROUTE) |= (0x00000081<<8); //dam1 audio source 2 /* Set DMA to use channel 0 for audio */ //*mcf2Reg8p(MCFA_DMACONF) &= ~MCFA_DMA_0REQ; // //*mcf2Reg32p(MCFSIM2_DMAROUTE) = 0x00000081; //dam0 audio source 1 if (request_dma(WTAUDIO_RXDMA, "AUDIO_IN")) { printk("WTAUDIO: RX DMA channel %d already in use?\n", WTAUDIO_RXDMA); } WTAudio_chipinit();// sema_init (&sem,1);// memset((void *)DelayBuf,0,AudioDev.packsize); return (0); }#ifdef MODULEvoid WTAudio_cleanup(void){ kfree(AudioDev.rxbuf); free_dma(WTAUDIO_RXDMA); unregister_chrdev(AUDIOINMAJOR, "WTAUDIOIN"); 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 + -