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

📄 cx5530audio.cpp

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// CX5530Audio.cpp: implementation of the CCX5530Audio class.
//
//////////////////////////////////////////////////////////////////////
#include "includes.h"
#include <nkintr.h>
#include <pc_pnp.h>
#include <dsdriver.h>
#include "globals.h"
#include "mixhw.h"
#include "hardware.h"
#include "DMAChannel.h"
#include "HardwareBuffer.h"
#include "DsDriverBuffer.h"
#include "DsCaptureDriverBuffer.h"
#include "AC97CODEC.h"
#include "CX5530Audio.h"

extern "C" unsigned short  __cdecl _outpw(unsigned short, unsigned short);

// a couple of mixer driver defines (for SetVolumePan)

DWORD SetMixerVolume(PDRIVER_CONTEXT pDriverContext, DWORD dwId, DWORD dwLeft, DWORD dwRight );


typedef enum 
{
	PCM_TYPE_M8,
	PCM_TYPE_M16,
	PCM_TYPE_S8,
	PCM_TYPE_S16
} PCM_TYPE, *PPCM_TYPE;

CCX5530Audio* CCX5530Audio::m_pSingleObject= NULL;

DWORD WINAPI InterruptThreadHelper(PVOID lpParm)
{
	FUNCMSG("+InterruptThreadHelper");
	((CCX5530Audio*)lpParm)->InterruptThreadRoutine();
	return FALSE;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CCX5530Audio::CCX5530Audio():
	m_pCodec(NULL),
	m_hInterruptThread(NULL),
	m_hInterruptEvent(NULL),
	m_bExiting(false),
	m_pAudioRegisters(NULL),
	m_dwInterrupt(0)
{
    FUNCMSG("+CCX5530Audio::CCX5530Audio()");
	for (UINT i = 0; i < sizeof(m_PlaybackChannels)/sizeof(m_PlaybackChannels[0]); i++)
		m_PlaybackChannels[i] = NULL;
	for (i = 0; i < sizeof(m_CaptureChannels)/sizeof(m_CaptureChannels[0]); i++)
		m_CaptureChannels[i] = NULL;
	InitializeCriticalSection(&m_csCX5530Audio);
}

CCX5530Audio::~CCX5530Audio()
{
    FUNCMSG("+CCX5530Audio::~CCX5530Audio()");
	CleanUpObject();
}


bool CCX5530Audio::Initialize()
{
	DWORD dwThreadId;
    FUNCMSG("+CCX5530Audio::Initialize()");
	
	// get the interrupt from the registry
	
	if (!GetRegistryConfig())
	{
        ERRMSG("CCX5530Audio::Initialize(): registry info not found");
		return false;
	}
	
    // initialize the hardware
	
	if (!InitAudio())
	{
        ERRMSG("CCX5530Audio::Initialize(): sound device error");
        return false;
    }
	
	// Create and register for the interrupt
	
	// CAUTION: on Cedar the call to InterruptInitialize(hEvent,IRQ) 
	// must be made before the Interrupt Service Thread (IST) calls 
	// WaitForSingleObject(hEvent).  InterruptInitialize() will fail if the 
	// event is already being waited upon, and the interrupt will not be enabled.
	// The solution is to call InterruptInitialize() before CreateThread(), or you can 
	// create the thread suspended and call ResumeThread() after InterruptInitialize().

	
	m_hInterruptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	
	if (!m_hInterruptEvent)
	{
		ERRMSG1("Can't create interrupt event: %d!", GetLastError());
		return false;
	}

	m_dwInterrupt = MapIrq2SysIntr(m_dwInterrupt);
	
	INFMSG1("Mapped Interrupt is %d", m_dwInterrupt);
	
    if (!InterruptInitialize(m_dwInterrupt, m_hInterruptEvent, NULL, 0))
	{
		ERRMSG1("Can't initialize interrupt: %d!", GetLastError());
		return false;
	}

	m_hInterruptThread = CreateThread(NULL, 0, InterruptThreadHelper, this, 0, &dwThreadId);
	
	if (!m_hInterruptThread)
	{
		ERRMSG1("Can't create interrupt thread: %d!", GetLastError());
		return false;
	}
	
	SetThreadPriority (m_hInterruptThread, THREAD_PRIORITY_HIGHEST);
	
    InterruptDone(m_dwInterrupt);
	FUNCMSG("-CCX5530Audio::Initialize()");
    return true;
}

bool CCX5530Audio::InitAudio()
{
    PCI_SLOT_NUMBER     pciSlotNumber;
    PCI_COMMON_CONFIG   pciConfig;
    ULONG               bus;
    ULONG               readVal;
	BYTE byHeaderType;
	
    FUNCMSG("+CCX5530Audio::InitAudio()");
	
    // find the card and get its memory mapped base address
    if (!PciFindDevice(CYRIX_VENDOR_ID, AUDIO_DEVICE_ID, &bus, &pciSlotNumber, &pciConfig))
	{
        ERRMSG("Couldn't find PCI device");
        return false;
    }
	
	InitVSA();


	ULONG ulOffset = offsetof(PCI_COMMON_CONFIG, HeaderType);
	
	// find out header type
	HalGetBusDataByOffset(
        PCIConfiguration, bus, pciSlotNumber.u.AsULONG,
        &byHeaderType, 
        ulOffset,
        sizeof(UCHAR));
	
	if (byHeaderType == 0)
		ulOffset = offsetof(PCI_COMMON_CONFIG, u.type0.BaseAddresses);
	else 
		ulOffset = offsetof(PCI_COMMON_CONFIG, u.type1.BaseAddresses);
	
	//---- Mem-map the audio regs.
	
	// Mem-map of PCI audio regs (Enable 5530 audio regs memory) done by BIOS
	// get the physical address where the BIOS mapped the audio registers
	
	HalGetBusDataByOffset(
        PCIConfiguration, 
        bus, 
        pciSlotNumber.u.AsULONG,
        &readVal, 
        ulOffset,	// get the base address register from the PCI header structure,
        sizeof(ULONG));
	
	INFMSG2("Reading base at 0x%x, retval is 0x%x", ulOffset, readVal);

	if (readVal == 0)
	{
		ERRMSG("Badly mapped registers!");
		return false;
	}
	
	//---- Create an address window to map to the regs.
	
	{
		PHYSICAL_ADDRESS ioPhysicalBase = {readVal, 0};
		ULONG	inIoSpace = 0;	// 0 : memory space, 1: I/O space
		
		if (!HalTranslateBusAddress(PCIBus, bus, ioPhysicalBase, &inIoSpace, &ioPhysicalBase)) 
		{
			ERRMSG("Error translating register address");
			return false;
		}
		if (!inIoSpace) 
		{
			//INFMSG1("Base is 0x%8.8x, calling MmMapIoSpace", ioPhysicalBase.LowPart);
			m_pAudioRegisters = (struct AudioRegisters *)MmMapIoSpace(ioPhysicalBase, 128, FALSE);
			if (m_pAudioRegisters == NULL) 
			{
				ERRMSG1("MmMapIoSpace failed: %d", GetLastError());
				return false;
			}
		} 
		else
		{
			INFMSG("Not in IO space, direct mapping");
			m_pAudioRegisters = (struct AudioRegisters *)ioPhysicalBase.LowPart;
		}
	}

	INFMSG2("Registers physical addr 0x%8.8x, mapped at 0x%8.8x", readVal, m_pAudioRegisters);
	
	m_pAudioRegisters->regCodecCommand.dwValue = 0;	// reset codec circuitry
	
	// identify codec
	{
		m_pCodec = CAC97Codec::CreateCodec(this);
		if (!m_pCodec)
		{
			ERRMSG("Error creating codec");
			return false;
		}
	}
	
	// initialize codec
	
	m_pCodec->Reset();
    FUNCMSG("-CCX5530Audio::InitAudio()");
	return true;
}

bool CCX5530Audio::PciFindDevice(
								 IN USHORT VendorId,
								 IN USHORT DeviceId,
								 OUT PULONG pBusNumber,
								 OUT PPCI_SLOT_NUMBER pPciSlotNumber,
								 OUT PPCI_COMMON_CONFIG pPciCommonConfig
								 )
{
	PCI_SLOT_NUMBER     slotNumber;
    PCI_COMMON_CONFIG   pciConfig;
    int                 bus, device, function;
    int                 length;
	
	//    FUNCMSG("+CCX5530Audio::PciFindDevice()");
    
    for (bus = 0; bus < PCI_MAX_BUS; bus++) 
	{  
        for (device = 0; device < PCI_MAX_DEVICES; device++) 
		{
            slotNumber.u.bits.DeviceNumber = device;
			
            for (function = 0; function < PCI_MAX_FUNCTION; function++) 
			{
                slotNumber.u.bits.FunctionNumber = function;
                length = HalGetBusData(
                    PCIConfiguration, 
                    bus, 
                    slotNumber.u.AsULONG,
                    &pciConfig, 
                    sizeof(pciConfig) - sizeof(pciConfig.DeviceSpecific));
                if(length == 0) 
				{
					//					RETAILMSG(1, (TEXT("Not found %d, %d, %d\r\n"), bus, device, function));
                    break;
                }
				//				RETAILMSG(1, (TEXT("PciFindDevice: VendorId: 0x%x, DeviceID: 0x%x\r\n"), pciConfig.VendorID, pciConfig.DeviceID));
                if((VendorId == pciConfig.VendorID) && 
                    (DeviceId == pciConfig.DeviceID)) 
				{
                    if (pBusNumber)
						*pBusNumber = bus;
                    if (pPciSlotNumber)
						*pPciSlotNumber = slotNumber;
                    if (pPciCommonConfig )
						*pPciCommonConfig = pciConfig;
					
					//				    FUNCMSG("-CCX5530Audio::PciFindDevice() success");
                    return true;
                }                        
				// Is device multifunction?
                if(!function && !(pciConfig.HeaderType & PCI_MULTIFUNCTION)) 
				{
                    break;
                }
            }
        }
    }
    FUNCMSG("-CCX5530Audio::PciFindDevice() FAILURE");
    return false;
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

	Function:

		CCX5530Audio::WriteAC97

	Description:

		writes a 16-bit value to a register on an AC97 compliant audio codec.

	Arguments:

		Index - register index to write
		Data  - 16-bit value to write

	Return Value: bool: true for success or false if CODEC timed out
			  
-------------------------------------------------------------------*/

bool CCX5530Audio::WriteAC97(USHORT  Index, USHORT  Data)
{
    union CodecCommand cmd;
    int writeCount = CODEC_TIMEOUT_COUNT;
	
	CriticalSectionAcquisition csa(&m_csCX5530Audio);
	
	// wait for the codec to finish processing previous command
	
	// loop until either we tried CODEC_TIMEOUT_COUNT times, 
	// or the command becomes invalid (that is, it's been sent)
    while(writeCount >= 0 && m_pAudioRegisters->regCodecCommand.fields.bCommandValid) 
	{
		writeCount--;
        Sleep(1);
    }
	
	// command still not sent?
    if (m_pAudioRegisters->regCodecCommand.fields.bCommandValid)
	{
		ERRMSG("Codec Not Allowing Write");
		return  false;
	}
	// set up new command
	cmd.dwValue = 0;
	cmd.fields.Codec = PRIMARY_CODEC;	// hardwired here! This driver only handles the primary codec!
	cmd.fields.Command = Data;
	// the Index has 7 bits for register addresses; the eighth bit is the read flag
	cmd.fields.CommandAddress = Index;
	
	// and write it;
	//INFMSG1("Writing command 0x%8.8x", cmd.dwValue);
	m_pAudioRegisters->regCodecCommand.dwValue = cmd.dwValue;
	
	// Wait for ready state, check AC CODEC access time out
	writeCount = CODEC_TIMEOUT_COUNT;
    while(writeCount >= 0 && m_pAudioRegisters->regCodecCommand.fields.bCommandValid)
	{
		writeCount--;
		Sleep(1);
	}
	
	// command still not sent?
    if (m_pAudioRegisters->regCodecCommand.fields.bCommandValid)
	{
		ERRMSG("Codec Timed Out On Write");
		return  false;
	}
	
	// all seems Ok

⌨️ 快捷键说明

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