📄 audioinit.c
字号:
*/ temp1 = readl(CS4281_pBA0 + BA0_HIMR) & 0xfffbfcff; writel(temp1, CS4281_pBA0+BA0_HIMR); printf("\nCS4281 Hardware Initialization Complete!!\n"); return 0;}/*************************************************************************** Function - start_dac* Parameters - none* Returns - none* Purpose - Start DAC and ADC.* Enables DMA0 an DMA1, Enables Interrupt, sets volume to 0 db.*****************************************************************************/void start_dac(void){ UINT32 temp1; int lockkey; lockkey = intLock(); /* enable DMA0 */ temp1 = readl(CS4281_pBA0+BA0_DCR0); writel(temp1 & ~DCRn_MSK, CS4281_pBA0+BA0_DCR0); /* enable DMA1*/ temp1 = readl(CS4281_pBA0+BA0_DCR1); writel(temp1 & ~DCRn_MSK, CS4281_pBA0+BA0_DCR1); /* enable Interrupt */ writel(HICR_IEV | HICR_CHGM, CS4281_pBA0+BA0_HICR); /* set volume to 0 db */ writel(0, CS4281_pBA0+BA0_PPRVC); writel(0, CS4281_pBA0+BA0_PPLVC); intUnlock(lockkey);}/*************************************************************************** Function - stop_dac* Parameters - none* Returns - none* Purpose - Stops DAC and ADC.* Disables DMA0 and DMA1, disables interrupt*****************************************************************************/void stop_dac(void){ UINT32 temp1; int lockkey; lockkey = intLock(); /* disable DMA0 */ temp1 = readl(CS4281_pBA0+BA0_DCR0); writel(temp1 | DCRn_MSK, CS4281_pBA0+BA0_DCR0); /* disable DMA1*/ temp1 = readl(CS4281_pBA0+BA0_DCR1); writel(temp1 | DCRn_MSK, CS4281_pBA0+BA0_DCR1); /* disable Interrupt */ writel(HICR_CHGM, CS4281_pBA0+BA0_HICR); intUnlock(lockkey);}/*************************************************************************** Function - prog_codec* Parameters - none* Returns - none* Purpose - Programs the codec according to the current_mode global* variable. Note that DMA should be stopped before changing* the codec. It also sets the sample rate to 11025.*****************************************************************************/int prog_codec(void){ UINT32 format,temp1; int lockkey; lockkey = intLock(); /*stop the DMAs if active*/ temp1 = readl( CS4281_pBA0+BA0_DCR0); writel(temp1 | DCRn_MSK, CS4281_pBA0+BA0_DCR0); /* Stop play DMA, if active.*/ temp1 = readl( CS4281_pBA0+BA0_DCR1); writel(temp1 | DCRn_MSK, CS4281_pBA0+BA0_DCR1); /* Stop capture DMA, if active.*/ /* DAC */ /* if 8-bit mono, then set size to 8 and set mono bit */ if( current_mode == 1 ) { format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ | DMRn_USIGN | DMRn_SIZE8 | DMRn_MONO; } if( current_mode == 2 ) /*for 8-bit stero set size 8, but not mono*/ { format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ |DMRn_USIGN | DMRn_SIZE8; } if( current_mode == 3 ) /*for 16 bit stereo don't set size 8 or mono*/ { format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ | DMRn_USIGN; } writel(format, CS4281_pBA0+BA0_DMR0); /* ADC*/ /* if 8-bit mono, then set size to 8 and set mono bit */ if( current_mode == 1 ) { format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE | DMRn_USIGN | DMRn_SIZE8 | DMRn_MONO; } if( current_mode == 2 ) /*for 8-bit stero set size 8, but not mono*/ { format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE | DMRn_USIGN | DMRn_SIZE8; } if( current_mode == 3 ) /*for 16 bit stereo don't set size 8 or mono*/ { format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE | DMRn_USIGN; } if( current_mode == 4 ) /*for 20 bit stereo set size 20 and not mono*/ { format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE | DMRn_USIGN | DMRn_SIZE20; } writel(format, CS4281_pBA0+BA0_DMR1); /*ADC,DAC set record sampling rate to 11025*/ writel(0x04, CS4281_pBA0+BA0_DACSR); writel(0x04, CS4281_pBA0+BA0_ADCSR); intUnlock(lockkey); return 0;}/*************************************************************************** Function - cs4281_interrupt* Parameters - param* Returns - none* Purpose - Interrupt handler routing. If TC of HTC interrupt for* either DMA, then set variable indicating which one and do a* semGive for either record or play.*****************************************************************************/void cs4281_interrupt(int param){ UINT32 temp1; int lockkey; /* if it's not DMA interrupts, jump out */ temp1 = readl(CS4281_pBA0+BA0_HISR); if(!(temp1 &(HISR_DMA0 | HISR_DMA1))) { writel(HICR_IEV| HICR_CHGM, CS4281_pBA0+BA0_HICR); return; } /* if DMA0 interrupt, playback DMA0 */ if(temp1 & HISR_DMA0) { CNT_DMA_Playback++; if(0x00010000 & readl(CS4281_pBA0+BA0_HDSR0)) { /*DMA Terminal Count interrupt, set flag saying that */ DTC_DMA_Playback = 1; } else /*HTC interrupt, set flag saying that*/ { DTC_DMA_Playback = 0; } semGive(SEM_DMA_Playback); } /* if DMA1 interrupt, record DMA1 */ if(temp1 & HISR_DMA1) { CNT_DMA_Record++; if(0x00010000 & readl(CS4281_pBA0+BA0_HDSR1)) { /*DMA Terminal Count interrupt, set flag saying that */ DTC_DMA_Record = 1; } else /*HTC interrupt, set flag saying that*/ { DTC_DMA_Record = 0; } semGive(SEM_DMA_Record); } /*clear interrupt*/ writel(HICR_IEV| HICR_CHGM, CS4281_pBA0+BA0_HICR);}/*************************************************************************** Function - startCS4281* Parameters - none* Returns - none* Purpose - Install the cs4281/ac97 driver:* -bring up the hardware* -allocate and set DMA buffer/DMA engine* -connect ISR to IRQ* -start_adc/dac*****************************************************************************/int startCS4281(){ unsigned int pciBusNo, pciDevNo, pciFuncNo; unsigned char byte; UINT32 s_pBA0, s_pBA1; if (pciConfigLibInit (PCI_MECHANISM_1, 0xCF8, 0xCFC, 0) != OK) { printf("PCI lib config error\n"); return 1; } /**************************** * Find SoundCard * Set BaseAddr0, BaseAddr1 ****************************/ if(!(pciFindDevice(PCI_VENDOR_ID_CIRRUS,PCI_DEVICE_ID_CRYSTAL_CS4281, 0, &pciBusNo, &pciDevNo, &pciFuncNo)==OK)) { printf("\n CS4281 sound card NOT FOUND!!! \n"); return 1; } printf("\n FIND CS4281 sound card, configuring BA0,BA1... \n"); pciConfigOutLong( pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_BASE_ADDRESS_0, CS4281_pBA0); pciConfigInLong( pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_BASE_ADDRESS_0, &s_pBA0); pciConfigInLong( pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_BASE_ADDRESS_1, &s_pBA1 ); printf ("\npBusNo pDeviceNo pFuncNo pBA0 pBA1\n\n"); printf ("%.8x %.8x %.8x %.8x %.8x \n", pciBusNo, pciDevNo, pciFuncNo, s_pBA0,s_pBA1); /******************************** * Config PCI Device Capability * DMA Master * MEM mapped ********************************/ /* Set the INTA vector */ pciConfigInByte(pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_DEV_INT_LINE, &cs4281_irq); printf("\nFound CS4281 configured for IRQ %d\n", cs4281_irq); pciConfigInByte(pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_DEV_INT_PIN, &byte); printf("\tINT_PIN=%.8x\n", byte); /* Enable the device's capabilities as specified * Bus Master Enable/ Mem Space Enable */ pciConfigOutWord(pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_COMMAND, (unsigned short)0x0006); /*************************** * BringUp Hardware ***************************/ if(cs4281_hw_init()) return 1; /**************************** * Allocate ADC_BUFFER * Allocate DAC_BUFFER * * Hook cs4281_interrupt * * Program CoDec ****************************/ if((DAC_BUFFER=valloc(DAC_BUFFER_SIZE))==NULL) { printf("\n DAC_BUFFER valloc failed!\n"); return 1; } if((ADC_BUFFER=valloc(ADC_BUFFER_SIZE))==NULL) { printf("\n ADC_BUFFER valloc failed!\n"); return 1; } /*setup DMA BUFFERs for ADC and DAC according to current_mode*/ program_dac_buffers(); /* connect interrupt */ printf("\n Hook cs4281_interrupt to vector %d\n", (INUM_TO_IVEC (cs4281_irq+INT_NUM_IRQ0))); pciIntConnect((INUM_TO_IVEC (cs4281_irq+INT_NUM_IRQ0)), (VOIDFUNCPTR)cs4281_interrupt, 0); sysIntEnablePIC(cs4281_irq); SEM_DMA_Playback = semBCreate(SEM_Q_FIFO,SEM_EMPTY); SEM_DMA_Record = semBCreate(SEM_Q_FIFO,SEM_EMPTY); CNT_DMA_Playback = CNT_DMA_Record = 0; /* program coDec */ printf("\n Program CoDec (sample rate, DMA...)\n"); prog_codec(); /********************************************* * start dac and adc, interrupt is comming... *********************************************/ printf("\n\n>>>Start DAC !!!!!!!!!!\n"); start_dac(); return 0;}/*************************************************************************** Function - program_dac_buffers* Parameters - none* Returns - none* Purpose - Setup the pointer into and size of buffers.*****************************************************************************/int program_dac_buffers(){ /*tell DMA engine where start of DAC Buffer is*/ /*this had an offset of (-16) which is not needed*/ writel((UINT32)DAC_BUFFER,CS4281_pBA0 + BA0_DBA0); /*now set the number of FIFO-to-DMA transfers -- this basically corresponds to size, and it will be different depending on the mode because the higher modes transfer more data each time, so it requires fewer transfers to fill the DMA buffer, furthermore we set the number to one less because we get an interrupt when rolling over as well*/ if( current_mode == 1 ) /*8 bit mono*/ { writel(DAC_BUFFER_SIZE-1, CS4281_pBA0 + BA0_DBC0); } if( current_mode == 2 ) /*8 bit stereo*/ { writel((DAC_BUFFER_SIZE/2)-1, CS4281_pBA0 + BA0_DBC0); } if( current_mode == 3 ) /*16 bit stereo*/ { writel((DAC_BUFFER_SIZE/4)-1, CS4281_pBA0 + BA0_DBC0); } /*tell DMA engine where start of ADC Buffer is*/ /*this had an offset of (-16) which is not needed*/ writel((UINT32)ADC_BUFFER,CS4281_pBA0 + BA0_DBA1); /*set # transfers for ADC*/ if( current_mode == 1 ) /*8 bit mono*/ { writel(ADC_BUFFER_SIZE-1, CS4281_pBA0 + BA0_DBC1); } if( current_mode == 2 ) /*8 bit stereo*/ { writel((ADC_BUFFER_SIZE/2)-1, CS4281_pBA0 + BA0_DBC1); } if( current_mode == 3 ) /*16 bit stereo*/ { writel((ADC_BUFFER_SIZE/4)-1, CS4281_pBA0 + BA0_DBC1); }}/*************************************************************************** Function - audio_switchMode* Parameters - none* Returns - none* Purpose - This re-configures the codec and DMA buffers to a new mode,* it assumes new mode has already been set via the global* current_mode variable.*****************************************************************************/int audio_switchMode(){ prog_codec(); program_dac_buffers(); start_dac(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -