1 /* 2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "accelerant_protos.h" 11 #include "accelerant.h" 12 13 14 #undef TRACE 15 //#define TRACE_DPMS 16 #ifdef TRACE_DPMS 17 # define TRACE(x...) _sPrintf("intel_extreme: " x) 18 #else 19 # define TRACE(x...) 20 #endif 21 22 #define ERROR(x...) _sPrintf("intel_extreme: " x) 23 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 24 25 26 static void 27 enable_all_pipes(bool enable) 28 { 29 // Go over each port and enable pipe/plane 30 for (uint32 i = 0; i < gInfo->port_count; i++) { 31 if (gInfo->ports[i] == NULL) 32 continue; 33 if (!gInfo->ports[i]->IsConnected()) 34 continue; 35 36 gInfo->ports[i]->Power(enable); 37 } 38 39 read32(INTEL_DISPLAY_A_BASE); 40 // flush the possibly cached PCI bus writes 41 42 set_frame_buffer_base(); 43 } 44 45 46 static void 47 enable_lvds_panel(bool enable) 48 { 49 bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE); 50 51 int controlRegister = hasPCH ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL; 52 int statusRegister = hasPCH ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS; 53 54 uint32 control = read32(controlRegister); 55 uint32 panelStatus; 56 57 if (enable) { 58 if ((control & PANEL_CONTROL_POWER_TARGET_ON) == 0) { 59 write32(controlRegister, control | PANEL_CONTROL_POWER_TARGET_ON 60 | (hasPCH ? PANEL_REGISTER_UNLOCK : 0)); 61 } 62 63 do { 64 panelStatus = read32(statusRegister); 65 } while ((panelStatus & PANEL_STATUS_POWER_ON) == 0); 66 } else { 67 if ((control & PANEL_CONTROL_POWER_TARGET_ON) != 0) { 68 write32(controlRegister, (control & ~PANEL_CONTROL_POWER_TARGET_ON) 69 | (hasPCH ? PANEL_REGISTER_UNLOCK : 0)); 70 } 71 72 do { 73 panelStatus = read32(statusRegister); 74 } while ((panelStatus & PANEL_STATUS_POWER_ON) != 0); 75 } 76 } 77 78 79 void 80 set_display_power_mode(uint32 mode) 81 { 82 uint32 monitorMode = 0; 83 84 if (mode == B_DPMS_ON) { 85 uint32 pll = read32(INTEL_DISPLAY_A_PLL); 86 if ((pll & DISPLAY_PLL_ENABLED) == 0) { 87 // reactivate PLL 88 write32(INTEL_DISPLAY_A_PLL, pll); 89 read32(INTEL_DISPLAY_A_PLL); 90 spin(150); 91 write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED); 92 read32(INTEL_DISPLAY_A_PLL); 93 spin(150); 94 write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED); 95 read32(INTEL_DISPLAY_A_PLL); 96 spin(150); 97 } 98 99 pll = read32(INTEL_DISPLAY_B_PLL); 100 if ((pll & DISPLAY_PLL_ENABLED) == 0) { 101 // reactivate PLL 102 write32(INTEL_DISPLAY_B_PLL, pll); 103 read32(INTEL_DISPLAY_B_PLL); 104 spin(150); 105 write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED); 106 read32(INTEL_DISPLAY_B_PLL); 107 spin(150); 108 write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED); 109 read32(INTEL_DISPLAY_B_PLL); 110 spin(150); 111 } 112 113 enable_all_pipes(true); 114 } 115 116 wait_for_vblank(); 117 118 switch (mode) { 119 case B_DPMS_ON: 120 monitorMode = DISPLAY_MONITOR_ON; 121 break; 122 case B_DPMS_SUSPEND: 123 monitorMode = DISPLAY_MONITOR_SUSPEND; 124 break; 125 case B_DPMS_STAND_BY: 126 monitorMode = DISPLAY_MONITOR_STAND_BY; 127 break; 128 case B_DPMS_OFF: 129 monitorMode = DISPLAY_MONITOR_OFF; 130 break; 131 } 132 133 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 134 write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) 135 & ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED)) 136 | monitorMode 137 | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); 138 } 139 140 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 141 write32(INTEL_DIGITAL_PORT_B, (read32(INTEL_DIGITAL_PORT_B) 142 & ~(/*DISPLAY_MONITOR_MODE_MASK |*/ DISPLAY_MONITOR_PORT_ENABLED)) 143 | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); 144 // TODO: monitorMode? 145 } 146 147 if (mode != B_DPMS_ON) 148 enable_all_pipes(false); 149 150 if (mode == B_DPMS_OFF) { 151 write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL) 152 | DISPLAY_PLL_ENABLED); 153 write32(INTEL_DISPLAY_B_PLL, read32(INTEL_DISPLAY_B_PLL) 154 | DISPLAY_PLL_ENABLED); 155 156 read32(INTEL_DISPLAY_B_PLL); 157 // flush the possibly cached PCI bus writes 158 159 spin(150); 160 } 161 162 if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0) 163 enable_lvds_panel(mode == B_DPMS_ON); 164 165 read32(INTEL_DISPLAY_A_BASE); 166 // flush the possibly cached PCI bus writes 167 } 168 169 170 // #pragma mark - 171 172 173 uint32 174 intel_dpms_capabilities(void) 175 { 176 CALLED(); 177 return B_DPMS_ON | B_DPMS_SUSPEND | B_DPMS_STAND_BY | B_DPMS_OFF; 178 } 179 180 181 uint32 182 intel_dpms_mode(void) 183 { 184 CALLED(); 185 return gInfo->shared_info->dpms_mode; 186 } 187 188 189 status_t 190 intel_set_dpms_mode(uint32 mode) 191 { 192 CALLED(); 193 gInfo->shared_info->dpms_mode = mode; 194 set_display_power_mode(mode); 195 196 return B_OK; 197 } 198 199