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 if (!hasPCH) { 64 do { 65 panelStatus = read32(statusRegister); 66 } while ((panelStatus & PANEL_STATUS_POWER_ON) == 0); 67 } 68 } else { 69 if ((control & PANEL_CONTROL_POWER_TARGET_ON) != 0) { 70 write32(controlRegister, (control & ~PANEL_CONTROL_POWER_TARGET_ON) 71 /*| (hasPCH ? PANEL_REGISTER_UNLOCK : 0)*/); 72 } 73 74 if (!hasPCH) 75 { 76 do { 77 panelStatus = read32(statusRegister); 78 } while ((panelStatus & PANEL_STATUS_POWER_ON) != 0); 79 } 80 } 81 } 82 83 84 void 85 set_display_power_mode(uint32 mode) 86 { 87 uint32 monitorMode = 0; 88 89 if (mode == B_DPMS_ON) { 90 uint32 pll = read32(INTEL_DISPLAY_A_PLL); 91 if ((pll & DISPLAY_PLL_ENABLED) == 0) { 92 // reactivate PLL 93 write32(INTEL_DISPLAY_A_PLL, pll); 94 read32(INTEL_DISPLAY_A_PLL); 95 spin(150); 96 write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED); 97 read32(INTEL_DISPLAY_A_PLL); 98 spin(150); 99 write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED); 100 read32(INTEL_DISPLAY_A_PLL); 101 spin(150); 102 } 103 104 pll = read32(INTEL_DISPLAY_B_PLL); 105 if ((pll & DISPLAY_PLL_ENABLED) == 0) { 106 // reactivate PLL 107 write32(INTEL_DISPLAY_B_PLL, pll); 108 read32(INTEL_DISPLAY_B_PLL); 109 spin(150); 110 write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED); 111 read32(INTEL_DISPLAY_B_PLL); 112 spin(150); 113 write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED); 114 read32(INTEL_DISPLAY_B_PLL); 115 spin(150); 116 } 117 118 enable_all_pipes(true); 119 } 120 121 wait_for_vblank(); 122 123 switch (mode) { 124 case B_DPMS_ON: 125 monitorMode = DISPLAY_MONITOR_ON; 126 break; 127 case B_DPMS_SUSPEND: 128 monitorMode = DISPLAY_MONITOR_SUSPEND; 129 break; 130 case B_DPMS_STAND_BY: 131 monitorMode = DISPLAY_MONITOR_STAND_BY; 132 break; 133 case B_DPMS_OFF: 134 monitorMode = DISPLAY_MONITOR_OFF; 135 break; 136 } 137 138 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 139 write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) 140 & ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED)) 141 | monitorMode 142 | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); 143 } 144 145 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 146 write32(INTEL_DIGITAL_PORT_B, (read32(INTEL_DIGITAL_PORT_B) 147 & ~(/*DISPLAY_MONITOR_MODE_MASK |*/ DISPLAY_MONITOR_PORT_ENABLED)) 148 | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); 149 // TODO: monitorMode? 150 } 151 152 if (mode != B_DPMS_ON) 153 enable_all_pipes(false); 154 155 if (mode == B_DPMS_OFF) { 156 write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL) 157 | DISPLAY_PLL_ENABLED); 158 write32(INTEL_DISPLAY_B_PLL, read32(INTEL_DISPLAY_B_PLL) 159 | DISPLAY_PLL_ENABLED); 160 161 read32(INTEL_DISPLAY_B_PLL); 162 // flush the possibly cached PCI bus writes 163 164 spin(150); 165 } 166 167 if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0) 168 enable_lvds_panel(mode == B_DPMS_ON); 169 170 read32(INTEL_DISPLAY_A_BASE); 171 // flush the possibly cached PCI bus writes 172 } 173 174 175 // #pragma mark - 176 177 178 uint32 179 intel_dpms_capabilities(void) 180 { 181 CALLED(); 182 return B_DPMS_ON | B_DPMS_SUSPEND | B_DPMS_STAND_BY | B_DPMS_OFF; 183 } 184 185 186 uint32 187 intel_dpms_mode(void) 188 { 189 CALLED(); 190 return gInfo->shared_info->dpms_mode; 191 } 192 193 194 status_t 195 intel_set_dpms_mode(uint32 mode) 196 { 197 CALLED(); 198 gInfo->shared_info->dpms_mode = mode; 199 set_display_power_mode(mode); 200 201 return B_OK; 202 } 203 204