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 + -
显示快捷键?