📄 record.c
字号:
#include "khead.h"#include <sound_config.h>#include <dev_table.h>#include <linux/soundcard.h>#include "sound.h"#include <asm/arch/pio.h>#include <asm/arch/AT91RM9200_PDC.h>#include <asm/arch/AT91RM9200_SSC.h>#include <linux/spinlock.h>#include "lib_SSC.h" /* HHTech add, uda1380 i2c commands */extern unsigned int I2C_test(void);extern unsigned int I2C_read(unsigned int reg, unsigned int *_data, int);extern unsigned int I2C_write(unsigned int reg, unsigned int data, int);#define I2S_ASY_MASTER_TX_SETTING(nb_bit_by_slot, nb_slot_by_frame)( +\AT91C_SSC_CKS_DIV +\AT91C_SSC_CKO_CONTINOUS +\AT91C_SSC_START_FALL_RF +\((1<<16) & AT91C_SSC_STTDLY) +\((((nb_bit_by_slot*nb_slot_by_frame)/2)-1) <<24))#define I2S_ASY_TX_FRAME_SETTING(nb_bit_by_slot, nb_slot_by_frame)( +\(nb_bit_by_slot-1) +\AT91C_SSC_MSBF +\(((nb_slot_by_frame-1)<<8) & AT91C_SSC_DATNB) +\(((nb_bit_by_slot-1)<<16) & AT91C_SSC_FSLEN) +\AT91C_SSC_FSOS_NEGATIVE) static int audio_dev_dsp; static spinlock_t tx_count_lock;static spinlock_t rx_count_lock;static wait_queue_head_t rx_buffer_end; AT91PS_SSC ssc_regs;AT91PS_PDC pdc_regs;AT91PS_AIC aic_regs; //#define dmatrans#define BUFSIZE (256*1024)#define DMASIZE (64*1024)int a9200_isopen;int a9200_txbusy,a9200_rxbusy;int a9200_dmaing,a9200_rxdmaing;unsigned int a9200_speed;unsigned int a9200_stereo;unsigned int a9200_bits;unsigned int a9200_format;volatile unsigned int a9200_rxstart;volatile unsigned int a9200_rxend;unsigned char *a9200_tx_buf;unsigned char *a9200_rx_buf;volatile unsigned int a9200_dmastart;volatile unsigned int a9200_dmacount,a9200_rxdmacount;volatile unsigned int a9200_append; unsigned char uda1380_rx_init[] = { 0x00, 0x0f, 0x3f, 0x01, 0x00, 0x88, 0x02, 0xaf, 0xff, 0x03, 0x00, 0x00, 0x04, 0x02, 0x02, 0x10, 0x00, 0x00, 0x11, 0xb0, 0xb0, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x08, 0x08, 0x22, 0x16, 0x0C, 0x23, 0x00, 0x00}; void codec_init(unsigned char *command){ int ic; unsigned int msb, lsb, data, reg; // PDEBUG("Testing I2C\n");// printk("Init uda1380...\n"); for (ic = 0; ic < 42; ic += 3) { reg = command[ic]; lsb = command[ic + 1]; msb = command[ic + 2]; data = msb << 8 | lsb; I2C_write(reg, data, 2); //I2C_read(reg,&tata,2); //printk("0x%p data set to = %p ( %p )\n",reg,tata,data); }// printk("UDA1380 init ok.\n");} void SSC_init(void){ // printk("Init SSC...\n"); ssc_regs = (AT91PS_SSC) AT91C_VA_BASE_SSC1; pdc_regs = (AT91PS_PDC) AT91C_VA_BASE_PDC_SSC1; aic_regs = (AT91PS_AIC) AT91C_VA_BASE_AIC; 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; spin_lock_init(&tx_count_lock); spin_lock_init(&rx_count_lock); init_waitqueue_head(&rx_buffer_end); AT91_SYS->PMC_PCER = 1 << AT91C_ID_SSC1;/* Peripheral Clock Enable */ /*soft reset */ ssc_regs->SSC_CR = AT91C_SSC_SWRST; /* Clear Transmit and Receive Counters */ AT91F_PDC_Close(pdc_regs); 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);} static unsigned int ssi_audio_setbits(int dev, unsigned int bits){ return 1 ; } static signed short ssi_audio_setchannel(int dev, signed short channels){ return 1 ; } static int ssi_audio_setspeed(int dev, int speed){ return 1 ; }void a9200_mute(void){} /******************************************************************************************************* Input:* dev: The major number of the device.* cmd: The command to control the codec.* Value Returned: 1 success.* -1 falure.** Description: This routine will be used to control the codec.** Modification History:* 8 JAN,2002, Initial version. Li Qin*******************************************************************************************************/static int at91_audio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,unsigned long arg){ // int val, ret = 0; // U32 tmpdata; // U8 lsb, msb; return 1;}//int a9200_tx_dmarunflag=0;void __inline__ a9200_tx_dmarun(void){ unsigned long *bp; U32 dma_tx_addr; // if(a9200_tx_dmarunflag==0)// {// printk("a9200_tx_dmarun.\n");// a9200_tx_dmarunflag = 1;// } a9200_dmaing = 1; a9200_txbusy = 1; bp = (unsigned long *) & a9200_tx_buf[a9200_dmastart]; dma_tx_addr = virt_to_phys((void *)bp); AT91F_PDC_SetTx(pdc_regs,(char *)dma_tx_addr,a9200_dmacount/2);// AT91F_PDC_SetNextTx(pdc_regs,(char *)dma_tx_addr,a9200_dmacount/2); //pdc_regs->PDC_PTCR = AT91C_PDC_TXTDIS; pdc_regs->PDC_PTCR = AT91C_PDC_TXTEN; ssc_regs->SSC_CR = AT91C_SSC_TXEN;//printk("pdc_ptsr = %p ssc_sr = %p \n",pdc_regs->PDC_PTSR,ssc_regs->SSC_SR); ssc_regs->SSC_IER = 0x1 << 2; // endtx interrupt }//int a9200_tx_dmabufflag=0;void a9200_tx_dmabuf(void){ // if already running// if(a9200_tx_dmabufflag == 0)// {// printk("a9200_tx_dmabuf.\n");// a9200_tx_dmabufflag = 1;// } if(a9200_dmaing) return; spin_lock(&tx_count_lock); // set dma buff size a9200_dmacount = (a9200_append >= a9200_dmastart) ? (a9200_append - a9200_dmastart) : (BUFSIZE - a9200_dmastart); if(a9200_dmacount > DMASIZE) a9200_dmacount = DMASIZE ; if(a9200_dmacount > 0) a9200_tx_dmarun(); else a9200_txbusy = 0; spin_unlock(&tx_count_lock);}//int a9200_rx_dmarunflag=0;void __inline__ a9200_rx_dmarun(void){ unsigned long *bp; U32 dma_rx_addr; a9200_rxdmaing = 1; a9200_rxbusy = 1;// if(a9200_rx_dmarunflag==0)// {// printk("a9200_rx_dmarun. \n");// a9200_rx_dmarunflag=1;// } bp = (unsigned long *) a9200_rx_buf + a9200_rxstart; dma_rx_addr = virt_to_phys((void *)bp); AT91F_PDC_SetRx(pdc_regs,(char *)dma_rx_addr,a9200_rxdmacount); pdc_regs->PDC_PTCR = AT91C_PDC_RXTEN; ssc_regs->SSC_CR = AT91C_SSC_RXEN;//printk("pdc_ptsr = %p ssc_sr = %p \n",pdc_regs->PDC_PTSR,ssc_regs->SSC_SR); ssc_regs->SSC_IER = 0x1 << 6; // enable endrx interrupt//printk("ssc_imr = %p \n",ssc_regs->SSC_IMR);}//int a9200_rx_dmabufflag=0;void a9200_rx_dmabuf(void){ // if already running then nothing to do// if(a9200_rx_dmabufflag ==0)// {// printk("a9200_rx_dmabuf \n");// a9200_rx_dmabufflag = 1;// } if(a9200_rxdmaing) return; //printk("a9200_rxend = %d \n",a9200_rxend); // set dma transfer count spin_lock(&rx_count_lock); a9200_rxdmacount = a9200_rxend - a9200_rxstart; a9200_rxdmacount = (a9200_rxdmacount > DMASIZE) ? DMASIZE : a9200_rxdmacount; if(a9200_rxdmacount > 0) { a9200_rx_dmarun(); } else { ssc_regs->SSC_IDR = 0x1 << 6; ssc_regs->SSC_CR = AT91C_SSC_RXDIS; a9200_rxbusy = 0; wake_up_interruptible(&rx_buffer_end); } spin_unlock(&rx_count_lock);}//int rxflag=0;//int txflag=0;void a9200_dma_isr(int irq,void *dev_id,struct pt_regs *regs){ // clear dma interrupt aic_regs->AIC_ICCR = 0x1 << AT91C_ID_SSC1; // clear interrupt if((ssc_regs->SSC_SR & (0x1 << 6)) && (ssc_regs->SSC_IMR & (0x1 << 6)) ) { //if(rxflag==0) // {// printk("rx interrupt ... \n");// rxflag=1;// } ssc_regs->SSC_IDR = 0x1 << 6; // disbale endrx interrupt a9200_rxdmaing = 0; a9200_rxstart += a9200_rxdmacount; //printk("a9200_rxstart = %d \n",a9200_rxstart); spin_lock(&rx_count_lock); a9200_rxdmacount = 0; spin_unlock(&rx_count_lock); a9200_rx_dmabuf(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -