1e404297eSAxel Dörfler /*
2d7e91d92SAxel Dörfler * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3e404297eSAxel Dörfler * Distributed under the terms of the MIT License.
4e404297eSAxel Dörfler *
5e404297eSAxel Dörfler * Authors:
6e404297eSAxel Dörfler * Axel Dörfler, axeld@pinc-software.de
7e404297eSAxel Dörfler */
8e404297eSAxel Dörfler
9e404297eSAxel Dörfler
10e404297eSAxel Dörfler #include "accelerant_protos.h"
11e404297eSAxel Dörfler #include "accelerant.h"
12e404297eSAxel Dörfler
13e404297eSAxel Dörfler
14881a823eSAlexander von Gluck IV #undef TRACE
15943578b1SAxel Dörfler //#define TRACE_DPMS
16943578b1SAxel Dörfler #ifdef TRACE_DPMS
17be3f7a8fSAlexander von Gluck IV # define TRACE(x...) _sPrintf("intel_extreme: " x)
18943578b1SAxel Dörfler #else
19881a823eSAlexander von Gluck IV # define TRACE(x...)
20943578b1SAxel Dörfler #endif
21943578b1SAxel Dörfler
22be3f7a8fSAlexander von Gluck IV #define ERROR(x...) _sPrintf("intel_extreme: " x)
23881a823eSAlexander von Gluck IV #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
24881a823eSAlexander von Gluck IV
25943578b1SAxel Dörfler
26b979c66cSAlexander von Gluck IV static void
enable_all_pipes(bool enable)27b979c66cSAlexander von Gluck IV enable_all_pipes(bool enable)
28e404297eSAxel Dörfler {
29b979c66cSAlexander von Gluck IV // Go over each port and enable pipe/plane
30b979c66cSAlexander von Gluck IV for (uint32 i = 0; i < gInfo->port_count; i++) {
31b979c66cSAlexander von Gluck IV if (gInfo->ports[i] == NULL)
32b979c66cSAlexander von Gluck IV continue;
33b979c66cSAlexander von Gluck IV if (!gInfo->ports[i]->IsConnected())
34b979c66cSAlexander von Gluck IV continue;
350af04dccSRudolf Cornelissen if (gInfo->ports[i]->GetPipe() == NULL)
360af04dccSRudolf Cornelissen continue;
37e404297eSAxel Dörfler
38b979c66cSAlexander von Gluck IV gInfo->ports[i]->Power(enable);
39c788baedSMichael Lotz }
40cbd40810SAxel Dörfler
41cbd40810SAxel Dörfler read32(INTEL_DISPLAY_A_BASE);
42b979c66cSAlexander von Gluck IV // flush the possibly cached PCI bus writes
43cbd40810SAxel Dörfler
44cbd40810SAxel Dörfler set_frame_buffer_base();
45a0902420SAxel Dörfler }
46e404297eSAxel Dörfler
47e404297eSAxel Dörfler
482d5f339dSAxel Dörfler static void
enable_lvds_panel(bool enable)492d5f339dSAxel Dörfler enable_lvds_panel(bool enable)
502d5f339dSAxel Dörfler {
5192e254d0SAlexander von Gluck IV bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE);
52f0468be3SMichael Lotz
539e2e0d8dSMichael Lotz int controlRegister = hasPCH ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL;
549e2e0d8dSMichael Lotz int statusRegister = hasPCH ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS;
5516cc5977SMichael Lotz
5616cc5977SMichael Lotz uint32 control = read32(controlRegister);
572d5f339dSAxel Dörfler uint32 panelStatus;
582d5f339dSAxel Dörfler
592d5f339dSAxel Dörfler if (enable) {
602d5f339dSAxel Dörfler if ((control & PANEL_CONTROL_POWER_TARGET_ON) == 0) {
6116cc5977SMichael Lotz write32(controlRegister, control | PANEL_CONTROL_POWER_TARGET_ON
62adc0f76eSAdrien Destugues /*| (hasPCH ? PANEL_REGISTER_UNLOCK : 0)*/);
632d5f339dSAxel Dörfler }
642d5f339dSAxel Dörfler
65adc0f76eSAdrien Destugues if (!hasPCH) {
662d5f339dSAxel Dörfler do {
6716cc5977SMichael Lotz panelStatus = read32(statusRegister);
682d5f339dSAxel Dörfler } while ((panelStatus & PANEL_STATUS_POWER_ON) == 0);
69adc0f76eSAdrien Destugues }
702d5f339dSAxel Dörfler } else {
712d5f339dSAxel Dörfler if ((control & PANEL_CONTROL_POWER_TARGET_ON) != 0) {
7216cc5977SMichael Lotz write32(controlRegister, (control & ~PANEL_CONTROL_POWER_TARGET_ON)
73adc0f76eSAdrien Destugues /*| (hasPCH ? PANEL_REGISTER_UNLOCK : 0)*/);
742d5f339dSAxel Dörfler }
752d5f339dSAxel Dörfler
76adc0f76eSAdrien Destugues if (!hasPCH)
77adc0f76eSAdrien Destugues {
782d5f339dSAxel Dörfler do {
7916cc5977SMichael Lotz panelStatus = read32(statusRegister);
802d5f339dSAxel Dörfler } while ((panelStatus & PANEL_STATUS_POWER_ON) != 0);
812d5f339dSAxel Dörfler }
822d5f339dSAxel Dörfler }
83adc0f76eSAdrien Destugues }
842d5f339dSAxel Dörfler
852d5f339dSAxel Dörfler
86e404297eSAxel Dörfler void
set_display_power_mode(uint32 mode)87e404297eSAxel Dörfler set_display_power_mode(uint32 mode)
88e404297eSAxel Dörfler {
89e404297eSAxel Dörfler uint32 monitorMode = 0;
90e404297eSAxel Dörfler
91e404297eSAxel Dörfler if (mode == B_DPMS_ON) {
92f0468be3SMichael Lotz uint32 pll = read32(INTEL_DISPLAY_A_PLL);
93cbd40810SAxel Dörfler if ((pll & DISPLAY_PLL_ENABLED) == 0) {
94cbd40810SAxel Dörfler // reactivate PLL
95f0468be3SMichael Lotz write32(INTEL_DISPLAY_A_PLL, pll);
96f0468be3SMichael Lotz read32(INTEL_DISPLAY_A_PLL);
97cbd40810SAxel Dörfler spin(150);
98f0468be3SMichael Lotz write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED);
99f0468be3SMichael Lotz read32(INTEL_DISPLAY_A_PLL);
100cbd40810SAxel Dörfler spin(150);
101f0468be3SMichael Lotz write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED);
102f0468be3SMichael Lotz read32(INTEL_DISPLAY_A_PLL);
103cbd40810SAxel Dörfler spin(150);
104cbd40810SAxel Dörfler }
105cbd40810SAxel Dörfler
106f0468be3SMichael Lotz pll = read32(INTEL_DISPLAY_B_PLL);
1072d5f339dSAxel Dörfler if ((pll & DISPLAY_PLL_ENABLED) == 0) {
1082d5f339dSAxel Dörfler // reactivate PLL
109f0468be3SMichael Lotz write32(INTEL_DISPLAY_B_PLL, pll);
110f0468be3SMichael Lotz read32(INTEL_DISPLAY_B_PLL);
1112d5f339dSAxel Dörfler spin(150);
112f0468be3SMichael Lotz write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED);
113f0468be3SMichael Lotz read32(INTEL_DISPLAY_B_PLL);
1142d5f339dSAxel Dörfler spin(150);
115f0468be3SMichael Lotz write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED);
116f0468be3SMichael Lotz read32(INTEL_DISPLAY_B_PLL);
1172d5f339dSAxel Dörfler spin(150);
1182d5f339dSAxel Dörfler }
1192d5f339dSAxel Dörfler
120b979c66cSAlexander von Gluck IV enable_all_pipes(true);
121e404297eSAxel Dörfler }
122e404297eSAxel Dörfler
123a0902420SAxel Dörfler wait_for_vblank();
124e404297eSAxel Dörfler
125e404297eSAxel Dörfler switch (mode) {
126e404297eSAxel Dörfler case B_DPMS_ON:
127e404297eSAxel Dörfler monitorMode = DISPLAY_MONITOR_ON;
128e404297eSAxel Dörfler break;
129e404297eSAxel Dörfler case B_DPMS_SUSPEND:
130e404297eSAxel Dörfler monitorMode = DISPLAY_MONITOR_SUSPEND;
131e404297eSAxel Dörfler break;
132e404297eSAxel Dörfler case B_DPMS_STAND_BY:
133e404297eSAxel Dörfler monitorMode = DISPLAY_MONITOR_STAND_BY;
134e404297eSAxel Dörfler break;
135e404297eSAxel Dörfler case B_DPMS_OFF:
136e404297eSAxel Dörfler monitorMode = DISPLAY_MONITOR_OFF;
137e404297eSAxel Dörfler break;
138e404297eSAxel Dörfler }
139e404297eSAxel Dörfler
140*95b7699fSRudolf Cornelissen //fixme: port DPMS programming should better be in Ports.cpp. Resetup..
141a0902420SAxel Dörfler if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
14250f0b3feSAlexander von Gluck IV write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT)
143e404297eSAxel Dörfler & ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
144c788baedSMichael Lotz | monitorMode
145c788baedSMichael Lotz | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
146a0902420SAxel Dörfler }
14750f0b3feSAlexander von Gluck IV
148*95b7699fSRudolf Cornelissen //fixme: port DPMS programming should better be in Ports.cpp and is faulty. Resetup..
149*95b7699fSRudolf Cornelissen if (false) {//gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
15050f0b3feSAlexander von Gluck IV write32(INTEL_DIGITAL_PORT_B, (read32(INTEL_DIGITAL_PORT_B)
15150f0b3feSAlexander von Gluck IV & ~(/*DISPLAY_MONITOR_MODE_MASK |*/ DISPLAY_MONITOR_PORT_ENABLED))
1522d5f339dSAxel Dörfler | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
1532d5f339dSAxel Dörfler // TODO: monitorMode?
154a0902420SAxel Dörfler }
155e404297eSAxel Dörfler
156b979c66cSAlexander von Gluck IV if (mode != B_DPMS_ON)
157b979c66cSAlexander von Gluck IV enable_all_pipes(false);
15861dad86aSAxel Dörfler
159cbd40810SAxel Dörfler if (mode == B_DPMS_OFF) {
160f0468be3SMichael Lotz write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL)
1612d5f339dSAxel Dörfler | DISPLAY_PLL_ENABLED);
162f0468be3SMichael Lotz write32(INTEL_DISPLAY_B_PLL, read32(INTEL_DISPLAY_B_PLL)
1632d5f339dSAxel Dörfler | DISPLAY_PLL_ENABLED);
1642d5f339dSAxel Dörfler
165f0468be3SMichael Lotz read32(INTEL_DISPLAY_B_PLL);
166951b5e51SMichael Lotz // flush the possibly cached PCI bus writes
1672d5f339dSAxel Dörfler
168cbd40810SAxel Dörfler spin(150);
169cbd40810SAxel Dörfler }
170cbd40810SAxel Dörfler
171f0468be3SMichael Lotz if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0)
1722d5f339dSAxel Dörfler enable_lvds_panel(mode == B_DPMS_ON);
1732d5f339dSAxel Dörfler
17461dad86aSAxel Dörfler read32(INTEL_DISPLAY_A_BASE);
175f0468be3SMichael Lotz // flush the possibly cached PCI bus writes
176e404297eSAxel Dörfler }
177e404297eSAxel Dörfler
178e404297eSAxel Dörfler
179e404297eSAxel Dörfler // #pragma mark -
180e404297eSAxel Dörfler
181e404297eSAxel Dörfler
182e404297eSAxel Dörfler uint32
intel_dpms_capabilities(void)183e404297eSAxel Dörfler intel_dpms_capabilities(void)
184e404297eSAxel Dörfler {
185881a823eSAlexander von Gluck IV CALLED();
186e404297eSAxel Dörfler return B_DPMS_ON | B_DPMS_SUSPEND | B_DPMS_STAND_BY | B_DPMS_OFF;
187e404297eSAxel Dörfler }
188e404297eSAxel Dörfler
189e404297eSAxel Dörfler
190e404297eSAxel Dörfler uint32
intel_dpms_mode(void)191e404297eSAxel Dörfler intel_dpms_mode(void)
192e404297eSAxel Dörfler {
193881a823eSAlexander von Gluck IV CALLED();
194e404297eSAxel Dörfler return gInfo->shared_info->dpms_mode;
195e404297eSAxel Dörfler }
196e404297eSAxel Dörfler
197e404297eSAxel Dörfler
198e404297eSAxel Dörfler status_t
intel_set_dpms_mode(uint32 mode)199e404297eSAxel Dörfler intel_set_dpms_mode(uint32 mode)
200e404297eSAxel Dörfler {
201881a823eSAlexander von Gluck IV CALLED();
202e404297eSAxel Dörfler gInfo->shared_info->dpms_mode = mode;
203e404297eSAxel Dörfler set_display_power_mode(mode);
204e404297eSAxel Dörfler
205e404297eSAxel Dörfler return B_OK;
206e404297eSAxel Dörfler }
207e404297eSAxel Dörfler
208