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

📄 hwctxt.cpp

📁 realtek562x系列驱动源码。wince
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        }
        
        m_fOutputRenderMonoOnly = (dwOutputRenderMonoOnly == 1);

        RegCloseKey(hDevKey);
    }

    return (TRUE);   
}

DWORD HardwareContext::GetInterruptThreadPriority()
{
    HKEY hDevKey;
    DWORD dwValType;
    DWORD dwValLen;
    LONG regError;
    
    DWORD dwPrio = INTERRUPT_THREAD_PRIORITY_DEFAULT; // Default priority

    hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
    if (hDevKey)
    {
        dwValLen = sizeof(DWORD);
        regError = RegQueryValueEx(hDevKey,
                                   TEXT("Priority256"),
                                   NULL,
                                   &dwValType,
                                   (PUCHAR)&dwPrio,
                                   &dwValLen);

        if (regError != ERROR_SUCCESS)
        {
            DEBUGMSG(ZONE_INIT,(TEXT("WAVEDEV_GetRegKeys: INFO: Failed opening \\Drivers\\BuiltIn\\WaveDev\\Priority256\r\n")));
        }

        RegCloseKey(hDevKey);
    }

    return dwPrio;
}



BOOL HardwareContext::Deinit()
{
    DEBUGMSG(ZONE_INIT, (TEXT("HardwareContext::Deinit\r\n")));

    m_audioDeinit = TRUE;
    
    StopOutputDMA();
    StopInputDMA();
    
    UnmapDMA();


    //Power down Codec and  shutdown the AClink/IIS
    PowerDown();

#if USE_I2S_INTERFACE

	//De-allocate the I2S
	DeInitializeI2S(m_InPowerHandler);
	
#else

	//De-allocate the AC97
    DeInitializeACLink(FALSE, DEV_AUDIO);
    
#endif


    DeinitAudioDMA();
        
    UnMapDeviceRegisters();

    m_Initialized = FALSE;
    return TRUE;
}

ULONG HardwareContext::TransferInputBuffer(ULONG NumBuf)
{
    ULONG BytesTransferred;
    PBYTE pBufferStart = m_Input_pbDMA_PAGES[NumBuf];
    PBYTE pBufferEnd = pBufferStart + AUDIO_BUFFER_SIZE;
    PBYTE pBufferLast;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("TransferInputBuffer %d"), NumBuf));

    pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
    BytesTransferred = pBufferLast-pBufferStart;

    return BytesTransferred;
}

ULONG HardwareContext::TransferOutputBuffer(ULONG NumBuf)
{
    ULONG BytesTransferred;
    PBYTE pBufferStart = m_Output_pbDMA_PAGES[NumBuf];
    PBYTE pBufferEnd = pBufferStart + AUDIO_BUFFER_SIZE;
    PBYTE pBufferLast;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("TransferOutputBuffer %d\r\n"), NumBuf));

    pBufferLast = m_OutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
    BytesTransferred = pBufferLast-pBufferStart;

    // PXA27x AC'97 Controller will transmit data in multiple of 32 bytes only.
    // The trailing bytes will not be transmitted.
    // So we pad the buffer with zeroes to a multiple of 32 bytes.
    if(int pad = (BytesTransferred % 32))
    {
        // number of bytes to pad
        pad = 32 - pad;
        StreamContext::ClearBuffer(pBufferLast, pBufferLast+pad);
        BytesTransferred += pad;
    }

    // Set DMA transfer length based on actual data in buffer.
    // Also set STOP bit if it is the last buffer (ie. zero length buffer).
    if(NumBuf == 0)
    {
        m_vpAudioXmitA->dcmd = DMAC_AC97_XMITAB_CMD_MASK | BytesTransferred;

        if(BytesTransferred)
        {
            m_vpAudioXmitA->ddadr &= ~DESC_ADDRESS_STOP_MASK;
        }
        else
        {
            m_vpAudioXmitA->ddadr |= DESC_ADDRESS_STOP_MASK;
        }
    }
    else
    {
        m_vpAudioXmitB->dcmd = DMAC_AC97_XMITAB_CMD_MASK | BytesTransferred;

        if(BytesTransferred)
        {
            m_vpAudioXmitB->ddadr &= ~DESC_ADDRESS_STOP_MASK;
        }
        else
        {
            m_vpAudioXmitB->ddadr |= DESC_ADDRESS_STOP_MASK;
        }
    }

    DEBUGMSG(ZONE_VERBOSE, (TEXT("Fill buffer[%d]: 0x%x\r\n"), NumBuf, BytesTransferred));

    return BytesTransferred;
}

void HardwareContext::HandleAudioInterrupt()
{
    DWORD dwDCSR;
    DWORD dwDINT;
    ULONG InputTransferred;
    ULONG OutputTransferred;
    int buffer;


    dwDINT = m_pDMARegisters->dint;

    if(dwDINT & DMAC_AC97AUDIORCV)
    {
        //
        // I N P U T
        //
        dwDCSR  = m_pDMARegisters->dcsr[m_RecordingChannel];

        //did we get an input error?
        if (dwDCSR & DCSR_BUSERRINTR)
        {
            DEBUGMSG(ZONE_ERROR, (TEXT( "DCSR_BUSERRINTR ERROR on input\r\n" )) );
            DEBUGCHK(0);  // an unplanned dma interrupt occured 
            DumpDmacRegs();
        }
    
        //did we get an input start interrupt?
        if (dwDCSR & DCSR_STARTINTR)  
        {
            DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_STARTINTR on input\r\n" )) );
            DEBUGCHK(0); // an unplanned dma interrupt occured 
        }
    
        //did we get an input end interrupt?
        if (dwDCSR & DCSR_ENDINTR)  //if the input channel stopped at the end of a buffer xfer
        {
            DEBUGMSG(ZONE_ERROR, (TEXT( "DCSR_ENDINTR on intput\r\n" )) );
        }

        //did we get an input stop interrupt?
        if (dwDCSR & DCSR_STOPINTR)  
        {
            DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_STOPINTR on input\r\n" )) );
            dwDCSR &= ~DCSR_STOPIRQEN;
            DEBUGCHK(0); // an unplanned dma interrupt occured 
        }

        // Clear the status
        m_pDMARegisters->dcsr[m_RecordingChannel] = dwDCSR;

        // Handle the interrupt
        buffer = GetLastInputBuffer();
        InputTransferred = TransferInputBuffer(buffer);

        if( InputTransferred==0 )
        {
            StopInputDMA();
        }
    }

    if(dwDINT & DMAC_AC97AUDIOXMIT)
    {
        //
        // O U T P U T
        //
        dwDCSR  = m_pDMARegisters->dcsr[m_PlaybackChannel];

        //did we get an output error?
        if (dwDCSR & DCSR_BUSERRINTR)
        {
            DEBUGMSG(ZONE_ERROR, (TEXT( "DCSR_BUSERRINTR ERROR on output\r\n" )) );
            DumpDmacRegs();

            //note if we get here, we have a lot more to do than clear the interrupt.
            DEBUGCHK(0); // an unplanned dma interrupt occured 
        }

        //did we get an output start interrupt?
        if (dwDCSR & DCSR_STARTINTR)   
        {
            DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_STARTINTR on output\r\n" )) );
        }

        //did we get an output end interrupt?
        if (dwDCSR & DCSR_ENDINTR)      //if the out channel stopped at the end of a buffer xfer
        {       
            DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_ENDINTR on output\r\n" )) );
        }

        //did we get an output stop interrupt?
        if (dwDCSR & DCSR_STOPINTR)  
        {
            DEBUGMSG(ZONE_VERBOSE, (TEXT( "DCSR_STOPINTR on output\r\n" )) );
            dwDCSR &= ~DCSR_STOPIRQEN;

            m_OutputDMARunning = FALSE;
        }

        // Clear the status
        m_pDMARegisters->dcsr[m_PlaybackChannel] = dwDCSR;

        // Handle the interrupt
        buffer = GetNextOutputBuffer();
        OutputTransferred = TransferOutputBuffer(buffer);

        if(!m_OutputDMARunning)
        {
            if(OutputTransferred)
            {
                // More data to play. Restart DMA engine by loading the descriptor
               // address reg to initialize DMA, pointing to the buffer just loaded.
                m_pDMARegisters->ddg[m_PlaybackChannel].ddadr =
                    (buffer == 0) ? (UINT32)m_vpAudioXmitA_Physical : (UINT32)m_vpAudioXmitB_Physical;;
                
                // Set the RUN bit and also enable STOPINTR so that we know DMA is done
                // on last buffer. A zero length buffer is considered the last buffer.
                m_pDMARegisters->dcsr[m_PlaybackChannel] |=  DCSR_RUN | DCSR_STOPIRQEN;
                m_OutputDMARunning=TRUE;
            }
            else
            {
                // No more data to play. Will stop when the previous buffer
                StopOutputDMA();
            }
        }
    }

    return;
}


