int i2s_dev_enable(i2s_config_type* ptri2s_config) { unsigned int data, int_en, Ret; int_en = i2s_inw(I2S_INT_EN); data = i2s_inw(I2S_I2SCFG); data |= REGBIT(0x1, I2S_EN); #ifdef I2S_FIFO_MODE data &= ~REGBIT(0x1, I2S_DMA_EN); #else data |= REGBIT(0x1, I2S_DMA_EN); #endif data &= ~REGBIT(0x1, I2S_CH_SWAP); data &= ~REGBIT(0x1, I2S_CH1_OFF); data &= ~REGBIT(0x1, I2S_CH0_OFF); int_en |= REGBIT(0x1, I2S_INT3_EN); int_en |= REGBIT(0x1, I2S_INT2_EN); int_en |= REGBIT(0x1, I2S_INT1_EN); //int_en |= REGBIT(0x1, I2S_INT0_EN); #ifdef I2S_FIFO_MODE int_en = 0; #endif MSG("I2S_INT_EN=0x%08X\n",int_en); MSG("I2S_I2SCFG=0x%08X\n",data); i2s_outw(I2S_INT_EN, int_en); i2s_outw(I2S_I2SCFG, data); return I2S_OK; }
/* Turn Off Rx DMA and INT */ int i2s_rx_disable(i2s_config_type* ptri2s_config) { unsigned long data; data = i2s_inw(I2S_INT_EN); data &= ~REGBIT(0x1, I2S_RX_INT3_EN); data &= ~REGBIT(0x1, I2S_RX_INT2_EN); data &= ~REGBIT(0x1, I2S_RX_INT1_EN); //data &= ~REGBIT(0x1, I2S_RX_INT0_EN); i2s_outw(I2S_INT_EN, data); data = i2s_inw(I2S_I2SCFG); #if defined(CONFIG_I2S_TXRX) data &= ~REGBIT(0x1, I2S_RX_EN); data &= ~REGBIT(0x1, I2S_EN); #else data &= ~REGBIT(0x1, I2S_EN); #endif if(ptri2s_config->bTxDMAEnable==0) { ptri2s_config->bRxDMAEnable = 0; data &= ~REGBIT(0x1, I2S_DMA_EN); } i2s_outw(I2S_I2SCFG, data); return I2S_OK; }
irqreturn_t i2s_irq_isr(int irq, void *irqaction) { u32 i2s_status; MSG("i2s_st=%X\n",i2s_status); i2s_status=i2s_inw(I2S_INT_STATUS); if(i2s_status®BIT(1, I2S_DMA_FAULT)) { #ifdef I2S_STATISTIC pi2s_status->txdmafault++; #endif } if(i2s_status®BIT(1, I2S_OVRUN)) { #ifdef I2S_STATISTIC pi2s_status->ovrun++; #endif } if(i2s_status®BIT(1, I2S_UNRUN)) { #ifdef I2S_STATISTIC pi2s_status->unrun++; #endif } if(i2s_status®BIT(1, I2S_THRES)) { #ifdef I2S_STATISTIC pi2s_status->thres++; #endif } i2s_outw(I2S_INT_STATUS, 0xFFFFFFFF); return IRQ_HANDLED; }
int i2s_dev_disable(i2s_config_type* ptri2s_config) { unsigned int data, int_en; data = i2s_inw(I2S_I2SCFG); data &= 0x3FFFFFFF; i2s_outw(I2S_I2SCFG, data); i2s_outw(I2S_INT_EN, 0); return I2S_OK; }
/* Turn On Rx DMA and INT */ int i2s_rx_enable(i2s_config_type* ptri2s_config) { unsigned long data; data = i2s_inw(I2S_INT_EN); #if defined(I2S_FIFO_MODE) data = 0; #else data |= REGBIT(0x1, I2S_RX_INT3_EN); data |= REGBIT(0x1, I2S_RX_INT2_EN); data |= REGBIT(0x1, I2S_RX_INT1_EN); //data |= REGBIT(0x1, I2S_RX_INT0_EN); #endif i2s_outw(I2S_INT_EN, data); data = i2s_inw(I2S_I2SCFG); #if defined(CONFIG_I2S_TXRX) data |= REGBIT(0x1, I2S_RX_EN); #else data |= REGBIT(0x1, I2S_EN); #endif #if defined(I2S_FIFO_MODE) data &= ~REGBIT(0x1, I2S_DMA_EN); #else ptri2s_config->bRxDMAEnable = 1; data |= REGBIT(0x1, I2S_DMA_EN); #endif i2s_outw(I2S_I2SCFG, data); data = i2s_inw(I2S_I2SCFG); data |= REGBIT(0x1, I2S_EN); #if defined(I2S_RX_BYTE_SWAP) data |= REGBIT(0x1, I2S_BYTE_SWAP); #else data &= ~REGBIT(0x1, I2S_BYTE_SWAP); #endif i2s_outw(I2S_I2SCFG, data); MSG("i2s_rx_enable done\n"); return I2S_OK; }
int i2s_rx_config(i2s_config_type* ptri2s_config) { unsigned long data; /* set I2S_I2SCFG */ data = i2s_inw(I2S_I2SCFG); data &= 0xFFFF81FF; data |= REGBIT(ptri2s_config->rx_ff_thres, I2S_RX_FF_THRES); data |= REGBIT(ptri2s_config->rx_ch_swap, I2S_RX_CH_SWAP); data &= ~REGBIT(1, I2S_RX_CH0_OFF); data &= ~REGBIT(1, I2S_RX_CH1_OFF); i2s_outw(I2S_I2SCFG, data); #if defined(CONFIG_I2S_EXTENDCFG) /* set I2S_I2SCFG1 */ data = i2s_inw(I2S_I2SCFG1); data |= REGBIT(ptri2s_config->lbk, I2S_LBK_EN); data |= REGBIT(ptri2s_config->extlbk, I2S_EXT_LBK_EN); data &= 0xFFFFFFFC; data |= REGBIT(ptri2s_config->fmt, I2S_DATA_FMT); i2s_outw(I2S_I2SCFG1, data); #endif return 0; }
int i2s_clock_disable(i2s_config_type* ptri2s_config) { unsigned long data; i2s_codec_disable(ptri2s_config); /* disable internal MCLK */ #if defined(CONFIG_I2S_IN_MCLK) data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); #if defined(CONFIG_RALINK_RT3350) data &= ~(0x1<<8); #elif defined(CONFIG_RALINK_RT3883) data &= ~(0x03<<13); #elif defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) data &= ~(0x03<<8); #elif defined(CONFIG_RALINK_RT63365) //FIXME #endif i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); #endif return 0; }
void i2s_dma_rx_handler(u32 dma_ch) { u32 i2s_status; #if defined(CONFIG_I2S_TXRX) i2s_status=i2s_inw(I2S_INT_STATUS); pi2s_config->rx_isr_cnt++; if(pi2s_config->bRxDMAEnable==0) { /* if(dma_ch==GDMA_I2S_RX0) { GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage0RxBuf8ptr, 0, 128, NULL, NULL); } else { GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage1RxBuf8ptr, 1, 128, NULL, NULL); } */ MSG("RxDMA not enable\n"); return; } #ifdef I2S_STATISTIC if(pi2s_config->rx_isr_cnt%40==0) MSG("risr i=%u,l=%d,o=%d,u=%d,s=%X [r=%d,w=%d]\n",pi2s_config->rx_isr_cnt,pi2s_status->rxbuffer_len,pi2s_status->rxbuffer_ovrun,pi2s_status->rxbuffer_unrun,i2s_status,pi2s_config->rx_r_idx,pi2s_config->rx_w_idx); #endif if(((pi2s_config->rx_w_idx+1)%MAX_I2S_PAGE)==pi2s_config->rx_r_idx) { /* Buffer Empty */ MSG("RXBE r=%d w=%d[i=%u,c=%u]\n",pi2s_config->rx_r_idx,pi2s_config->rx_w_idx,pi2s_config->rx_isr_cnt,dma_ch); #ifdef I2S_STATISTIC pi2s_status->rxbuffer_unrun++; #endif if(dma_ch==GDMA_I2S_RX0) { GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_unmask_handler); } else { GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage1RxBuf8ptr, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_unmask_handler); } goto EXIT; } #ifdef I2S_STATISTIC pi2s_status->rxbuffer_len++; #endif if(dma_ch==GDMA_I2S_RX0) { pi2s_config->rx_w_idx = (pi2s_config->rx_w_idx+1)%MAX_I2S_PAGE; memcpy(pi2s_config->pMMAPRxBufPtr[pi2s_config->rx_w_idx], pi2s_config->pPage0RxBuf8ptr, I2S_PAGE_SIZE); GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pPage0RxBuf8ptr), 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_unmask_handler); pi2s_config->dmach = GDMA_I2S_RX0; } else { pi2s_config->rx_w_idx = (pi2s_config->rx_w_idx+1)%MAX_I2S_PAGE; memcpy(pi2s_config->pMMAPRxBufPtr[pi2s_config->rx_w_idx], pi2s_config->pPage1RxBuf8ptr, I2S_PAGE_SIZE); GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pPage1RxBuf8ptr), 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_unmask_handler); pi2s_config->dmach = GDMA_I2S_RX1; } EXIT: wake_up_interruptible(&(pi2s_config->i2s_rx_qh)); #endif return; }
void i2s_dma_tx_handler(u32 dma_ch) { u32 i2s_status; i2s_status=i2s_inw(I2S_INT_STATUS); pi2s_config->tx_isr_cnt++; if(pi2s_config->bTxDMAEnable==0) { /* if(dma_ch==GDMA_I2S_TX0) { GdmaI2sTx((u32)pi2s_config->pPage0TxBuf8ptr, I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); } else { GdmaI2sTx((u32)pi2s_config->pPage1TxBuf8ptr, I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); } */ MSG("TxDMA not enable\n"); return; } #ifdef I2S_STATISTIC if(pi2s_config->tx_isr_cnt%40==0) MSG("tisr i=%u,c=%u,o=%u,u=%d,s=%X [r=%d,w=%d]\n",pi2s_config->tx_isr_cnt,dma_ch,pi2s_status->txbuffer_ovrun,pi2s_status->txbuffer_unrun,i2s_status,pi2s_config->tx_r_idx,pi2s_config->tx_w_idx); #endif if(pi2s_config->tx_r_idx==pi2s_config->tx_w_idx) { /* Buffer Empty */ MSG("TXBE r=%d w=%d[i=%u,c=%u]\n",pi2s_config->tx_r_idx,pi2s_config->tx_w_idx,pi2s_config->tx_isr_cnt,dma_ch); #ifdef I2S_STATISTIC pi2s_status->txbuffer_unrun++; #endif if(dma_ch==GDMA_I2S_TX0) { memset(pi2s_config->pPage0TxBuf8ptr, 0, I2S_PAGE_SIZE); GdmaI2sTx((u32)pi2s_config->pPage0TxBuf8ptr, I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); } else { memset(pi2s_config->pPage1TxBuf8ptr, 0, I2S_PAGE_SIZE); GdmaI2sTx((u32)pi2s_config->pPage1TxBuf8ptr, I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); } goto EXIT; } if(pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx]==NULL) { MSG("mmap buf NULL\n"); if(dma_ch==GDMA_I2S_TX0) GdmaI2sTx((u32)pi2s_config->pPage0TxBuf8ptr, I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); else GdmaI2sTx((u32)pi2s_config->pPage1TxBuf8ptr, I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); goto EXIT; } #ifdef I2S_STATISTIC pi2s_status->txbuffer_len--; #endif if(dma_ch==GDMA_I2S_TX0) { #if defined(CONFIG_I2S_MMAP) dma_cache_sync(NULL, pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx], I2S_PAGE_SIZE, DMA_TO_DEVICE); GdmaI2sTx((u32)(pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx]), I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); #else memcpy(pi2s_config->pPage0TxBuf8ptr, pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx], I2S_PAGE_SIZE); GdmaI2sTx((u32)(pi2s_config->pPage0TxBuf8ptr), I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); #endif pi2s_config->dmach = GDMA_I2S_TX0; pi2s_config->tx_r_idx = (pi2s_config->tx_r_idx+1)%MAX_I2S_PAGE; } else { #if defined(CONFIG_I2S_MMAP) dma_cache_sync(NULL, pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx], I2S_PAGE_SIZE, DMA_TO_DEVICE); GdmaI2sTx((u32)(pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx]), I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); #else memcpy(pi2s_config->pPage1TxBuf8ptr, pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx], I2S_PAGE_SIZE); GdmaI2sTx((u32)(pi2s_config->pPage1TxBuf8ptr), I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); #endif pi2s_config->dmach = GDMA_I2S_TX1; pi2s_config->tx_r_idx = (pi2s_config->tx_r_idx+1)%MAX_I2S_PAGE; } EXIT: wake_up_interruptible(&(pi2s_config->i2s_tx_qh)); return; }
/* * Ralink Audio System Clock Enable * * I2S_WS : signal direction opposite to/same as I2S_CLK * * I2S_CLK : Integer division or fractional division * REFCLK from Internal or External (external REFCLK not support for fractional division) * Suppose external REFCLK always be the same as external MCLK * * MCLK : External OSC or internal generation * */ int i2s_clock_enable(i2s_config_type* ptri2s_config) { unsigned long data; unsigned long index; unsigned long* pTable; /* audio sampling rate decision */ switch(ptri2s_config->srate) { case 8000: index = 0; break; case 11025: index = 1; break; case 12000: index = 2; break; case 16000: index = 3; break; case 22050: index = 4; break; case 24000: index = 5; break; case 32000: index = 6; break; case 44100: index = 7; break; case 48000: index = 8; break; case 88200: index = 9; break; case 96000: index = 10; break; default: index = 7; } /* enable internal MCLK */ #if defined(CONFIG_I2S_IN_MCLK) #if defined(CONFIG_RALINK_RT63365) //FIXME #else data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); #endif #if defined(CONFIG_I2S_MCLK_12MHZ) MSG("Enable SoC MCLK 12Mhz\n"); #if defined(CONFIG_RALINK_RT3350) data |= (0x1<<8); #elif defined(CONFIG_RALINK_RT3883) data &= ~(0x03<<13); data |= (0x1<<13); #elif defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) data &= ~(0x0F<<8); data |= (0x3<<8); #elif defined(CONFIG_RALINK_RT63365) //FIXME #else #error "This SoC do not provide MCLK to audio codec\n"); #endif #endif #if defined(CONFIG_I2S_MCLK_12P288MHZ) MSG("Enable SoC MCLK 12.288Mhz\n"); #if defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) data &= ~(0x01F<<18); data |= 31<<18; data &= ~(0x01F<<12); data |= 1<<12; data |= (0xF<<8); #elif defined(CONFIG_RALINK_RT63365) #else #error "This SoC do not provide MCLK 12.288Mhz audio codec\n"); #endif #endif #if defined(CONFIG_RALINK_RT63365) #else i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); #endif #else MSG("Disable SoC MCLK, use external OSC\n"); #if defined(CONFIG_RALINK_RT63365) #else data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); #endif #if defined(CONFIG_RALINK_RT3350) data &= ~(0x1<<8); #elif defined(CONFIG_RALINK_RT3883) #elif defined(CONFIG_RALINK_RT3352) data &= ~(0x0F<<8); #elif defined(CONFIG_RALINK_RT5350) data |= (0x0F<<8); #elif defined (CONFIG_RALINK_RT6855) data &= ~(0x0F<<8); #endif #if defined(CONFIG_RALINK_RT63365) #else i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); #endif #endif /* set share pins to i2s/gpio mode and i2c mode */ #if defined(CONFIG_RALINK_RT63365) data = i2s_inw(RALINK_SYSCTL_BASE+0x860); data |= 0x00008080; i2s_outw(RALINK_SYSCTL_BASE+0x860, data); #else data = i2s_inw(RALINK_SYSCTL_BASE+0x60); data &= 0xFFFFFFE2; data |= 0x00000018; i2s_outw(RALINK_SYSCTL_BASE+0x60, data); #endif if(ptri2s_config->slave_en==0) { /* Setup I2S_WS and I2S_CLK */ #if defined(CONFIG_I2S_IN_CLK) /* REFCLK is 15.625Mhz or 40Mhz(fractional division) */ #if defined(CONFIG_I2S_FRAC_DIV) MSG("Internal REFCLK with fractional division\n"); pTable = i2sMaster_inclk_int; data = (unsigned long)(pTable[index]); i2s_outw(I2S_DIVINT_CFG, data); pTable = i2sMaster_inclk_comp; data = (unsigned long)(pTable[index]); data |= REGBIT(1, I2S_CLKDIV_EN); i2s_outw(I2S_DIVCOMP_CFG, data); #else MSG("Internal REFCLK 15.625Mhz \n"); pTable = i2sMaster_inclk_15p625Mhz; data = i2s_inw(RALINK_SYSCTL_BASE+0x30); data &= 0xFFFF00FF; data |= (unsigned long)(pTable[index]); data |= 0x00008000; i2s_outw(RALINK_SYSCTL_BASE+0x30, data); #endif #else #if defined(CONFIG_I2S_MCLK_12MHZ) /* REFCLK = MCLK = 12Mhz */ MSG("External REFCLK 12Mhz \n"); pTable = i2sMaster_exclk_12Mhz; data = i2s_inw(RALINK_SYSCTL_BASE+0x30); data &= 0xFFFF00FF; data |= (unsigned long)(pTable[index]); data |= 0x0000C000; i2s_outw(RALINK_SYSCTL_BASE+0x30, data); #else /* REFCLK = MCLK = 12.288Mhz */ pTable = i2sMaster_exclk_12p288Mhz; MSG("External REFCLK 12.288Mhz \n"); data = i2s_inw(RALINK_SYSCTL_BASE+0x30); data &= 0xFFFF00FF; data |= (unsigned long)(pTable[index]); data |= 0x0000C000; i2s_outw(RALINK_SYSCTL_BASE+0x30, data); #endif #endif /* Not CONFIG_I2S_IN_CLK */ #if defined(CONFIG_I2S_WS_EDGE) data = i2s_inw(I2S_I2SCFG); data |= REGBIT(0x1, I2S_WS_INV); i2s_outw(I2S_I2SCFG, data); #endif #if defined(CONFIG_RALINK_RT3052) data = i2s_inw(I2S_I2SCFG); data &= ~REGBIT(0x1, I2S_SLAVE_EN); data &= ~REGBIT(0x1, I2S_CLK_OUT_DIS); i2s_outw(I2S_I2SCFG, data); #elif defined(CONFIG_RALINK_RT3883)||defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) ||\ defined(CONFIG_RALINK_RT63365) data = i2s_inw(I2S_I2SCFG); data &= ~REGBIT(0x1, I2S_SLAVE_MODE); i2s_outw(I2S_I2SCFG, data); #else #error "a strange clock mode" #endif i2s_codec_enable(ptri2s_config); #if defined(CONFIG_I2S_MCLK_12MHZ) pTable = i2sSlave_exclk_12Mhz; data = pTable[index]; audiohw_set_frequency(data|0x01); #else pTable = i2sSlave_exclk_12p288Mhz; data = pTable[index]; audiohw_set_frequency(data); #endif } else { #if defined(CONFIG_RALINK_RT3052) data = i2s_inw(I2S_I2SCFG); data |= REGBIT(0x1, I2S_SLAVE_EN); data |= REGBIT(0x1, I2S_CLK_OUT_DIS); i2s_outw(I2S_I2SCFG, data); #elif defined(CONFIG_RALINK_RT3883)||defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) ||\ defined(CONFIG_RALINK_RT63365) data = i2s_inw(I2S_I2SCFG); data |= REGBIT(0x1, I2S_SLAVE_MODE); i2s_outw(I2S_I2SCFG, data); #else #error "a strange clock mode " #endif i2s_codec_enable(ptri2s_config); #if defined(CONFIG_I2S_MCLK_12MHZ) pTable = i2sSlave_exclk_12Mhz; data = pTable[index]; audiohw_set_frequency(data|0x1); /* for MCLK=12Mhz only. */ #else pTable = i2sSlave_exclk_12p288Mhz; data = pTable[index]; audiohw_set_frequency(data); #endif } return 0; }
int i2s_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) #endif { int i ; unsigned long flags, data; i2s_config_type* ptri2s_config; ptri2s_config = filp->private_data; switch (cmd) { case I2S_SRATE: spin_lock_irqsave(&ptri2s_config->lock, flags); { data = *(unsigned long*)(RALINK_SYSCTL_BASE+0x834); data |=(1<<17); *(unsigned long*)(RALINK_SYSCTL_BASE+0x834) = data; data = *(unsigned long*)(RALINK_SYSCTL_BASE+0x834); data &=~(1<<17); *(unsigned long*)(RALINK_SYSCTL_BASE+0x834) = data; audiohw_preinit(); } if((arg>MAX_SRATE_HZ)||(arg<MIN_SRATE_HZ)) { MSG("audio sampling rate %u should be %d ~ %d Hz\n", (u32)arg, MIN_SRATE_HZ, MAX_SRATE_HZ); break; } ptri2s_config->srate = arg; MSG("set audio sampling rate to %d Hz\n", ptri2s_config->srate); spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_TX_VOL: spin_lock_irqsave(&ptri2s_config->lock, flags); if((int)arg > 127) { ptri2s_config->txvol = 127; } else if((int)arg < 96) { ptri2s_config->txvol = 96; } else ptri2s_config->txvol = arg; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_RX_VOL: spin_lock_irqsave(&ptri2s_config->lock, flags); if((int)arg > 63) { ptri2s_config->rxvol = 63; } else if((int)arg < 0) { ptri2s_config->rxvol = 0; } else ptri2s_config->rxvol = arg; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_TX_ENABLE: spin_lock_irqsave(&ptri2s_config->lock, flags); MSG("I2S_TXENABLE\n"); /* allocate tx buffer */ ptri2s_config->pPage0TxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE*2 , &i2s_txdma_addr); if(ptri2s_config->pPage0TxBuf8ptr==NULL) { MSG("Allocate Tx Page Buffer Failed\n"); return -1; } ptri2s_config->pPage1TxBuf8ptr = ptri2s_config->pPage0TxBuf8ptr + I2S_PAGE_SIZE; for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) { #if defined(CONFIG_I2S_MMAP) ptri2s_config->pMMAPTxBufPtr[i] = ptri2s_config->pMMAPBufPtr[i]; #else if(ptri2s_config->pMMAPTxBufPtr[i]==NULL) ptri2s_config->pMMAPTxBufPtr[i] = kmalloc(I2S_PAGE_SIZE, GFP_KERNEL); #endif } #if defined(I2S_FIFO_MODE) #else GdmaI2sTx((u32)ptri2s_config->pPage0TxBuf8ptr, I2S_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); GdmaI2sTx((u32)ptri2s_config->pPage1TxBuf8ptr, I2S_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_unmask_handler); #endif i2s_reset_tx_config(ptri2s_config); ptri2s_config->bTxDMAEnable = 1; i2s_tx_config(ptri2s_config); if(ptri2s_config->bRxDMAEnable==0) i2s_clock_enable(ptri2s_config); audiohw_set_lineout_vol(1, ptri2s_config->txvol, ptri2s_config->txvol); i2s_tx_enable(ptri2s_config); #if defined(I2S_FIFO_MODE) #else GdmaUnMaskChannel(GDMA_I2S_TX0); #endif data = i2s_inw(RALINK_REG_INTENA); data |=0x0400; i2s_outw(RALINK_REG_INTENA, data); MSG("I2S_TXENABLE done\n"); spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_TX_DISABLE: spin_lock_irqsave(&ptri2s_config->lock, flags); MSG("I2S_TXDISABLE\n"); i2s_tx_disable(ptri2s_config); i2s_reset_tx_config(ptri2s_config); if(ptri2s_config->bRxDMAEnable==0) i2s_clock_disable(ptri2s_config); //i2s_tx_disable(ptri2s_config); if(ptri2s_config->bRxDMAEnable==0) { data = i2s_inw(RALINK_REG_INTENA); data &= 0xFFFFFBFF; i2s_outw(RALINK_REG_INTENA, data); } for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) { if(ptri2s_config->pMMAPTxBufPtr[i] != NULL) { #if defined(CONFIG_I2S_MMAP) dma_unmap_single(NULL, i2s_mmap_addr[i], I2S_PAGE_SIZE, DMA_TO_DEVICE); #endif kfree(ptri2s_config->pMMAPTxBufPtr[i]); ptri2s_config->pMMAPTxBufPtr[i] = NULL; } } pci_free_consistent(NULL, I2S_PAGE_SIZE*2, ptri2s_config->pPage0TxBuf8ptr, i2s_txdma_addr); ptri2s_config->pPage0TxBuf8ptr = NULL; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_RX_ENABLE: spin_lock_irqsave(&ptri2s_config->lock, flags); MSG("I2S_RXENABLE\n"); /* allocate rx buffer */ ptri2s_config->pPage0RxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE*2 , &i2s_rxdma_addr); if(ptri2s_config->pPage0RxBuf8ptr==NULL) { MSG("Allocate Rx Page Buffer Failed\n"); return -1; } ptri2s_config->pPage1RxBuf8ptr = ptri2s_config->pPage0RxBuf8ptr + I2S_PAGE_SIZE; for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) { if(ptri2s_config->pMMAPRxBufPtr[i]==NULL) ptri2s_config->pMMAPRxBufPtr[i] = kmalloc(I2S_PAGE_SIZE, GFP_KERNEL); } #if defined(I2S_FIFO_MODE) #else GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)ptri2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_unmask_handler); GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)ptri2s_config->pPage1RxBuf8ptr, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_unmask_handler); #endif i2s_reset_rx_config(ptri2s_config); ptri2s_config->bRxDMAEnable = 1; i2s_rx_config(ptri2s_config); #if defined(I2S_FIFO_MODE) #else GdmaUnMaskChannel(GDMA_I2S_RX0); #endif if(ptri2s_config->bTxDMAEnable==0) i2s_clock_enable(ptri2s_config); #if defined(CONFIG_I2S_TXRX) audiohw_set_linein_vol(ptri2s_config->rxvol, ptri2s_config->rxvol); #endif i2s_rx_enable(ptri2s_config); data = i2s_inw(RALINK_REG_INTENA); data |=0x0400; i2s_outw(RALINK_REG_INTENA, data); spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_RX_DISABLE: spin_lock_irqsave(&ptri2s_config->lock, flags); MSG("I2S_RXDISABLE\n"); i2s_reset_rx_config(ptri2s_config); if(ptri2s_config->bTxDMAEnable==0) i2s_clock_disable(ptri2s_config); i2s_rx_disable(ptri2s_config); if(ptri2s_config->bRxDMAEnable==0) { data = i2s_inw(RALINK_REG_INTENA); data &= 0xFFFFFBFF; i2s_outw(RALINK_REG_INTENA, data); } for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) { if(ptri2s_config->pMMAPRxBufPtr[i] != NULL) kfree(ptri2s_config->pMMAPRxBufPtr[i]); ptri2s_config->pMMAPRxBufPtr[i] = NULL; } pci_free_consistent(NULL, I2S_PAGE_SIZE*2, ptri2s_config->pPage0RxBuf8ptr, i2s_rxdma_addr); ptri2s_config->pPage0RxBuf8ptr = NULL; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; case I2S_PUT_AUDIO: //MSG("I2S_PUT_AUDIO\n"); #if defined(I2S_FIFO_MODE) { long* pData ; //MSG("I2S_PUT_AUDIO FIFO\n"); copy_from_user(ptri2s_config->pMMAPTxBufPtr[0], (char*)arg, I2S_PAGE_SIZE); pData = ptri2s_config->pMMAPTxBufPtr[0]; for(i = 0 ; i < I2S_PAGE_SIZE>>2 ; i++ ) { int j; unsigned long status = i2s_inw(I2S_FF_STATUS); while((status&0x0F)==0) { for(j = 0 ; j < 50 ; j++); status = i2s_inw(I2S_FF_STATUS); } *((volatile uint32_t *)(I2S_TX_FIFO_WREG)) = cpu_to_le32(*pData); if(i==16) MSG("I2S_PUT_AUDIO FIFO[0x%08X]\n", *pData); pData++; } } break; #else do{ spin_lock_irqsave(&ptri2s_config->lock, flags); if(((ptri2s_config->tx_w_idx+4)%MAX_I2S_PAGE)!=ptri2s_config->tx_r_idx) { ptri2s_config->tx_w_idx = (ptri2s_config->tx_w_idx+1)%MAX_I2S_PAGE; //printk("put TB[%d] for user write\n",ptri2s_config->tx_w_idx); #if defined(CONFIG_I2S_MMAP) put_user(ptri2s_config->tx_w_idx, (int*)arg); #else copy_from_user(ptri2s_config->pMMAPTxBufPtr[ptri2s_config->tx_w_idx], (char*)arg, I2S_PAGE_SIZE); #endif pi2s_status->txbuffer_len++; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; } else { /* Buffer Full */ //printk("TBF tr=%d, tw=%d\n", ptri2s_config->tx_r_idx, ptri2s_config->tx_w_idx); pi2s_status->txbuffer_ovrun++; spin_unlock_irqrestore(&ptri2s_config->lock, flags); interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh)); } }while(1); break; #endif case I2S_GET_AUDIO: #if defined(I2S_FIFO_MODE) { long* pData ; pData = ptri2s_config->pMMAPRxBufPtr[0]; for(i = 0 ; i < I2S_PAGE_SIZE>>2 ; i++ ) { int j; unsigned long status = i2s_inw(I2S_FF_STATUS); while((status&0x0F0)==0) { for(j = 0 ; j < 50 ; j++); status = i2s_inw(I2S_FF_STATUS); } *pData = i2s_inw(I2S_RX_FIFO_RREG); if(i==16) MSG("I2S_GET_AUDIO FIFO[0x%08X]\n", *pData); pData++; } copy_to_user((char*)arg, ptri2s_config->pMMAPRxBufPtr[0], I2S_PAGE_SIZE); } break; #else do{ spin_lock_irqsave(&ptri2s_config->lock, flags); if(ptri2s_config->rx_r_idx!=ptri2s_config->rx_w_idx) { copy_to_user((char*)arg, ptri2s_config->pMMAPRxBufPtr[ptri2s_config->rx_r_idx], I2S_PAGE_SIZE); ptri2s_config->rx_r_idx = (ptri2s_config->rx_r_idx+1)%MAX_I2S_PAGE; pi2s_status->rxbuffer_len--; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; } else { /* Buffer Full */ //printk("RBF rr=%d, rw=%d\n", ptri2s_config->rx_r_idx, ptri2s_config->rx_w_idx); pi2s_status->rxbuffer_ovrun++; spin_unlock_irqrestore(&ptri2s_config->lock, flags); interruptible_sleep_on(&(ptri2s_config->i2s_rx_qh)); } }while(1); break; #endif case I2S_DEBUG_CLKGEN: case I2S_DEBUG_INLBK: case I2S_DEBUG_EXLBK: case I2S_DEBUG_CODECBYPASS: case I2S_DEBUG_FMT: case I2S_DEBUG_RESET: i2s_debug_cmd(cmd, arg); break; default : MSG("i2s_ioctl: command format error\n"); } return 0; }
irqreturn_t i2s_irq_isr(int irq, void *irqaction) { u32 i2s_status; #if defined(I2S_FIFO_MODE) i2s_outw(I2S_INT_STATUS, 0xFFFFFFFF); return IRQ_HANDLED; #endif //MSG("i2s_irq_isr [0x%08X]\n",i2s_inw(I2S_INT_STATUS)); if((pi2s_config->tx_isr_cnt>0)||(pi2s_config->rx_isr_cnt>0)) { i2s_status=i2s_inw(I2S_INT_STATUS); MSG("i2s_irq_isr [0x%08X]\n",i2s_status); } else return IRQ_HANDLED; if(i2s_status®BIT(1, I2S_TX_DMA_FAULT)) { #ifdef I2S_STATISTIC pi2s_status->txdmafault++; #endif } if(i2s_status®BIT(1, I2S_TX_OVRUN)) { #ifdef I2S_STATISTIC pi2s_status->txovrun++; #endif } if(i2s_status®BIT(1, I2S_TX_UNRUN)) { #ifdef I2S_STATISTIC pi2s_status->txunrun++; #endif } if(i2s_status®BIT(1, I2S_TX_THRES)) { #ifdef I2S_STATISTIC pi2s_status->txthres++; #endif } if(i2s_status®BIT(1, I2S_RX_DMA_FAULT)) { #ifdef I2S_STATISTIC pi2s_status->rxdmafault++; #endif } if(i2s_status®BIT(1, I2S_RX_OVRUN)) { #ifdef I2S_STATISTIC pi2s_status->rxovrun++; #endif } if(i2s_status®BIT(1, I2S_RX_UNRUN)) { #ifdef I2S_STATISTIC pi2s_status->rxunrun++; #endif } if(i2s_status®BIT(1, I2S_RX_THRES)) { #ifdef I2S_STATISTIC pi2s_status->rxthres++; #endif } i2s_outw(I2S_INT_STATUS, 0xFFFFFFFF); return IRQ_HANDLED; }
void i2s_dma_handler(u32 dma_ch) { int i,iline; int srate =0; u32 i2s_status; int mute = -1; int bWakeUp = 0; int data; i2s_status=i2s_inw(I2S_INT_STATUS); pi2s_config->isr_cnt++; #ifdef I2S_STATISTIC if(pi2s_config->isr_cnt%200==0) MSG("isr i=%d,l=%d,o=%d,u=%d,s=%X [r=%d,w=%d]\n",pi2s_config->isr_cnt,pi2s_status->buffer_len,pi2s_status->buffer_ovrun,pi2s_status->buffer_unrun,i2s_status,pi2s_config->r_idx,pi2s_config->w_idx); #endif //i2s_outw(I2S_INT_STATUS, 0xFFFFFFFF); if(pi2s_config->bDMAStart==0) { goto EXIT; } if(pi2s_config->r_idx==pi2s_config->w_idx) { /* Buffer Empty */ MSG("BE r=%d w=%d[i=%d,c=%d]\n",pi2s_config->r_idx,pi2s_config->w_idx,pi2s_config->isr_cnt,dma_ch); #ifdef I2S_STATISTIC pi2s_status->buffer_unrun++; #endif if(dma_ch==GDMA_I2S_TX0) { GdmaI2sTx(pi2s_config->page0buf8ptr , I2S_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_handler, i2s_unmask_handler); } else { GdmaI2sTx(pi2s_config->page1buf8ptr, I2S_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_handler, i2s_unmask_handler); } goto EXIT; } if(pi2s_config->pMMAPBufPtr==NULL) { MSG("mmap buf NULL\n"); if(dma_ch==GDMA_I2S_TX0) GdmaI2sTx(pi2s_config->page0buf8ptr, I2S_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_handler, i2s_unmask_handler); else GdmaI2sTx(pi2s_config->page1buf8ptr, I2S_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_handler, i2s_unmask_handler); goto EXIT; } #ifdef I2S_STATISTIC pi2s_status->buffer_len--; #endif if(dma_ch==GDMA_I2S_TX0) { //pi2s_config->page0buf8ptr = (pi2s_config->pMMAPBufPtr)+(pi2s_config->r_idx)*I2S_PAGE_SIZE; //dma_cache_wback_inv(pi2s_config->page0buf8ptr, I2S_PAGE_SIZE); memcpy(pi2s_config->page0buf8ptr, pi2s_config->pMMAPBufPtr+(pi2s_config->r_idx)*I2S_PAGE_SIZE, I2S_PAGE_SIZE); GdmaI2sTx((unsigned long)(pi2s_config->page0buf8ptr) , I2S_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_handler, i2s_unmask_handler); pi2s_config->dmach = GDMA_I2S_TX0; pi2s_config->r_idx = (pi2s_config->r_idx+1)%MAX_I2S_PAGE; } else { //pi2s_config->page1buf8ptr = (pi2s_config->pMMAPBufPtr)+(pi2s_config->r_idx)*I2S_PAGE_SIZE; //dma_cache_wback_inv((unsigned long)(pi2s_config->page1buf8ptr), I2S_PAGE_SIZE); memcpy(pi2s_config->page1buf8ptr, pi2s_config->pMMAPBufPtr+(pi2s_config->r_idx)*I2S_PAGE_SIZE, I2S_PAGE_SIZE); GdmaI2sTx((unsigned long)(pi2s_config->page1buf8ptr) , I2S_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_handler, i2s_unmask_handler); pi2s_config->dmach = GDMA_I2S_TX1; pi2s_config->r_idx = (pi2s_config->r_idx+1)%MAX_I2S_PAGE; } EXIT: if(pi2s_config->bSleep==1) { wake_up_interruptible(&(pi2s_config->i2s_qh)); pi2s_config->bSleep = 0; } return; }
static int i2s_dev_open(i2s_config_type* ptri2s_config) { int i, result, db, srate; unsigned int data = 0; MSG("i2s_dev_open \n"); /* set i2s clk */ data = i2s_inw(RALINK_SYSCTL_BASE+0x30); data &= 0xFFFF00FF; #ifdef I2S_MS_MODE #ifdef I2S_IN_CLKSRC data |= 0x00008000; /* for internal clock = 15.625 Mhz */ switch(ptri2s_config->srate) { case 8000: srate = 60<<8; break; case 11250: srate = 43<<8; break; case 16000: srate = 30<<8; break; case 22050: srate = 21<<8; break; case 24000: srate = 19<<8; break; case 32000: srate = 14<<8; break; case 44100: srate = 10<<8; break; case 48000: srate = 9<<8; break; case 88200: srate = 7<<8; break; case 96000: srate = 4<<8; break; default: srate = 10<<8; } #ifdef FPGA_BOARD_RT3052 /* for internal clock = 12.5Mhz */ switch(ptri2s_config->srate) { case 8000: srate = 48<<8; break; case 11250: srate = 34<<8; break; case 16000: srate = 23<<8; break; case 22050: srate = 17<<8; break; case 24000: srate = 15<<8; break; case 32000: srate = 11<<8; break; case 44100: srate = 8<<8; break; case 48000: srate = 7<<8; break; case 88200: srate = 5<<8; break; case 96000: srate = 3<<8; break; default: srate = 8<<8; } #endif #else data |= 0x0000C000; /* for external clock = 12.288Mhz */ switch(ptri2s_config->srate) { case 8000: srate = 48<<8; break; case 11250: srate = 34<<8; break; case 16000: srate = 23<<8; break; case 22050: srate = 17<<8; break; case 24000: srate = 15<<8; break; case 32000: srate = 11<<8; break; case 44100: srate = 8<<8; break; case 48000: srate = 7<<8; break; case 88200: srate = 5<<8; break; case 96000: srate = 3<<8; break; default: srate = 8<<8; } #endif data |= srate; #else /* for external clock = 12.288Mhz, I2S slave mode */ switch(ptri2s_config->srate) { case 8000: srate = 0x04; break; case 11250: srate = 0x10; break; case 16000: srate = 0x14; break; case 22050: srate = 0x38; break; case 24000: srate = 0x38; break; case 32000: srate = 0x18; break; case 44100: srate = 0x20; break; case 48000: srate = 0x00; break; case 88200: srate = 0x00; break; case 96000: srate = 0x1C; break; default: srate = 0x20; } #endif i2s_outw(RALINK_SYSCTL_BASE+0x30, data); MSG("RALINK_SYSCTL_BASE+0x30=0x%08X\n",data); /* set share pins to i2c */ data = i2s_inw(RALINK_REG_GPIOMODE); data &= 0xFFFFFFE0; data |= 0x00000008; i2s_outw(RALINK_REG_GPIOMODE, data); MSG("RALINK_REG_GPIOMODE=0x%08X\n",data); /* DAC initialization */ audiohw_preinit(); audiohw_postinit(); #ifdef I2S_MS_MODE #else audiohw_set_frequency(srate); #endif //saudiohw_enable_output(); //db = tenthdb2master(ptri2s_config->vol); //audiohw_set_lineout_vol(db, db); /* set I2S_I2SCFG */ data = i2s_inw(I2S_I2SCFG); data &= 0xFFFFFF80; data |= REGBIT(ptri2s_config->ff_thres, I2S_FF_THRES); data |= REGBIT(ptri2s_config->ch_swap, I2S_CH_SWAP); #ifdef I2S_MS_MODE data &= ~REGBIT(0x1, I2S_SLAVE_EN); data &= ~REGBIT(0x1, I2S_CLK_OUT_DIS); #else data |= REGBIT(0x1, I2S_SLAVE_EN); data |= REGBIT(0x1, I2S_CLK_OUT_DIS); #endif i2s_outw(I2S_I2SCFG, data); MSG("I2S_I2SCFG=%X\n",data); i2s_dev_enable(ptri2s_config); return I2S_OK; }
int i2s_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int x; unsigned long flags, data; i2s_config_type* ptri2s_config; ptri2s_config = filp->private_data; switch (cmd) { case I2S_SRATE: if((arg>MAX_SRATE_HZ)||(arg<MIN_SRATE_HZ)) { MSG("audio sampling rate %d should be %d ~ %d Hz\n", arg, MIN_SRATE_HZ, MAX_SRATE_HZ); break; } ptri2s_config->srate = arg; MSG("set audio sampling rate to %d Hz\n", ptri2s_config->srate); break; case I2S_VOL: if(((int)arg>MAX_VOL_DB)||((int)arg<MIN_VOL_DB)) { MSG("audio volumn %d should be %d ~ %d dB\n", arg, MIN_VOL_DB, MAX_VOL_DB); break; } ptri2s_config->vol = arg; x = 2*arg+255; audiohw_set_master_vol(x, x); MSG("set audio volumn to %d dB\n", ptri2s_config->vol); break; case I2S_ENABLE: ptri2s_config->isr_cnt = 0; pi2s_status->buffer_unrun = 0; pi2s_status->buffer_ovrun = 0; pi2s_status->txdmafault = 0; pi2s_status->ovrun = 0; pi2s_status->unrun = 0; pi2s_status->thres = 0; pi2s_status->buffer_len = 0; data = i2s_inw(RALINK_REG_INTENA); //data |=0x0400; data &=0xFFBFF; i2s_outw(RALINK_REG_INTENA, data); MSG("i2s audio enable\n"); if(i2s_dev_open(ptri2s_config)!=I2S_OK) { i2s_release(inode, filp); return -1; } wake_up_interruptible(&(ptri2s_config->i2s_qh)); break; case I2S_DISABLE: MSG("i2s audio disable\n"); data = i2s_inw(RALINK_REG_INTENA); data &= 0xFFFFFBFF; i2s_outw(RALINK_REG_INTENA, data); ptri2s_config->bDMAStart = 0; i2s_dev_close(ptri2s_config); wake_up_interruptible(&(ptri2s_config->i2s_qh)); break; case I2S_GET_WBUF: #ifdef I2S_FIFO_MODE { int i,j; long* pBufPtr = pi2s_config->pMMAPBufPtr+(pi2s_config->w_idx)*I2S_PAGE_SIZE; for(i=0; i<I2S_PAGE_SIZE>>2; i++) { long status; i2s_outw(I2S_FIFO_WREG, bswap_32(pBufPtr[i])); while(1) { status = i2s_inw(I2S_FF_STATUS); if(status&0x00F!=0) break; } } ptri2s_config->w_idx = (ptri2s_config->w_idx+1)%MAX_I2S_PAGE; (int)(*(int*)arg) = (int)ptri2s_config->w_idx; break; } #endif if(ptri2s_config->bDMAStart==0) { GdmaI2sTx(ptri2s_config->page0buf8ptr, I2S_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_handler, i2s_unmask_handler); GdmaI2sTx(ptri2s_config->page1buf8ptr, I2S_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_handler, i2s_unmask_handler); ptri2s_config->bDMAStart=1; GdmaUnMaskChannel(GDMA_I2S_TX0); } do{ spin_lock_irqsave(&ptri2s_config->lock, flags); if(((ptri2s_config->w_idx+1)%MAX_I2S_PAGE)!=ptri2s_config->r_idx) { ptri2s_config->w_idx = (ptri2s_config->w_idx+1)%MAX_I2S_PAGE; (int)(*(int*)arg) = (int)ptri2s_config->w_idx; pi2s_status->buffer_len++; spin_unlock_irqrestore(&ptri2s_config->lock, flags); break; } else { /* Buffer Full */ //printk("BF w=%d, r=%d\n", ptri2s_config->w_idx, ptri2s_config->r_idx); pi2s_status->buffer_ovrun++; ptri2s_config->bSleep = 1; spin_unlock_irqrestore(&ptri2s_config->lock, flags); interruptible_sleep_on(&(ptri2s_config->i2s_qh)); } }while(1); break; default : MSG("i2s_ioctl: command format error\n"); } return 0; }