📄 wmxscaleaclink.c
字号:
void WMPlatformACLinkShutdown( WM_DEVICE_HANDLE hDevice )
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
/* Return the GPIO to general use */
private_UnconfigureACLinkGPIO( hDevice );
pDeviceContext->flags &= ~DEVICE_INITIALISED;
}
/*-----------------------------------------------------------------------------
* Function: WMPlatformACLinkRead
*
* Reads the value from the given register.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* reg register to read from
* pValue variable to receive value
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkRead( WM_DEVICE_HANDLE hDevice,
WM_REGTYPE reg,
WM_REGVAL *pValue
)
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
WMSTATUS status;
/*
* Parameter validation.
*/
if ( reg > WM97_MAX_REGISTER )
{
status = WMS_REG_NOT_PRESENT;
goto error;
}
#if WM_USE_XLLP_AC97
{
XLLP_ACODEC_CONTEXT_T ACodecCtxStruct;
XLLP_ACODEC_ERROR_T xllpStatus;
ACODEC_FROM_DEVICE_CONTEXT( &ACodecCtxStruct, pDeviceContext );
xllpStatus = XllpAc97ACodecRead( &ACodecCtxStruct, reg, pValue );
if ( XLLP_ACODEC_SUCCESS != xllpStatus )
{
WM_TRACE( hDevice, ( "XllpAc97ACodecRead failed: 0x%X", xllpStatus ));
status = XllpStatusToWMStatus( xllpStatus );
goto error;
}
}
#else /* WM_USE_XLLP_AC97 */
{
unsigned int pCodecAddr;
volatile unsigned int *regAddr;
/*
* Just to make things complicated, the WM97_GPIO_PIN_STATUS is better
* supported through the modem codec registers than the audio codec
* registers, and is cached on the controller, so we don't need to
* wait for a read to conplete.
*
* Due to an issue with PXA27x silicon after A1, reads to register 54h
* in the modem IO space will cause all subsequent reads and writes
* to either the codec and/or modem IO space to fail, so on Bulverde we
* do an ordinary codec-space read instead.
*/
#if !WM_CPU_PXA27X
if ( WM97_GPIO_PIN_STATUS == reg )
{
unsigned int pModemAddr;
/*
* Find the right bank of registers.
*/
if ( WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID )
pModemAddr = PRIMARY_MODEM_REGS( pDeviceContext );
else
pModemAddr = SECONDARY_MODEM_REGS( pDeviceContext );
regAddr = (volatile unsigned int *) (pModemAddr + (reg << 1));
/*
* Read the data.
*/
*pValue = (WM_REGVAL) *regAddr;
/*
* And we don't need to wait for the read to complete.
*/
goto done;
}
#endif /* !WM_CPU_PXA27X */
/*
* Find the right bank of registers.
*/
if ( WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID )
pCodecAddr = PRIMARY_CODEC_REGS( pDeviceContext );
else
pCodecAddr = SECONDARY_CODEC_REGS( pDeviceContext );
/*
* Work out the virtual address corresponding to the register.
* The registers are based at v_pAC97Regs->CodecRegsPrimaryAud
* and are at 4-byte increments, i.e. at offset reg*2 from the base.
*
*/
regAddr = (volatile unsigned int *) (pCodecAddr + (reg << 1));
/*
* Clear SDONE and CDONE to be safe.
*/
pDeviceContext->v_pAC97Regs->GSR = AC97GSR_SDONE | AC97GSR_CDONE;
/*
* Do a dummy read to start the data off.
*/
*pValue = (WM_REGVAL) *regAddr;
/*
* Check for SDONE, and do the real read if it's set.
*/
status = private_WaitForStatusDone( hDevice );
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice, (
"WMPlatformACLinkRead: SDONE didn't get set after dummy read"
));
goto error;
}
/*
* Check there was no read error.
*/
if ( pDeviceContext->v_pAC97Regs->GSR & AC97GSR_READ_COMPLETION_STATUS )
{
/*
* There was.
*/
status = WMS_DATA_TIMED_OUT;
WM_TRACE( hDevice, (
"WMPlatformACLinkRead: didn't receive data (timeout on dummy read)"
));
goto error;
}
/*
* Clear SDONE and CDONE and do the real read.
*/
pDeviceContext->v_pAC97Regs->GSR = AC97GSR_SDONE | AC97GSR_CDONE;
*pValue = (WM_REGVAL) *regAddr;
/*
* Check for SDONE again. Once set, we're done.
*/
status = private_WaitForStatusDone( hDevice );
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice, (
"WMPlatformACLinkRead: SDONE didn't get set after real read"
));
goto error;
}
/*
* Check there was no read error.
*/
if ( pDeviceContext->v_pAC97Regs->GSR & AC97GSR_READ_COMPLETION_STATUS )
{
/*
* There was.
*/
status = WMS_DATA_TIMED_OUT;
WM_TRACE( hDevice, (
"WM97PlatformRead: didn't receive data (timeout)"
));
goto error;
}
}
/*
* Clear SDONE and CDONE again.
*/
pDeviceContext->v_pAC97Regs->GSR = AC97GSR_SDONE | AC97GSR_CDONE;
/*
* It worked.
*/
#if !WM_CPU_PXA27X
done:
#endif /* !WM_CPU_PXA27X */
#endif /* WM_USE_XLLP_AC97 */
return WMS_SUCCESS;
/*
* Error cleanup.
*/
error:
/*
* Clear the various flags by writing 1 to them.
*/
pDeviceContext->v_pAC97Regs->GSR = AC97GSR_SDONE | AC97GSR_CDONE |
AC97GSR_READ_COMPLETION_STATUS;
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMPlatformACLinkWrite
*
* Writes the value to the given register.
*
* Note: to clear GPIOs configured as interrupt sources (i.e. inputs held high
* by the sticky bit), use WM97PlatformClearGPIOs instead.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* reg register to write to
* value value to write
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkWrite( WM_DEVICE_HANDLE hDevice,
WM_REGTYPE reg,
WM_REGVAL value
)
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
WMSTATUS status;
/*
* Parameter validation.
*/
if ( reg > WM97_MAX_REGISTER )
{
status = WMS_REG_NOT_PRESENT;
goto error;
}
#if WM_USE_XLLP_AC97
{
XLLP_ACODEC_CONTEXT_T ACodecCtxStruct;
XLLP_ACODEC_ERROR_T xllpStatus;
ACODEC_FROM_DEVICE_CONTEXT( &ACodecCtxStruct, pDeviceContext );
xllpStatus = XllpAc97ACodecWrite( &ACodecCtxStruct, reg, value );
if ( XLLP_ACODEC_SUCCESS != xllpStatus )
{
WM_TRACE( hDevice, ( "XllpAc97ACodecWrite failed: 0x%X", xllpStatus ));
status = XllpStatusToWMStatus( xllpStatus );
goto error;
}
}
#else /* WM_USE_XLLP_AC97 */
{
unsigned int pCodecAddr;
volatile unsigned int *regAddr;
/*
* Just to make things complicated, the WM97_GPIO_PIN_STATUS is better
* supported through the modem codec registers than the audio codec
* registers, and is cached on the controller, so we don't need to
* wait for a write to complete.
*/
if ( WM97_GPIO_PIN_STATUS == reg )
{
WM_REGVAL slotValue;
unsigned int pModemAddr;
/*
* Find the right bank of registers.
*/
if ( (WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID)
&& !IS_WM9712_FAMILY( hDevice )
)
{
pModemAddr = PRIMARY_MODEM_REGS( pDeviceContext );
}
else
{
pModemAddr = SECONDARY_MODEM_REGS( pDeviceContext );
}
regAddr = (volatile unsigned int *) (pModemAddr + (reg << 1));
/*
* We need to write to the modem space to set the appropriate bits
* in slot 12.
*/
if ( IS_WM9712_FAMILY( hDevice ) )
slotValue = value << 1;
else
slotValue = value;
/*
* Write the data.
*/
*regAddr = (unsigned int) slotValue;
#if WM_CPU_PXA27X
/*
* On PXA27x silicon after A1 we now need to wait at least 2 frames
* otherwise the controller will hang. 2 frames = approx 42us. Round
* this up to 50us.
*/
MicroSleep( hDevice, 50 );
#endif /* WM_CPU_PXA27X */
/*
* We're done. NB: This will not clear sticky bits on the WM9712!
* Use WM97PlatformClearGPIOs instead.
*/
goto done;
}
/*
* Find the right bank of registers.
*/
if ( WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID )
pCodecAddr = PRIMARY_CODEC_REGS( pDeviceContext );
else
pCodecAddr = SECONDARY_CODEC_REGS( pDeviceContext );
/*
* Work out the virtual address corresponding to the register.
* The registers are based at v_pAC97Regs->CodecRegsPrimaryAud
* and are each 16-bits wide, i.e. at offset reg*2 from the base.
*/
regAddr = (volatile unsigned int *) (pCodecAddr + (reg << 1));
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -