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