void HardwareContext::InterruptThread()
{
    while (TRUE)
    {
        InterruptDone(m_SysIntrAudioDMA);

        WaitForSingleObject(m_hAudioInterrupt,  INFINITE);
        if (TRUE == m_audioDeinit)
        {
            return;
        }

        Lock();

        HandleAudioInterrupt();

        Unlock();
        
    }  // while(TRUE)

}

void CallInterruptThread(HardwareContext *pHWContext)
{
    DEBUGMSG(ZONE_INIT, (TEXT("CallInterruptThread")));
    pHWContext->InterruptThread();
}


#if !USE_I2S_INTERFACE

BOOL HardwareContext::TestAcLink()
{
    BOOL RetVal=TRUE;

    int i;

    unsigned short int Value;

    for (i=0;i<0x80;i+=2)
    {
        SafeReadCodec(i, &Value, DEV_AUDIO);
        RETAILMSG(1, (TEXT( "register::value %x %x" ),i,Value ));
    }

    return (RetVal);
}

#endif

//------------------------------------------------------------------------------------------------------------
// Function: FillDescriptors
// 
// Purpose: Fill the descriptors with appropriate data
//
// Note: This code could be cleaner, but I want to be explicit on the programming of descriptors
//
//-------------------------------------------------------------------------------------------------------------
BOOL HardwareContext::FillOutputDescriptors( void )
{
    union DmaCmdReg     CmdBuff;
    memset (&CmdBuff,0, sizeof (CmdBuff));

        // set individual bit fields to for debug.  

#define USE_BITFIELD
#ifdef USE_BITFIELD  
        
        // set values with bit fields
        CmdBuff.DcmdReg.len = AUDIO_BUFFER_SIZE;  //length of memory buffer
        CmdBuff.DcmdReg.width = 0x3;    // binary 11 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
        CmdBuff.DcmdReg.size = 0x3;     // binary 11 
        CmdBuff.DcmdReg.endian = 0;     // little endian
        CmdBuff.DcmdReg.flybyt = 0;     // Flowthrough
        CmdBuff.DcmdReg.flybys = 0;     // Flowthrough
        CmdBuff.DcmdReg.endirqen = 1;   // 1 means Interrupt when decrement length = 0;
        CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
        CmdBuff.DcmdReg.flowtrg = 1;    // 1 means the target is an external peripheral
        CmdBuff.DcmdReg.flowsrc = 0;    // 1 means the source is an external peripheral (and needs flow con
        CmdBuff.DcmdReg.inctrgadd = 0;  // 1 means increment the target address (since it's memory) 
        CmdBuff.DcmdReg.incsrcadd = 1;  // 1 means increment the source address (since it's a peripheral)
#else  
        // set value based on masks
        CmdBuff.DcmdDword = DMAC_AC97_XMITAB_CMD_MASK | AUDIO_BUFFER_SIZE; 
#endif

        //
        // fill XmitA Descriptor
        //

        m_vpAudioXmitA->ddadr= (UINT32)m_vpAudioXmitB_Physical ;             // address of the next (XmitB) descriptor

#if USE_I2S_INTERFACE

		m_vpAudioXmitA->dtadr=  DMAC_IIS_AUDIO_XMIT_FIFO;                   // source address of the IIS XmitA buffer
		
#else

        m_vpAudioXmitA->dtadr=  DMAC_AC97_AUDIO_XMIT_FIFO;                   // source address of the AC97 XmitA buffer
        
#endif

        m_vpAudioXmitA->dsadr= (UINT32)(m_Output_pbDMA_PAGES_Physical[0]);   // destination address of the XmitA buffer
        m_vpAudioXmitA->dcmd = CmdBuff.DcmdDword ;                           // size and cmd values of the XmitA buffer

        //
        // fill XmitB Descriptor
        //

        m_vpAudioXmitB->ddadr= (UINT32)m_vpAudioXmitA_Physical;              // address of the next (XmitA) descriptor

#if USE_I2S_INTERFACE

		m_vpAudioXmitB->dtadr= DMAC_IIS_AUDIO_XMIT_FIFO;                    // source address of the IIS XmitB buffer
		
#else

        m_vpAudioXmitB->dtadr= DMAC_AC97_AUDIO_XMIT_FIFO;                    // source address of the AC97 XmitB buffer
        
#endif

        m_vpAudioXmitB->dsadr= (UINT32)(m_Output_pbDMA_PAGES_Physical[1]) ;  // destination address of the XmitB buffer
        m_vpAudioXmitB->dcmd = CmdBuff.DcmdDword ;                           // size and cmd values of the XmitB buffer

        return TRUE;
}

//------------------------------------------------------------------------------------------------------------
// Function: FillDescriptors
// 
// Purpose: Fill the descriptors with appropriate data
//
// Note: This code could be cleaner, but I want to be explicit on the programming of descriptors
//
//-------------------------------------------------------------------------------------------------------------
BOOL HardwareContext::FillInputDescriptors( void )
{
    union DmaCmdReg     CmdBuff;
    memset (&CmdBuff,0, sizeof (CmdBuff));

        // set individual bit fields to for debug.  

#define USE_BITFIELD
#ifdef USE_BITFIELD  
        
        // set values with bit fields  
        CmdBuff.DcmdReg.len = AUDIO_BUFFER_SIZE;  //length of the memory buffer
        CmdBuff.DcmdReg.width = 0x3;    // binary 11 (see quick Quick Reference sheet to DMA programming in the cotulla EAS)
        CmdBuff.DcmdReg.size = 0x3;     // binary 11 
        CmdBuff.DcmdReg.endian = 0;     // little endian
        CmdBuff.DcmdReg.flybyt = 0;     // Flowthrough
        CmdBuff.DcmdReg.flybys = 0;     // Flowthrough
        CmdBuff.DcmdReg.endirqen = 1;   // 1 means Interrupt when decrement length = 0;
        CmdBuff.DcmdReg.startirqen = 0; // 1 means Interrupt when the desc is loaded
        CmdBuff.DcmdReg.flowtrg = 0;    // 1 means the target is an external peripheral
        CmdBuff.DcmdReg.flowsrc = 1;    // 1 means the source is an external peripheral (and needs flow control)
        CmdBuff.DcmdReg.inctrgadd = 1;  // 1 means increment the target address (since it's memory) 
        CmdBuff.DcmdReg.incsrcadd = 0;  // 1 means increment the source address (since it's a peripheral)
#else  
        // set value based on masks
        CmdBuff.DcmdDword = DMAC_AC97_RCVAB_CMD_MASK | AUDIO_BUFFER_SIZE;  
#endif

        //
        // fill RcvA Descriptor
        //

        m_vpAudioRcvA-> ddadr= (UINT32)m_vpAudioRcvB_Physical;           // address of the next (RcvB) descriptor
        m_vpAudioRcvA-> dtadr= (UINT32)(m_Input_pbDMA_PAGES_Physical[0]);                        // source address of the AC97 RcvA buffer

#if USE_I2S_INTERFACE

		m_vpAudioRcvA-> dsadr= DMAC_IIS_AUDIO_RCV_FIFO;           // destination address of the RcvA buffer
		
#else

        m_vpAudioRcvA-> dsadr= DMAC_AC97_AUDIO_RCV_FIFO;           // destination address of the RcvA buffer
        
#endif

        m_vpAudioRcvA-> dcmd = CmdBuff.DcmdDword ;                                                           // size and cmd values of the RcvA buffer

        //
        // fill RcvB Descriptor
        //

        m_vpAudioRcvB-> ddadr= (UINT32)m_vpAudioRcvA_Physical ;             // address of the next (RcvA) descriptor
        m_vpAudioRcvB-> dtadr= (UINT32)(m_Input_pbDMA_PAGES_Physical[1]);                        // source address of the AC97 RcvB buffer

⌨️ 快捷键说明

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