📄 dac3550drv.c
字号:
{ int dmaChannel = 0; AT91PS_SSC pSSC = (AT91PS_SSC)pDev->port; if (pDev->pDsp->dmaDirection != O_WRONLY ) { pDev->dmaAuto = 0; pDev->pDsp->dmaDirection = mDma.direction; } if (pDev->dmaAuto) { if (mDma.length != MAX_DMA_SIZE) { /* If this was the interrupt from the middle of the block, * then wait around for the next one. */ if (pDev->dmaAuto) { pDev->dmaAuto = 0; if (semTake (pDev->intSem, 5 * sysClkRateGet())) logMsg ("SB16: Interrupt timeout\n", 0, 0, 0, 0, 0, 0); freeDmaBuffer (pDev); } /* Setup a one-shot. */ cacheFlush(DATA_CACHE,mDma.buffer, mDma.length);/* dmaSetup (DMA_MODE_SINGLE | DMA_MODE_WRITE, mDma.buffer, mDma.length, dmaChannel);*/ /* Send out this block. */ AT91F_PDC_SetNextTx ((AT91PS_PDC) &(pSSC->SSC_RPR), (char *)mDma.buffer, mDma.length/2); /*dsp_output (pDev->pDsp, mDma.length);*/ } } else { if (mDma.buffer == snd_dmaBuffer && mDma.length == MAX_DMA_SIZE) { pDev->dmaAuto = 2; cacheFlush(DATA_CACHE,snd_dmaBuffer, MAX_DMA_MSGS * MAX_DMA_SIZE); /* dmaSetup (DMA_MODE_SINGLE | DMA_MODE_WRITE | DMA_MODE_AUTO_ENABLE, snd_dmaBuffer, MAX_DMA_MSGS * MAX_DMA_SIZE, dmaChannel);*/ /* Check for the next buffer available when half the buffer * has been transferred. */ /*mDma.length >>= 1;*/ } else { cacheFlush(DATA_CACHE,mDma.buffer, mDma.length); /* dmaSetup (DMA_MODE_SINGLE | DMA_MODE_WRITE, mDma.buffer, mDma.length, dmaChannel);*/ /*AT91F_PDC_SetNextTx ((AT91PS_PDC) &(pSSC->SSC_RPR), (char *)mDma.buffer, mDma.length/2); */ } /* Send out this block. */ AT91F_PDC_SetTx ((AT91PS_PDC) &(pSSC->SSC_RPR), (char *)mDma.buffer, mDma.length/2);/* AT91F_PDC_SetNextTx ((AT91PS_PDC) &(pSSC->SSC_RPR), (char *)(mDma.buffer+mDma.length), mDma.length/2); */ }}#endif/* Interrupt handler and Helper task */static void dspInterrupt (SND_DEV *pDev){ volatile unsigned int status; AT91PS_SSC pSSC = (AT91PS_SSC)pDev->port; /* Get status and acknowledge IT*/ status = pSSC->SSC_SR; /* Reload the PDC*/ /* logBuf[++logIndex]=status;*/ if(pDev->dmaAuto) { pDev->dmaAuto--;/* if(!pDev->dmaAuto) { AT91F_SSC_DisableIt (pSSC, AT91C_SSC_ENDTX); AT91F_PDC_DisableTx ((AT91PS_PDC) &(pSSC->SSC_RPR)); AT91F_SSC_DisableTx (pSSC); }*/ freeDmaBuffer (pDev); }else { /*AT91F_SSC_DisableIt (pSSC, AT91C_SSC_ENDTX); AT91F_PDC_DisableTx ((AT91PS_PDC) &(pSSC->SSC_RPR)); AT91F_SSC_DisableTx (pSSC);*/ stopCount++; if( status & AT91C_SSC_TXBUFE) { AT91F_SSC_DisableIt (pSSC, AT91C_SSC_ENDTX); return; } } /* if(status& AT91C_SSC_TXBUFE) { AT91F_SSC_DisableIt (pSSC, AT91C_SSC_ENDTX); AT91F_PDC_DisableTx ((AT91PS_PDC) &(pSSC->SSC_RPR)); AT91F_SSC_DisableTx (pSSC); pDev->dmaAuto=TWO_BUFF_EMPTY ; }else { if(pDev->dmaAuto) pDev->dmaAuto--; else { AT91F_SSC_DisableIt (pSSC, AT91C_SSC_ENDTX); AT91F_PDC_DisableTx ((AT91PS_PDC) &(pSSC->SSC_RPR)); AT91F_SSC_DisableTx (pSSC); pDev->dmaAuto=TWO_BUFF_EMPTY ; } } if(status& AT91C_SSC_ENDTX)*/ /* semGive (pDev->intSem);*/ /*AT91F_PDC_SetNextTx ((AT91PS_PDC) &(pSSC->SSC_RPR), (char *)wav_file, AT91C_WAV_FILE_SIZE/2);*/}static int dspHelperTask (SND_DEV *pDev){ if (semTake (pDev->intSem, WAIT_FOREVER)) logMsg ("SB16: Interrupt timeout\n", 0, 0, 0, 0, 0, 0); if(pDev->dmaAuto>TWO_BUFF_EMPTY) { pDev->dmaAuto--; if(pDev->dmaAuto==TWO_BUFF_EMPTY) { AT91PS_SSC pSSC = (AT91PS_SSC ) pDev->port; AT91F_SSC_DisableTx (pSSC); } freeDmaBuffer (pDev); }else logMsg ("DAC3550: buffer error\n", 0, 0, 0, 0, 0, 0); }#if 0static int dspHelperTask (SND_DEV *pDev){ DMA_MSG mDma; while (1) { pDev->taskBusy = pDev->dmaAuto = 0; if (msgQReceive (pDev->dmaQ, (char *)&mDma, sizeof (mDma), WAIT_FOREVER) != sizeof (mDma)) return 0; pDev->taskBusy = 1; do { switch (mDma.direction) { case O_WRONLY: processOutput (pDev, mDma); break; case O_RDONLY: break; } /* wait for a DMA interrupt */ if (semTake (pDev->intSem, 5 * sysClkRateGet())) logMsg ("SB16: Interrupt timeout\n", 0, 0, 0, 0, 0, 0); if (pDev->dmaAuto) { /* We can do this, because we know the stream will be * non-contiguous if any properties change (rate, direction, etc). */ while (pDev->dmaAuto) { pDev->dmaAuto--; if (pDev->dmaAuto) { if (msgQReceive (pDev->dmaQ, (char *)&mDma, sizeof (mDma), NO_WAIT) != sizeof (mDma)) { pDev->dmaAuto = 0; } } else { /* Great, we can keep going with 2 more interrupts to follow. */ pDev->dmaAuto = 2; freeDmaBuffer (pDev); } /* wait for the next DMA interrupt */ if (semTake (pDev->intSem, 5 * sysClkRateGet())) logMsg ("SB16: Interrupt timeout\n", 0, 0, 0, 0, 0, 0); } /* We can't do any more DMA continuously. */ } freeDmaBuffer (pDev); } while (msgQReceive (pDev->dmaQ, (char *)&mDma, sizeof (mDma), NO_WAIT) == sizeof (mDma)); }}#endif/* DMA buffer management routines *//* DMA buffers are never grabbed by the interrupt routine */static int createDmaBuffer (void){/* snd_dmaBuffer = sysDmaMalloc (MAX_DMA_MSGS * MAX_DMA_SIZE); */ int i=0;/* bzero (snd_buffer, sizeof(snd_buffer));*/ for( i=0;i<MAX_DMA_MSGS;i++) { snd_buffer[i].buffer=snd_dmaBuffer + MAX_DMA_SIZE*i; } return snd_buffer ? OK : ERROR;}static DMA_MSG *getDmaBuffer (SND_DEV *pDev){ DMA_MSG *dmaBuffer; semTake (pDev->bufSem, WAIT_FOREVER); semTake (pDev->devSem, WAIT_FOREVER);/* dmaBuffer = snd_dmaBuffer + pDev->dmaIndex * MAX_DMA_SIZE;*/ dmaBuffer = &snd_buffer[pDev->dmaIndex]; pDev->dmaIndex = (pDev->dmaIndex + 1) % MAX_DMA_MSGS; semGive (pDev->devSem); return dmaBuffer;}/* DMA buffers are always freed by the interrupt routine */static void freeDmaBuffer (SND_DEV *pDev){ semGive (pDev->bufSem);}/* Low level register access routines. */static int dsp_init (SND_DEV *pDev){ int version; AT91PS_SSC pSSC = (AT91PS_SSC ) pDev->port; /* Initialization the DSP */ /* ============================= Init SSC1 in Output mode =============================*/ /* Configure SSC1 PIOs TF/TK/TD */ *AT91C_PIOB_PDR= ((unsigned int) AT91C_PB7_TK1 ) | ((unsigned int) AT91C_PB8_TD1 ) | ((unsigned int) AT91C_PB6_TF1 ); /* Configure PMC by enabling SSC1 clock */ AT91F_SSC1_CfgPMC(); /* Reset All the Peripheral */ pSSC->SSC_CR = AT91C_SSC_SWRST ; /* Clear Transmit and Receive Counters*/ AT91F_PDC_Close((AT91PS_PDC) &(pSSC->SSC_RPR)); /* Define the Clock Mode Register at 2*16*44100 => 1.4112 MHz */ AT91F_SSC_SetBaudrate(pSSC, MCK, FILE_SAMPLING_FREQ*(BITS_BY_SLOT*SLOT_BY_FRAME)); /* Write the Transmit Frame Mode Register*/ pSSC->SSC_TFMR = I2S_ASY_TX_FRAME_SETTING(BITS_BY_SLOT, SLOT_BY_FRAME); /* Configure AIC controller to handle SSC interrupts*//* AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SSC1, IRQ_LEVEL_I2S, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, AT91F_ASM_I2S_Handler );*/ /* Enable SSC interrupt in AIC*/ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SSC1); return 0;}static int __div = 2;void dsp_output(SND_DEV*pDev ,DMA_MSG* buf ){ int lockKey; AT91PS_SSC pSSC = (AT91PS_SSC ) pDev->port; /*/printErr ("dsp_output: dmaAuto = %d\n", pDev->dmaAuto); */lockKey = intLock(); if(pDev->dmaAuto==TWO_BUFF_EMPTY) { AT91F_PDC_SetTx ((AT91PS_PDC) &(pSSC->SSC_RPR), (char *)buf->buffer, buf->length/__div);/* AT91F_PDC_SetNextTx ((AT91PS_PDC) &(pSSC->SSC_RPR), (char *)(buf->buffer+buf->length/2), buf->length/4);*/ AT91F_SSC_EnableIt (pSSC, AT91C_SSC_ENDTX); AT91F_PDC_EnableTx ((AT91PS_PDC) &(pSSC->SSC_RPR)); /* Write the Transmit Clock Mode Register and Enable TK and TF*/ pSSC->SSC_TCMR = I2S_ASY_MASTER_TX_SETTING(BITS_BY_SLOT, SLOT_BY_FRAME); pDev->dmaAuto++; AT91F_SSC_EnableTx (pSSC); }else /*if(pDev->dmaAuto==ONE_BUFF_READY)*/ { AT91F_PDC_SetNextTx ((AT91PS_PDC) &(pSSC->SSC_RPR), (char *)buf->buffer, buf->length/__div); pDev->dmaAuto++; /* }else { logMsg ("DAC3550 : Error\n", 0, 0, 0, 0, 0, 0);*/ } intUnlock(lockKey);}/**$Log: sb16drv.c,v $Revision 1.5 1999/12/18 00:01:38 stevehCorrected loop bug for audio on small buffers.Connected up fwd,back and stop buttons.Attempted to connect up logic to display link that mouse is over,but api seems to not work for this.Revision 1.4 1999/12/03 06:52:09 stevehCreated new IOCTL to set 8-bit uLaw format in SB driver.Moved uLaw code from java to driver.*/#elseSTATUS dac3550Drv (void){ return ERROR ;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -