?? hspdif.c
字號:
// DMA Enable & Next Request Enable
dwValue = DCMDR_DMEN;
dma_SetCommand(pOpen->pTxDma, dwValue);
pOpen -> pInfo -> dwStatus |= SPDIF_TRANSMITTING;
}
return dwWritten;
}
/*++
StopTransmitting :
The DMA controller is stopped.
Then, SPDIF transmitting is canceled.
--*/
BOOL
StopTransmitting(
PSPDIF_OPEN_INFO pOpen
)
{
SPDIFControlRegister cr;
if ( pOpen -> pInfo -> dwStatus & SPDIF_TRANSMITTING ){
cr.AsDWORD = READ_REGISTER_ULONG(pOpen -> pInfo -> pvControl);
cr.bits.TME = 0;
cr.bits.TDE = 0;
WRITE_REGISTER_ULONG(pOpen -> pInfo -> pvControl, cr.AsDWORD);
pOpen -> pInfo -> dwStatus &= ~SPDIF_TRANSMITTING;
dma_Stop(pOpen->pTxDma);
DEBUGMSG(SPDIF_TEST, (TEXT("SPDIF:Transmission was stopped.\r\n")));
}
return TRUE;
}
#pragma optimize("", off)
/*++
SPDIF_FillBuffer :
Copy transmit data to a transmitting buffer.
--*/
BOOL
SPDIF_FillBuffer(
PSPDIF_OPEN_INFO pOpen
)
{
//DWORD dwLastDataSize;
//DWORD dwCopyDataSize;
DWORD dwFillOffset = 0;
PVBYTE pvOutBuff = (pOpen -> pvOutBufferBase + (pOpen -> dwTxFlipBuff * SPDIF_OUT_DMA_PAGE_SIZE));
BOOL bReturn = TRUE;
DWORD dmy;
EnterCriticalSection( &(pOpen -> TxCS) );
// DEBUGMSG(SPDIF_TEST, (TEXT("SPDIF:++FillBuffer BufferRemainder[%x] Size[%x] TransmittedSize[%x]\r\n"),
// pOpen -> dwTxRemainOffset, pOpen -> dwOutReqSize, pOpen -> dwTransmitted));
if ( pOpen -> dwOutWorkWPtr != pOpen -> dwOutWorkTPtr ){
ConvertTo32Bits(pOpen);
if ( pOpen -> dwOutWorkWPtr == pOpen -> dwOutWorkTPtr ){
bReturn = FALSE;
}
pOpen -> dwTxFlipBuff = 1 - pOpen -> dwTxFlipBuff;
}else{
memset((PVOID)pvOutBuff, 0, SPDIF_OUT_DMA_PAGE_SIZE);
bReturn = FALSE;
pOpen -> dwTxFlipBuff = 1 - pOpen -> dwTxFlipBuff;
pOpen -> dwTxWork = 0;
pOpen -> dwTxShiftPtr = 0;
DEBUGMSG(SPDIF_TEST, (TEXT("SPDIF:Writing 0 to a transmitting buffer.\r\n")));
// RETAILMSG(1, (TEXT("SPDIF:Writing 0 to a transmitting buffer.\r\n")));
}
dmy = *(pvOutBuff + SPDIF_OUT_DMA_PAGE_SIZE - sizeof(DWORD));
// DEBUGMSG(SPDIF_TEST, (TEXT("SPDIF:--FillBuffer BufferRemainder[%x] Size[%x] TransmittedSize[%x]\r\n"),
// pOpen -> dwTxRemainOffset, pOpen -> dwOutReqSize, pOpen -> dwTransmitted));
LeaveCriticalSection( &(pOpen -> TxCS) );
return bReturn;
}
#pragma optimize("", on)
/*++
FillWorkBuffer :
Write PCM data passed from application
--*/
DWORD
FillWorkBuffer(
PSPDIF_OPEN_INFO pOpen,
PVOID pBuff,
DWORD dwSize
)
{
DWORD i = 0;
if ( pOpen -> dwTxSampleSize == SPDIF_SAMPLE_BIT_SIZE_16 ){
PUSHORT pSrc = (PUSHORT)pBuff;
for( i=0;i < dwSize; ){
if ( ((pOpen -> dwOutWorkWPtr+2) & (SPDIF_WORK_OBUFFER_SIZE-1)) == pOpen -> dwOutWorkTPtr ){
ResetEvent( pOpen -> hTxWaitEvent );
if ( WaitForSingleObject(pOpen -> hTxWaitEvent, 1000) == WAIT_TIMEOUT ){
break;
}
}
WRITE_REGISTER_USHORT((pOpen -> pvOutWorkBuffer + pOpen -> dwOutWorkWPtr), *(pSrc++));
pOpen -> dwOutWorkWPtr += sizeof(USHORT);
pOpen -> dwOutWorkWPtr &= (SPDIF_WORK_OBUFFER_SIZE-1);
i += sizeof(USHORT);
}
}else{
PDWORD pSrc = (PDWORD)pBuff;
for( i=0;i < dwSize; ){
if ( ((pOpen -> dwOutWorkWPtr+4) & (SPDIF_WORK_OBUFFER_SIZE-1)) == pOpen -> dwOutWorkTPtr ){
ResetEvent( pOpen -> hTxWaitEvent );
if ( WaitForSingleObject(pOpen -> hTxWaitEvent, 1000) == WAIT_TIMEOUT ){
break;
}
}
WRITE_REGISTER_ULONG((PVBYTE)(pOpen -> pvOutWorkBuffer + pOpen -> dwOutWorkWPtr), *(pSrc++));
pOpen -> dwOutWorkWPtr += sizeof(DWORD);
pOpen -> dwOutWorkWPtr &= (SPDIF_WORK_OBUFFER_SIZE-1);
i += sizeof(DWORD);
}
}
return i;
}
DWORD
SPDIFInterruptThread(
PSPDIF_DRIVER_INFO pSpdif
)
{
while( TRUE ){
if ( WaitForSingleObject(pSpdif -> hInterrupt, INFINITE) == WAIT_TIMEOUT ){
continue;
}
if ( pSpdif -> pvGlobal -> dwTxStatus ){
if ( pSpdif -> hTxEvent ){
SetEvent( pSpdif -> hTxEvent );
}
pSpdif -> pvGlobal -> dwTxStatus = 0;
}
if ( pSpdif -> pvGlobal -> dwRxStatus ){
if ( pSpdif -> hRxEvent ){
SetEvent( pSpdif -> hRxEvent );
}
pSpdif -> pvGlobal -> dwRxStatus = 0;
}
InterruptDone(SYSINTR_HSPDIF);
}
DEBUGMSG(SPDIF_TEST, (TEXT("End an interruption thread.\r\n")));
return 0;
}
/*++
SPDIFInterruptThreadTx :
Interrupt service thread for TX
--*/
DWORD
SPDIFInterruptThreadTx(
PSPDIF_OPEN_INFO pOpen
)
{
while( pOpen -> bTxThread == TRUE ){
if ( WaitForSingleObject(pOpen -> pInfo -> hTxEvent, 3000) == WAIT_TIMEOUT ){
continue;
}
if ( pOpen -> bTxThread != TRUE ){
break;
}
if ( SPDIF_FillBuffer( pOpen ) == FALSE ){
}
SetEvent( pOpen -> hTxWaitEvent );
DEBUGMSG(SPDIF_TEST, (TEXT("SPDIF:Transmit interrupt occurred.\r\n")));
}
DEBUGMSG(SPDIF_TEST, (TEXT("End an interruption thread.\r\n")));
return 0;
}
/*++
SPDIF_ReceivingData :
Perform data reception.
When receiving for the first time, start DMA and SPDIF.
--*/
DWORD
SPDIF_ReceivingData(
PSPDIF_OPEN_INFO pOpen,
PVOID pBuff,
DWORD dwSize
)
{
DWORD dwLoop = 0;
DWORD dwValue;
if ( !(pOpen -> dwAccess & GENERIC_READ) ){
return 0;
}
if ( !(pOpen -> pInfo -> dwStatus & SPDIF_RECEIVING) ){
SPDIFControlRegister cr;
pOpen -> dwRxShiftPtr = 0;
pOpen -> dwRxWork = 0;
pOpen -> dwRxFlipBuff = 0;
if ( pOpen -> dwRxSampleSize == SPDIF_SAMPLE_BIT_SIZE_20 ){
pOpen -> RxBits = &ConvBitsRx20[0];
}else if ( pOpen -> dwRxSampleSize == SPDIF_SAMPLE_BIT_SIZE_24 ){
pOpen -> RxBits = &ConvBitsRx24[0];
}
// DMA Control Register Setting
dwValue = DCR_DTAMD_PIN |
DCR_DTAC_DISABLE |
DCR_DTAU_BYTE |
DCR_BTMD_DISABLE |
DCR_PKMD_DISABLE |
DCR_CT_ENABLE |
DCR_ACMD_ENABLE |
DCR_DIP_2PAGE |
DCR_SMDL_PERIPHERAL |
DCR_SPDAM_FIX |
DCR_SDRMD_MODULE |
DCR_SPDS_32BIT |
DCR_DMDL_MEMORY |
DCR_DPDAM_INCREMENT |
DCR_DDRMD_MODULE |
DCR_DPDS_32BIT ;
dma_SetControl(pOpen->pRxDma, dwValue);
// DMA-TransferCompleteInterrupt Enable
dma_InterruptEnable(pOpen->pRxDma);
cr.AsDWORD = READ_REGISTER_ULONG(pOpen -> pInfo -> pvControl);
cr.bits.AOS = 1; // Audio only samples
// cr.bits.NCSI = 1; // New channel status information
cr.bits.RME = 1; // Recieve module enable
cr.bits.RDE = 1; // Recieve dma enable
cr.bits.RASS = pOpen -> dwRxSampleSize; // Recieve audio samlple bit size
WRITE_REGISTER_ULONG(pOpen -> pInfo -> pvControl, cr.AsDWORD);
// DMA Enable & Next Request Enable
dwValue = DCMDR_DMEN;
dma_SetCommand(pOpen->pRxDma, dwValue);
pOpen -> pInfo -> dwStatus |= SPDIF_RECEIVING;
}
return GetWorkBuffer(pOpen, pBuff, dwSize);
}
/*++
GetWorkBuffer :
--*/
DWORD
GetWorkBuffer(
PSPDIF_OPEN_INFO pOpen,
PVOID pBuff,
DWORD dwSize
)
{
DWORD i = 0;
if ( pOpen -> dwTxSampleSize == SPDIF_SAMPLE_BIT_SIZE_16 ){
PUSHORT pSrc = (PUSHORT)pBuff;
for( i=0;i < dwSize; ){
if ( pOpen -> dwInWorkRPtr == pOpen -> dwInWorkWPtr ){
ResetEvent( pOpen -> hRxWaitEvent );
if ( WaitForSingleObject(pOpen -> hRxWaitEvent, 1000) == WAIT_TIMEOUT ){
break;
}
if ( pOpen -> dwInWorkRPtr == pOpen -> dwInWorkWPtr ){
break;
}
}
*(pSrc++) = READ_REGISTER_USHORT((pOpen -> pvInWorkBuffer + pOpen -> dwInWorkRPtr));
pOpen -> dwInWorkRPtr += sizeof(USHORT);
pOpen -> dwInWorkRPtr &= (SPDIF_WORK_IBUFFER_SIZE-1);
i += sizeof(USHORT);
}
}else{
PDWORD pSrc = (PDWORD)pBuff;
for( i=0;i < dwSize; ){
if ( pOpen -> dwInWorkRPtr == pOpen -> dwInWorkWPtr ){
ResetEvent( pOpen -> hRxWaitEvent );
if ( WaitForSingleObject(pOpen -> hRxWaitEvent, 1000) == WAIT_TIMEOUT ){
break;
}
if ( pOpen -> dwInWorkRPtr == pOpen -> dwInWorkWPtr ){
break;
}
}
*(pSrc++) = READ_REGISTER_USHORT((pOpen -> pvInWorkBuffer + pOpen -> dwInWorkRPtr));
pOpen -> dwInWorkRPtr += sizeof(DWORD);
pOpen -> dwInWorkRPtr &= (SPDIF_WORK_IBUFFER_SIZE-1);
i += sizeof(DWORD);
}
}
return i;
}
/*++
StopReceiving :
The DMA controller is stopped.
Then, SPDIF receiving is canceled.
--*/
BOOL
StopReceiving(
PSPDIF_OPEN_INFO pOpen
)
{
SPDIFControlRegister cr;
if ( pOpen -> pInfo -> dwStatus & SPDIF_RECEIVING ){
cr.AsDWORD = READ_REGISTER_ULONG(pOpen -> pInfo -> pvControl);
cr.bits.RME = 0;
cr.bits.RDE = 0;
WRITE_REGISTER_ULONG(pOpen -> pInfo -> pvControl, cr.AsDWORD);
dma_Stop(pOpen->pRxDma);
pOpen -> pInfo -> dwStatus &= ~SPDIF_RECEIVING;
DEBUGMSG(SPDIF_TEST, (TEXT("SPDIF:Reception was stopped.\r\n")));
}
return TRUE;
}
/*++
SPDIF_GetData :
Copy receive data from a receiving buffer.
--*/
BOOL
SPDIF_GetData(
PSPDIF_OPEN_INFO pOpen
)
{
PVBYTE pvInBuff = (pOpen -> pvInBufferBase + (pOpen -> dwRxFlipBuff * SPDIF_IN_DMA_PAGE_SIZE));
EnterCriticalSection( &(pOpen -> RxCS) );
ConvertFrom32Bits(pOpen);
pOpen -> dwRxFlipBuff = 1 - pOpen -> dwRxFlipBuff;
LeaveCriticalSection( &(pOpen -> RxCS) );
return TRUE;
}
/*++
SPDIFInterruptThreadRx :
Interrupt service thread for RX
--*/
DWORD
SPDIFInterruptThreadRx(
PSPDIF_OPEN_INFO pOpen
)
{
while( pOpen -> bRxThread == TRUE ){
if ( WaitForSingleObject(pOpen -> pInfo -> hRxEvent, 3000) == WAIT_TIMEOUT ){
continue;
}
if ( pOpen -> bRxThread != TRUE ){
break;
}
if ( SPDIF_GetData( pOpen ) == FALSE ){
}
SetEvent( pOpen -> hRxWaitEvent );
}
return 0;
}
/*++
SPDIF_StopTransmit :
Perform transmitting processing.
Execution of this function stops a transmitting clock.
--*/
VOID
SPDIF_StopTransmit(
PSPDIF_OPEN_INFO pOpen
)
{
DEBUGMSG(SPDIF_TEST, (TEXT("SPDIF:Stop transmitting\r\n")));
StopTransmitting(pOpen);
}
/*++
SPDIF_StopReceive :
Perform receiving processing.
Execution of this function stops a receiving clock.
--*/
VOID
SPDIF_StopReceive(
PSPDIF_OPEN_INFO pOpen
)
{
StopReceiving(pOpen);
}
/*++
ConvertTo32Bits :
Data to transmit is 32 bits although demand data is 16, 20, and 24 bits.
So, perform data conversion to 32 bits.
--*/
VOID
ConvertTo32Bits(
PSPDIF_OPEN_INFO pOpen
)
{
PVDWORD pOutBuff = (PVDWORD)(pOpen -> pvOutBufferBase + (pOpen -> dwTxFlipBuff * SPDIF_OUT_DMA_PAGE_SIZE));
DWORD i;
if ( pOpen -> dwTxSampleSize == SPDIF_SAMPLE_BIT_SIZE_16 ){
for( i=0;i < SPDIF_OUT_DMA_PAGE_SIZE; ){
if ( pOpen -> dwOutWorkTPtr != pOpen -> dwOutWorkWPtr ){
*(pOutBuff++) = (DWORD)(READ_REGISTER_USHORT(((PVBYTE)(pOpen -> pvOutWorkBuffer+pOpen -> dwOutWorkTPtr))));
pOpen -> dwOutWorkTPtr += 2;
pOpen -> dwOutWorkTPtr &= (SPDIF_WORK_OBUFFER_SIZE-1);
}else{
*(pOutBuff++) = 0;
}
i += sizeof(DWORD);
}
}else{
PBITS_CONVERSION Convert;
Convert = pOpen -> TxBits + pOpen -> dwTxShiftPtr;
for( i=0;i < SPDIF_OUT_DMA_PAGE_SIZE;){
if ( pOpen -> dwOutWorkTPtr != pOpen -> dwOutWorkWPtr ){
if ( Convert -> dwDirection == SHIFT_N ){
DWORD dwWork = READ_REGISTER_ULONG(((PVBYTE)(pOpen -> pvOutWorkBuffer + pOpen -> dwOutWorkTPtr)));
pOpen -> dwTxWork |= dwWork & Convert -> dwData;
}else if ( Convert -> dwDirection == SHIFT_L ){
DWORD dwWork = READ_REGISTER_ULONG(((PVBYTE)(pOpen -> pvOutWorkBuffer + pOpen -> dwOutWorkTPtr)));
pOpen -> dwTxWork |= (dwWork & Convert -> dwData) << Convert -> dwShift;
}else{
DWORD dwWork = READ_REGISTER_ULONG(((PVBYTE)(pOpen -> pvOutWorkBuffer + pOpen -> dwOutWorkTPtr)));
pOpen -> dwTxWork |= (dwWork & Convert -> dwData) >> Convert -> dwShift;
}
}else{
// pOpen -> dwTxWork = 0;
*(pOutBuff++) = 0;
i += sizeof(DWORD);
continue;
}
if ( Convert -> dwInc & INC_SRC ){
pOpen -> dwOutWorkTPtr += sizeof(DWORD);
pOpen -> dwOutWorkTPtr &= (SPDIF_WORK_OBUFFER_SIZE-1);
}
if ( Convert -> dwInc & INC_DST ){
*(pOutBuff++) = pOpen -> dwTxWork;
pOpen -> dwTxWork = 0;
i += sizeof(DWORD);
}
if ( Convert -> dwInc == (INC_SRC|INC_DST) ){
pOpen -> dwTxShiftPtr = 0;
Convert = pOpen -> TxBits;
}else{
Convert++;
pOpen -> dwTxShiftPtr ++;
}
}
}
}
/*++
ConvertFrom32Bits :
Although data to receive is 32 bits, data to return is 16, 20 or 24 bits.
So, perform data conversion to 16, 20 or 24 bits.
--*/
VOID
ConvertFrom32Bits(
PSPDIF_OPEN_INFO pOpen
)
{
PVDWORD pInBuff = (PVDWORD)(pOpen -> pvInBufferBase + (pOpen -> dwRxFlipBuff * SPDIF_IN_DMA_PAGE_SIZE));
DWORD i;
if ( pOpen -> dwRxSampleSize == SPDIF_SAMPLE_BIT_SIZE_16 ){
for( i=0;i < SPDIF_IN_DMA_PAGE_SIZE; ){
WRITE_REGISTER_USHORT(((PVBYTE)(pOpen -> pvInWorkBuffer + pOpen -> dwInWorkWPtr)), (USHORT)*(pInBuff++));
pOpen -> dwInWorkWPtr += sizeof(USHORT);
pOpen -> dwInWorkWPtr &= (SPDIF_WORK_IBUFFER_SIZE-1);
i += sizeof(DWORD);
}
}else{
PBITS_CONVERSION Convert;
Convert = pOpen -> RxBits + pOpen -> dwRxShiftPtr;
for( i=0;i < SPDIF_IN_DMA_PAGE_SIZE;){
if ( Convert -> dwDirection == SHIFT_N ){
pOpen -> dwRxWork |= *pInBuff & Convert -> dwData;
}else if ( Convert -> dwDirection == SHIFT_L ){
pOpen -> dwRxWork |= (*pInBuff & Convert -> dwData) << Convert -> dwShift;
}else{
pOpen -> dwRxWork |= (*pInBuff & Convert -> dwData) >> Convert -> dwShift;
}
if ( Convert -> dwInc & INC_SRC ){
pInBuff ++;
i += sizeof(DWORD);
}
if ( Convert -> dwInc & INC_DST ){
WRITE_REGISTER_ULONG(((PVBYTE)(pOpen -> pvInWorkBuffer + pOpen -> dwInWorkWPtr)), pOpen -> dwRxWork);
pOpen -> dwInWorkWPtr += sizeof(DWORD);
pOpen -> dwInWorkWPtr &= (SPDIF_WORK_IBUFFER_SIZE-1);
pOpen -> dwRxWork = 0;
}
if ( Convert -> dwInc == (INC_SRC|INC_DST) ){
pOpen -> dwRxShiftPtr = 0;
Convert = pOpen -> RxBits;
}else{
Convert++;
pOpen -> dwRxShiftPtr ++;
}
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -