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