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

📄 hwctxt.cpp

📁 realtek562x系列驱动源码。wince
💻 CPP
📖 第 1 页 / 共 5 页
字号:

            // Enable STOPINTR so that we know DMA is done on final buffer. A zero length buffer
            // is considered the final buffer.
            // And finally set RUN bit to start DMA.
            m_pDMARegisters->dcsr[m_PlaybackChannel] |=  DCSR_RUN | DCSR_STOPIRQEN;

            DEBUGMSG(ZONE_ERROR, (TEXT("Started Output DMA\r\n")));
        }
        else
        {
            m_OutputDMARunning=FALSE;
            DEBUGMSG(ZONE_ERROR, (TEXT("no Output started with DMA\r\n")));
        }
    }
}

void HardwareContext::StopOutputDMA()
{
    DEBUGMSG(ZONE_VERBOSE, (TEXT("StopOutputDMA\r\n")));
    if (m_OutputDMARunning)
    {
        //stop the dma channel and mute
        StopDmac(m_PlaybackChannel);
        m_OutputDMARunning=FALSE;

    }

}

int HardwareContext::GetLastInputBuffer(void)
{
   
   return ((UINT32)m_pDMARegisters->ddg[m_RecordingChannel].dtadr >= (UINT32)m_Input_pbDMA_PAGES_Physical[1]) ? 0 : 1 ;

}

void HardwareContext::StartInputDMA()
{
    if (!m_InputDMARunning)
    {
#if RT_ALC5621
		m_RTCodec->WriteCodecRegMask(RT5621_MISC_CTRL,DISABLE_FAST_VREG,DISABLE_FAST_VREG);	//disable fast vreg,it will affect quality of audio
#else
		m_RTCodec->WriteCodecRegMask(RT_MISC_CTRL,DISABLE_FAST_VREG,DISABLE_FAST_VREG);	//disable fast vreg,it will affect quality of audio
#endif

        //set it on every buffer due to ac97 work around. (???)
        SetSampleRate(SAMPLERATE, WAPI_IN);

        // For now, pretend input dma is running in case we accidentally get reentered
        m_InputDMARunning=TRUE;

        //DMA_CH_RCV:
        DEBUGMSG(ZONE_ERROR, (TEXT( "Starting DMA Recieve channel \r\n" )) );
        m_pDMARegisters->ddg[m_RecordingChannel].ddadr = (UINT32)m_vpAudioRcvA_Physical;

#if	USE_I2S_INTERFACE

        m_pDMARegisters->drcmr[DMA_CHMAP_I2S_RCV] = DMA_MAP_VALID_MASK | m_RecordingChannel ;
		m_pI2SRegs->SAICR=XLLP_SAICR_ROR;//clear receive FIFO overrun

#else

        m_pDMARegisters->drcmr[DMA_CHMAP_AC97_RCV] = DMA_MAP_VALID_MASK | m_RecordingChannel ;
        m_pAc97regs->PISR = 0x10;  // clear Pcm Input Fifo status
        m_pAc97regs->PISR = 0x8;   // dedicated write to clear EOC bit

#endif

        m_pDMARegisters->dcsr[m_RecordingChannel] |=  DCSR_RUN;          // set the RUN bit
    }
}

void HardwareContext::StopInputDMA()
{
    if (m_InputDMARunning)
    {
        m_InputDMARunning=FALSE;
        StopDmac(m_RecordingChannel);
    }
}

/* ;resample stereo output to mono output?
   ;set this if your platform has only mono speaker. if your platform supports
   ; both mono speaker and a stereo headset you'll have to dynamically change
   ; the flag in wavedev2 driver for proper output rendering (mono vs. stereo)
   ;MainstoneIII has both a mono speaker and a stereo headphone jack. But unfortunately
   ; headphone presence detection is not supported by the onboard philips codec.
   ; For this reason we only render mono output.
   "HKLM\Drivers\BuiltIn\WaveDev\OutputRenderMonoOnly"=dword:1          <-- Reg Key
   m_fOutputRenderMonoOnly                                              <-- flag in wavedev2 driver
*/
#define WAV_OUTPUT_RENDER_MONO_ONLY TEXT("OutputRenderMonoOnly")

BOOL HardwareContext::GetRegKeys()
{

    HKEY hDevKey;

    hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
    
    if (hDevKey)
    {
        DWORD dwValLen = sizeof(DWORD);
        DWORD dwOutputRenderMonoOnly = 0;
        LONG regError = RegQueryValueEx(hDevKey, WAV_OUTPUT_RENDER_MONO_ONLY, NULL, NULL,
            (PUCHAR)&dwOutputRenderMonoOnly, &dwValLen);

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

        RegCloseKey(hDevKey);
    }

    return (TRUE);   
}

DWORD HardwareContext::GetInterruptThreadPriority()
{

//    HKEY hDevKey;
//    DWORD dwValType;
//    DWORD dwValLen;
    DWORD dwPrio = 249; // Default priority
/*    hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
    if (hDevKey)
    {
        dwValLen = sizeof(DWORD);
        RegQueryValueEx(
            hDevKey,
            TEXT("Priority256"),
            NULL,
            &dwValType,
            (PUCHAR)&dwPrio,
            &dwValLen);
        RegCloseKey(hDevKey);
    }
*/
    return dwPrio;
}


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

    m_hAudioInputInterruptThread  = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
                                            0,
                                            (LPTHREAD_START_ROUTINE)CallInputInterruptThread,
                                            this,
                                            0,
                                            NULL);
    m_hAudioOutputInterruptThread  = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
                                            0,
                                            (LPTHREAD_START_ROUTINE)CallOutputInterruptThread,
                                            this,
                                            0,
                                            NULL);

    if (!m_hAudioInputInterruptThread)
    {
        return FALSE;
    }

    if (!m_hAudioOutputInterruptThread)
    {
        return FALSE;
    }
   

    // Bump up the priority since the interrupt must be serviced immediately.
    CeSetThreadPriority(m_hAudioInputInterruptThread, GetInterruptThreadPriority());
    CeSetThreadPriority(m_hAudioOutputInterruptThread, GetInterruptThreadPriority());

    DEBUGMSG(ZONE_INIT, (TEXT("-InitInterruptThread\r\n")));
    return TRUE;
}

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

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


    //Power down Codec and  shutdown the AClink
    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::GetInterruptType()
{
    DWORD dwDCSR;
    DWORD dwDINT;

    dwDINT = m_pDMARegisters->dint;
    DEBUGMSG(ZONE_VERBOSE, (TEXT( "HardwareContext::GetInterruptType: DINT=0x%x\r\n" ), dwDINT));

    if(dwDINT & DMAC_AC97AUDIORCV)
    {
        //
        // I N P U T
        //
        dwDCSR  = m_pDMARegisters->dcsr[m_RecordingChannel];
        DEBUGMSG(ZONE_VERBOSE, (TEXT( "GetInterruptType: RCV DCSR: 0x%x\r\n" ),dwDCSR));

        // Provide waiting Object the current value of DCSR
        // SetEventData(hInputIntEvent, dwDCSR);

        //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;

        SetEvent(hInputIntEvent);
    }

    if(dwDINT & DMAC_AC97AUDIOXMIT)
    {
        //
        // O U T P U T
        //
        dwDCSR  = m_pDMARegisters->dcsr[m_PlaybackChannel];
        DEBUGMSG(ZONE_VERBOSE, (TEXT( "GetInterruptType: OUT DCSR: 0x%x\r\n" ),dwDCSR));

        // Provide waiting Object the current value of DCSR
        // SetEventData(hOutputIntEvent, dwDCSR);

        //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;

        SetEvent(hOutputIntEvent);
    }
//	RETAILMSG(1, (TEXT( "dwDINT=%x"),dwDINT));
    return;
}


void HardwareContext::InterruptThread()
{
    while (TRUE)
    {
        WaitForSingleObject(m_hAudioInterrupt,  INFINITE);
        if (TRUE == m_audioDeinit)
        {
            return;
        }

        // Grab the lock
        Lock();

        GetInterruptType();

        Unlock();
        

⌨️ 快捷键说明

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