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

📄 audio.c

📁 9200下的音频驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
			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 + -