📄 aaci_audio.c
字号:
//
// 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.
//
// Release Status:OS005-SW-70002-r0p0-00REL0
// $Copyright:
// ----------------------------------------------------------------
// This confidential and proprietary software may be used only as
// authorised by a licensing agreement from ARM Limited
// (C) COPYRIGHT 2004 ARM Limited
// ALL RIGHTS RESERVED
// The entire notice above must be reproduced on all authorised
// copies and copies may only be made to the extent permitted
// by a licensing agreement from ARM Limited.
// ----------------------------------------------------------------
// File: aaci_audio.c,v
// Revision: 1.2
// ----------------------------------------------------------------
// $
//--------------------------------------------------------------------------------
//
// PL041 AACI & LM4549A - Audio functions
//
// This is a group of hardware specific functions that define a general
// interface to be portable to other Operating systems and to run on the
// National Semiconductor LM4549A CODEC and ARM PL041 AACI.
//
// These functions include interfaces to an AC'97 Codec, Hardware
// Initialization and currently run on the Intergrator/CP platforms.
//
// This driver is set-up to use the dedicated AACI h/w registers to send
// and receive configuration data on slots 1 & 2, of the CODEC frame, to and
// from the LM4549A CODEC.
// The AACI FIFOs are only used for sending and receiving wave channel data
// on slots 3 & 4, of the CODEC frame, left and right channels respectively.
// Please read the ARM PrimeCell AACI (PL041) Technical Reference Manual for
// more information.
//--------------------------------------------------------------------------------
#include <windows.h>
#include <pkfuncs.h>
#include <ceddk.h>
#include <types.h>
#include <waveddsi.h>
#include <wavedbg.h>
#include <oalfuncs.h>
#include "wavmsg.h"
#include "pdd_audio.h"
#include <dma.h>
#include "oalintr.h"
#include "wavemdd.h"
#define DBG_AACI 0
//add whs
DWORD WINAPI DeviceThreadProc(PVOID pvParam);
int Volume = 0xd0d;
BOOL playflags=FALSE;//当前是否在播放
BOOL headphone=FALSE;//耳机输出
BOOL lout=FALSE;//喇叭输出
BOOL pauseflags=FALSE;//当前是否在播放
//add whs
int OnInit();
int OnDeinit();
int OnPlayOpen();
int OnPlayStart();
int OnPlayStop();
int OnPlayClose();
int OnRecordOpen();
int OnRecordStart();
int OnRecordStop();
int OnRecordClose();
CRITICAL_SECTION Criticalthread;
//---------------------------
// AACI Control
//---------------------------
VOID AACI_RegWrite32(USHORT reg, ULONG val);
ULONG AACI_RegRead32(USHORT reg);
//---------------------------
// CODEC Control
//---------------------------
VOID AACI_CodecWrite16( USHORT codec_reg, USHORT codec_data );
USHORT AACI_CodecRead16( USHORT codec_reg );
//---------------------------
// FIFO operations
//---------------------------
VOID FillFIFO_M8(PWAVEHDR pwh){};
VOID FillFIFO_M16(PWAVEHDR pwh){};
VOID FillFIFO_S8(PWAVEHDR pwh){};
VOID FillFIFO_S16(PWAVEHDR pwh){};
VOID GetFIFO_M8(PWAVEHDR pwh){};
VOID GetFIFO_M16(PWAVEHDR pwh){};
VOID GetFIFO_S8(PWAVEHDR pwh){};
VOID GetFIFO_S16(PWAVEHDR pwh){};
// Internal functions
static void DumpCurrentSettings();
static VOID CodecSend( ULONG raw_codec_reg, ULONG raw_codec_data );
static BOOL ResetDevice();
static void PowerUp();
static void PowerDown();
static BOOL ClearTransmitFIFO();
static BOOL ClearReceiveFIFO(DWORD *);
// for debug
void FileDebugOut(char *lpFormat, ...);
void doTest();
void set_pa_on(void);
void set_pa_off(void);
extern HANDLE hMutex;
#define ENTERMUTEX //WaitForSingleObject(hMutex, INFINITE);
#define RELEASEMUTEX //ReleaseMutex(hMutex)
extern HANDLE hd_9712;
#define WAV_DEBUG
#ifdef TEST_API
// Internal test functions
static DWORD TestTransmit_FIFOSize(BOOL);
static DWORD TestTransmit_Complete(BOOL);
static DWORD TestTransmit_HalfEmpty(BOOL);
static DWORD TestReceive_Overrun(BOOL);
static DWORD TestReceive_HalfFull(BOOL);
static DWORD TestReceive_Runaway(BOOL);
#endif
// Keep this uncommented to enable transmit compact mode (recommended)
//#define TX_COMPACT_MODE
// Keep this uncommented to enable receive compact mode (recommended)
//#define RX_COMPACT_MODE
// Test and wait for flags to clear
#define _TWMAX 10
#define TESTWAIT(test,dbgmsg) \
{ \
int _testwait = 0; \
while( (test) && _testwait < _TWMAX ) \
{ \
Sleep(1); \
_testwait++; \
} \
if( _testwait == _TWMAX ) \
FileDebugOut("AACI: Failed to wait for %s", dbgmsg); \
}
// ERRMSG1("AACI: Failed to wait for %s", TEXT(dbgmsg) ); \
//}
// FIFO Sizes for testing and use in filling/clearing the FIFOs
#define TX_FIFOSIZE_NOTCOMPACT 512
#define TX_FIFOSIZE_COMPACT (TX_FIFOSIZE_NOTCOMPACT/2)
#define RX_FIFOSIZE_NOTCOMPACT 512
#define RX_FIFOSIZE_COMPACT (RX_FIFOSIZE_NOTCOMPACT/2)
#ifdef TX_COMPACT_MODE
#define TX_FIFOSIZE TX_FIFOSIZE_COMPACT
#else
#define TX_FIFOSIZE TX_FIFOSIZE_NOTCOMPACT
#endif
#ifdef RX_COMPACT_MODE
#define RX_FIFOSIZE RX_FIFOSIZE_COMPACT
#else
#define RX_FIFOSIZE RX_FIFOSIZE_NOTCOMPACT
#endif
//junxz
//#define SET_SLOT12_FALSE AACI_RegWrite32( AACIReg_Slot12Tx, 0x00000);
//#define SET_SLOT12_TRUE AACI_RegWrite32( AACIReg_Slot12Tx, 0xfffff);
//#define SET_SLOT12_FALSE AACI_RegWrite32( AACIReg_Slot12Tx, (AACI_CodecRead16(0x54)&(~0x06))<<4);
//#define SET_SLOT12_TRUE AACI_RegWrite32( AACIReg_Slot12Tx, (AACI_CodecRead16(0x54)|(0x06))<<4);
USHORT MakeTest();
//--------------------------------------------------------------------------------
// Variables - local and globally global
//--------------------------------------------------------------------------------
// The event handler (from MDD layer)
extern HANDLE hAudioInterrupt;
#ifdef DEBUG
// To get access to the debug zones (from MDD layer)
extern DBGPARAM dpCurSettings;
#endif
// System Interrupt - used by MDD layer
ULONG gIntrAudio;
static BOOL g_fPowerOn; // Current Power setting
static ULONG g_nVolume; // Current master volume setting (MSFT format)
static UCHAR *g_AudioRegBase = NULL;// Pointer to memory mapped AACI regs.
#ifdef TEST_API
// When we are performing tests
static BOOL g_fTesting = FALSE; // Specifies whether testing or not
static BOOL g_fTestIntDisable; // AACI Interrupts disabled on AACI interrupt?
static HANDLE g_hTestInterrupt; // Test interrupt event - set on AACI interrupt
static DWORD g_dwTestIntStatus; // AACI status flags on interrupt
#endif
// The following arrays contains 2 entries, One for input, one for output
static BOOL g_fInUse[2]; // Channel in use?
static DWORD g_dwRunMode[2]; // Channel receiving/transmitting data?
static BOOL g_fTxEndOfData; // Channel transmit end of data?
static PWAVEFORMATEX g_pwfx[2]; // Current channel format
#define RUNMODE_STOPPED 0
#define RUNMODE_STOPPING 1
#define RUNMODE_RUNNING 2
// This variable may be accessed by different processes (i.e. via interrupts)
// and is likely to change in a time critical fashion. Optimization may cause
// errors if not declared volatile.
static volatile BOOL gv_fMoreData[2]; // Any more data to transmit/receive?
// Current shortcuts to FIFO fill/get functions - dependent on wave format
static VOID (*pfnFillFIFO)(PWAVEHDR);
static VOID (*pfnGetFIFO)(PWAVEHDR);
//add junxz
BOOL leftout = TRUE;
// Volume control translation array - from MSFT format to CODEC format
/*
const USHORT VolumeLUT[] = {
0x20, 0x20, 0x1d, 0x1d, 0x1a, 0x1a, 0x17, 0x17,
0x13, 0x13, 0x0f, 0x0f, 0x0d, 0x0d, 0x0a, 0x0a,
0x08, 0x08, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04,
0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00 };
*/
/*
const USHORT VolumeLUT[] = {
0x20, 0x20, 0x1d, 0x1d, 0x1b, 0x1b, 0x19, 0x19,
0x17, 0x17, 0x15, 0x15, 0x13, 0x13, 0x11, 0x11,
0x0f, 0x0f, 0x0d, 0x0d, 0x0b, 0x0b, 0x09, 0x09,
0x07, 0x07, 0x05, 0x05, 0x03, 0x03, 0x01, 0x01 };
*/
///
/*
const USHORT VolumeLUT[] = {
0x1d, 0x1d, 0x1d, 0x1d, 0x1b, 0x1b, 0x1b, 0x19,
0x19, 0x19, 0x17, 0x17, 0x17, 0x15, 0x15, 0x15,
0x13, 0x13, 0x13, 0x11, 0x11 0x11, 0x0f, 0x0f,
0x0f, 0x0d, 0x0d, 0x0d, 0x0b, 0x0b, 0x0b, 0x0b };
*/
// junxz
const USHORT VolumeLUT[] = {
0x1f, 0x1f, 0x1c, 0x1c, 0x1a, 0x1a, 0x17, 0x17,
0x14, 0x14, 0x12, 0x12, 0x10, 0x10, 0x0e, 0x0e,
0x0c, 0x0c, 0x0b, 0x0b, 0x0a, 0x0a, 0x09, 0x09,
0x08, 0x08, 0x07, 0x07, 0x06, 0x06, 0x05, 0x05 };
/*
const USHORT VolumeLUT[] = {
0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02 };
*/
//add by whs for ---- power amplifier
/*
const SHORT PowerAmplifier[] = {
-22, -22, -19, -19, -16, -16, -13, -13,
-10, -10, -7, -7, -4, -4, 0, 0,
0, 2, 2, 2, 5, 5, 5, 8,
8, 8, 11, 11, 14, 14, 20,20,
};
*/
/*
const SHORT PowerAmplifier[] = {
-4, -4,-4, -4, 0, 0, 0, 0,
2, 2,2, 2, 5, 5, 5, 5,
8, 8,8, 8, 11, 11, 11, 11,
14, 14, 14, 14, 20,20, 20,20,
};
*/
// Keep a record of all the bytes played and recorded in a
// wavestart-wavestop session
#ifdef AACI_STATS
static DWORD g_dwBytesRecorded[2];
#endif
//-----------------------------------------------------------------------------
//
// UCHAR AACI_Initialize (UINT Irq, UINT SysIntr, UINT IoBase)
//
// Initializes the AACI and LM4549 hardware.
// It has to be called with the resources that were assigned by the OS
//
// This function:
//
// - Maps the Irq to a system interrupt number
// - Maps in the AACI hardware register addresses
// - Reset and initialize the CODEC
//
// Resources assigned by the system:
//
// unsigned int Irq,
// unsigned int SysIntr,
// unsigned int IoBase
//
//--------------------------------------------------------------------------------
BOOL AACI_Initialize (UINT Irq, UINT SysIntr, UINT IoBase)
{
BOOL bRet = FALSE;
PHYSICAL_ADDRESS PhysicalAddress;
//add whs
HANDLE hWaveThread;
//add whs
// Turn on various DEBUG messages - (see public\common\oak\inc\wavedbg.h)
#ifdef DEBUG
// All INIT messages
dpCurSettings.ulZoneMask |= (1<<10);
// PDD Function debug
//dpCurSettings.ulZoneMask |= (1<<6) | (1<<13);
// All debug messages (even MDD layer)
//dpCurSettings.ulZoneMask = 0xFFFF;
#endif
FUNC_WPDD("+AACI_Initialize");
RETAILMSG(DBG_AACI,(TEXT("AACI PDD 1.5\r\n")));
PRINTMSG(ZONE_INIT, (TEXT("AACI Initialising - version %d.%d"),
WAVEDEV_VERSION_MAJOR,WAVEDEV_VERSION_MINOR) );
// Set up system interrupt for MDD layer
gIntrAudio = SysIntr;
// Setup global variables for input and output buffers
gv_fMoreData[WAPI_OUT] = FALSE;
gv_fMoreData[WAPI_IN] = FALSE;
g_fInUse[WAPI_OUT] = FALSE;
g_fInUse[WAPI_IN] = FALSE;
g_dwRunMode[WAPI_OUT] = RUNMODE_STOPPED;
g_dwRunMode[WAPI_IN] = RUNMODE_STOPPED;
g_fTxEndOfData = FALSE;
g_pwfx[WAPI_OUT] = NULL;
g_pwfx[WAPI_IN] = NULL;
// NOTE: g_nVolume should get properly set on boot up by a WPDM_SETVOLOUME
// message (from the WAVAPI.DLL). We set it here to 0 to reflect the
// default CODEC setting (mute)
g_nVolume = 0;
// Map in address space for AACI hardware registers
PhysicalAddress.HighPart = 0;
PhysicalAddress.LowPart = IoBase;
g_AudioRegBase = (UCHAR *)MmMapIoSpace (PhysicalAddress, AACI_HWREGS_SIZE,//物理地址影射到虚拟地址
FALSE);
if( !g_AudioRegBase )//如果影射失败
{
ERRMSG("PDD_AudioInitialize: Map audio registers failed");
}
else
{
// Set up the device
if( ResetDevice() )
{
g_fPowerOn = TRUE;
#if 0
// Show what the initialised settings are
DumpCurrentSettings();
#endif
// All is well, AACI is up and working
bRet = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -