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

📄 waveutil.c

📁 windows ce 下ARM9音频驱动代码
💻 C
字号:
/*++
Copyright (c) 2001,2002,2004 BSQUARE Corporation.  All rights reserved.

Module Name:

    waveutil.c

Module Description:

    This module contains the implementation of various utility funtions for
    the platform audio driver.

Author:

    Benny Ng    25-June-2001

Revision History:

    Yuqun Cao   16-Jan-2002

        1. Turn on the DMA clock in InitiateDma().
        2. Activate Rx and Tx DMA channel seperately.

    Yuqun Cao   22-Mar-2002
        1. MapTransfer() only call HalMapTransfer() if Start==TRUE.

    Jason Browne Jan-2004
	Fixed DMA buffering issue.

--*/

#include "chip.h"
#include "audio.h"

//TSAT* 27-Dec-2002 Turn on debug messages
//#undef  DEBUGMSG
//#define DEBUGMSG(cond, msg) RETAILMSG(1, msg)

VOID
MapTransfer(
    IN BOOLEAN Start,
    IN PWAVE_RESOURCE WaveResource,
    IN PULONG Buffer
    )
{
#ifdef NOAUDIODMA
    return;
#else
    BOOLEAN UseBufferA;
    ULONG BufferLength;
    ULONG RequestedLength;
    PHYSICAL_ADDRESS PhysAddr;

    if(Start == FALSE) {
        return;
    }

    if (Buffer == WaveResource->DmaBufferA) {
        UseBufferA = TRUE;
    }
    else if (Buffer == WaveResource->DmaBufferB) {
        UseBufferA = FALSE;
    }
    else {
        DEBUGMSG(1, (TEXT("MapTransfer: Unexpected buffer.")));
        goto ErrorReturn;
    }

    BufferLength = (UseBufferA == TRUE) ?
                    WaveResource->DmaBufferABytes :
                    WaveResource->DmaBufferBBytes;

    //
    // Map Dma buffer address
    //

    RequestedLength = BufferLength;

    PhysAddr = HalMapTransfer(WaveResource->AdapterObject,
                              WaveResource->DmaBufferMdl,
                              WaveResource->MapRegsBase,
                              Buffer,
                              &RequestedLength,
                              TRUE);

    if (RequestedLength != BufferLength) {
        DEBUGMSG(1, (TEXT("MapTransfer: HalMapTransfer error\r\n")));
        goto ErrorReturn;
    }

    // This DMA physical address will be written to DMA base register in StartDMA()

    DEBUGMSG(1, (TEXT("MapTransfer: PhysAddr=0x%x BufferLength=0x%x\r\n"),
                 PhysAddr.LowPart, BufferLength));

    if (UseBufferA == TRUE) {
        WaveResource->BufferAPhysAddr.LowPart = PhysAddr.LowPart;
    }
    else {
        WaveResource->BufferBPhysAddr.LowPart = PhysAddr.LowPart;
    }

ErrorReturn:
    return;
#endif
}


PULONG
GetNextDmaBuffer(
    IN PWAVE_RESOURCE WaveResource
    )
{
    return ( (WaveResource->NextDMABuf & 1) ?
              WaveResource->DmaBufferB :
              WaveResource->DmaBufferA );
}


VOID
NextDmaBuffer(
    IN PWAVE_RESOURCE WaveResource
    )
{
    WaveResource->NextDMABuf ^= 1;
}


VOID
SetBufferSize(
    IN PWAVE_RESOURCE WaveResource,
    IN PULONG Buffer,
    IN ULONG NumBytes
    )
{
    if (Buffer == WaveResource->DmaBufferA) {
        WaveResource->DmaBufferABytes = NumBytes;
    }
    else if (Buffer == WaveResource->DmaBufferB) {
        WaveResource->DmaBufferBBytes = NumBytes;
    }
    else {
        DEBUGMSG(1, (TEXT("SetBufferSize: Unknown buffer.\r\n")));
    }
}


ULONG
GetBufferSize(
    IN PWAVE_RESOURCE WaveResource,
    IN PULONG Buffer,
    IN ULONG NumBytes
    )
{
    ULONG BufferSize = 0;

    if (Buffer == WaveResource->DmaBufferA) {

        BufferSize = WaveResource->DmaBufferABytes;;
    }
    else if (Buffer == WaveResource->DmaBufferB) {

        BufferSize = WaveResource->DmaBufferBBytes;;
    }
    else {
        DEBUGMSG(1, (TEXT("GetBufferSize: Unknown buffer\r\n")));
    }

    return BufferSize;
}


VOID
InitiateDma(
    IN PWAVE_RESOURCE WaveResource
    )
{
    ULONG tmp = 0;

#ifdef NOAUDIODMA
    return;
#endif

    DEBUGMSG(1, (TEXT("InitiateDma:\r\n")));

    /*********************************************************************\
     *                                                                   *
     * DMA clock must be turned on before DMA registers can be accessed! *
     * There must be a delay before the clock become available.          *
     *                                                                   *
    \*********************************************************************/

    //
    // Enable DMA clock for AAC0_RX and AAC0_TX
    //


    tmp = READ_REGISTER_ULONG(&WaveResource->ABPClkCtrlRegPrt->PWRCNT);

    if(WaveResource->WaveDirection == WAPI_IN) {
        tmp |= CLK_DMA_AAC0_RX;
    } else {
        tmp |= CLK_DMA_AAC0_TX;
    }

    WRITE_REGISTER_ULONG(&WaveResource->ABPClkCtrlRegPrt->PWRCNT, tmp);

    // delay for the clock
    Drv_AHBBus_ExtraWrite();

    //
    // Enable DMA interrupt for AAC0_RX and AAC0_TX
    //
    WRITE_REGISTER_ULONG(&(WaveResource->DmaRegPtr->Control),
                         DMA_CTL_ICE |
                         DMA_CTL_ENABLE |
                         DMA_CTL_STALLINTEN |
                         DMA_CTL_CHERRINTEN |
                         DMA_CTL_NFBINTEN);

    Drv_AHBBus_ExtraWrite();
}


VOID
ShutdownDma(
    IN PWAVE_RESOURCE WaveResource
    )
{
    DEBUGMSG(1, (TEXT("ShutdownDma:\r\n")));
    WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->Control, 0);

    return;
}


VOID
StartDmaIn(
    IN PWAVE_RESOURCE WaveResource
    )
{
    DEBUGMSG(1, (TEXT("StartDma:\r\n")));

#ifdef NOAUDIODMA
    SetEvent(hAudioInterrupt);
#else

//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// RETAILMSG(1, (TEXT("\r\n")));
    if(WaveResource->DmaBufferABytes) {
        DEBUGMSG(1,(TEXT("StartDma=A\r\n")));
        DEBUGMSG(1, (TEXT("StartDma-Base0: %d\r\n"), WaveResource->DmaBufferABytes));
//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// DEBUGMSG(1, (TEXT("StartDma-Base0: MaxCnt0:  0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->MaxCnt0));
// DEBUGMSG(1, (TEXT("StartDma-Base0: Base0:    0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Base0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current0));

        WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->MaxCnt0, WaveResource->DmaBufferABytes);

        WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->Base0, WaveResource->BufferAPhysAddr.LowPart);

        WaveResource->DmaBufferABytes = 0;
//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// DEBUGMSG(1, (TEXT("StartDma-Base0: MaxCnt0:  0x%8.8X After\r\n"), WaveResource->DmaRegPtr->MaxCnt0));
// DEBUGMSG(1, (TEXT("StartDma-Base0: Base0:    0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Base0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current0));
    }

    if(WaveResource->DmaBufferBBytes) {
        DEBUGMSG(1,(TEXT("StartDma=B\r\n")));
        DEBUGMSG(1, (TEXT("StartDma-Base1: %d\r\n"), WaveResource->DmaBufferBBytes));
//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// DEBUGMSG(1, (TEXT("StartDma-Base1: MaxCnt1:  0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->MaxCnt1));
// DEBUGMSG(1, (TEXT("StartDma-Base1: Base1:    0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Base1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current1));

        WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->MaxCnt1, WaveResource->DmaBufferBBytes);

        WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->Base1, WaveResource->BufferBPhysAddr.LowPart);

        WaveResource->DmaBufferBBytes = 0;
//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// DEBUGMSG(1, (TEXT("StartDma-Base1: MaxCnt1:  0x%8.8X After\r\n"), WaveResource->DmaRegPtr->MaxCnt1));
// DEBUGMSG(1, (TEXT("StartDma-Base1: Base1:    0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Base1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current1));
    }

#endif

    return;
}

VOID
StartDmaOut(
    IN PWAVE_RESOURCE WaveResource
    )
{
    DEBUGMSG(1, (TEXT("StartDma:\r\n")));

#ifdef NOAUDIODMA
    SetEvent(hAudioInterrupt);
#else

//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// RETAILMSG(1, (TEXT("\r\n")));
    if(GetNextDmaBuffer(WaveResource)==WaveResource->DmaBufferA) {
        DEBUGMSG(1,(TEXT("StartDma=A\r\n")));
        DEBUGMSG(1, (TEXT("StartDma-Base0: %d\r\n"), WaveResource->DmaBufferABytes));
//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// DEBUGMSG(1, (TEXT("StartDma-Base0: MaxCnt0:  0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->MaxCnt0));
// DEBUGMSG(1, (TEXT("StartDma-Base0: Base0:    0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Base0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current0));

        WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->MaxCnt0, WaveResource->DmaBufferABytes);

        WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->Base0, WaveResource->BufferAPhysAddr.LowPart);

//        WaveResource->DmaBufferABytes = 0;
//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// DEBUGMSG(1, (TEXT("StartDma-Base0: MaxCnt0:  0x%8.8X After\r\n"), WaveResource->DmaRegPtr->MaxCnt0));
// DEBUGMSG(1, (TEXT("StartDma-Base0: Base0:    0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Base0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current0));
// RETAILMSG(1, (TEXT("StartDma-Base0: Current0: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current0));
    }

    if(GetNextDmaBuffer(WaveResource)==WaveResource->DmaBufferB) {
        DEBUGMSG(1,(TEXT("StartDma=B\r\n")));
        DEBUGMSG(1, (TEXT("StartDma-Base1: %d\r\n"), WaveResource->DmaBufferBBytes));
//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// DEBUGMSG(1, (TEXT("StartDma-Base1: MaxCnt1:  0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->MaxCnt1));
// DEBUGMSG(1, (TEXT("StartDma-Base1: Base1:    0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Base1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X Before\r\n"), WaveResource->DmaRegPtr->Current1));

        WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->MaxCnt1, WaveResource->DmaBufferBBytes);

        WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->Base1, WaveResource->BufferBPhysAddr.LowPart);

//        WaveResource->DmaBufferBBytes = 0;
//*TSAT* 22-Apr-2002 Test code to watch DMA ok/corrupted status as a file is passed to the codec.
// DEBUGMSG(1, (TEXT("StartDma-Base1: MaxCnt1:  0x%8.8X After\r\n"), WaveResource->DmaRegPtr->MaxCnt1));
// DEBUGMSG(1, (TEXT("StartDma-Base1: Base1:    0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Base1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current1));
// RETAILMSG(1, (TEXT("StartDma-Base1: Current1: 0x%8.8X After\r\n"), WaveResource->DmaRegPtr->Current1));
    }

#endif

    return;
}

VOID
ClearDmaStatus(
    IN PWAVE_RESOURCE WaveResource
    )
{
    DEBUGMSG(1, (TEXT("ClearDmaStatus:\r\n")));

    WRITE_REGISTER_ULONG(&WaveResource->DmaRegPtr->Interrupt,
                         (DMA_INT_STALLINT | DMA_INT_NFBINT | DMA_INT_CHERRINT));

    Drv_AHBBus_ExtraWrite();
}


VOID
WaitForDmaComplete(
    IN PWAVE_RESOURCE WaveResource
    )
{
    ULONG Status = 0;
    ULONG CurrentState = 0;
    DMA_CHANNEL_REG* DmaRegPtr;

    DmaRegPtr = WaveResource->DmaRegPtr;

#ifdef NOAUDIODMA
    return;
#endif

    while (1) {
        Status = READ_REGISTER_ULONG(&DmaRegPtr->Status);
        CurrentState = Status & DMA_STATUS_CURRENTSTATE;

        DEBUGMSG(1, (TEXT("WaitForDmaComplete: Status=0x%x\r\n"), Status));

        //
        // If the channel is in STALL or IDLE state, the DMA channel has stopped.
        //
        if (CurrentState == DMA_CURRENTSTATE_IDLE ||
            CurrentState == DMA_CURRENTSTATE_STALL) {
            break;
        }

        //
        // Allow a reschedule to keep from burning processor time spinning
        // in this loop.
        //
        Sleep(1);

        DEBUGMSG(1, (TEXT("WaitForDmaComplete: Waiting for %s to complete.\r\n"),
                     DIR_STR(WaveResource->WaveDirection)));
    }  // end while (1)
}

⌨️ 快捷键说明

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