📄 wmxscaledmacontext.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: WMXScaleDMAContext.c 2530 2005-12-07 10:48:44Z ian $
*
* This file contains XScale functionality for DMA initialisation and
* allocation.
*
* Warning:
* This driver is specifically written for Wolfson Codecs. It is not a
* general CODEC device driver.
*
* This platform file is specifically designed to work with the Cotulla AC'97
* controller and the Lubbock and Mainstone XScale platforms from Intel. There
* is no guarantee of correct operation with other platforms/controllers.
*
* -----------------------------------------------------------------------------*/
/*
* Include files
*/
#include <windows.h>
#include "WMCommon.h"
#include "WMDMAContext.h"
#include "WMPlatform_OS.h"
#include "WMPlatformDeviceContext.h"
#include "WMAudioInternal.h"
/* Sanity check on library Audio configuration */
#if WMAUDIO_MAX_BUFFER_SIZE > AUDIO_BUFFER_SIZE
#error WMAUDIO_MAX_BUFFER_SIZE is too large
#endif /* WMAUDIO_MAX_BUFFER_SIZE > AUDIO_BUFFER_SIZE */
/*
* Only build this if we're doing Audio support.
*/
#if WM_AUDIO_STREAM
/*
* Global definitions
*/
/*
* A macro for initialising the DMA Details table.
*/
#define DMA_CHAN( _channel, _addr, _flags, _bytesPerSample, _burstSize, _device ) \
{ _channel, (void *)_addr, _flags, _bytesPerSample, _burstSize, _device }
/*
* Public data.
*/
DMAContext g_WMDMAContext = {0};
/*
* Private data
*/
/*
* The predefined details of the channels we use.
*/
static DMA_CHANNEL_DETAILS s_ChannelDetails[] =
{
#if WM_AC97
DMA_CHAN(
WMAUDIO_AC97_STEREO_OUT, /* API channel ID*/
DMAC_AC97_AUDIO_XMIT_FIFO, /* FIFO address */
WM_OUTPUT|WM_STEREO, /* whether: input, stereo or wide */
4, /* bytes per sample */
DMAC_BURST_SIZE_32_BYTES, /* Maximum burst size */
DMA_CHAN_AC97_STEREO_OUT /* DMA Device ID (DRCMR) */
),
DMA_CHAN(
WMAUDIO_AC97_STEREO_IN, /* API channel ID*/
DMAC_AC97_AUDIO_RCV_FIFO, /* FIFO address */
WM_INPUT|WM_STEREO, /* whether: input, stereo or wide */
4, /* bytes per sample */
DMAC_BURST_SIZE_32_BYTES, /* Maximum burst size */
DMA_CHAN_AC97_STEREO_IN /* DMA Device ID (DRCMR) */
),
#if WM_MONODAC
DMA_CHAN(
WMAUDIO_AC97_MONO_OUT, /* API channel ID*/
DMAC_AC97_MONO_XMIT_FIFO, /* FIFO address */
WM_OUTPUT|WM_MONO|WM_WIDE, /* whether: input, stereo or wide */
4, /* bytes per sample */
DMAC_BURST_SIZE_32_BYTES, /* Maximum burst size */
DMA_CHAN_AC97_MONO_OUT /* DMA Device ID (DRCMR) */
),
#endif /* WM_MONODAC */
#endif /* WM_AC97 */
#if WM_I2S
DMA_CHAN(
WMAUDIO_I2S_STEREO_OUT, /* API channel ID*/
DMAC_I2S_AUDIO_XMIT_FIFO, /* FIFO address */
WM_OUTPUT|WM_STEREO, /* whether: input, stereo or wide */
4, /* bytes per sample */
DMAC_BURST_SIZE_32_BYTES, /* Maximum burst size */
DMA_CHAN_I2S_STEREO_OUT /* DMA Device ID (DRCMR) */
),
DMA_CHAN(
WMAUDIO_I2S_STEREO_IN, /* API channel ID*/
DMAC_I2S_AUDIO_RCV_FIFO, /* FIFO address */
WM_INPUT|WM_STEREO, /* whether: input, stereo or wide */
4, /* bytes per sample */
DMAC_BURST_SIZE_32_BYTES, /* Maximum burst size */
DMA_CHAN_I2S_STEREO_IN /* DMA Device ID (DRCMR) */
),
#endif /* WM_I2S */
#if WM_VOICE
DMA_CHAN(
WMAUDIO_VOICE_OUT, /* API channel ID*/
DMAC_SSP2_AUDIO_XMIT_FIFO, /* FIFO address */
WM_OUTPUT|WM_MONO, /* whether: input, stereo or wide */
2, /* bytes per sample */
DMAC_BURST_SIZE_16_BYTES, /* Maximum burst size */
DMA_CHAN_VOICE_OUT /* DMA Device ID (DRCMR) */
),
DMA_CHAN(
WMAUDIO_VOICE_IN, /* API channel ID*/
DMAC_SSP2_AUDIO_RCV_FIFO, /* FIFO address */
WM_INPUT|WM_MONO, /* whether: input, stereo or wide */
2, /* bytes per sample */
DMAC_BURST_SIZE_16_BYTES, /* Maximum burst size */
DMA_CHAN_VOICE_IN /* DMA Device ID (DRCMR) */
),
#endif /* WM_VOICE */
/* Place holder for end of array */
DMA_CHAN(
WMAUDIO_INVALID_CHANNEL, /* API channel ID*/
0, /* FIFO address */
0, /* whether: input, stereo or wide */
0, /* bytes per sample */
0, /* Maximum burst size */
0 /* DMA Device ID (DRCMR) */
)
};
/*
* We can not use the last array member as this is only a placeholder This is
* why we subtract 1 from the the array count to give the available channels.
*/
#define WM_AVAILABLE_DMA_CHANNELS (WM_ARRAY_COUNT( s_ChannelDetails ) - 1)
/*
* Function prototypes
*/
static WMSTATUS private_AllocateDMAMemory( WM_DEVICE_HANDLE hDevice,
DMAContext *pDMAContext
);
static void private_InitialiseDMAMemory( WM_DEVICE_HANDLE hDevice,
DMAContext *pDMAContext
);
static void private_AssignDMAMemory( WM_DEVICE_HANDLE hDevice,
DMAContext *pDMAContext,
int DMAChannels
);
static void private_PrepareDeviceMapping( WM_DEVICE_HANDLE hDevice,
DMAContext *pDMAContext
);
/*-----------------------------------------------------------------------------
* Function: WMInitDMAContext
*
* Initialises the DMA and returns a pointer to the DMA context for passing
* to the device context.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* ppContext a variable to receive the pointer to the context structure.
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMInitDMAContext( WM_DEVICE_HANDLE hDevice, DMAContext **ppContext )
{
WMSTATUS status;
DMAContext *pDMAContext;
pDMAContext = &g_WMDMAContext;
/* Check whether we're initialised */
if ( pDMAContext->initialised )
{
goto InitDone;
}
/*
* Allocate the memory for the DMA buffers and descriptors.
*/
status = private_AllocateDMAMemory( hDevice, pDMAContext );
if( WM_ERROR( status ) )
{
goto error;
}
/*
* Map the memory for the DMA buffers and descriptors.
*/
private_InitialiseDMAMemory( hDevice, pDMAContext );
/*
* Fill in the device mapping table.
*/
private_PrepareDeviceMapping( hDevice, pDMAContext );
/*
* Set the DMA Context flag to TRUE as we have filled
* in the DMA Context and it is ready to be used.
*/
pDMAContext->initialised = TRUE;
InitDone:
*ppContext = pDMAContext;
return WMS_SUCCESS;
/*
* Error handling.
*/
error:
pDMAContext->initialised = FALSE;
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMDMAGetChannelDef
*
* Returns a pointer to the requested channel definition corresponding to
* the channel.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* APIChannel the API channel ID.
*
* Returns: ChannelDef *
* NULL indicates an error -
* the appropriate structure was not found
*---------------------------------------------------------------------------*/
ChannelDef *WMDMAGetChannelDef( WM_DEVICE_HANDLE hDevice,
WMAUDIO_CHANNEL APIChannel
)
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
DMAContext *pDMAContext = pDeviceContext->pDMAContext;
unsigned int i;
WM_ASSERT( hDevice, pDMAContext->initialised );
for ( i = 0; i < WM_AVAILABLE_DMA_CHANNELS; i++ )
{
if ( APIChannel == pDMAContext->pDMAChannels[i].APIChannel )
{
return ( &(pDMAContext->pDMAChannels[i]) );
}
}
/* No matching channel found */
WM_TRACE( hDevice, (
"WMDMAGetChannelDef - NO definition for channel %d found",
APIChannel
)
);
return ((ChannelDef *)NULL);
}
/*-----------------------------------------------------------------------------
* Function: WMDMAGetChannelDetails
*
* Returns a pointer to the requested static DMA setup structure corresponding
* to the channel.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* APIChannel the Wolfson channel ID
*
* Returns: DMA_CHANNEL_DETAILS *
* NULL indicates an error -
* the appropriate structure was not found
*---------------------------------------------------------------------------*/
const DMA_CHANNEL_DETAILS *WMDMAGetChannelDetails( WM_DEVICE_HANDLE hDevice,
WMAUDIO_CHANNEL APIChannel
)
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
DMAContext *pDMAContext = pDeviceContext->pDMAContext;
unsigned int i;
WM_ASSERT( hDevice, WMAUDIO_DEFAULT_INPUT != APIChannel );
WM_ASSERT( hDevice, WMAUDIO_DEFAULT_OUTPUT != APIChannel );
for ( i = 0; i < WM_AVAILABLE_DMA_CHANNELS; i++ )
{
if ( APIChannel == pDMAContext->pChannelDetails[i].APIChannel )
{
return ( &pDMAContext->pChannelDetails[i] );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -