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 accelerant:" x) 18 #else 19 # define TRACE(x...) 20 #endif 21 22 #define ERROR(x...) _sPrintf("intel_extreme accelerant: " x) 23 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 24 25 26 void 27 enable_display_plane(bool enable) 28 { 29 uint32 planeAControl = read32(INTEL_DISPLAY_A_CONTROL); 30 uint32 planeBControl = read32(INTEL_DISPLAY_B_CONTROL); 31 32 if (enable) { 33 // when enabling the display, the register values are updated 34 // automatically 35 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 36 write32(INTEL_DISPLAY_A_CONTROL, 37 planeAControl | DISPLAY_CONTROL_ENABLED); 38 } 39 40 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 41 write32(INTEL_DISPLAY_B_CONTROL, 42 planeBControl | DISPLAY_CONTROL_ENABLED); 43 } 44 45 read32(INTEL_DISPLAY_A_BASE); 46 // flush the eventually cached PCI bus writes 47 } else { 48 // when disabling it, we have to trigger the update using a write to 49 // the display base address 50 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 51 write32(INTEL_DISPLAY_A_CONTROL, 52 planeAControl & ~DISPLAY_CONTROL_ENABLED); 53 } 54 55 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 56 write32(INTEL_DISPLAY_B_CONTROL, 57 planeBControl & ~DISPLAY_CONTROL_ENABLED); 58 } 59 60 set_frame_buffer_base(); 61 } 62 } 63 64 65 static void 66 enable_display_pipe(bool enable) 67 { 68 uint32 pipeAControl = read32(INTEL_DISPLAY_A_PIPE_CONTROL); 69 uint32 pipeBControl = read32(INTEL_DISPLAY_B_PIPE_CONTROL); 70 71 if (enable) { 72 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 73 write32(INTEL_DISPLAY_A_PIPE_CONTROL, 74 pipeAControl | DISPLAY_PIPE_ENABLED); 75 } 76 77 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 78 write32(INTEL_DISPLAY_B_PIPE_CONTROL, 79 pipeBControl | DISPLAY_PIPE_ENABLED); 80 } 81 } else { 82 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 83 write32(INTEL_DISPLAY_A_PIPE_CONTROL, 84 pipeAControl & ~DISPLAY_PIPE_ENABLED); 85 } 86 87 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 88 write32(INTEL_DISPLAY_B_PIPE_CONTROL, 89 pipeBControl & ~DISPLAY_PIPE_ENABLED); 90 } 91 } 92 93 read32(INTEL_DISPLAY_A_BASE); 94 // flush the eventually cached PCI bus writes 95 } 96 97 98 static void 99 enable_lvds_panel(bool enable) 100 { 101 bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub(); 102 if (hasPCH) { 103 // TODO: fix for PCH 104 return; 105 } 106 107 int controlRegister = hasPCH ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL; 108 int statusRegister = hasPCH ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS; 109 110 uint32 control = read32(controlRegister); 111 uint32 panelStatus; 112 113 if (enable) { 114 if ((control & PANEL_CONTROL_POWER_TARGET_ON) == 0) { 115 write32(controlRegister, control | PANEL_CONTROL_POWER_TARGET_ON 116 | (hasPCH ? PANEL_REGISTER_UNLOCK : 0)); 117 } 118 119 do { 120 panelStatus = read32(statusRegister); 121 } while ((panelStatus & PANEL_STATUS_POWER_ON) == 0); 122 } else { 123 if ((control & PANEL_CONTROL_POWER_TARGET_ON) != 0) { 124 write32(controlRegister, (control & ~PANEL_CONTROL_POWER_TARGET_ON) 125 | (hasPCH ? PANEL_REGISTER_UNLOCK : 0)); 126 } 127 128 do { 129 panelStatus = read32(statusRegister); 130 } while ((panelStatus & PANEL_STATUS_POWER_ON) != 0); 131 } 132 } 133 134 135 void 136 set_display_power_mode(uint32 mode) 137 { 138 uint32 monitorMode = 0; 139 140 if (mode == B_DPMS_ON) { 141 uint32 pll = read32(INTEL_DISPLAY_A_PLL); 142 if ((pll & DISPLAY_PLL_ENABLED) == 0) { 143 // reactivate PLL 144 write32(INTEL_DISPLAY_A_PLL, pll); 145 read32(INTEL_DISPLAY_A_PLL); 146 spin(150); 147 write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED); 148 read32(INTEL_DISPLAY_A_PLL); 149 spin(150); 150 write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED); 151 read32(INTEL_DISPLAY_A_PLL); 152 spin(150); 153 } 154 155 pll = read32(INTEL_DISPLAY_B_PLL); 156 if ((pll & DISPLAY_PLL_ENABLED) == 0) { 157 // reactivate PLL 158 write32(INTEL_DISPLAY_B_PLL, pll); 159 read32(INTEL_DISPLAY_B_PLL); 160 spin(150); 161 write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED); 162 read32(INTEL_DISPLAY_B_PLL); 163 spin(150); 164 write32(INTEL_DISPLAY_B_PLL, pll | DISPLAY_PLL_ENABLED); 165 read32(INTEL_DISPLAY_B_PLL); 166 spin(150); 167 } 168 169 enable_display_pipe(true); 170 enable_display_plane(true); 171 } 172 173 wait_for_vblank(); 174 175 switch (mode) { 176 case B_DPMS_ON: 177 monitorMode = DISPLAY_MONITOR_ON; 178 break; 179 case B_DPMS_SUSPEND: 180 monitorMode = DISPLAY_MONITOR_SUSPEND; 181 break; 182 case B_DPMS_STAND_BY: 183 monitorMode = DISPLAY_MONITOR_STAND_BY; 184 break; 185 case B_DPMS_OFF: 186 monitorMode = DISPLAY_MONITOR_OFF; 187 break; 188 } 189 190 if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { 191 write32(INTEL_DISPLAY_A_ANALOG_PORT, 192 (read32(INTEL_DISPLAY_A_ANALOG_PORT) 193 & ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED)) 194 | monitorMode 195 | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); 196 } 197 if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { 198 write32(INTEL_DISPLAY_B_DIGITAL_PORT, 199 (read32(INTEL_DISPLAY_B_DIGITAL_PORT) 200 & ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED)) 201 | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); 202 // TODO: monitorMode? 203 } 204 205 if (mode != B_DPMS_ON) { 206 enable_display_plane(false); 207 wait_for_vblank(); 208 enable_display_pipe(false); 209 } 210 211 if (mode == B_DPMS_OFF) { 212 write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL) 213 | DISPLAY_PLL_ENABLED); 214 write32(INTEL_DISPLAY_B_PLL, read32(INTEL_DISPLAY_B_PLL) 215 | DISPLAY_PLL_ENABLED); 216 217 read32(INTEL_DISPLAY_B_PLL); 218 // flush the possibly cached PCI bus writes 219 220 spin(150); 221 } 222 223 if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0) 224 enable_lvds_panel(mode == B_DPMS_ON); 225 226 read32(INTEL_DISPLAY_A_BASE); 227 // flush the possibly cached PCI bus writes 228 } 229 230 231 // #pragma mark - 232 233 234 uint32 235 intel_dpms_capabilities(void) 236 { 237 CALLED(); 238 return B_DPMS_ON | B_DPMS_SUSPEND | B_DPMS_STAND_BY | B_DPMS_OFF; 239 } 240 241 242 uint32 243 intel_dpms_mode(void) 244 { 245 CALLED(); 246 return gInfo->shared_info->dpms_mode; 247 } 248 249 250 status_t 251 intel_set_dpms_mode(uint32 mode) 252 { 253 CALLED(); 254 gInfo->shared_info->dpms_mode = mode; 255 set_display_power_mode(mode); 256 257 return B_OK; 258 } 259 260