📄 wm8731audio.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: WM8731Audio.c 2333 2005-10-20 14:06:34Z 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 "WMControlLink.h"
#include "WMPlatformI2S.h"
#include "WM8731Audio.h"
/*
* Only build this if we're doing Audio support for WM8731 devices.
*/
#if WM_AUDIO && WM8731_FAMILY
/*
* Global definitions
*/
/*
* Private data
*/
/*
* Private data
*/
typedef struct tagSampleRateSetting
{
WM_SAMPLE_RATE adcRate; /* Requested ADC rate */
WM_SAMPLE_RATE dacRate; /* Requested DAC rate */
WM_REGVAL regSetting; /* Value of WM8731_SAMPLERATE_MASK field */
} SampleRateSetting;
#define SAMPLE_SETTING(_adc, _dac, _rateval, _bosr ) \
{ _adc, _dac, WM8731_SAMPLE_RATE(_rateval) | _bosr }
/*
* Base over-sample rate.
*/
#if (12288000 == WM_MCLK_FREQUENCY) || (11289600 == WM_MCLK_FREQUENCY) || (6144000 == WM_MCLK_FREQUENCY) || (5644800 == WM_MCLK_FREQUENCY)
# define BOSR_VAL WM8731_SAMPLE_256FS
# define MCLK_DIV WM8731_SAMPLE_MCLK
# define SAMPLE_MODE WM8731_SAMPLE_NORMAL
#elif (18432000 == WM_MCLK_FREQUENCY) || (16934400 == WM_MCLK_FREQUENCY) || (9216000 == WM_MCLK_FREQUENCY) || (8467200 == WM_MCLK_FREQUENCY)
# define BOSR_VAL WM8731_SAMPLE_384FS
# define MCLK_DIV WM8731_SAMPLE_MCLK
# define SAMPLE_MODE WM8731_SAMPLE_NORMAL
#elif (24576000 == WM_MCLK_FREQUENCY) || (22579200 == WM_MCLK_FREQUENCY)
# define BOSR_VAL WM8731_SAMPLE_256FS
# define MCLK_DIV WM8731_SAMPLE_MCLK_DIV_2
# define SAMPLE_MODE WM8731_SAMPLE_NORMAL
#elif (36864000 == WM_MCLK_FREQUENCY) || (33868800 == WM_MCLK_FREQUENCY)
# define BOSR_VAL WM8731_SAMPLE_384FS
# define MCLK_DIV WM8731_SAMPLE_MCLK_DIV_2
# define SAMPLE_MODE WM8731_SAMPLE_NORMAL
#elif (12000000 == WM_MCLK_FREQUENCY)
# define MCLK_DIV WM8731_SAMPLE_MCLK
# define SAMPLE_MODE WM8731_SAMPLE_USB
#elif (24000000 == WM_MCLK_FREQUENCY)
# define MCLK_DIV WM8731_SAMPLE_MCLK_DIV_2
# define SAMPLE_MODE WM8731_SAMPLE_USB
#endif /* BOSR_VAL */
/*
* And now the tables of sample rate settings.
*/
#if (12288000 == WM_MCLK_FREQUENCY) || (18432000 == WM_MCLK_FREQUENCY) || (24576000 == WM_MCLK_FREQUENCY) || (36864000 == WM_MCLK_FREQUENCY)
static const SampleRateSetting s_hifiRates[] =
{
/* First the matched sample rates */
SAMPLE_SETTING( 8000, 8000, 0x03, BOSR_VAL ),
SAMPLE_SETTING( 32000, 32000, 0x06, BOSR_VAL ),
SAMPLE_SETTING( 48000, 48000, 0x00, BOSR_VAL ),
SAMPLE_SETTING( 96000, 96000, 0x07, BOSR_VAL ),
/* Now the unmatched sample rates */
SAMPLE_SETTING( 8000, 48000, 0x02, BOSR_VAL ),
SAMPLE_SETTING( 48000, 8000, 0x01, BOSR_VAL ),
};
#elif (11289600 == WM_MCLK_FREQUENCY) || (16934400 == WM_MCLK_FREQUENCY) || (22579200 == WM_MCLK_FREQUENCY) || (33868800 == WM_MCLK_FREQUENCY)
static const SampleRateSetting s_hifiRates[] =
{
/* First the matched sample rates */
SAMPLE_SETTING( 8000, 8000, 0x0B, BOSR_VAL ),
SAMPLE_SETTING( 44100, 44100, 0x08, BOSR_VAL ),
SAMPLE_SETTING( 88200, 88200, 0x0F, BOSR_VAL ),
/* Now the unmatched sample rates */
SAMPLE_SETTING( 8000, 44100, 0x0A, BOSR_VAL ),
SAMPLE_SETTING( 44100, 8000, 0x09, BOSR_VAL ),
};
#elif (6144000 == WM_MCLK_FREQUENCY) || (9216000 == WM_MCLK_FREQUENCY)
static const SampleRateSetting s_hifiRates[] =
{
SAMPLE_SETTING( 48000, 48000, 0x07, BOSR_VAL ),
};
#elif (5644800 == WM_MCLK_FREQUENCY) || (8467200 == WM_MCLK_FREQUENCY)
static const SampleRateSetting s_hifiRates[] =
{
SAMPLE_SETTING( 44100, 44100, 0x0F, BOSR_VAL ),
};
#elif (12000000 == WM_MCLK_FREQUENCY) || (24000000 == WM_MCLK_FREQUENCY)
static const SampleRateSetting s_hifiRates[] =
{
/* First the matched sample rates */
SAMPLE_SETTING( 8000, 8000, 0x03, WM8731_SAMPLE_250FS ),
SAMPLE_SETTING( 32000, 32000, 0x06, WM8731_SAMPLE_250FS ),
SAMPLE_SETTING( 44100, 44100, 0x08, WM8731_SAMPLE_272FS ),
SAMPLE_SETTING( 48000, 48000, 0x00, WM8731_SAMPLE_250FS ),
SAMPLE_SETTING( 88200, 88200, 0x0F, WM8731_SAMPLE_272FS ),
SAMPLE_SETTING( 96000, 96000, 0x07, WM8731_SAMPLE_250FS ),
/* Now the unmatched sample rates */
SAMPLE_SETTING( 8000, 44100, 0x0A, WM8731_SAMPLE_272FS ),
SAMPLE_SETTING( 8000, 48000, 0x02, WM8731_SAMPLE_250FS ),
SAMPLE_SETTING( 44100, 8000, 0x09, WM8731_SAMPLE_272FS ),
SAMPLE_SETTING( 48000, 8000, 0x01, WM8731_SAMPLE_250FS ),
};
#endif /* MCLK rates */
/*
* Function prototypes
*/
/*-----------------------------------------------------------------------------
* Function: WM8731SetSampleRate
*
* Called to Set the sample rate in the audio-specific sections of the chip.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* stream The stream for which to set the sample rate
* sampleRate The requested sample rate.
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WM8731SetSampleRate( WM_DEVICE_HANDLE hDevice,
WM_STREAM_ID stream,
WM_SAMPLE_RATE sampleRate
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status;
const SampleRateSetting *pSettings;
unsigned int nSettings;
unsigned int setting;
WM_REGVAL rateval;
WM_BOOL isMaster;
WM_BOOL found = FALSE;
/*
* Look up our sample rate setting.
*/
pSettings = s_hifiRates;
nSettings = WM_ARRAY_COUNT( s_hifiRates );
isMaster = pDeviceContext->v_pWMData->audioData.flags & WM_AUDIO_HIFI_MASTER;
/*
* Note: We don't currently handle whether ADC and DAC rates are
* compatible. The ADC and voice DAC will overwrite each other, and
* the HiFi DAC will just take the first option.
*/
if ( WM_IS_INPUT_STREAM( stream ) ) /* ADC */
{
for ( setting = 0; setting < nSettings; setting++ )
{
WM_SAMPLE_RATE adcRate = pSettings[ setting ].adcRate;
if ( sampleRate == adcRate )
{
rateval = pSettings[ setting ].regSetting;
found = TRUE;
break;
}
}
}
else /* output stream - DAC */
{
for ( setting = 0; setting < nSettings; setting++ )
{
WM_SAMPLE_RATE dacRate = pSettings[ setting ].dacRate;
if ( sampleRate == dacRate )
{
rateval = pSettings[ setting ].regSetting;
found = TRUE;
break;
}
}
}
if ( !found )
{
status = WMS_INVALID_PARAMETER;
goto error;
}
/*
* Add in the extras.
*/
rateval |= SAMPLE_MODE | MCLK_DIV;
if ( isMaster )
{
/*
* Write the sample rate to the codec.
*/
status = WMSetField( hDevice,
WM8731_SAMPLE_RATE_CONTROL,
rateval,
( WM8731_SAMPLERATE_MASK |
WM8731_SAMPLE_CLOCK_MASK |
WM8731_SAMPLE_FEQUENCY_MASK |
WM8731_SAMPLE_MCLKDIV
)
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
else
{
/*
* Set the I2S sample rate.
*/
status = WMPlatformI2SSetSampleRate( hDevice, sampleRate );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/*
* We're done.
*/
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WM8731ConfigureInterface
*
* Configures the streaming format for the link for the given interface.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -