📄 wm97power.c
字号:
}
/* Turn on VREF (PR3). */
if ( powerUp & WM_POWER_VREF )
{
if ( !IS_WM9713_FAMILY( hDevice ) )
{
powerReg &= ~WM97_PWR_VREF;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
}
/*
* Turn on the mixers and input PGAs
* and for WM9712 only OUT2 (PR2).
*/
if ( powerUp & WM_POWER_MIXERS )
{
powerReg &= ~WM97_PWR_MIXERS;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
if ( IS_WM9713_FAMILY( hDevice ) )
{
/*
* For WM9713 both the PR2 in register 26h and
* mixers in register 3Ch must be cleared.
*/
status = WMClearField( hDevice,
WM9713_EXT_POWERDOWN_1,
( WM9713_EXTPWR_MONOMIX |
WM9713_EXTPWR_SPEAKERMIX |
WM9713_EXTPWR_HPMIX_RIGHT |
WM9713_EXTPWR_HPMIX_LEFT )
);
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* For WM9713 both the PR2 in register 26h and
* input PGAs in register 3Eh must be cleared.
*/
status = WMClearField( hDevice,
WM9713_EXT_POWERDOWN_2,
( WM9713_EXTPWR_MIC_PREAMP_B |
WM9713_EXTPWR_MIC_PREAMP_A |
WM9713_EXTPWR_MIC_B |
WM9713_EXTPWR_MIC_A |
WM9713_EXTPWR_MONOIN |
WM9713_EXTPWR_LINEIN_RIGHT |
WM9713_EXTPWR_LINEIN_LEFT )
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
}
/* Turn on the DACs (PR1) */
if ( powerUp & WM_POWER_AUDIO_DACS )
{
powerReg &= ~WM97_PWR_DAC;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
if ( IS_WM9713_FAMILY( hDevice ) )
{
/*
* For WM9713 both the PR1 in register 26h and
* DACs in register 3Ch must be cleared.
*/
status = WMClearField( hDevice,
WM9713_EXT_POWERDOWN_1,
( WM9713_EXTPWR_DAC_LEFT |
WM9713_EXTPWR_DAC_RIGHT |
WM9713_EXTPWR_AUXDAC |
WM9713_EXTPWR_VXDAC )
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
}
/* Turn on the ADC (PR0) */
if ( powerUp & WM_POWER_AUDIO_ADCS )
{
powerReg &= ~WM97_PWR_ADC;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
if ( IS_WM9713_FAMILY( hDevice ) )
{
/*
* For WM9713 both the PR0 in register 26h and
* ADCs in register 3Ch must be cleared.
*/
status = WMClearField( hDevice,
WM9713_EXT_POWERDOWN_1,
( WM9713_EXTPWR_ADC_LEFT |
WM9713_EXTPWR_ADC_RIGHT )
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
}
/* Turn on the outputs. (PR6) */
if ( powerUp & WM_POWER_OUTPUTS )
{
if ( !IS_WM9713_FAMILY( hDevice ) )
{
powerReg &= ~WM97_PWR_OUTPUTS;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
else
{
/*
* Make sure that we switch off fast power up to save power
*/
// TODO: Make sure we only call this once after WM97PowerInit has been called.
status = WMClearField( hDevice,
WM9713_FAST_POWER_CONTROL,
( WM9713_FAST_POWER_OUT4_ENABLE |
WM9713_FAST_POWER_OUT3_ENABLE |
WM9713_FAST_POWER_HPR_ENABLE |
WM9713_FAST_POWER_HPL_ENABLE |
WM9713_FAST_POWER_SPKR_ENABLE |
WM9713_FAST_POWER_SPKL_ENABLE |
WM9713_FAST_POWER_MONO_ENABLE )
);
}
}
/*
* Finally turn on the on-board amplifiers if needed.
*
* Note: this needs to happen even if these parts of the
* chip were already powered up - hence why we're using
* newPowered instead of powerUp.
*/
if ( newPowered & ( WM_POWER_OUTPUTS ) )
{
WMPlatformEnableAmplifiers( hDevice );
}
}
/*
* Make sure our digitiser is powered up.
*/
if ( powerUp & (WM_POWER_TOUCH|WM_POWER_AUXADC) )
{
WM_REGVAL adcMask, adcVal = 0;
/* Work out what to write to power up these sections */
adcVal = private_CalcPdwValue( hDevice, newPowered );
adcMask = WM97_TOUCHSETUP_PRP_PDW_MASK;
status = WMSetField( hDevice, WM97_DIGITISER_SETUP, adcVal, adcMask );
if ( WM_ERROR( status ) )
{
goto error;
}
/* Powerup Auxiliary ADC */
if ( IS_WM9713_FAMILY( hDevice ) )
{
/* We need touch => hit extended powerdown register */
status = WMClearField( hDevice,
WM9713_EXT_POWERDOWN_1,
WM9713_EXTPWR_AUXADC
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
}
/*
* Now remember what we've got on.
*/
#if WM_CACHE_POWER_STATE
if ( pDeviceContext->v_pWMData )
{
pDeviceContext->v_pWMData->powerReg[PWR_REG_1] = powerReg;
pDeviceContext->v_pWMData->WmPower = newPowered;
}
#endif /* WM_CACHE_POWER_STATE */
return WMS_SUCCESS;
/*
* Something went wrong.
*/
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WM97PowerDown
*
* Called to power down the specific sections of the chip on behalf of this
* driver. Note if the driver can tell that the sections are still in use
* by another driver they will not actually be powered down.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* driverId The device ID (e.g. WM_DRIVER_TOUCH)
* powerSections The sections to power down.
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WM97PowerDown( WM_DEVICE_HANDLE hDevice,
WM_DRIVER_ID driverId,
WM_POWERFLAG powerSections
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WM_POWERFLAG newPowered = 0; /* What should be powered up at the end */
WM_POWERFLAG powerDown; /* What is powered that shouldn't be */
WM_REGVAL powerReg;
WM_POWERFLAG currentPower;
WMSTATUS status;
/*
* If we're not yet initialised, there's nothing to do.
*/
if ( !pDeviceContext->flags & DEVICE_INITIALISED )
{
goto done;
}
/*
* Work out what we need powered off. We set up a few
* variables here:
*
* - newPowered holds what should still be powered up at the
* end of the function.
* - powerDown holds what needs to be powered down.
* - pDeviceContext->v_pWMData->WmPower holds what is currently powered up.
*/
newPowered = calcPowered( hDevice, driverId, 0, powerSections, ¤tPower );
/* Power down the bits currently powered up which shouldn't be */
powerDown = currentPower & ~newPowered;
/* Make sure we'll power down anything they explicitly asked for */
powerDown |= powerSections;
newPowered &= ~powerSections;
/*
* If there's nothing to do, get out now.
*/
if ( 0 == powerDown )
{
goto done;
}
/*
* Get the current reading if necessary.
*/
#if WM_CACHE_POWER_STATE
if ( pDeviceContext->v_pWMData &&
(pDeviceContext->v_pWMData->flags & WM_POWERREG_VALID)
)
{
powerReg = pDeviceContext->v_pWMData->powerReg[PWR_REG_1];
}
else
#endif /* WM_CACHE_POWER_STATE */
{
status = WMRead( hDevice, WM97_POWER_CONTROL, &powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
#if WM_CACHE_POWER_STATE
if ( pDeviceContext->v_pWMData )
{
pDeviceContext->v_pWMData->flags |= WM_POWERREG_VALID;
}
#endif /* WM_CACHE_POWER_STATE */
}
/*
* Disable audio. All or nothing for now.
* Recommended power-down sequence is
* WM9705: PR0, PR1, PR6, PR2, [PR3], PR5, PR4
* WM9712: PR6, PR0, PR1, PR2, PR3, PR5, PR4
*/
if ( powerDown & WM_POWER_AUDIO )
{
/*
* Turn off output PGAs first (PR6).
* Only do this for the WM9712/13 at this point because the WM9705
* will give a loud pop if we do it now.
*/
if ( IS_WM9712_FAMILY( hDevice ) || IS_WM9713_FAMILY( hDevice ) )
{
if ( (powerDown & WM_POWER_OUTPUTS)
&& 0 == (newPowered & WM_POWER_OUTPUTS)
)
{
/*
* Disable any onboard amps.
*/
WMPlatformDisableAmplifiers( hDevice );
if ( !IS_WM9713_FAMILY( hDevice ) )
{
powerReg |= WM97_PWR_OUTPUTS;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
}
}
/* Turn off the ADC (PR0) */
if ( powerDown & WM_POWER_AUDIO_ADCS )
{
if ( IS_WM9713_FAMILY( hDevice ) )
{
/*
* For WM9713 both the PR0 in register 26h and
* ADCs in register 3Ch must be set
*/
status = WMSetField( hDevice,
WM9713_EXT_POWERDOWN_1,
( WM9713_EXTPWR_ADC_LEFT |
WM9713_EXTPWR_ADC_RIGHT ),
WM9713_EXTPWR_ADC_MASK
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
powerReg |= WM97_PWR_ADC;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/* Turn off the DAC (PR1) */
if ( powerDown & WM_POWER_AUDIO_DACS )
{
if ( IS_WM9713_FAMILY( hDevice ) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -