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

📄 at91_audio.c

📁 H9200F(2.6.12)的音频接口驱动。 操作方法: 1、将驱动程序rsound.ko拷贝到系统目录:/lib/modules 2、执行如下命令加载模块: insmod /
💻 C
📖 第 1 页 / 共 2 页
字号:
                      buflp = (unsigned short *)(b->start + s->fragsize - b->size);       for(i = 0;i < chunksize;i+=2)     {         *appbuflp++ = (((unsigned long) *buflp) << 16) | *buflp;         buflp++;     }	 				 tmpint2 = chunksize/2;     b->size -= chunksize;     bufcnt -= tmpint2 ;         if(a9200_stereo == 1)   	    tmpint2 <<= 1;     if(a9200_bits == 16)        tmpint2 <<= 1;                tmpint += tmpint2 ;              		 if (b->size > 0) 		 {			  up(&b->sem);			  break;	 	 }		 /* Make current buffer available for DMA again */		 at91rm9200_dma_queue_buffer(s->dma, (void *) b,					b->dma_addr, s->fragsize);		 wmb();		   	 NEXT_BUF(s, buf);		 wmb();		 b = s->buf;		 }   ssc_regs->SSC_CR |= AT91C_SSC_RXDIS;   pdc_regs->PDC_PTCR |= AT91C_PDC_RXTDIS;	 ret = tmpint;			 DPRINTK("audio_read: return=%d\n", ret);	 return ret;}/*----------------------------------------------------- * Name :      at91_audio_write() * Function:   Write Data to Audio   * Last rework data: 06-04-13   wujh@hyesco.com *----------------------------------------------------*/static ssize_t at91_audio_write(struct file *file, const char *buffer, size_t count,loff_t *ppos){   const char *buffer0 = buffer;   audio_stream_t *s = &output_stream;   int chunksize, ret = 0;   unsigned int bufcnt;   DPRINTK("audio_write: count=%d\n", count);   if (*ppos != file->f_pos)       return -ESPIPE;   	 if (!s->active) {       if (!s->buffers && at91_audio_setup_buf(s))          return -ENOMEM;   }          bufcnt = count & ~0x3;       while (bufcnt) {       audio_buf_t *b = s->buf;       /* Wait for a buffer to become free */       if (file->f_flags & O_NONBLOCK) {            ret = -EAGAIN;            if (down_trylock(&b->sem))              break;       } else {            ret = -ERESTARTSYS;            if (down_interruptible(&b->sem))               break;       }       /* Feed the current buffer */       chunksize = s->fragsize - b->size;       if (chunksize > bufcnt)           chunksize = bufcnt;       DPRINTK("write %d to %d\n", chunksize, s->buf_idx);                       if (copy_from_user(b->start + b->size, buffer, chunksize)) {            up(&b->sem);            return -EFAULT;       }              b->size += chunksize;       buffer += chunksize;       bufcnt -= chunksize;             if (b->size < s->fragsize)       {       up(&b->sem);       break;      }              /* Send current buffer to dma */       s->active = 1;       at91rm9200_dma_queue_buffer(s->dma, (void *) b,                                   b->dma_addr, b->size);       b->size = 0;    /* indicate that the buffer has been sent */              NEXT_BUF(s, buf);    }    if ((buffer - buffer0))    ret = buffer - buffer0;        DPRINTK("audio_write: return=%d\n", ret);    return ret;                        }/*----------------------------------------------------- * Name :      at91_audio_out_done_callback() * Function:   Out done callback function  * Last rework data: 06-04-14   wujh@hyesco.com *----------------------------------------------------*/void at91_audio_out_done_callback(void *buf_id, int size){	  audio_buf_t *b = (audio_buf_t *) buf_id;	  audio_stream_t *s = b->stream;    //release sem 		up(&b->sem);	  b->size = 0;	  /* And any process polling on write. */	  wake_up(&s->wq);	}/*----------------------------------------------------- * Name :      audio_in_done_callback() * Function:   In done callback function  * Last rework data: 06-04-14   wujh@hyesco.com *----------------------------------------------------*/void at91_audio_in_done_callback(void *buf_id, int size){	   audio_buf_t *b = (audio_buf_t *) buf_id;	   audio_stream_t *s = b->stream;    //release sem 		 b->size = size;	   wmb();		 up(&b->sem);	  /* And any process polling on write. */	  wake_up(&s->wq);	}/*----------------------------------------------------- * Name :      at91_audio_out_irq_oper() * Function:   diable or enable endtx irq function  * Last rework data: 06-04-14   wujh@hyesco.com *----------------------------------------------------*/void at91_audio_out_irq_oper(U8 size){   if(size)   {       // enable endtx interrupt    	       //ssc_regs->SSC_CR |= AT91C_SSC_TXEN;       ssc_regs->SSC_IER |= (AT91C_SSC_ENDTX | AT91C_SSC_TXBUFE) ;			 //pdc_regs->PDC_PTCR |= AT91C_PDC_TXTEN;		    }   else   {	      //Disable ssc Rx and endrx irq		      ssc_regs->SSC_IDR |= (AT91C_SSC_ENDTX | AT91C_SSC_TXBUFE);        //ssc_regs->SSC_CR |= (AT91C_SSC_ENDTX | AT91C_SSC_TXBUFE) ;				//pdc_regs->PDC_PTCR |= AT91C_PDC_TXTDIS;		    }	      	}/*----------------------------------------------------- * Name :      at91_audio_in_irq_oper() * Function:   diable or enable endrx irq function  * Last rework data: 06-04-14   wujh@hyesco.com *----------------------------------------------------*/void at91_audio_in_irq_oper(U8 size){   if(size)   {        // enable endrx interrupt     	        //ssc_regs->SSC_CR |= AT91C_SSC_RXEN  ;        ssc_regs->SSC_IER |= (AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF); 		    //pdc_regs->PDC_PTCR |= AT91C_PDC_RXTEN;     }   else   {	      //Disable ssc Rx and endrx irq		      ssc_regs->SSC_IDR |= (AT91C_SSC_ENDRX | AT91C_SSC_RXBUFF);        //ssc_regs->SSC_CR |= AT91C_SSC_RXDIS;					//pdc_regs->PDC_PTCR |= AT91C_PDC_RXTDIS;		    }	      	}/*----------------------------------------------------- * Name :      at91_audio_in_done_callback() * Function:   In done callback function  * Last rework data: 06-04-14   wujh@hyesco.com *----------------------------------------------------*/void at91_audio_status_callback(U8* status){	int temp,temp2;		temp = ssc_regs->SSC_SR;	temp2 = ssc_regs->SSC_IMR;		if((temp & AT91C_SSC_TXBUFE) && (temp2 & AT91C_SSC_TXBUFE))		*status = 2;	else if((temp & AT91C_SSC_ENDTX) && (temp2 & AT91C_SSC_ENDTX))		*status = 1;	else if((temp & AT91C_SSC_RXBUFF) && (temp2 & AT91C_SSC_RXBUFF))		*status = 4;	else if((temp & AT91C_SSC_ENDRX) && (temp2 & AT91C_SSC_ENDRX))		*status = 3;	else     *status = 0 ; }/*----------------------------------------------------- * Name :      at91_audio_poll() * Function:   support poll sys-call function  * Last rework data: 06-04-14   wujh@hyesco.com *----------------------------------------------------*/static unsigned int at91_audio_poll(struct file *file,			       struct poll_table_struct *wait){	  audio_stream_t *is = &input_stream;	  audio_stream_t *os = &output_stream;	  unsigned int mask = 0;	  int i;	  DPRINTK("audio_poll(): mode=%s%s\n",		(file->f_mode & FMODE_READ) ? "r" : "",		(file->f_mode & FMODE_WRITE) ? "w" : "");	  if (file->f_mode & FMODE_READ) {		/* Start ssc input if not already active */		if (!is->active) {			if (!is->buffers && at91_audio_setup_buf(is))				return -ENOMEM;			at91_audio_prime_dma(is);		 }		 poll_wait(file, &is->wq, wait);	  }	  if (file->f_mode & FMODE_WRITE) {		if (!os->buffers && at91_audio_setup_buf(os))			return -ENOMEM;					poll_wait(file, &os->wq, wait);	 }	 if (file->f_mode & FMODE_READ) {			for (i = 0; i < is->nbfrags; i++) {				if (atomic_read(&is->buffers[i].sem.count) > 0) {					mask |= POLLIN | POLLRDNORM;					break;				}			}	 }	 if (file->f_mode & FMODE_WRITE) {			for (i = 0; i < os->nbfrags; i++) {				if (atomic_read(&os->buffers[i].sem.count) > 0) {					mask |= POLLOUT | POLLWRNORM;					break;				}			}	 }	 DPRINTK("audio_poll() returned mask of %s%s\n",		(mask & POLLIN) ? "r" : "",		(mask & POLLOUT) ? "w" : "");	 return mask;}/* file operation stuct for Audio */                                                                                 struct file_operations at91_audio_fops = { 	owner:		        THIS_MODULE,	open:           	at91_audio_open,	release:        	at91_audio_release,  read:           	at91_audio_read,		  write:           	at91_audio_write,	  	  ioctl:            at91_audio_ioctl,  poll:             at91_audio_poll,	};     /*----------------------------------------------------- * Name :      AUDIO_At91_Init() * Function:   Init Audio driver module  * Last rework data: 06-04-13   wujh@hyesco.com *----------------------------------------------------*/                                                                          static int __init AUDIO_At91_Init(void){                                                                                     unsigned int err=0;        DPRINTK("AT91RM9200 audio driver version 0.1, build time:" __TIME__ "\n");                audio_dev_dsp = register_sound_dsp(&at91_audio_fops, -1);          // Init SSC regs        SSC_init();         //init the output at91rm9200_dma_t struct          		    output_stream.fragsize = AUDIO_FRAGSIZE_DEFAULT;		    output_stream.nbfrags = AUDIO_NBFRAGS_DEFAULT;		    output_stream.dma = &dma_chan[OUT_CHAN];        output_stream.active = 0;		    init_waitqueue_head(&(output_stream.wq));         dma_chan[IN_CHAN].flag = 0 ; 		              dma_chan[OUT_CHAN].regs = pdc_regs ;        dma_chan[OUT_CHAN].irq_on_off = at91_audio_out_irq_oper ;                        dma_chan[OUT_CHAN].callback = at91_audio_out_done_callback ;           dma_chan[OUT_CHAN].type =  SLOT_BY_FRAME;                dma_chan[OUT_CHAN].dma_channel = 2;         //init the input at91rm9200_dma_t struct  		    input_stream.fragsize = AUDIO_FRAGSIZE_DEFAULT;		    input_stream.nbfrags = AUDIO_NBFRAGS_DEFAULT;  		    input_stream.dma = &dma_chan[IN_CHAN]; 		    init_waitqueue_head(&(input_stream.wq));        input_stream.active = 0;		                   dma_chan[IN_CHAN].flag = 1 ;                   dma_chan[IN_CHAN].regs = pdc_regs ;         dma_chan[IN_CHAN].irq_on_off = at91_audio_in_irq_oper ;                                                     dma_chan[IN_CHAN].callback = at91_audio_in_done_callback ;        dma_chan[IN_CHAN].type =  SLOT_BY_FRAME;         dma_chan[IN_CHAN].dma_channel = 2;                  audio_state.irq = AT91C_ID_SSC1 ;        audio_state.device_id = AUDIO_MODULE_NAME ;         audio_state.readstatback = at91_audio_status_callback ;          audio_state.out_chan = &dma_chan[OUT_CHAN];            audio_state.in_chan = &dma_chan[IN_CHAN];                        //register the at91rm9200_dma irq               err = at91rm9200_dma_init(&audio_state);        if(err)        {        	 DPRINTK("<1>init out at91rm9200_dma_t err! \n");		       return err;        }                                         I2C_test();                        codec_init(uda1380_rx_init);	      return 0;}/*----------------------------------------------------- * Name :      AUDIO_At91_Cleanup() * Function:   Exit Audio driver module  * Last rework data: 06-04-13   wujh@hyesco.com *----------------------------------------------------*/static void __exit AUDIO_At91_Cleanup(void){        DPRINTK("Rmmod audio driver.\n");	              at91rm9200_free_dma(&audio_state);				at91_audio_clear_buf(&input_stream);				at91_audio_clear_buf(&output_stream);	        unregister_sound_dsp(audio_dev_dsp);}                                                                                               module_init(AUDIO_At91_Init);module_exit(AUDIO_At91_Cleanup);/*-----------------------------------------------------*/MODULE_AUTHOR("casiawu <wujh@hyesco.com>");MODULE_DESCRIPTION("AT91 AUDIO Driver (AT91_AUDIO)");MODULE_LICENSE("Proprietary");

⌨️ 快捷键说明

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