📄 wm8753audio.c
字号:
break;
default:
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Work out our settings based on the interface.
*/
if ( WM_AUDIOIF_HIFI == audioIF )
{
isMaster = WM_AUDIOIF_DEFAULT_HIFI_IS_MASTER;
format = WM_AUDIOIF_DEFAULT_HIFI_FORMAT;
width = WM_AUDIOIF_DEFAULT_HIFI_WIDTH;
flags = WM_AUDIOIF_DEFAULT_HIFI_FLAGS;
configuredFlag = WM_AUDIO_HIFI_CONFIGURED;
}
else
{
isMaster = WM_AUDIOIF_DEFAULT_VOICE_IS_MASTER;
format = WM_AUDIOIF_DEFAULT_VOICE_FORMAT;
width = WM_AUDIOIF_DEFAULT_VOICE_WIDTH;
flags = WM_AUDIOIF_DEFAULT_VOICE_FLAGS;
configuredFlag = WM_AUDIO_VOICE_CONFIGURED;
}
/*
* Configure the interface if we haven't already done so.
*/
if ( !pDeviceContext->v_pWMData ||
!(pDeviceContext->v_pWMData->audioData.flags & configuredFlag)
)
{
status = WMAudioConfigureInterface( hDevice,
audioIF,
isMaster,
format,
width,
flags
);
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice,
( "WM8753EnableStream: WMAudioConfigureInterface failed: %s",
WMStatusText( status )
)
);
goto error;
}
WM_ASSERT( hDevice,
WMS_RETURN_TRUE == WMAudioIsInterfaceConfigured( hDevice, audioIF )
);
}
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WM8753DisableStream
*
* Called to disable the given stream. This unconfigures the interface.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* stream The stream to enable
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WM8753DisableStream( WM_DEVICE_HANDLE hDevice,
WM_STREAM_ID stream
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status, enabled;
WM_AUDIO_INTERFACE audioIF;
/*
* Work out our which interface we need.
*/
switch ( stream )
{
case WM_STREAM_HIFI_OUT:
enabled = WMAudioIsStreamEnabled( hDevice, WM_STREAM_HIFI_IN );
if ( WMS_RETURN_FALSE == enabled )
audioIF = WM_AUDIOIF_HIFI;
else
audioIF = WM_AUDIOIF_NONE;
break;
case WM_STREAM_HIFI_IN:
if ( !IS_VOICE_ENABLED( pDeviceContext ) )
{
/*
* We're set up for HiFi only.
*/
enabled = WMAudioIsStreamEnabled( hDevice, WM_STREAM_HIFI_OUT );
if ( WMS_RETURN_FALSE == enabled )
audioIF = WM_AUDIOIF_HIFI;
else
audioIF = WM_AUDIOIF_NONE;
break;
}
/*
* Else we're set up for HiFi DAC + voice codec => "HiFi in" is really
* voice in. Fall through.
*/
case WM_STREAM_VOICE_IN:
enabled = WMAudioIsStreamEnabled( hDevice, WM_STREAM_VOICE_OUT );
if ( WMS_RETURN_FALSE == enabled )
audioIF = WM_AUDIOIF_VOICE;
else
audioIF = WM_AUDIOIF_NONE;
break;
case WM_STREAM_VOICE_OUT:
enabled = WMAudioIsStreamEnabled( hDevice, WM_STREAM_VOICE_IN );
if ( WMS_RETURN_FALSE == enabled )
audioIF = WM_AUDIOIF_VOICE;
else
audioIF = WM_AUDIOIF_NONE;
break;
default:
status = WMS_UNSUPPORTED;
goto error;
}
/*
* Unconfigure the interface, if it's not still in use.
*/
if ( WM_AUDIOIF_NONE != audioIF )
{
status = WMAudioUnconfigureInterface( hDevice,
audioIF
);
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice,
( "WM8753DisableStream: WMAudioUnconfigureInterface failed: %s",
WMStatusText( status )
)
);
goto error;
}
WM_ASSERT( hDevice,
WMS_RETURN_FALSE == WMAudioIsInterfaceConfigured( hDevice, audioIF )
);
}
return WMS_SUCCESS;
error:
return status;
}
#if WM_VOICE && defined( DEBUG )
/*-----------------------------------------------------------------------------
* Function: WM8753VoiceDumpRegs
*
* Dump all the Voice DAC related registers
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: none
*---------------------------------------------------------------------------*/
void WM8753VoiceDumpRegs( WM_DEVICE_HANDLE hDevice )
{
WM_REGVAL reg = 0;
WM_TRACE( hDevice, (" WM8753 Voice DAC Reg Dump") );
WM_TRACE( hDevice, ("-----------------------------") );
WMRead( hDevice, WM8753_VOICE_AUDIO_INTERFACE, ® );
WM_TRACE( hDevice, ("Voice Audio Interface 0x03 = 0x%04X", reg ) );
WMRead( hDevice, WM8753_INTERFACE_CONTROL, ® );
WM_TRACE( hDevice, ("Interface Control 0x05 = 0x%04X", reg ) );
WMRead( hDevice, WM8753_SAMPLE_RATE_CTRL_1, ® );
WM_TRACE( hDevice, ("Sample Rate Control 1 0x06 = 0x%04X", reg ) );
WMRead( hDevice, WM8753_SAMPLE_RATE_CTRL_2, ® );
WM_TRACE( hDevice, ("Sample Rate Control 2 0x07 = 0x%04X", reg ) );
WMRead( hDevice, WM8753_CLOCK_CONTROL, ® );
WM_TRACE( hDevice, ("Clock Control 0x34 = 0x%04X", reg ) );
WMRead( hDevice, WM8753_PLL2_CONTROL_1, ® );
WM_TRACE( hDevice, ("PLL2 Control 1 0x39 = 0x%04X", reg ) );
WMRead( hDevice, WM8753_PLL2_CONTROL_2, ® );
WM_TRACE( hDevice, ("PLL2 Control 2 0x3A = 0x%04X", reg ) );
WMRead( hDevice, WM8753_PLL2_CONTROL_3, ® );
WM_TRACE( hDevice, ("PLL2 Control 3 0x3B = 0x%04X", reg ) );
WMRead( hDevice, WM8753_PLL2_CONTROL_4, ® );
WM_TRACE( hDevice, ("PLL2 Control 4 0x3C = 0x%04X", reg ) );
WMPlatformDumpSSP2Regs( hDevice );
}
#endif /* WM_VOICE && DEBUG */
/*-----------------------------------------------------------------------------
* Function: private_ConfigurePLL
*
* Configures the PLL for the given frequency.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* WM8753_PLL the PLL to configure
* targetFreq the target output frequency
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
static WMSTATUS private_ConfigurePLL( WM_DEVICE_HANDLE hDevice,
WM8753_PLL pll,
unsigned int targetFreq
)
{
WMSTATUS status;
int N, K;
WM_BOOL divMclk;
WM_REGTYPE baseReg;
WM_REGVAL controlVal;
/*
* Work out our base register.
*/
if ( WM8753_PLL1 == pll )
{
baseReg = WM8753_PLL1_CONTROL_1;
}
else
{
baseReg = WM8753_PLL2_CONTROL_1;
}
/*
* Set our coefficients.
*/
private_calcPLLCoefficients( WM_MCLK_FREQUENCY,
targetFreq,
&N,
&K,
&divMclk
);
status = WMWrite( hDevice, baseReg + 1 , WM8753_PLL_R2VAL( N, K ) );
if ( WM_ERROR( status ) )
{
goto error;
}
status = WMWrite( hDevice, baseReg + 2 , WM8753_PLL_R3VAL( N, K ) );
if ( WM_ERROR( status ) )
{
goto error;
}
status = WMWrite( hDevice, baseReg + 3 , WM8753_PLL_R4VAL( N, K ) );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* Now set up the PLL.
*/
controlVal = WM8753_PLL_ENABLE |
WM8753_PLL_ACTIVE |
WM8753_PLLOUT_DIV2 |
WM8753_CLOCKOUT_PLL;
if ( divMclk )
controlVal |= WM8753_MCLK_DIV2;
status = WMWrite( hDevice, baseReg, controlVal );
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* And enable the bits in clock control.
*/
if ( WM8753_PLL1 == pll )
{
status = WMSetField( hDevice,
WM8753_CLOCK_CONTROL,
( WM8753_MCLKSEL_PLL1 |
WM8753_GP1CLK1_CLOCK ),
( WM8753_MCLKSEL_MASK |
WM8753_GP1CLK1_MASK )
);
}
else
{
status = WMSetField( hDevice,
WM8753_CLOCK_CONTROL,
( WM8753_PCMCLKSEL_PLL2 |
WM8753_VXCLOCK_PLL2 |
WM8753_GP2CLK2_CLOCK ),
( WM8753_PCMCLKSEL_MASK |
WM8753_VXCLOCK_MASK |
WM8753_GP2CLK2_MASK )
);
}
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* And we're done.
*/
return WMS_SUCCESS;
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: private_calcPLLCoefficients
*
* Calculates the PLL coefficients for the given MCLK and target frequency.
*
* Parameters:
* MCLKFreq the MCLK frequency
* targetFreq the target output frequency
* pN variable to receive N value
* pK variable to receive K value
* pDivMclk variable to receive whether to use MCLK/2 instead of MCLK
*
* Returns: void
*---------------------------------------------------------------------------*/
static void private_calcPLLCoefficients( unsigned int MCLKFreq,
unsigned int targetFreq,
int *pN,
int *pK,
WM_BOOL *pDivMclk
)
{
double multiplier;
double fraction;
/* Use MCLK/2 if freq > 15MHz */
if ( MCLKFreq > 15000000 )
{
multiplier = 16.0;
*pDivMclk = TRUE;
}
else
{
multiplier = 8.0;
*pDivMclk = FALSE;
}
/* Work out the fraction */
fraction = multiplier * targetFreq / (double) MCLKFreq;
/* Now convert to N and K values */
*pN = (int) fraction;
*pK = (int) ((((double) PLL_K_BASE) * (fraction - (double) *pN)) + 0.5);
}
#if WM_TESTING
/*-----------------------------------------------------------------------------
* Function: WMTest8753Internals
*
* This function tests the internal code in WM8753Audio.c.
*
* Parameters:
* hDevice device handle to use
*
* Returns: WM_BOOL
* TRUE iff it worked.
*---------------------------------------------------------------------------*/
WMTEST_START( WMTest8753Internals( WM_DEVICE_HANDLE hDevice ) )
{
unsigned int coeff;
/*
* Test the PLL coefficients.
*/
for ( coeff = 0; coeff < WM_ARRAY_COUNT( s_PLLCoeffs ); coeff++ )
{
int N, K;
WM_BOOL divMclk;
const PLLCoeffTest *pTest = &s_PLLCoeffs[coeff];
private_calcPLLCoefficients( pTest->MCLKFreq,
pTest->targetFreq,
&N,
&K,
&divMclk
);
WMTEST_EQUALS( N, pTest->N );
WMTEST_EQUALS( K, pTest->K );
WMTEST_LESS_EQUAL( divMclk, pTest->divMclk );
}
}
WMTEST_END
#endif /* WM_TESTING */
#endif /* WM_AUDIO && WM8753_FAMILY */
/*------------------------------ END OF FILE ---------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -