* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel DΓΆrfler, axeld@pinc-software.de
*/
#include "accelerant_protos.h"
#include "accelerant.h"
#undef TRACE
#ifdef TRACE_DPMS
# define TRACE(x...) _sPrintf("intel_extreme: " x)
#else
# define TRACE(x...)
#endif
#define ERROR(x...) _sPrintf("intel_extreme: " x)
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
static void
enable_all_pipes(bool enable)
{
for (uint32 i = 0; i < gInfo->port_count; i++) {
if (gInfo->ports[i] == NULL)
continue;
if (!gInfo->ports[i]->IsConnected())
continue;
if (gInfo->ports[i]->GetPipe() == NULL)
continue;
gInfo->ports[i]->Power(enable);
}
read32(INTEL_DISPLAY_A_BASE);
set_frame_buffer_base();
}
static void
enable_lvds_panel(bool enable)
{
bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE);
int controlRegister = hasPCH ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL;
int statusRegister = hasPCH ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS;
uint32 control = read32(controlRegister);
uint32 panelStatus;
if (enable) {
if ((control & PANEL_CONTROL_POWER_TARGET_ON) == 0) {
write32(controlRegister, control | PANEL_CONTROL_POWER_TARGET_ON
);
}
if (!hasPCH) {
do {
panelStatus = read32(statusRegister);
} while ((panelStatus & PANEL_STATUS_POWER_ON) == 0);
}
} else {
if ((control & PANEL_CONTROL_POWER_TARGET_ON) != 0) {
write32(controlRegister, (control & ~PANEL_CONTROL_POWER_TARGET_ON)
);
}
if (!hasPCH)
{
do {
panelStatus = read32(statusRegister);
} while ((panelStatus & PANEL_STATUS_POWER_ON) != 0);
}
}
}
void
set_display_power_mode(uint32 mode)
{
uint32 monitorMode = 0;
if (mode == B_DPMS_ON) {
uint32 pll = read32(INTEL_DISPLAY_A_PLL);
if ((pll & DISPLAY_PLL_ENABLED) == 0) {
write32(INTEL_DISPLAY_A_PLL, pll);
read32(INTEL_DISPLAY_A_PLL);
spin(150);
write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_A_PLL);
spin(150);
write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_A_PLL);
spin(150);
}
pll = read32(INTEL_DISPLAY_B_PLL);
if ((pll & DISPLAY_PLL_ENABLED) == 0) {
write32(INTEL_DISPLAY_B_PLL, pll);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
}
enable_all_pipes(true);
}
wait_for_vblank();
switch (mode) {
case B_DPMS_ON:
monitorMode = DISPLAY_MONITOR_ON;
break;
case B_DPMS_SUSPEND:
monitorMode = DISPLAY_MONITOR_SUSPEND;
break;
case B_DPMS_STAND_BY:
monitorMode = DISPLAY_MONITOR_STAND_BY;
break;
case B_DPMS_OFF:
monitorMode = DISPLAY_MONITOR_OFF;
break;
}
if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT)
& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
| monitorMode
| (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
}
if (false) {
write32(INTEL_DIGITAL_PORT_B, (read32(INTEL_DIGITAL_PORT_B)
& ~( DISPLAY_MONITOR_PORT_ENABLED))
| (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
}
if (mode != B_DPMS_ON)
enable_all_pipes(false);
if (mode == B_DPMS_OFF) {
write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL)
| DISPLAY_PLL_ENABLED);
write32(INTEL_DISPLAY_B_PLL, read32(INTEL_DISPLAY_B_PLL)
| DISPLAY_PLL_ENABLED);
read32(INTEL_DISPLAY_B_PLL);
spin(150);
}
if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0)
enable_lvds_panel(mode == B_DPMS_ON);
read32(INTEL_DISPLAY_A_BASE);
}
uint32
intel_dpms_capabilities(void)
{
CALLED();
return B_DPMS_ON | B_DPMS_SUSPEND | B_DPMS_STAND_BY | B_DPMS_OFF;
}
uint32
intel_dpms_mode(void)
{
CALLED();
return gInfo->shared_info->dpms_mode;
}
status_t
intel_set_dpms_mode(uint32 mode)
{
CALLED();
gInfo->shared_info->dpms_mode = mode;
set_display_power_mode(mode);
return B_OK;
}