📄 wmcontrollink.c
字号:
WM_BOOL isPhysicalRead = FALSE;
WM_BOOL isDefaultReg = FALSE;
/* Make sure we are reading from a valid register */
if ( !private_IsValidRegister( hDevice, reg ) )
{
status = WMS_REG_NOT_PRESENT;
goto error0;
}
/* Protect ourselves */
if ( !WMLockGlobalData( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto error0;
}
if ( !WMLockLink( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto error1;
}
/* Check the link's up */
#if WM_CACHE_POWER_STATE
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
if ( pDeviceContext->v_pWMData &&
!( pDeviceContext->v_pWMData->WmPower & WM_POWER_LINK )
)
{
status = WMS_ACLINK_NOT_ACTIVE;
goto error2;
}
}
#endif
#if WM_USE_SHADOW_REGISTERS
/* Get it from the shadow register if available */
status = private_ReadShadowRegister( hDevice, reg, &value );
if ( WM_SUCCESS( status ) )
{
goto done;
}
#endif /* WM_USE_SHADOW_REGISTERS */
/* We need to go to the register itself */
platformStatus = WMPlatformRead( hDevice, reg, &value );
isPhysicalRead = TRUE;
/*
* Check to see if the error was due to a uninitialised read-only register:
* If so report this back to the caller.
*/
if ( ( WMS_SHADOW_UNINTIALISED == status ) && WMS_UNSUPPORTED == platformStatus )
{
goto error2;
}
/* We are only interested in the status from WMPlatformRead now */
status = platformStatus;
if ( WM_ERROR( status ) && ( WMS_UNSUPPORTED != status ) )
{
goto error2;
}
#if WM_USE_SHADOW_REGISTERS
done:
#endif /* WM_USE_SHADOW_REGISTERS */
*pValue = value;
/* Let other threads in again */
WMUnlockLink( hDevice );
WMUnlockGlobalData( hDevice );
#if WM_USE_SHADOW_REGISTERS
if( WMS_UNSUPPORTED != status )
{
isDefaultReg = WMIsDefaultRegValue( hDevice, reg, value );
}
#endif /* WM_USE_SHADOW_REGISTERS */
WM_REG_TRACE( hDevice, (
"==> WMRead: R%02Xh == 0x%04X %s %s",
reg,
value,
isPhysicalRead ? WMStatusText( status ) : "shadowed",
isDefaultReg ? "** DEFAULT **" : ""
));
return status;
/*
* Error handling.
*/
error2:
WMUnlockLink( hDevice );
error1:
/* Let other threads in again */
WMUnlockGlobalData( hDevice );
error0:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMWrite
*
* Writes the value to the given register.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* reg register to write to
* value value to write
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMWrite( WM_DEVICE_HANDLE hDevice,
WM_REGTYPE reg,
WM_REGVAL value
)
{
WMSTATUS status = WMS_SUCCESS;
const WM_CHIPDEF *pChipDef;
WM_BOOL isReset;
WM_BOOL isPhysicalWrite = TRUE;
/* Make sure we are writing to a valid register */
if ( !private_IsValidRegister( hDevice, reg ) )
{
/*
* We need to allow WM_I2S_INIT_TEST_REGISTER for I2S devices
* even though it does not exist.
*/
if ( !(WM_IS_I2S( hDevice ) && WM_I2S_INIT_TEST_REGISTER == reg) )
{
status = WMS_REG_NOT_PRESENT;
goto error0;
}
}
/* Protect ourselves */
if ( !WMLockGlobalData( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto error0;
}
if ( !WMLockLink( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto error1;
}
/* Check the link's up */
#if WM_CACHE_POWER_STATE
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
if ( pDeviceContext->v_pWMData &&
!( pDeviceContext->v_pWMData->WmPower & WM_POWER_LINK )
)
{
status = WMS_ACLINK_NOT_ACTIVE;
goto error2;
}
}
#endif
pChipDef = WMGetChipDef( hDevice );
if ( !pChipDef )
{
status = WMS_NO_SUPPORTED_DEVICE;
goto error2;
}
/*
* Work out if it's a reset - we need to do various extra tasks if so.
*/
isReset = ( pChipDef->resetReg == reg );
#if WM_USE_SHADOW_REGISTERS
/*
* Save it to the shadow register if appropriate.
* If this is the reset register then we need to restore
* default values to the shadow registers.
* If the return value is WMS_RETURN_TRUE then the value
* to be written is the value that is currently on the
* device so we do not need to do the physical write.
* For all other return codes we must write to the device.
*/
if ( isReset )
{
status = WMS_SUCCESS;
}
else
{
status = private_WriteShadowRegister( hDevice, reg, value );
}
#if !WM_DEBUG_WRITE_THROUGH
if ( WMS_RETURN_TRUE == status && WM_I2S_INIT_TEST_REGISTER != reg )
{
/*
* The register already held the value we were setting, so
* we won't actually do the write.
*/
isPhysicalWrite = FALSE;
status = WMS_SUCCESS;
}
else
#endif /* !WM_DEBUG_WRITE_THROUGH */
#endif /* WM_USE_SHADOW_REGISTERS */
{
/* Now do the write */
status = WMPlatformWrite( hDevice, reg, value );
if ( WM_ERROR( status ) )
{
goto error2;
}
if ( isReset )
{
/*
* Now update our state to match the reset.
*/
private_ResetState( hDevice );
}
}
/* Let other threads in again */
WMUnlockLink( hDevice );
WMUnlockGlobalData( hDevice );
WM_REG_TRACE( hDevice, (
"==> WMWrite: R%02Xh := 0x%04X %s %s",
reg,
value,
isPhysicalWrite ? WMStatusText( status ) : "not changed",
isReset ? "** RESET **" : ""
));
return status;
/*
* Error handling.
*/
error2:
WMUnlockLink( hDevice );
error1:
/* Let other threads in again */
WMUnlockGlobalData( hDevice );
error0:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMSetField
*
* Sets the given field of the given register to the given value.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* reg register to write to
* value value to write
* mask mask of field to update
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMSetField( WM_DEVICE_HANDLE hDevice,
WM_REGTYPE reg,
WM_REGVAL value,
WM_REGVAL mask
)
{
WMSTATUS status;
WM_REGVAL regVal;
/* Get the current value */
status = WMRead( hDevice, reg, ®Val );
if ( WM_ERROR( status ) )
{
goto end;
}
/* Clear the field we're wanting to update */
regVal &= ~mask;
/* Set it to our new value */
regVal |= (value & mask);
/* And write it back again */
status = WMWrite( hDevice, reg, regVal );
end:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMClearField
*
* Sets the given field of the given register to 0.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* reg register to write to
* mask mask of field to update
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMClearField( WM_DEVICE_HANDLE hDevice,
WM_REGTYPE reg,
WM_REGVAL mask
)
{
return WMSetField( hDevice, reg, 0, mask );
}
/*-----------------------------------------------------------------------------
* Function: WMReset
*
* Forces a cold reset of a Wolfson device.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMReset( WM_DEVICE_HANDLE hDevice )
{
WMSTATUS status;
/*
* Do a cold reset.
*/
status = WMPlatformReset( hDevice );
WM_REG_TRACE( hDevice, (
"==> WMReset: %s",
WMStatusText( status )
));
if ( WM_ERROR( status ) )
{
goto error0;
}
/*
* Now update our state to match.
*/
private_ResetState( hDevice );
/*
* We're done.
*/
return WMS_SUCCESS;
/*
* Error cleanup.
*/
error0:
return status;
}
/*-----------------------------------------------------------------------------
* Function: private_ResetState
*
* Resets our global state to default values.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: void
*---------------------------------------------------------------------------*/
static void private_ResetState( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
const WM_CHIPDEF *pChipDef;
if ( pDeviceContext->v_pWMData )
{
/*
* Lock our global data.
*/
if ( WMLockGlobalData( hDevice ) )
{
/*
* Look up our chipdef.
*/
pChipDef = WMGetChipDef( hDevice );
WM_ASSERT( hDevice, pChipDef );
if ( !pChipDef )
{
goto finish;
}
#if WM_CACHE_POWER_STATE
/*
* The power is back to default.
*/
pDeviceContext->v_pWMData->WmPower = pChipDef->defaultPower;
/*
* And our cached power register values are no longer valid.
*/
pDeviceContext->v_pWMData->flags &= ~(WM_POWERREG_VALID);
#endif
#if WM_USE_SHADOW_REGISTERS
/*
* Set our shadow registers to their default values.
*/
private_InitShadowRegisters( hDevice );
#endif
#if WM_AUDIO
/* Clear the flags */
pDeviceContext->v_pWMData->audioData.flags = 0;
/* Mute everything */
pDeviceContext->v_pWMData->audioData.mutes = 0xFFFF;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -