📄 wm97power.c
字号:
/*
* For WM9713 both the PR1 in register 26h and
* DACs in register 3Ch must be set.
*/
status = WMSetField( hDevice,
WM9713_EXT_POWERDOWN_1,
( WM9713_EXTPWR_DAC_LEFT |
WM9713_EXTPWR_DAC_RIGHT |
WM9713_EXTPWR_AUXDAC |
WM9713_EXTPWR_VXDAC ),
WM9713_EXTPWR_DAC_MASK
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
powerReg |= WM97_PWR_DAC;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/* It's okay to turn off output PGAs on the WM9705 now (PR6) */
if ( IS_WM9705_FAMILY( hDevice ) || IS_WM9707_FAMILY( hDevice ) )
{
if ( (powerDown & (WM_POWER_OUTPUTS))
&& 0 == (newPowered & (WM_POWER_OUTPUTS))
)
{
/*
* Disable any onboard amps.
*/
WMPlatformDisableAmplifiers( hDevice );
powerReg |= WM97_PWR_OUTPUTS;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
}
/*
* Turn off the mixers and input PGAs
* and for WM9713 only OUT2 (PR2).
*/
if ( (powerDown & (WM_POWER_MIXERS))
&& 0 == (newPowered & (WM_POWER_MIXERS))
)
{
if ( IS_WM9713_FAMILY( hDevice ) )
{
/*
* For WM9713 both the PR2 in register 26h and
* mixers in register 3Ch must be set.
*/
status = WMSetField( hDevice,
WM9713_EXT_POWERDOWN_1,
( WM9713_EXTPWR_MONOMIX |
WM9713_EXTPWR_SPEAKERMIX |
WM9713_EXTPWR_HPMIX_RIGHT |
WM9713_EXTPWR_HPMIX_LEFT ),
WM9713_EXTPWR_MIXER_MASK
);
if ( WM_ERROR( status ) )
{
goto error;
}
/*
* For WM9713 both the PR2 in register 26h and
* input PGAs in register 3Eh must be set.
*/
status = WMSetField( 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 ),
WM9713_EXTPWR_INPUT_MASK
);
if ( WM_ERROR( status ) )
{
goto error;
}
}
powerReg |= WM97_PWR_MIXERS;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
/*
* Take down the analogue references (PR3).
*
* However, on the WM9705 this can result in a pop on power up, so only do it if
* explicitly asked.
*
* In the WM9712/13 we the capacitors are kept charged by an internal resistor,
* so we're okay.
*/
if ( powerDown & WM_POWER_VREF )
{
if ( ( IS_WM9712_FAMILY( hDevice ) )
|| powerSections & WM_POWER_VREF )
{
powerReg |= WM97_PWR_VREF;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
else
{
newPowered |= WM_POWER_VREF;
}
WMPlatformDisableAmplifiers( hDevice );
}
/*
* We only need the clock for the audio side of things, not for touch or
* battery monitoring. (PR5)
*/
if ( powerDown & WM_POWER_CLOCK )
{
powerReg |= WM97_PWR_CLOCK;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
}
}
/*
* Touchscreen and Auxiliary ADC.
*/
if ( powerDown & (WM_POWER_TOUCH|WM_POWER_AUXADC) )
{
WM_REGVAL adcMask, adcVal = 0;
/*
* Work out what to write to power down these sections.
* Or to put it another way, what we need to write to leave
* the remaining sections powered up.
*/
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;
}
}
/*
* If there's nothing left except the link, power down the AC link (PR4).
* Also power down the link if the user explicitly asks for it.
*/
if ( powerDown & WM_POWER_LINK &&
( WM_POWER_NONE == newPowered || powerSections & WM_POWER_LINK )
)
{
powerReg |= WM97_PWR_ACLINK;
status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
if ( WM_ERROR( status ) )
{
goto error;
}
WMPlatformACLinkDisableController( hDevice );
}
else
{
newPowered |= WM_POWER_LINK;
}
/*
* Remember what we've got powered up.
*/
#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 */
/*
* We're done.
*/
done:
return WMS_SUCCESS;
/*
* Error cleanup.
*/
error:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WM97GetCurrentPower
*
* Returns the current power state by looking at the register.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WM_POWERFLAG
* The current power state.
*---------------------------------------------------------------------------*/
WM_POWERFLAG WM97GetCurrentPower( WM_DEVICE_HANDLE hDevice )
{
WM_REGVAL powerReg;
WM_POWERFLAG currentPower = 0;
WMSTATUS status;
/*
* Check what we've got.
*/
if ( WMPlatformACLinkIsCodecReady( hDevice ) )
{
status = WMRead( hDevice, WM97_POWER_CONTROL, &powerReg );
}
else
{
status = WMS_CODEC_NOT_READY;
}
/*
* Convert from register values to power flags.
* Note the register values are "powered off".
*/
if ( WM_SUCCESS( status ) )
{
currentPower |= WM_POWER_LINK;
if ( !(powerReg & WM97_PWR_ADC ) )
{
currentPower |= WM_POWER_AUDIO_ADCS;
}
if ( !(powerReg & WM97_PWR_DAC ) )
{
currentPower |= WM_POWER_AUDIO_DACS;
}
if ( !(powerReg & WM97_PWR_MIXERS ) )
{
currentPower |= WM_POWER_MIXERS;
}
if ( !(powerReg & WM97_PWR_VREF ) )
{
currentPower |= WM_POWER_VREF;
}
if ( !(powerReg & WM97_PWR_CLOCK ) )
{
currentPower |= WM_POWER_CLOCK;
}
if ( !(powerReg & WM97_PWR_OUTPUTS ) )
{
currentPower |= WM_POWER_OUTPUTS;
}
#if WM_TOUCH
currentPower |= private_CalcTouchPower( hDevice );
#endif
}
else
{
currentPower = 0;
}
return currentPower;
}
/*-----------------------------------------------------------------------------
* Function: private_CalcPdwValue
*
* Works out the value for TOUCHCONTROL1_PDW for a given set of powerflags.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* powerSections The sections to power up.
*
* Returns: WM_REGVAL value of TOUCHCONTRL1_PDW
*---------------------------------------------------------------------------*/
static WM_REGVAL private_CalcPdwValue( WM_DEVICE_HANDLE hDevice,
WM_POWERFLAG powerSections
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WM_REGVAL adcVal = 0;
if ( IS_WM9705_FAMILY( hDevice ) &&
WM_REV_B == pDeviceContext->revision
)
{
/* Pen digitiser powered up */
if ( powerSections & WM_POWER_AUXADC_DIGITISER )
adcVal = WM97_TOUCHSETUP_PRP;
if ( powerSections & WM_POWER_PEN_DETECT )
adcVal |= WM97_TOUCHSETUP_PDW;
}
else
{
if ( powerSections & WM_POWER_AUXADC_DIGITISER )
/* Pen digitiser powered up */
adcVal = WM97_TOUCHSETUP_PRP_PDW_3;
else if ( powerSections & WM_POWER_PEN_DETECT )
/* powered off, pen detect enabled, wakeup on pendown */
adcVal = WM97_TOUCHSETUP_PRP_PDW_1;
else
/* powered down, pen detect disabled, no wakeup on pendown */
adcVal = WM97_TOUCHSETUP_PRP_PDW_0;
}
return adcVal;
}
/*-----------------------------------------------------------------------------
* Function: private_CalcTouchPower
*
* Works out which touch powerflag is set depending on the value of
* TOUCHCONTROL1_PDW.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WM_POWERFLAG The section that is powered up.
*---------------------------------------------------------------------------*/
static WM_POWERFLAG private_CalcTouchPower( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WM_REGVAL adcVal = 0;
WM_POWERFLAG powerSection = 0;
WMRead( hDevice, WM97_DIGITISER_SETUP, &adcVal );
if ( IS_WM9705_FAMILY( hDevice ) &&
WM_REV_B == pDeviceContext->revision
)
{
/* Pen digitiser powered up */
if ( adcVal & WM97_TOUCHSETUP_PRP )
powerSection = WM_POWER_AUXADC_DIGITISER;
if ( adcVal & WM97_TOUCHSETUP_PDW )
powerSection |= WM_POWER_PEN_DETECT;
}
else
{
if ( adcVal & WM97_TOUCHSETUP_PRP_PDW_3 )
/* Pen digitiser powered up */
powerSection = WM_POWER_AUXADC_DIGITISER;
else if( adcVal & WM97_TOUCHSETUP_PRP_PDW_1 )
/* powered off, pen detect enabled, wakeup on pendown */
powerSection = WM_POWER_PEN_DETECT;
}
return powerSection;
}
#endif /* WM_AC97 */
/*------------------------------ END OF FILE ---------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -