📄 hwctxt.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2004-2006, Freescale Semiconductor, Inc. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// FREESCALE SEMICONDUCTOR, INC.
//
//------------------------------------------------------------------------------
//
// Copyright (C) 2005, MOTOROLA, INC. All Rights Reserved
// THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
// BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
// MOTOROLA, INC.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
// Module: hwctxt.cpp
//
// Hardware context for audio driver. Contains code to support both STAC9753 and
// WM8731 codecs. The audio driver uses DMA chaining with double buffering to
// remove SSI overruns/underruns.
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// INCLUDE FILES
//------------------------------------------------------------------------------
#include "wavemain.h"
#include <ceddk.h>
//------------------------------------------------------------------------------
// GLOBAL DEFINITIONS
//------------------------------------------------------------------------------
//#if AC97
// Set 1 to use variable rate mode, default is fixed rate.
//#define VRA 0
//#endif
#define AUDIO_CH_OUT 2
#define AUDIO_CH_IN 1
//------------------------------------------------------------------------------
// GLOBAL OR STATIC VARIABLES
//------------------------------------------------------------------------------
HardwareContext *g_pHWContext = NULL;
//------------------------------------------------------------------------------
// STATIC FUNCTION PROTOTYPES
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXT("WaveDriver"), {
TEXT("Test") // 0 ZONE_TEST
,TEXT("Params") // 1 ZONE_PARAMS
,TEXT("Verbose") // 2 ZONE_VERBOSE
,TEXT("Interrupt") // 3 ZONE_INTERRUPT
,TEXT("WODM") // 4 ZONE_WODM
,TEXT("WIDM") // 5 ZONE_WIDM
,TEXT("PDD") // 6 ZONE_PDD
,TEXT("MDD") // 7 ZONE_MDD
,TEXT("Regs") // 8 ZONE_REGS
,TEXT("Misc") // 9 ZONE_MISC
,TEXT("Init") // 10 ZONE_INIT
,TEXT("IOcontrol") // 11 ZONE_IOCTL
,TEXT("Alloc") // 12 ZONE_ALLOC
,TEXT("Function") // 13 ZONE_FUNCTION
,TEXT("Warning") // 14 ZONE_WARN
,TEXT("Error") // 15 ZONE_ERROR
},
(1 << 15) // Errors
| (1 << 14) // Warnings
};
#endif
BOOL HardwareContext::CreateHWContext(DWORD Index)
{
if (g_pHWContext)
{
return(TRUE);
}
g_pHWContext = new HardwareContext;
if (!g_pHWContext)
{
return(FALSE);
}
return(g_pHWContext->Init(Index));
}
HardwareContext::HardwareContext()
: m_InputDeviceContext(), m_OutputDeviceContext()
{
InitializeCriticalSection(&m_Lock);
m_Initialized=FALSE;
}
HardwareContext::~HardwareContext()
{
DeleteCriticalSection(&m_Lock);
}
BOOL HardwareContext::Init(DWORD Index)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+Init\r\n")));
if(m_Initialized)
{
return FALSE;
}
m_dwInputGain = 0xFFFF;
m_dwOutputGain = 0xFFFF;
m_fInputMute = FALSE;
m_fOutputMute = FALSE;
//----- 1. Initialize the state/status variables -----
m_DriverIndex = Index;
m_InPowerHandler = FALSE;
m_InputDMARunning = FALSE;
m_OutputDMARunning = FALSE;
//----- 2. Map the DMA buffers into driver's virtual address space -----
if(!MapDMABuffers())
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - Failed to map DMA buffers.\r\n")));
goto Exit;
}
//----- 3. Call BSP function to initialize audio -----
BSPAudioInit();
//----- 3. Power up the audio -----
PowerUp();
//----- 4. Configure the Codec -----
BSPAudioInitCodec();
//----- 5. Initialize the interrupt thread -----
if (!InitInterruptThread())
{
DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - Failed to initialize interrupt thread.\r\n")));
goto Exit;
}
m_Initialized = TRUE;
Exit:
DEBUGMSG(ZONE_FUNCTION, (TEXT("+Init m_Initialized=%d\r\n"), m_Initialized));
return m_Initialized;
}
//------------------------------------------------------------------------------
//
// FUNCTION: Deinit
//
// DESCRIPTION: De-initialises the audio hardware
//
// PARAMETERS:
// None
//
// RETURNS:
// TRUE for success initialisation.
// FALSE otherwise
//
//------------------------------------------------------------------------------
BOOL HardwareContext::Deinit()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+Deinit\r\n")));
//----- 1. Disable the input/output channels -----
BSPAudioStartOutput(FALSE);
BSPAudioStartInput(FALSE);
//----- 2. Disable/clear DMA input/output interrupts -----
DDKDmacDisableChannelIntr(m_DmaRxChannel);
DDKDmacStopChan(m_DmaRxChannel);
DDKDmacDisableChannelIntr(m_DmaTxChannel);
DDKDmacStopChan(m_DmaTxChannel);
//----- 3. Turn the audio hardware off -----
AudioMute((AUDIO_CH_OUT | AUDIO_CH_IN), TRUE);
//----- 4. Unmap the control registers and DMA buffers -----
BSPAudioDeinit();
UnmapDMABuffers();
DEBUGMSG(ZONE_FUNCTION, (TEXT("-Deinit\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
//
// FUNCTION: MapDMABuffers
//
// DESCRIPTION: Map both DMA pages into the local address space
//
// PARAMETERS:
// None
//
// RETURNS:
// TRUE for success
// FALSE otherwise
//
//------------------------------------------------------------------------------
BOOL HardwareContext::MapDMABuffers()
{
PBYTE pVirtDMABufferAddr = NULL;
DMA_ADAPTER_OBJECT Adapter;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+MapDMABuffers\r\n")));
memset(&Adapter, 0, sizeof(DMA_ADAPTER_OBJECT));
Adapter.InterfaceType = Internal;
Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
// Allocate a block of virtual memory (physically contiguous) for the DMA buffers.
//
pVirtDMABufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter, (AUDIO_DMA_PAGE_SIZE * 4), &m_PhysDMABufferAddr, FALSE);
if (pVirtDMABufferAddr == NULL)
{
ERRORMSG(TRUE, (TEXT("WAVEDEV.DLL:HardwareContext::MapDMABuffers() - Failed to allocate DMA buffer.\r\n")));
return(FALSE);
}
// Setup the DMA page pointers.
// NOTE: Currently, input and output each have two DMA pages: these pages are used in a round-robin
// fashion so that the OS can read/write one buffer while the audio codec chip read/writes the other buffer.
//
m_Output_pbDMA_PAGES[0] = pVirtDMABufferAddr;
m_Output_pbDMA_PAGES[1] = pVirtDMABufferAddr + AUDIO_DMA_PAGE_SIZE;
m_Input_pbDMA_PAGES[0] = pVirtDMABufferAddr + (2 * AUDIO_DMA_PAGE_SIZE);
m_Input_pbDMA_PAGES[1] = pVirtDMABufferAddr + (3 * AUDIO_DMA_PAGE_SIZE);
// Return physical addresses for TX and RX buffer
m_DmaTxBuffer[0] = (UINT32)m_PhysDMABufferAddr.QuadPart;
m_DmaTxBuffer[1] = (UINT32)m_PhysDMABufferAddr.QuadPart + AUDIO_DMA_PAGE_SIZE;
m_DmaRxBuffer[0] = (UINT32)m_PhysDMABufferAddr.QuadPart + (2 * AUDIO_DMA_PAGE_SIZE);
m_DmaRxBuffer[1] = (UINT32)m_PhysDMABufferAddr.QuadPart + (3 * AUDIO_DMA_PAGE_SIZE);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-MapDMABuffers\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
//
// FUNCTION: UnmapDMABuffers
//
// DESCRIPTION: Unmap DMA pages
//
// PARAMETERS:
// None
//
// RETURNS:
// TRUE for success
// FALSE otherwise
//
//------------------------------------------------------------------------------
BOOL HardwareContext::UnmapDMABuffers()
{
if(m_Output_pbDMA_PAGES[0])
{
DMA_ADAPTER_OBJECT Adapter;
memset(&Adapter, 0, sizeof(DMA_ADAPTER_OBJECT));
Adapter.InterfaceType = Internal;
Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
HalFreeCommonBuffer(&Adapter, 0, m_PhysDMABufferAddr, m_Output_pbDMA_PAGES[0], FALSE);
}
return TRUE;
}
MMRESULT HardwareContext::SetOutputGain (DWORD dwGain)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+SetOutputGain\r\n")));
BSPSetOutputGain(dwGain);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-SetOutputGain\r\n")));
return MMSYSERR_NOERROR;
}
MMRESULT HardwareContext::SetOutputMute(BOOL fMute)
{
m_fOutputMute = fMute;
// Mute outputs
DEBUGMSG(ZONE_FUNCTION, (TEXT("+SetOutputMute\r\n")));
BSPSetOutputMute(m_fOutputMute);
DEBUGMSG(ZONE_FUNCTION, (TEXT("+SetOutputMute\r\n")));
return MMSYSERR_NOERROR;
}
BOOL HardwareContext::GetOutputMute (void)
{
return m_fOutputMute;
}
DWORD HardwareContext::GetOutputGain (void)
{
return m_dwOutputGain;
}
BOOL HardwareContext::GetInputMute (void)
{
return m_fInputMute;
}
MMRESULT HardwareContext::SetInputMute (BOOL fMute)
{
m_fInputMute = fMute;
return m_InputDeviceContext.SetGain(fMute ? 0: m_dwInputGain);
}
DWORD HardwareContext::GetInputGain (void)
{
return m_dwInputGain;
}
MMRESULT HardwareContext::SetInputGain (DWORD dwGain)
{
m_dwInputGain = dwGain;
if (! m_fInputMute)
{
m_InputDeviceContext.SetGain(dwGain);
}
return MMSYSERR_NOERROR;
}
//------------------------------------------------------------------------------
//
// FUNCTION: StartOutputDMA
//
// DESCRIPTION: Start playback DMA
//
// PARAMETERS:
// None
//
// RETURNS:
// None
//
//------------------------------------------------------------------------------
BOOL HardwareContext::StartOutputDMA()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("+StartOutputDMA\r\n")));
UINT32 OutputTransferred;
if(!m_OutputDMARunning)
{
//----- 1. Initialize our buffer counters -----
// For now, pretend output dma is running in case we accidentally get reentered
m_OutputDMARunning=TRUE;
m_OutBytes[0] = 0;
m_OutBytes[1] = 0;
m_TxBufIndex = 0;
//----- 2. Prime the output buffer with sound data -----
OutputTransferred = TransferOutputBuffers();
OutputTransferred += TransferOutputBuffers();
//----- 3. If we did transfer any data to the DMA buffers, go ahead and enable DMA -----
if(OutputTransferred)
{
//----- 4. Configure the channel for playback -----
DDKDmacSetSrcAddress(m_DmaTxChannel, m_DmaTxBuffer[0]);
DDKDmacSetRepeatType(m_DmaTxChannel, DMAC_REPEAT_FOREVER);
DDKDmacEnableChannelIntr(m_DmaTxChannel);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -