📄 power.cpp
字号:
// Turn on CRT and panel
setDPMS(DPMS_ON);
panelPowerSequence(PANEL_ON, 4);
}
break;
case VGXPowerMinimal:
MESSAGE(MESSAGE_ZONE, (TEXT("[SMI::SetVGXPowerManagement] VGXPowerMinimal\r\n")));
// Fail under high power consumption circumstances
if (IsHighPowerConsumption())
{
dwResult = VGXPM_RET_HIGH_CONSUMPTION;
}
else
{
// Reduce the memory and engine clocks
if (SetClockMode(VGXPowerMinimal))
{
// Reduce the voltage from 1.8V to 1.35V
ReduceVoltage();
m_PowerState = VGXPowerMinimal;
}
// Turn on CRT and panel
setDPMS(DPMS_ON);
panelPowerSequence(PANEL_ON, 4);
}
break;
case VGXPowerStandBy:
MESSAGE(MESSAGE_ZONE, (TEXT("[SMI::SetVGXPowerManagement] VGXPowerStandBy\r\n")));
// Turn off CRT and panel
setDPMS(DPMS_OFF);
panelPowerSequence(PANEL_OFF, 4);
// By definition, don't put VGX to sleep when in Standby mode.
m_PowerState = VGXPowerStandBy;
break;
case VGXPowerSuspend:
MESSAGE(MESSAGE_ZONE, (TEXT("[SMI::SetVGXPowerManagement] VGXPowerSuspend\r\n")));
// Put the chip into slip.
m_PowerState = VGXPowerSuspend;
pokeRegisterDWord(POWER_MODE_CTRL, POWER_MODE_CTRL_MODE_SLEEP);
break;
case VGXPowerOff:
MESSAGE(MESSAGE_ZONE, (TEXT("[SMI::SetVGXPowerManagement] VGXPowerOff\r\n")));
// Turn off CRT and panel
setDPMS(DPMS_OFF);
panelPowerSequence(PANEL_OFF, 4);
if (m_SMISettings.m_nSaveRestoreEnabled)
{
// Save VGX registers and memory
SaveRestore(TRUE);
m_bVgxRegsMemorySaved = TRUE;
}
m_PowerState = VGXPowerOff;
#ifndef USI
// Put the chip into sleep.
pokeRegisterDWord(POWER_MODE_CTRL, POWER_MODE_CTRL_MODE_SLEEP);
#endif
for (j = 0; j < 0x70; j+=4)
MESSAGE(MESSAGE_ZONE, (TEXT("PowerOff Reg[0x%08X] = 0x%08X\r\n"), j, peekRegisterDWord(j)));
break;
default:
MESSAGE(MESSAGE_ZONE, (TEXT("[SMI::SetVGXPowerManagement] Invalid power mode!\r\n")));
// Unknown Powerstate
dwResult = VGXPM_RET_INVALID_PARAMETER;
}
}
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::SetVGXPowerManagement\r\n")));
LeaveCriticalSection(&m_PowerCriticalSection);
return dwResult;
}
///////////////////////////////////////////////////////////////////////////////
// Makes sure that the current power mode is at least the specified.
// If necessary, the current mode is adjusted.
VOID SMI::EnsureAtLeast(VGX_POWER_STATE MinimalPowerState)
{
#ifdef ENABLE_ALL_MESSAGES
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::EnsureAtLeast\r\n")));
#endif
if (GetCurrentPowerState() < VGXPowerStandBy)
{
DWORD dwCurrentTick = GetTickCountSafe();
switch (MinimalPowerState)
{
case VGXPowerOn:
m_dwPowerOnLastRequested = dwCurrentTick;
// Fall through...
case VGXPowerReduced:
m_dwReducedLastRequested = dwCurrentTick;
// Fall through...
case VGXPowerMinimal:
m_dwMinimalLastRequested = dwCurrentTick;
break;
default:
MESSAGE(MESSAGE_ZONE, (TEXT("SMI::EnsureAtLeast: invalid request\r\n")));
return;
}
if (GetCurrentPowerState() > MinimalPowerState)
SetVGXPowerManagement(MinimalPowerState);
}
#ifdef ENABLE_ALL_MESSAGES
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::EnsureAtLeast\r\n")));
#endif
}
///////////////////////////////////////////////////////////////////////////////
// Virtual API function. Can be called by WinCE.
void SMI::PowerHandler(BOOL bOff)
{
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::PowerHandler\r\n")));
m_bInPowerHandler = TRUE;
SetVGXPowerManagement(bOff? VGXPowerOff : VGXPowerOn);
m_bInPowerHandler = FALSE;
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::PowerHandler\r\n")));
}
///////////////////////////////////////////////////////////////////////////////
// Reduces the memory and engine clocks.
BOOL SMI::SetClockMode(VGX_POWER_STATE PowerState)
{
EnterCriticalSection(&m_PowerCriticalSection);
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::SetClockMode\r\n")));
BOOL bResult = FALSE;
TCHAR* lpszError = TEXT("clock settings do not exist for the mode\r\n");
__try
{
// Scan the clock table for the matching entry
for (INT i = 0; i < sizeof(m_ClockInfo) / sizeof(MODE_CLOCK); i++)
{
if ((m_ClockInfo[i].ScreenWidth == m_nScreenWidthSave) &&
(m_ClockInfo[i].ScreenHeigth == m_nScreenHeightSave) &&
(m_ClockInfo[i].ScreenBpp == m_nScreenBpp))
{
if (m_ClockInfo[i].ClockValue[PowerState].PowerState == PowerState)
{
MESSAGE(MESSAGE_ZONE, (TEXT("SMI::SetClockMode: reducing...\r\n")));
// Determine the current clock register
DWORD control_value = FIELD_GET(
peekRegisterDWord(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE);
DWORD clock_reg;
switch (control_value)
{
case POWER_MODE_CTRL_MODE_MODE0:
clock_reg = POWER_MODE0_CLOCK;
break;
case POWER_MODE_CTRL_MODE_MODE1:
clock_reg = POWER_MODE1_CLOCK;
break;
default:
lpszError = TEXT("cannot reduce clock - the chip is in sleep mode\r\n");
__leave;
}
// Program the clock
DWORD Clock = peekRegisterDWord(clock_reg);
Clock = FIELD_VALUE(Clock, CURRENT_POWER_CLOCK, MCLK_SELECT,
m_ClockInfo[i].ClockValue[PowerState].MCLKSelect);
Clock = FIELD_VALUE(Clock, CURRENT_POWER_CLOCK, MCLK_DIVIDER,
m_ClockInfo[i].ClockValue[PowerState].MCLKDivider);
Clock = FIELD_VALUE(Clock, CURRENT_POWER_CLOCK, MCLK_SHIFT,
m_ClockInfo[i].ClockValue[PowerState].MCLKShift);
Clock = FIELD_VALUE(Clock, CURRENT_POWER_CLOCK, M2XCLK_SELECT,
m_ClockInfo[i].ClockValue[PowerState].M2XCLKSelect);
Clock = FIELD_VALUE(Clock, CURRENT_POWER_CLOCK, M2XCLK_DIVIDER,
m_ClockInfo[i].ClockValue[PowerState].M2XCLKDivider);
Clock = FIELD_VALUE(Clock, CURRENT_POWER_CLOCK, M2XCLK_SHIFT,
m_ClockInfo[i].ClockValue[PowerState].M2XCLKShift);
pokeRegisterDWord(clock_reg, Clock);
if (!m_bProtectClockSource)
{
// Program the output frequency of PLL2
DWORD DRAMCtrl = peekRegisterDWord(SYSTEM_DRAM_CTRL);
DRAMCtrl = FIELD_VALUE(DRAMCtrl, SYSTEM_DRAM_CTRL, PLL2_OUTPUT,
m_ClockInfo[i].ClockValue[PowerState].PLL2Output);
pokeRegisterDWord(SYSTEM_DRAM_CTRL, DRAMCtrl);
}
lpszError = NULL;
__leave;
}
else
{
lpszError = TEXT("the specified power state is not supported\r\n");
__leave;
}
}
}
}
__finally
{
if (lpszError)
MESSAGE(MESSAGE_ZONE, (TEXT("SMI::SetClockMode: %s\r\n"), lpszError));
else
bResult = TRUE;
}
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::SetClockMode\r\n")));
LeaveCriticalSection(&m_PowerCriticalSection);
return bResult;
}
///////////////////////////////////////////////////////////////////////////////
// Reduces the voltage.
void SMI::ReduceVoltage(BOOL bReduce)
{
EnterCriticalSection(&m_PowerCriticalSection);
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::ReduceVoltage(%d)\r\n"), bReduce));
// Configure PWM2's pin to act as a GPIO's pin
pokeRegisterDWord(GPIO_MUX_LOW, FIELD_SET(
peekRegisterDWord(GPIO_MUX_LOW),
GPIO_MUX_LOW, 31, GPIO));
// Program the direction of the pin
pokeRegisterDWord(GPIO_DATA_DIRECTION_LOW, FIELD_SET(
peekRegisterDWord(GPIO_DATA_DIRECTION_LOW),
GPIO_DATA_DIRECTION_LOW, 31, OUTPUT));
if (bReduce)
{
// Reduce the voltage to 1.35V
pokeRegisterDWord(GPIO_DATA_LOW,
peekRegisterDWord(GPIO_DATA_LOW) | 0x80000000);
}
else
{
// Restore the full voltage to 1.8V
pokeRegisterDWord(GPIO_DATA_LOW,
peekRegisterDWord(GPIO_DATA_LOW) & ~0x80000000);
}
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::ReduceVoltage\r\n")));
LeaveCriticalSection(&m_PowerCriticalSection);
}
///////////////////////////////////////////////////////////////////////////////
// Returns the handle of the Power Management message queue.
HANDLE SMI::GetPMMessageQueue()
{
return m_hPMMessageQueue;
}
///////////////////////////////////////////////////////////////////////////////
// Returns the current video power state.
VGX_POWER_STATE SMI::GetCurrentPowerState()
{
return m_PowerState;
}
///////////////////////////////////////////////////////////////////////////////
// Returns the number of ticks since the last request for full power mode.
DWORD SMI::GetPowerOnLastRequested()
{
return m_dwPowerOnLastRequested;
}
///////////////////////////////////////////////////////////////////////////////
// Returns the number of ticks since the last request for reduced power mode.
DWORD SMI::GetReducedLastRequested()
{
return m_dwReducedLastRequested;
}
///////////////////////////////////////////////////////////////////////////////
// Returns the number of ticks since the last request for minimal power mode.
DWORD SMI::GetMinimalLastRequested()
{
return m_dwMinimalLastRequested;
}
///////////////////////////////////////////////////////////////////////////////
// Initializes the message queue and creates a thread.
DWORD SMI::GetTicksToReduced()
{
return m_dwTicksToReduced;
}
///////////////////////////////////////////////////////////////////////////////
// Initializes the message queue and creates a thread.
DWORD SMI::SetIdle(DWORD TicksToReduced, DWORD TicksToMinimal)
{
EnterCriticalSection(&m_PowerCriticalSection);
ResetPowerManagement();
m_dwTicksToReduced = TicksToReduced;
m_dwTicksToMinimal = TicksToMinimal;
LeaveCriticalSection(&m_PowerCriticalSection);
return VGXPM_RET_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
// Initializes the message queue and creates a thread.
DWORD SMI::GetTicksToMinimal()
{
return m_dwTicksToMinimal;
}
///////////////////////////////////////////////////////////////////////////////
// Returnes the current activity state for the Power Monitor.
BOOL SMI::IsPowerStateLocked()
{
return m_bPowerStateLocked;
}
///////////////////////////////////////////////////////////////////////////////
// Returnes the current activity state for the Power Monitor.
void SMI::LockPowerState(BOOL bLock)
{
ResetPowerManagement();
m_bPowerStateLocked = bLock;
}
///////////////////////////////////////////////////////////////////////////////
// Returnes the current activity state for the Power Monitor.
BOOL SMI::IsMonitorEnabled()
{
return m_bMonitorEnabled;
}
///////////////////////////////////////////////////////////////////////////////
// Sets the current activity state for the Power Monitor.
void SMI::SetMonitorEnabled(BOOL bEnabled)
{
EnterCriticalSection(&m_PowerCriticalSection);
ResetPowerManagement();
m_bMonitorEnabled = bEnabled;
LeaveCriticalSection(&m_PowerCriticalSection);
}
///////////////////////////////////////////////////////////////////////////////
// Sets the state of the monitor relative to the module.
DWORD SMI::SetModuleMonitorEnabled(VGXPM_MODULES Module, BOOL bEnabled)
{
EnterCriticalSection(&m_PowerCriticalSection);
DWORD dwResult = VGXPM_RET_INVALID_PARAMETER;
// Make sure we are within range
if (Module < VGXPM_MODULE_COUNT)
{
m_PowerInfo[Module].dwLastCallTickCount = GetTickCountSafe();
m_PowerInfo[Module].bMonitorEnabled = bEnabled;
dwResult = VGXPM_RET_SUCCESS;
}
else
{
MESSAGE(MESSAGE_ZONE, (TEXT("SMI::SetModuleMonitorEnabled: invalid module has been specified\r\n")));
}
LeaveCriticalSection(&m_PowerCriticalSection);
return dwResult;
}
///////////////////////////////////////////////////////////////////////////////
// Turns the specified module on/off.
// Allowed VGX_POWER_STATE constants are VGXPowerOn and VGXPowerOff.
DWORD SMI::SetModulePower(VGXPM_MODULES Module, VGX_POWER_STATE State)
{
EnterCriticalSection(&m_PowerCriticalSection);
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::SetModulePower\r\n")));
DWORD dwResult = VGXPM_RET_INVALID_PARAMETER;
// Make sure we are within range.
if (Module < VGXPM_MODULE_COUNT)
{
// Get current power mode.
DWORD control_value = FIELD_GET(
peekRegisterDWord(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE);
DWORD gate_reg = 0;
switch (control_value)
{
case POWER_MODE_CTRL_MODE_MODE0:
gate_reg = POWER_MODE0_GATE;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -