waveoutpdd.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,218 行 · 第 1/3 页
C
1,218 行
/*
Copyright(c) 1998,1999 SIC/Hitachi,Ltd.
Module Name:
waveOutpdd.c
Revision History:
26th April 1999 Released
30th June 1999 Modified audio out buffer address
Added AudioOutInterrupt Flag
suppress playback recording
6th July 1999 Fixed minor bug
21th September 1999 Modified audio volume
Added audio pause and Audio restart process
Fixed L-R turn bug
Added PCML(R) FIFO buffer clear in WaveOutStop & WaveOutEndOfData & WaveOutPause process
8th October 1999 Modified WaveData length extend
29-Nov-1999 cea Changed for SH3 (7709A) DMA control
*/
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <excpt.h>
#include <waveddsi.h>
#include <wavedbg.h>
#include <mmsystem.h>
#include "waveOutpddMacros.h"
#include "wavepdd.h"
#include "waveOutpdd.h"
#include "shx.h"
#include "cc.h"
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Replaced mobytel.h with platform.h
****************************************************************************/
#include "platform.h"
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
#include "drv_glob.h"
extern PWAVEFORMATEX g_pwfx[2];
extern PCM_TYPE g_pcmtype[2];
// Software Volume Control
#define scaleForVolume(sample) ((sample * multiplier) >> log2ofDivisor)
const struct { // table facilitates multiplying by fraction:
UINT16 multiplier; // multiply by "multiplier"
UINT16 divisor; // then shift right by "log2ofDivisor"
} VOL[] = { {0, 0}, // 0/1
{3, 5}, // 3/32
{7, 6}, // 7/64
{1, 3}, // 1/8
{5, 5}, // 5/32
{3, 4}, // 3/16
{7, 5}, // 7/32
{1, 2}, // 1/4
{5, 4}, // etc.
{3, 3},
{7, 4},
{1, 1},
{5, 3},
{3, 2},
{7, 3},
{1, 0}
};
// DMA Operation Registor
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Register Access size has been modified for SH4 from 16bit to 32bit.
****************************************************************************/
#if ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
PVULONG pDMAOR; // virtual address of DMA Operation Register
#else ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
PVUSHORT pDMAOR; // virtual address of DMA Operation Register
#endif ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
// DMA Channel 1 Registers (audio playback channel)
PVULONG pSAR1, pDAR1, pDMATCR1, pCHCR1; //virtual addrs of DMA1 control regs
PVULONG pCHCR0,pCHCR2,pCHCR3; //virtual addrs of DMA1 control regs
// Companion Chip Registers
PVUSHORT pCODEC_CR; // virtual addrs of C.C. registers
PVULONG pCODEC_ACR, pCODEC_CAR, pCODEC_CDR;
PVULONG pCODEC_ATAGR;
PVULONG pCODEC_PCML;
PVULONG pSMSCR;
PVUSHORT pCODEC_FSR;
// Double Buffer for Audio Playback
static const ULONG dma_pagePhysicalAddress[2] =
{
AUDIO_BUFFER_BASE,
(AUDIO_BUFFER_BASE + AUDIO_DMA_PAGE_SIZE)
};
static ULONG v_nNextPage;
static PBYTE pDMAC_RegBase; // page-base for register offsets
/****************************************************************************
* Modification done by Naresh Gupta
* Instead of separate Area_1 and Area_7, i'm using INTC_REGBASE
* for SH4
****************************************************************************/
#if ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
static PBYTE pINTC_RegBase; // page-base for register offsets
#else // ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
static PBYTE pINTC_Area_1_RegBase; // page-base for register offsets
static PBYTE pINTC_Area_7_RegBase; // page-base for register offsets
#endif // ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
/****************************************************************************
* End of Modification done by Naresh Gupta
****************************************************************************/
static PBYTE pCC_CODEC_RegBase; // Companion chip SERIAL CODEC register offsets
static PBYTE pCC_SYS_RegBase; // Companion chip SMSCR
static PBYTE pAudioBufferBase; // Audio buffer
volatile PDRIVER_GLOBALS pDriverGlobals; // Drivers Globals
static ULONG v_nVolume; // current volume setting
static volatile BOOL v_fMoreData[2];// TRUE iff MDD layer has called StopPlay
// v_fMoreData was volatile on D9000
// It could be involved in controlling
// multiple threads.
/*****************************************************************************
* FUNCTION : private_AudioOutGetInterruptType
* DESCRIPTION : decodes type of audio interrupt
* INPUTS : None
* OUTPUTS : interrupt type
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
AUDIO_STATE
private_AudioOutGetInterruptType(
VOID
)
{
FUNC_WPDD("+PDD_AudioOutGetInterruptType");
// An audio interrupt has occured. We need to tell the MDD who owns it
// and what state that puts us in.
if ( pDriverGlobals->aud.outInt == (USHORT)NULL )
{
DEBUGMSG(ZONE_TEST, (TEXT("PDD_AudioOutGetInterruptType: ignore")));
FUNC_WPDD("-PDD_AudioOutGetInterruptType");
return AUDIO_STATE_IGNORE; // assume audio-in generated interrupt
}
pDriverGlobals->aud.outInt--;
if (!v_fMoreData[WAPI_OUT])
{
DEBUGMSG(ZONE_TEST, (TEXT("PDD_AudioOutGetInterruptType: stopped")));
FUNC_WPDD("-PDD_AudioOutGetInterruptType");
return AUDIO_STATE_OUT_STOPPED;
}
else if (pDriverGlobals->aud.play_address != (ULONG)NULL)
{
DEBUGMSG(ZONE_TEST, (TEXT("PDD_AudioOutGetInterruptType: playing")));
FUNC_WPDD("-PDD_AudioOutGetInterruptType");
return AUDIO_STATE_OUT_PLAYING;
}
else
{
DEBUGMSG(ZONE_TEST, (TEXT("PDD_AudioOutGetInterruptType:underflow")));
FUNC_WPDD("-PDD_AudioOutGetInterruptType");
return AUDIO_STATE_OUT_UNDERFLOW;
}
}
/*****************************************************************************
* FUNCTION : private_AudioOutInitialize
* DESCRIPTION : sets up register access for audio-out
* sets DA, DMA, and CMT registers that remain constant
* sets volume to maximum (default)
* INPUTS : None
* OUTPUTS : None
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
BOOL
private_AudioOutInitialize(
VOID
)
{
ULONG ACR_VALUE;
USHORT CR_VALUE;
ULONG SizeOfBuffer;
char here[] = "PDD_AudioOutInitialize";
FUNC_WPDD("+PDD_AudioOutInitialize");
RETAILMSG( 1, (TEXT("WaveOutpdd.c private_AudioOutInitialize: START\r\n")));
// Set pointers to virtual addresses of playback registers
pDMAC_RegBase =(PBYTE)GetVirtualAddressOfUncachedMemory(
(PBYTE)DMAC_REGBASE,
(DWORD)DMAC_REGSIZE,
"PDD_AudioInitialize, pDMAC_RegBase");
if (pDMAC_RegBase == NULL) return FALSE;
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Register Access size has been modified for SH4 from 16bit to 32bit.
****************************************************************************/
#if ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
pDMAOR = (PVULONG)(pDMAC_RegBase + DMAC_DMAOR_OFFSET );
#else ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
pDMAOR = (PVUSHORT)(pDMAC_RegBase + DMAC_DMAOR_OFFSET );
#endif ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
pSAR1 = (PVULONG)(pDMAC_RegBase + DMAC_SAR1_OFFSET );
pDAR1 = (PVULONG)(pDMAC_RegBase + DMAC_DAR1_OFFSET );
pDMATCR1 = (PVULONG)(pDMAC_RegBase + DMAC_DMATCR1_OFFSET);
pCHCR1 = (PVULONG)(pDMAC_RegBase + DMAC_CHCR1_OFFSET );
pCHCR0 = (PVULONG)(pDMAC_RegBase + DMAC_CHCR0_OFFSET );
pCHCR2 = (PVULONG)(pDMAC_RegBase + DMAC_CHCR2_OFFSET );
pCHCR3 = (PVULONG)(pDMAC_RegBase + DMAC_CHCR3_OFFSET );
/****************************************************************************
* Modification done by Naresh Gupta
* Instead of separate Area_1 and Area_7, i'm using INTC_REGBASE
* for SH4
****************************************************************************/
#if ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
pINTC_RegBase =(PBYTE)GetVirtualAddressOfUncachedMemory(
(PBYTE)INTC_REGBASE,
(DWORD)INTC_REGSIZE,
"PDD_AudioInitialize, pINTC_RegBase");
if (pINTC_RegBase == NULL) return FALSE;
#else // ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
pINTC_Area_1_RegBase =(PBYTE)GetVirtualAddressOfUncachedMemory(
(PBYTE)INTC_AREA_1_REGBASE,
(DWORD)INTC_AREA_1_REGSIZE,
"PDD_AudioInitialize, pINTC_Area_1_RegBase");
if (pINTC_Area_1_RegBase == NULL) return FALSE;
pINTC_Area_7_RegBase =(PBYTE)GetVirtualAddressOfUncachedMemory(
(PBYTE)INTC_AREA_7_REGBASE,
(DWORD)INTC_AREA_7_REGSIZE,
"PDD_AudioInitialize, pINTC_Area_7_RegBase");
if (pINTC_Area_7_RegBase == NULL) return FALSE;
#endif // ((SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR))
/****************************************************************************
* End of Modification done by Naresh Gupta
****************************************************************************/
pCC_CODEC_RegBase =(PBYTE)GetVirtualAddressOfUncachedMemory(
(PBYTE)CC_CODEC_REGBASE,
(DWORD)CC_CODEC_REGSIZE,
"PDD_AudioInitialize, pCC_CODEC_RegBase");
if (pCC_CODEC_RegBase == NULL) return FALSE;
pCODEC_CR = (PVUSHORT) (pCC_CODEC_RegBase + CC_CODEC_CR_OFFSET );
pCODEC_CAR = (PVULONG ) (pCC_CODEC_RegBase + CC_CODEC_CAR_OFFSET );
pCODEC_CDR = (PVULONG ) (pCC_CODEC_RegBase + CC_CODEC_CDR_OFFSET );
pCODEC_ACR = (PVULONG ) (pCC_CODEC_RegBase + CC_CODEC_ACR_OFFSET );
pCODEC_ATAGR = (PVULONG ) (pCC_CODEC_RegBase + CC_CODEC_ATAGR_OFFSET );
pCODEC_PCML = (PVULONG ) (pCC_CODEC_RegBase + CC_CODEC_PCML_OFFSET );
pCODEC_FSR = (PVUSHORT) (pCC_CODEC_RegBase + CC_CODEC_FSR_OFFSET );
pCC_SYS_RegBase =(PBYTE)GetVirtualAddressOfUncachedMemory(
(PBYTE)CC_SYS_SMSCR,
(DWORD)CC_SYS_REGSIZE,
"PDD_AudioInitialize, pCC_SYS_RegBase");
if (pCC_SYS_RegBase == NULL) return FALSE;
pSMSCR = (PVULONG ) (pCC_SYS_RegBase );
// Set pointers to virtual addresses of audio buffers
SizeOfBuffer = (AUDIO_DMA_PAGE_SIZE * 2);
pAudioBufferBase = VirtualAlloc(
NULL,
SizeOfBuffer,
MEM_RESERVE,
PAGE_NOACCESS);
if (pAudioBufferBase == NULL) return FALSE;
if (!VirtualCopy((PVOID)pAudioBufferBase,
(PVOID)dma_pagePhysicalAddress[0],
(DWORD)SizeOfBuffer,
PAGE_READWRITE | PAGE_NOCACHE))
{
VirtualFree((PVOID)pAudioBufferBase, 0, MEM_RELEASE);
return FALSE;
}
if (pAudioBufferBase == NULL)
{
RETAILMSG( 1, (TEXT("pAudioBufferBase ---error---\r\n")));
return FALSE;
}
// Setup a Access to AudioPlayingAddress and AudioOutInterrupt
pDriverGlobals = VirtualAlloc(
NULL,
DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
MEM_RESERVE,
PAGE_NOACCESS);
if (pDriverGlobals == NULL) return FALSE;
if (!VirtualCopy((PVOID)pDriverGlobals,
(PVOID)DRIVER_GLOBALS_PHYSICAL_MEMORY_START,
(DWORD)DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
PAGE_READWRITE | PAGE_NOCACHE))
{
VirtualFree((PVOID)pDriverGlobals, 0, MEM_RELEASE);
return FALSE;
}
//
// AC97 Setting
//
//Reset AC97
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Software reset to Audio controller has made.
****************************************************************************/
WRITE_REGISTER_USHORT((PUSHORT)pCODEC_CR, 0x0100 );
Delay_AC();
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
WRITE_REGISTER_USHORT((PUSHORT)pCODEC_CR, 0x0a00 );
Delay_AC();
WRITE_REGISTER_USHORT((PUSHORT)pCODEC_FSR, 0x0000 );
Delay_AC();
WRITE_REGISTER_USHORT((PUSHORT)pCODEC_CR, 0x0235 );
Delay_AC();
//Init_Codec
ACR_VALUE = (ULONG)READ_REGISTER_ULONG((PULONG)pCODEC_ACR );
ACR_VALUE &= 0x7fffffff;
ACR_VALUE |= 0x001fffff;
WRITE_REGISTER_USHORT((PUSHORT)pCODEC_FSR, 0x0000 );
Delay_AC();
WRITE_REGISTER_ULONG((PULONG)pCODEC_ACR, ACR_VALUE );
Delay_AC();
//AC_Init
CR_VALUE = (USHORT)READ_REGISTER_USHORT((PUSHORT)pCODEC_CR );
CR_VALUE &= 0xf7ff;
CR_VALUE |= 0x0035;
WRITE_REGISTER_USHORT((PUSHORT)pCODEC_FSR, 0x0000 );
Delay_AC();
WRITE_REGISTER_USHORT((PUSHORT)pCODEC_CR, CR_VALUE );
Delay_AC();
RETAILMSG( 1, (TEXT("Control register =%08x\r\n"), (USHORT)READ_REGISTER_USHORT((PUSHORT)pCODEC_CR )));
//Codec Ready?
RETAILMSG( 1, (TEXT("ATAGR =%08x\r\n"), (ULONG)READ_REGISTER_ULONG((PULONG)pCODEC_ATAGR )));
RETAILMSG( 1, (TEXT("WAIT Condec Ready..............\r\n")));
while(!( (ULONG)READ_REGISTER_ULONG((PULONG)pCODEC_ATAGR ) & 0x80000000 )) ;
RETAILMSG( 1, (TEXT("codec ready!! \r\n")));
//RX TX Valid Slot
WRITE_REGISTER_ULONG((PULONG)pCODEC_ATAGR, 0x00001ff8 );
Delay_AC();
WRITE_REGISTER_ULONG((PULONG)pCODEC_CAR, (ULONG)0x000a6000 );
Delay_AC();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?