📄 audio.c
字号:
break;
case 106:
I2C_write(0x10, volume[6]<<8|volume[6], 2);
break;
case 107:
I2C_write(0x10, volume[7]<<8|volume[7], 2);
break;
case 108:
I2C_write(0x10, volume[8]<<8|volume[8], 2);
break;
case 109:
I2C_write(0x10, volume[9]<<8|volume[9], 2);
break;
default :
ret = -EINVAL;
break;
}
#endif
return ret;
}
static void ssc_interrupt_handler(int irq,void *dev_id,struct pt_regs *regs)
{
unsigned long *bp;
U32 dma_addr;
int i;
// aic_regs->AIC_ICCR = 0x1 << AT91C_ID_SSC1;// clear interrupt
// DPRINTK("ssc_interrupt_handler,SSC_SR=%x\n",ssc_regs->SSC_SR);
// DPRINTK("a9200_dmastart=%x a9200_append=%x\n",a9200_dmastart,a9200_append);
#if 0
if((ssc_regs->SSC_SR & AT91C_SSC_TXENA))
{
DPRINTK("I'm in at91_audio_interrupt for transfor!...\n");
if(a9200_dmastart == a9200_append)
{
aic_regs->AIC_IDCR = 0x1 << AT91C_ID_SSC1;// disable interrupt
aic_regs->AIC_ICCR = 0x1 << AT91C_ID_SSC1;// clear interrupt
ssc_regs->SSC_IDR = 0x1;// disable interrupt
while(!(ssc_regs->SSC_SR & AT91C_SSC_ENDTX)){
// udelay(16);
}
/* SSC Control Register */
pdc_regs->PDC_PTCR = AT91C_PDC_TXTDIS;
ssc_regs->SSC_CR = AT91C_SSC_TXDIS;
a9200_txbusy = 0;
DPRINTK("Transmit end...\n");
}
else
{
bp = (unsigned long *) & a9200_buf[a9200_dmastart];
dma_addr = virt_to_phys((void *)bp);
AT91F_PDC_SetTx(pdc_regs,(char *)dma_addr,DMASIZE/2);
//AT91F_PDC_SetNextTx(pdc_regs,(char *)(dma_addr + DMASIZE / 4),DMASIZE/4);
//printk("Transmit the buf.....\n");
//ssc_regs->SSC_THR = *bp;
while(!(ssc_regs->SSC_SR & AT91C_SSC_TXRDY)){
// udelay(1);
}
a9200_dmastart += DMASIZE;
if(a9200_dmastart >= BUFSIZE)
a9200_dmastart = 0;
}
}
#endif
#if 1
//if(!(ssc_regs->SSC_SR & AT91C_SSC_RXEN))
//DPRINTK("read interrupt -----> \n");
if(a9200_rxstart == a9200_rxend)
{
aic_regs->AIC_IDCR = 0x1 << AT91C_ID_SSC1;// disable interrupt
aic_regs->AIC_ICCR = 0x1 << AT91C_ID_SSC1;// clear interrupt
ssc_regs->SSC_IDR = 0x1 << 4;// disable interrupt
while(!(ssc_regs->SSC_SR & AT91C_SSC_ENDRX)){
// udelay(16);
}
/* SSC_CR */
ssc_regs->SSC_CR = AT91C_SSC_RXDIS;
a9200_rxbusy = 0;
a9200_rxstart = 0;
//DPRINTK("receive end.\n");
}
else
{
bp = (unsigned long *) a9200_buf + a9200_rxstart;
//DPRINTK("bp = %p rxstart = %p rxend = %p \n",bp,a9200_rxstart,a9200_rxend);
//dma_addr = virt_to_phys((void *)bp);
//AT91F_PDC_SetRx(pdc_regs,(char *)dma_addr,RXSIZE);
//AT91F_PDC_SetNextRx(pdc_regs,(char *)(dma_addr+4),RXSIZE);
for(i=0;i<8;i++) {
*bp++ = ssc_regs->SSC_RHR << 16 | ssc_regs->SSC_RHR;
while(!(ssc_regs->SSC_SR & AT91C_SSC_RXRDY)){
// udelay(1);
}
}
a9200_rxstart += 8;
}
#endif
}
static void at91_audio_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned int ssc_rsier,ssc_tsier;
// aic_regs->AIC_ICCR = 0x1 << AT91C_ID_SSC1;// clear interrupt
// ssc_regs->SSC_IDR = AT91C_SSC_ENDTX; // disbale endtx interrupt
// pdc_regs->PDC_PTCR = AT91C_PDC_TXTDIS;
// DPRINTK("I'm in at91_audio_interrupt!...\n");
// DPRINTK("ssc_interrupt_handler,SSC_SR=%x\n",ssc_regs->SSC_SR);//ssr_sr=10ccf
// ssc_rsier = (ssc_regs->SSC_SR) & AT91C_SSC_RXENA;
// pdc_rsier = (pdc_regs->PDC_PTSR) && AT91C_PDC_RXTEN;
// ssc_tsier = (ssc_regs->SSC_SR) & AT91C_SSC_TXENA;
// pdc_tsier = (pdc_regs->PDC_PTSR) && AT91C_PDC_TXTEN;
// DPRINTK("ssc_rsier=%x\n",ssc_rsier);
// DPRINTK("ssc_tsier=%x\n",ssc_tsier);
//do
//{
/*if it is a RFINT*/
if((ssc_regs->SSC_SR) & AT91C_SSC_RXENA)
{
//DPRINTK("I'm in at91_audio_interrupt for receive!...\n");
ssc_interrupt_handler(irq,dev_id,regs);
}
/*if it is a TFINT*/
if ((ssc_regs->SSC_SR) & AT91C_SSC_TXENA)
{
// DPRINTK("I'm in at91_audio_interrupt for transfer!...\n");
a9200_tx_dmaisr(irq,dev_id,regs);
}
//} while((ssc_rsier) || (ssc_tsier ));
}
/**********************************************************
本函数用于启动DMA传输,将数据从内核缓冲区
写入到用户缓冲区.
***********************************************************/
/*
void __inline__ a9200_rx_dmarun(void)
{
unsigned long *bp;
U32 dma_rx_addr;
// unsigned char pdc_ptcr_rx,ssc_cr_rx;
// unsigned char ssc_ier_rx;
a9200_rxdmaing = 1;
a9200_rxbusy = 1;
bp = (unsigned long *) a9200_buf + a9200_rxstart;
dma_rx_addr = virt_to_phys((void *)bp);
AT91F_PDC_SetRx(pdc_regs,(char *)dma_rx_addr,DMASIZE);
pdc_regs ->PDC_PTCR = AT91C_PDC_RXTEN;
ssc_regs ->SSC_CR = AT91C_SSC_RXEN;
// pdc_ptcr_rx = AT91C_PDC_RXTEN;
// ssc_cr_rx = AT91C_SSC_RXEN;
//DPRINTK("pdc_ptsr = %p ssc_sr = %p \n",pdc_regs->PDC_PTSR,ssc_regs->SSC_SR);
ssc_regs->SSC_IER = AT91C_SSC_ENDRX; // enable endrx interrupt
// ssc_ier_rx = AT91C_SSC_ENDRX >> 6;
//DPRINTK("ssc_imr = %p \n",ssc_regs->SSC_IMR);
}
*/
/*
void a9200_rx_dmabuf(void)
{
// if already running then nothing to do
if(a9200_rxdmaing)
return;
#if 0
// set dma transfer count
a9200_rxdmacount = a9200_rxappend - a9200_rxappstart;
a9200_rxdmacount = (a9200_rxdmacount > DMASIZE) ? DMASIZE : a9200_rxdmacount;
// adjust pointers and counters accordingly
a9200_rxappstart += a9200_rxdmacount;
DPRINTK("rxdmacount = %d rxappstart = %d rxappend = %d \n",a9200_rxdmacount,a9200_rxappstart,a9200_rxappend);
if(a9200_rxdmacount > 0)
{
a9200_rx_dmarun();
}
else
{
a9200_rxbusy = 0;
a9200_rxappstart = 0;
}
#else
a9200_rx_dmarun();
#endif
}
*/
/*
void a9200_rx_dmaisr(int irq,void *dev_id,struct pt_regs *regs)
{
// clear dma interrupt
aic_regs->AIC_ICCR = 0x1 << AT91C_ID_SSC1; // clear interrupt
ssc_regs->SSC_IDR = AT91C_SSC_ENDRX; // disbale endrx interrupt
a9200_rxdmaing = 0;
a9200_rxdmastart += DMASIZE;
a9200_rxdmacount = 0;
a9200_rx_dmabuf();
}
*/
/*
static int at91_mixer_open(struct inode * inode, struct file * filp)
{
UINT32 flags;
a9200_speed = 44100;
a9200_format = AFMT_S16_BE;
a9200_bits = 16;
a9200_stereo = 1;
a9200_isopen = 1;
a9200_rxbusy = 0;
a9200_dmaing = 0;
a9200_rxdmaing = 0;
//#if 1
/* Define the Clock Mode Register at 2*16*44100 => 1.4112 MHz */
/* AT91F_SSC_SetBaudrate(ssc_regs, AT91C_MASTER_CLOCK,FILE_SAMPLING_FREQ *
(BITS_BY_SLOT * SLOT_BY_FRAME));
ssc_regs->SSC_IDR = 0xCFF; //disabled all
aic_regs->AIC_IECR = 0x1 << AT91C_ID_SSC1; //Enable interrupt
/* SSC Transmit Clock Mode Register */
// ssc_regs->SSC_TCMR = I2S_ASY_MASTER_TX_SETTING(BITS_BY_SLOT,SLOT_BY_FRAME);
/* SSC Transmit Frame Mode Register */
// ssc_regs->SSC_TFMR = I2S_ASY_TX_FRAME_SETTING(BITS_BY_SLOT,SLOT_BY_FRAME);
/* SSC_RFMR */
// ssc_regs->SSC_RFMR = I2S_ASY_TX_FRAME_SETTING(BITS_BY_SLOT,SLOT_BY_FRAME);
/* SSC_RCMR */
// ssc_regs->SSC_RCMR = I2S_ASY_MASTER_TX_SETTING(BITS_BY_SLOT,SLOT_BY_FRAME);
//#endif
// codec_init(uda1380_init);
// return 0;
//}
static int at91_audio_open(struct inode * inode, struct file * filp)
{
UINT32 flags;
a9200_speed = 44100;
a9200_format = AFMT_S16_BE;
a9200_bits = 16;
a9200_stereo = 1;
a9200_isopen = 1;
a9200_rxbusy = 0;
a9200_dmaing = 0;
a9200_rxdmaing = 0;
/* Define the Clock Mode Register at 2*16*44100 => 1.4112 MHz */
AT91F_SSC_SetBaudrate(ssc_regs, AT91C_MASTER_CLOCK,FILE_SAMPLING_FREQ *
(BITS_BY_SLOT * SLOT_BY_FRAME));
ssc_regs->SSC_IDR = 0xCFF; //disabled all
aic_regs->AIC_IECR = 0x1 << AT91C_ID_SSC1; //Enable interrupt
/* SSC Transmit Clock Mode Register */
ssc_regs->SSC_TCMR = I2S_ASY_MASTER_TX_SETTING(BITS_BY_SLOT,SLOT_BY_FRAME);
/* SSC Transmit Frame Mode Register */
ssc_regs->SSC_TFMR = I2S_ASY_TX_FRAME_SETTING(BITS_BY_SLOT,SLOT_BY_FRAME);
//printk("open : ssc_tcmr = %p , ssc_tfmr = %p .\n",ssc_regs->SSC_TCMR,ssc_regs->SSC_TFMR);
//printk("open : ssc_rcmr = %p , ssc_rfmr = %p.\n",ssc_regs->SSC_RCMR,ssc_regs->SSC_RFMR);
/* SSC_RFMR */
ssc_regs->SSC_RFMR = I2S_ASY_TX_FRAME_SETTING(BITS_BY_SLOT,SLOT_BY_FRAME);
/* SSC_RCMR */
ssc_regs->SSC_RCMR = I2S_ASY_MASTER_TX_SETTING(BITS_BY_SLOT,SLOT_BY_FRAME);
//codec_init(uda1380_tx_init);
DPRINTK("open dev complete..! \n");
return 0;
}
static int at91_audio_close(struct inode *inode, struct file *filp)
{
//DPRINTK("now cloes ... \n");
a9200_txdrain();
// soft reset
ssc_regs->SSC_CR = AT91C_SSC_SWRST;
AT91F_PDC_Close(pdc_regs);
//DPRINTK("ssc_sr = %p ssc_imr = %p \n", ssc_regs->SSC_SR,ssc_regs->SSC_IMR);
a9200_dmaing = 0;
a9200_txbusy =0;
a9200_dmastart = 0;
a9200_dmacount = 0;
a9200_appstart = 0;
a9200_append = 0;
a9200_isopen = 0;
a9200_rxstart = 0;
a9200_rxend = 0;
DPRINTK("cloes dev complete! ... \n");
return (0);
}
/*
static int at91_mixer_close(struct inode *inode, struct file *filp)
{
//DPRINTK("now cloes ... \n");
// a9200_txdrain();
// soft reset
ssc_regs->SSC_CR = AT91C_SSC_SWRST;
//DPRINTK("ssc_sr = %p ssc_imr = %p \n", ssc_regs->SSC_SR,ssc_regs->SSC_IMR);
a9200_dmaing = 0;
a9200_txbusy =0;
a9200_dmastart = 0;
a9200_dmacount = 0;
a9200_appstart = 0;
a9200_append = 0;
a9200_isopen = 0;
a9200_rxstart = 0;
a9200_rxend = 0;
return (0);
}
*/
/**********************************************************
录音函数
***********************************************************/
static ssize_t at91_audio_read(struct file *file,char *buf,size_t count,loff_t * ppos)
{
unsigned long *buflp,*appbuflp,tmp;
unsigned long bufcnt,slen;
unsigned int i;
const unsigned long LBUFSIZE = BUFSIZE / 100;
if(count <= 0)
return 0;
bufcnt = count;
appbuflp = (unsigned long *) buf;
buflp = (unsigned long *) a9200_buf;
if(a9200_stereo == 1)
bufcnt >>= 1;
if(a9200_bits == 16)
bufcnt >>= 1;
tryagain:
a9200_rxstart = 0;
if(LBUFSIZE >= bufcnt)
{
slen = bufcnt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -