📄 wmxscaledmatest.c
字号:
/*-----------------------------------------------------------------------------
* Copyright (c) Wolfson Microelectronics plc. All rights reserved.
*
* This software as well as any related documentation is furnished under
* license and may only be used or copied in accordance with the terms of the
* license. The information in this file is furnished for informational use
* only, is subject to change without notice, and should not be construed as
* a commitment by Wolfson Microelectronics plc. Wolfson Microelectronics plc
* assumes no responsibility or liability for any errors or inaccuracies that
* may appear in this document or any software that may be provided in
* association with this document.
*
* Except as permitted by such license, no part of this document may be
* reproduced, stored in a retrieval system, or transmitted in any form or by
* any means without the express written consent of Wolfson Microelectronics plc.
*
* $Id: WMXScaleDMATest.c 2985 2006-04-24 08:55:38Z fb $
*
* This file contains XScale routines for testing the DMA functionality for
* the drivers for the Wolfson chips.
*
* Warning:
* This driver is specifically written for Wolfson Codecs. It is not a
* general CODEC device driver.
*
* -----------------------------------------------------------------------------*/
/*
* Include files
*/
#include "WMCommon.h"
#include "WMWaveGen.h"
#include "WMACLink.h"
#include "WMPlatformDeviceContext.h"
#include "WMDMAContext.h"
#include "WMPlatform_OS.h"
#include "WMPlatform_Raw.h"
#include "WMAudioDefs.h"
#include "WMVoice.h"
#include "WMAudioPaths.h"
#include "Test/WMTestCommon.h"
#include "Test/WMPlatformTests.h"
#include "Test/WMLinkTests.h"
#include "Test/WMAudioTestHelpers.h"
/*
* Only build this if we are asked to.
*/
#if WM_AUDIO_STREAM && WM_TESTING
/*
* Global definitions
*/
#define TEST_SAMPLE_RATE_HIFI 48000
#define TEST_SAMPLE_RATE_MONO 48000
#define TEST_SAMPLE_RATE_VOICE 8000
#define TEST_BUFFER_TIMESTAMPS 200 /* Needed for timing. This will cover about 4s @ 48kHz */
#define TEST_MILLISECOND_SLOP 5 /* Error bounds for allowable time discrepancy */
/*
* Define these to TRUE to run the tests forever.
*/
#define CONTINUAL_HIFI FALSE
#define CONTINUAL_MONO FALSE
#define CONTINUAL_VOICE FALSE
/*
* Define this to TRUE to verify the timing of the DMA.
* Note: if you're debugging this is probably _not_ a good idea.
*/
#define VERIFY_DMA_TIMING FALSE
/* Number of descriptors per channel */
#define WMDMA_DESCRIPTORS_PER_CHANNEL 2
/* Number of buffers per channel */
#define WMDMA_BUFFERS_PER_CHANNEL WMDMA_DESCRIPTORS_PER_CHANNEL
/* How long to wait (in ms) before giving up in disgust */
#define MAX_PATIENCE 1000
/*
* Private data
*/
static volatile XLLP_DMAC_DESCRIPTOR_T *v_pAudioXmitA_Virtual = NULL; /* VA: Audio transmit buffer A 128 bits (16 byte aligned) */
static volatile XLLP_DMAC_DESCRIPTOR_T *v_pAudioXmitA_Physical = NULL; /* PA: Audio transmit buffer A 128 bits (16 byte aligned) */
static volatile XLLP_DMAC_DESCRIPTOR_T *v_pAudioXmitB_Virtual = NULL; /* VA: Audio transmit buffer B 128 bits (16 byte aligned) */
static volatile XLLP_DMAC_DESCRIPTOR_T *v_pAudioXmitB_Physical = NULL; /* PA: Audio transmit buffer B 128 bits (16 byte aligned) */
WM_AUDIO_STEREO_SAMPLE *v_pDMABufXmitA_Virtual = NULL;
WM_AUDIO_STEREO_SAMPLE *v_pDMABufXmitA_Physical = NULL;
WM_AUDIO_STEREO_SAMPLE *v_pDMABufXmitB_Virtual = NULL;
WM_AUDIO_STEREO_SAMPLE *v_pDMABufXmitB_Physical = NULL;
static WM_BOOL s_Initialised = FALSE;
/*
* Function prototypes
*/
void private_InitDMA( WM_DEVICE_HANDLE hDevice, int channel, int channelId );
void private_CleanupDMA( WM_DEVICE_HANDLE hDevice, int channel, int channelId );
void private_ClearDescriptors();
WM_BOOL private_MapDMAMemory( WM_DEVICE_HANDLE hDevice );
void private_ReleaseDMAMemory();
void private_ClearDMABuffers();
void private_FillDescriptors( WM_DEVICE_HANDLE hDevice, int channel );
static WM_STATUS private_WaitForBuffer( WM_DEVICE_HANDLE hDevice,
unsigned int channel
);
/*-----------------------------------------------------------------------------
* Function: WMTestHiFiDACDMADirect
*
* Plays a sound directly to the HIFI DAC, using direct control of the
* DMA buffers.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WM_BOOL
* TRUE if it passed, FALSE if it failed in a way it could detect.
*---------------------------------------------------------------------------*/
WMTEST_START( WMTestHiFiDACDMADirect( WM_DEVICE_HANDLE hDevice ) )
{
WMSTATUS status;
unsigned int repeat;
unsigned int repeats;
unsigned int samplesPerBuffer;
unsigned int startTime, endTime, bufferStartTime;
unsigned int expectedDuration;
WM_AUDIO_STEREO_SAMPLE *pNextBuffer;
int channel = WMDMA_STEREO_OUT;
int channelId;
WM_WAVEGEN_CTX wavegenCtxLeft = WM_START_OF_WAVE;
WM_WAVEGEN_CTX wavegenCtxRight = WM_START_OF_WAVE;
const WM_TEST_SOUND *pTestSound = WMTestAudio_GetSound();
#if VERIFY_DMA_TIMING
unsigned int timestampArray[TEST_BUFFER_TIMESTAMPS] = {0};
#endif
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT *) hDevice;
VOLATILE_DMAC_T *v_pDmaReg =
pDeviceContext->v_pDmaReg;
#if WM_AC97
VOLATILE_AC97_T *v_pAC97Regs =
pDeviceContext->v_pAC97Regs;
#endif
#if WM_I2S
VOLATILE_I2S_T *v_pI2SRegs =
pDeviceContext->v_pI2SRegs;
#endif
/*
* The following values are put into variables so they can be
* altered in a debugger.
*/
int loopForever = CONTINUAL_HIFI;
WM_SAMPLE_RATE sampleRate = TEST_SAMPLE_RATE_HIFI;
unsigned short frequency = pTestSound->frequency;
unsigned short amplitude = pTestSound->amplitude;
unsigned int duration = pTestSound->duration;
/*
* Setup the DMA so that it is ready to run.
*/
#if WM_AC97
if ( WM_IS_AC97( hDevice ) )
{
channelId = DMA_CHAN_AC97_STEREO_OUT;
}
#endif
#if WM_I2S
if ( WM_IS_I2S( hDevice ) )
{
channelId = DMA_CHAN_I2S_STEREO_OUT;
}
#endif
WMTEST_BOOLEAN( private_MapDMAMemory( hDevice ) );
private_FillDescriptors( hDevice, channel );
/*
* Work out the number of repeats to get our duration.
* One buffer contains WMAUDIO_MAX_BUFFER_SIZE bytes.
*/
samplesPerBuffer = WMAUDIO_MAX_BUFFER_SIZE/sizeof(WM_AUDIO_STEREO_SAMPLE);
repeats = WM_TEST_REPEATS( duration,
sampleRate,
samplesPerBuffer
);
#if VERIFY_DMA_TIMING
WM_ASSERT( hDevice, repeats <= TEST_BUFFER_TIMESTAMPS );
#endif
/*
* Power up, enable and unmute the HiFi output path.
*/
WMTEST_CALL( WMAudioPowerUp( hDevice,WM_POWER_AUDIO_PLAYBACK ) );
WMTEST_CALL( WMAudioEnableOutputPaths( hDevice, WM_STREAM_HIFI_OUT, TRUE ) );
WMTEST_CALL( WMAudioMuteAllOutputs( hDevice, FALSE ) );
/*
* Set the sample rate for the HIFI.
*/
WMTEST_CALL( WMAudioSetSampleRate( hDevice,
WM_STREAM_HIFI_OUT,
sampleRate
)
);
/* Make sure our buffers are cleared */
private_ClearDMABuffers();
/* Fill the first buffer and set up our "next" pointer */
WMGenerateSineWave( v_pDMABufXmitA_Virtual,
samplesPerBuffer,
sampleRate,
frequency,
amplitude,
WM_WAVEGEN_LEFT,
&wavegenCtxLeft
);
WMGenerateSineWave( v_pDMABufXmitA_Virtual,
samplesPerBuffer,
sampleRate,
frequency * 2,
amplitude,
WM_WAVEGEN_RIGHT,
&wavegenCtxRight
);
pNextBuffer = v_pDMABufXmitB_Virtual;
/* Initialise the DMA */
private_InitDMA( hDevice, channel, channelId );
/*
* Clear any interrupts, and any output FIFO errors.
*/
v_pDmaReg->DCSR[channel] |= DCSR_DMA_INT_MASK;
#if WM_AC97
if ( WM_IS_AC97( hDevice ) )
{
v_pAC97Regs->POSR = 0x10;
}
#endif
#if WM_I2S
if ( WM_IS_I2S( hDevice ) )
{
v_pI2SRegs->SAICR = XLLP_SAICR_TUR;
}
#endif
/*
* Work out how long it should take:
* 4 bytes per (stereo) sample = WMAUDIO_MAX_BUFFER_SIZE/4 samples per buffer.
* repeats buffers.
* sampleRate samples per second =>
* 1000/sampleRate milliseconds per sample
*/
expectedDuration = ( samplesPerBuffer * repeats * 1000 ) /
sampleRate;
/*
* Start the DMA on the channel.
*/
v_pDmaReg->DCSR[channel] |= DCSR_RUN; /* set the RUN bit */
do
{
/* Get our start time for this loop */
startTime = GetMillisecondTimestamp( hDevice );
/* Send the buffer the requested number of times */
for ( repeat = 0; repeat < repeats; repeat++ )
{
/* Get the start time for this buffer */
bufferStartTime = GetMillisecondTimestamp( hDevice );
/* Fill the next buffer */
WMGenerateSineWave( pNextBuffer,
samplesPerBuffer,
sampleRate,
frequency,
amplitude,
WM_WAVEGEN_LEFT,
&wavegenCtxLeft
);
WMGenerateSineWave( pNextBuffer,
samplesPerBuffer,
sampleRate,
frequency * 2,
amplitude,
WM_WAVEGEN_RIGHT,
&wavegenCtxRight
);
if ( v_pDMABufXmitA_Virtual == pNextBuffer )
pNextBuffer = v_pDMABufXmitB_Virtual;
else
pNextBuffer = v_pDMABufXmitA_Virtual;
/*
* Wait for the current buffer to finish
*/
status = private_WaitForBuffer( hDevice, channel );
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice, ( "Timed out waiting for DMA to finish - skipping test" ) );
WMTEST_SKIP();
}
#if VERIFY_DMA_TIMING
/* Remember how long this buffer took */
timestampArray[repeat] = GetMillisecondTimestamp( hDevice ) - bufferStartTime;
#endif
/*
* Check the DMA status is correct - end interrupt and no errors.
*/
WMTEST_BOOLEAN( DCSR_ENDINTR == ( v_pDmaReg->DCSR[channel] & DCSR_DMA_INT_MASK ) );
WMTEST_BOOLEAN( v_pDmaReg->DINT & ( 1U << channel ) );
/*
* Clear the DMA interrupts
*/
v_pDmaReg->DCSR[channel] |= DCSR_DMA_INT_MASK;
}
/* Now work out how long it all took */
endTime = GetMillisecondTimestamp( hDevice );
duration = endTime - startTime;
WMTEST_TRACE(( "%d buffers of %d samples took %d ms (expected %dms)\n",
repeats,
samplesPerBuffer,
duration,
expectedDuration
));
#if VERIFY_DMA_TIMING
/* Make sure it's reasonably close to what we expect */
WMTEST_GREATER( duration, expectedDuration - TEST_MILLISECOND_SLOP );
WMTEST_LESS( duration, expectedDuration + TEST_MILLISECOND_SLOP );
#endif /* VERIFY_DMA_TIMING */
}
while ( loopForever );
/*
* Mute, disable and power down the HiFi output path.
*/
WMTEST_CALL( WMAudioMuteAllOutputs( hDevice, TRUE ) );
WMTEST_CALL( WMAudioEnableOutputPaths( hDevice, WM_STREAM_HIFI_OUT, FALSE ) );
WMTEST_CALL( WMAudioPowerDown( hDevice,WM_POWER_AUDIO_PLAYBACK ) );
/*
* Clean up the DMA now that the test is finished.
*/
private_CleanupDMA( hDevice, channel, channelId );
}
WMTEST_END
/*-----------------------------------------------------------------------------
* Function: WMTestMonoDACDMADirect
*
* Plays a sound directly to the Mono (AUX) DAC, using direct control of the
* DMA buffers.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WM_BOOL
* TRUE if it passed, FALSE if it failed in a way it could detect.
*---------------------------------------------------------------------------*/
WMTEST_START( WMTestMonoDACDMADirect( WM_DEVICE_HANDLE hDevice ) )
{
#if WM_MONODAC
WMSTATUS status;
unsigned int repeat;
unsigned int repeats;
unsigned int samplesPerBuffer;
unsigned int startTime, endTime, bufferStartTime;
unsigned int expectedDuration;
WM_AUDIO_STEREO_SAMPLE *pNextBuffer;
int channel = WMDMA_MONO_OUT;
int channelId = DMA_CHAN_AC97_MONO_OUT;
WM_WAVEGEN_CTX wavegenCtxLeft = WM_START_OF_WAVE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -