📄 wmaudio.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: WMAudio.c 2364 2005-11-04 15:56:03Z ib $
*
* This file contains platform-independent routines for controlling the audio
* operation on Wolfson codecs.
*
* Warning:
* This driver is specifically written for Wolfson Codecs. It is not a
* general CODEC device driver.
*
* -----------------------------------------------------------------------------*/
/*
* Include files
*/
#include "WMCommon.h"
#include "WMDevice.h"
#include "WMGlobals.h"
#include "WMControlLink.h"
#include "WMPlatformI2S.h"
#include "WM8753Audio.h"
#include "WMAudio.h"
#include "WMDMA.h"
#include "WMVoice.h"
#include "WMPower.h"
#if WM_TESTING
# include "Test/WMTestCommon.h"
# include "Test/WMAudioTests.h"
# include "Test/WMPlatformTests.h"
#endif
/*
* Only build this if we're doing Audio support.
*/
#if WM_AUDIO
/*
* Global definitions
*/
/*
* Private data
*/
/*
* Function prototypes
*/
/*-----------------------------------------------------------------------------
* Function: WMAudioInit
*
* Initialises the Audio functionality.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioInit( WM_DEVICE_HANDLE hDevice )
{
WMSTATUS status;
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
/* Initialise the I2S interface */
#if WM_I2S
if ( WM_IS_I2S( hDevice ) )
{
status = WMPlatformI2SInit( hDevice );
if ( WM_ERROR( status ) )
{
goto error0;
}
}
#endif
#if WM_TESTING && WM_AUTOTEST_AUDIO
/*
* Run audio tests, actually generating some sound.
* NOTE: This hits the hardware directly so it must
* be run before we initialise the DMA.
*/
WMTEST_RUN( WMTestPlatformAudio( hDevice ) );
#endif
#if WM_AUDIO_STREAM
/* Initialise the DMA */
status = WMDMAInit( hDevice );
if ( WM_ERROR( status ) )
{
goto error1;
}
#endif
/*
* Take the mutex.
*/
if ( !WMLockGlobalData( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto error2;
}
/*
* Initialise our global data.
*/
if ( pDeviceContext->v_pWMData )
{
/* Clear the flags */
pDeviceContext->v_pWMData->audioData.flags = 0;
/* Mute everything */
pDeviceContext->v_pWMData->audioData.mutes = 0xFFFF;
}
/*
* Set up our default streams.
*/
if ( WM_STREAM_INVALID_STREAM == pDeviceContext->defaultOutputStream )
{
if ( WM_IS_DAC_SUPPORTED( hDevice ) )
{
pDeviceContext->defaultOutputStream = WM_STREAM_HIFI_OUT;
/*
* Check the streams exist.
*/
WM_ASSERT( hDevice,
( WMAUDIO_INVALID_CHANNEL !=
_WMAudioStreamToChannel( hDevice,
pDeviceContext->defaultOutputStream
) )
);
}
if ( WM_IS_ADC_SUPPORTED( hDevice ) )
{
#if WM_VOICE && WM8753_FAMILY
if ( IS_WM8753_FAMILY( hDevice ) )
{
pDeviceContext->defaultInputStream = WM_STREAM_VOICE_IN;
}
else
#endif /* WM_VOICE && WM8753_FAMILY */
{
pDeviceContext->defaultInputStream = WM_STREAM_HIFI_IN;
}
/*
* Check the streams exist.
*/
WM_ASSERT( hDevice,
( WMAUDIO_INVALID_CHANNEL !=
_WMAudioStreamToChannel( hDevice,
pDeviceContext->defaultInputStream
) )
);
}
}
/* We're done */
WMUnlockGlobalData( hDevice );
#if WM_TESTING && WM_AUTOTEST_AUDIO
/*
* Run audio tests, actually generating some sound,
* using the library this time.
*/
WMTEST_RUN( WMTestAudio( hDevice ) );
#endif
return WMS_SUCCESS;
/*
* Error cleanup.
*/
error2:
#if WM_AUDIO_STREAM
WMDMAShutdown( hDevice );
error1:
#endif
#if WM_I2S
if ( WM_IS_I2S( hDevice ) )
{
WMPlatformI2SShutdown( hDevice );
}
error0:
#endif
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioShutdown
*
* Shuts down the Audio functionality.
*
* Parameters:
* (none)
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMAudioShutdown( WM_DEVICE_HANDLE hDevice )
{
#if WM_AUDIO_STREAM
WMDMAShutdown( hDevice );
#endif
WMLinkShutdown( hDevice, WM_DRIVER_AUDIO );
}
/*-----------------------------------------------------------------------------
* Function: WMAudioPowerUp
*
* Called to power up the Audio-specific sections of the chip.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* powerSections The sections to power up.
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioPowerUp( WM_DEVICE_HANDLE hDevice,
WM_POWERFLAG powerSections
)
{
WMSTATUS status;
/* Power up the relevant sections of the chip */
status = WMPowerUp( hDevice, WM_DRIVER_AUDIO, powerSections );
if ( WM_ERROR( status ) && WMS_UNSUPPORTED != status )
{
goto error;
}
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioPowerDown
*
* Called to power down the audio-specific sections of the chip. Note if the
* sections are still in use by another driver they will not actually be
* powered down.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* powerSections The sections to power down.
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioPowerDown( WM_DEVICE_HANDLE hDevice,
WM_POWERFLAG powerSections
)
{
WMSTATUS status;
/* Power down our section of the chip */
status = WMPowerDown( hDevice, WM_DRIVER_AUDIO, powerSections );
if ( WM_ERROR( status ) && WMS_UNSUPPORTED != status )
{
goto error;
}
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioConfigureInterface
*
* Configures the streaming format for the link for the given interface.
* Note: this is not required for AC'97 streams - HIFI and MONO on AC'97
* codecs.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* audioIF the interface to configure
* isMaster whether the codec masters the link
* format the streaming format to use
* width the number of bits per sample
* flags extra configuration flags
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioConfigureInterface( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_INTERFACE audioIF,
WM_BOOL isMaster,
WM_AUDIOIF_FORMAT format,
WM_AUDIOIF_WIDTH width,
WM_AUDIOIF_FLAGS flags
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status = WMS_UNSUPPORTED;
const WM_CHIPDEF *pChipDef;
/*
* Check the device supports the interface.
*/
if ( WM_IS_AC97( hDevice ) ||!WMAudioIsInterfaceSupported( hDevice, audioIF ) )
{
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Check we've got a function to call.
*/
pChipDef = WMGetChipDef( hDevice );
WM_ASSERT( hDevice, pChipDef );
if ( !pChipDef )
{
status = WMS_NO_SUPPORTED_DEVICE;
goto error;
}
if ( !pChipDef->vtable.fnConfigureInterface )
{
status = WMS_UNSUPPORTED;
goto error;
}
/*
* And call the codec-specific function.
*/
status = pChipDef->vtable.fnConfigureInterface( hDevice,
audioIF,
isMaster,
format,
width,
flags
);
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Save our settings.
*/
if ( pDeviceContext->v_pWMData )
{
/*
* Lock our global data.
*/
if ( WMLockGlobalData( hDevice ) )
{
if ( WM_AUDIOIF_HIFI == audioIF )
{
pDeviceContext->v_pWMData->audioData.flags |= WM_AUDIO_HIFI_CONFIGURED;
if ( isMaster )
pDeviceContext->v_pWMData->audioData.flags |= WM_AUDIO_HIFI_MASTER;
else
pDeviceContext->v_pWMData->audioData.flags &= ~WM_AUDIO_HIFI_MASTER;
}
#if WM_VOICE
else /* Voice */
{
pDeviceContext->v_pWMData->audioData.flags |= WM_AUDIO_VOICE_CONFIGURED;
if ( isMaster )
pDeviceContext->v_pWMData->audioData.flags |= WM_AUDIO_VOICE_MASTER;
else
pDeviceContext->v_pWMData->audioData.flags &= ~WM_AUDIO_VOICE_MASTER;
}
#endif /* WM_VOICE */
/* Let other threads in again */
WMUnlockGlobalData( hDevice );
}
}
/*
* We're done.
*/
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioUnconfigureInterface
*
* Unconfigures the streaming format for the link for the given interface.
* Note: this is not required for AC'97 streams - HIFI and MONO on AC'97
* codecs.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* audioIF the interface to configure
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioUnconfigureInterface( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_INTERFACE audioIF
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status = WMS_UNSUPPORTED;
const WM_CHIPDEF *pChipDef;
/*
* Check the device supports the interface.
*/
if ( WM_IS_AC97( hDevice ) ||!WMAudioIsInterfaceSupported( hDevice, audioIF ) )
{
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Check we've got a function to call.
*/
pChipDef = WMGetChipDef( hDevice );
WM_ASSERT( hDevice, pChipDef );
if ( !pChipDef )
{
status = WMS_NO_SUPPORTED_DEVICE;
goto error;
}
if ( !pChipDef->vtable.fnUnconfigureInterface )
{
status = WMS_UNSUPPORTED;
goto error;
}
/*
* And call the codec-specific function.
*/
status = pChipDef->vtable.fnUnconfigureInterface( hDevice, audioIF );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Save our settings.
*/
if ( pDeviceContext->v_pWMData )
{
/*
* Lock our global data.
*/
if ( WMLockGlobalData( hDevice ) )
{
if ( WM_AUDIOIF_HIFI == audioIF )
{
pDeviceContext->v_pWMData->audioData.flags &= ~WM_AUDIO_HIFI_CONFIGURED;
}
# if WM_VOICE
else /* Voice */
{
pDeviceContext->v_pWMData->audioData.flags &= ~WM_AUDIO_VOICE_CONFIGURED;
}
# endif /* WM_VOICE */
/* Let other threads in again */
WMUnlockGlobalData( hDevice );
}
}
/*
* We're done.
*/
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMAudioIsInterfaceConfigured
*
* Queries whether the given interface has been configured.
* Note: this requires global data. If there is no global data, this
* function will return WMS_UNSUPPORTED.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* audioIF the interface to query
*
* Returns: WMSTATUS
* WMS_RETURN_TRUE - interface is configured
* WMS_RETURN_FALSE - interface is not configured
* WMS_UNSUPPORTED - no global data, or interface not supported
*---------------------------------------------------------------------------*/
WMSTATUS WMAudioIsInterfaceConfigured( WM_DEVICE_HANDLE hDevice,
WM_AUDIO_INTERFACE audioIF
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status = WMS_UNSUPPORTED;
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -