xref: /haiku/src/add-ons/accelerants/intel_extreme/dpms.cpp (revision d9cebac2b77547b7064f22497514eecd2d047160)
1 /*
2  * Copyright 2006-2007, 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 void
75 set_display_power_mode(uint32 mode)
76 {
77 	uint32 monitorMode = 0;
78 
79 	if (mode == B_DPMS_ON) {
80 		uint32 pll = read32(INTEL_DISPLAY_A_PLL);
81 		if ((pll & DISPLAY_PLL_ENABLED) == 0) {
82 			// reactivate PLL
83 			write32(INTEL_DISPLAY_A_PLL, pll);
84 			read32(INTEL_DISPLAY_A_PLL);
85 			spin(150);
86 			write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED);
87 			read32(INTEL_DISPLAY_A_PLL);
88 			spin(150);
89 			write32(INTEL_DISPLAY_A_PLL, pll | DISPLAY_PLL_ENABLED);
90 			read32(INTEL_DISPLAY_A_PLL);
91 			spin(150);
92 		}
93 
94 		enable_display_pipe(true);
95 		enable_display_plane(true);
96 	}
97 
98 	wait_for_vblank();
99 
100 	switch (mode) {
101 		case B_DPMS_ON:
102 			monitorMode = DISPLAY_MONITOR_ON;
103 			break;
104 		case B_DPMS_SUSPEND:
105 			monitorMode = DISPLAY_MONITOR_SUSPEND;
106 			break;
107 		case B_DPMS_STAND_BY:
108 			monitorMode = DISPLAY_MONITOR_STAND_BY;
109 			break;
110 		case B_DPMS_OFF:
111 			monitorMode = DISPLAY_MONITOR_OFF;
112 			break;
113 	}
114 
115 	if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
116 		write32(INTEL_DISPLAY_A_ANALOG_PORT, (read32(INTEL_DISPLAY_A_ANALOG_PORT)
117 			& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
118 			| monitorMode | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
119 	}
120 	if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
121 		write32(INTEL_DISPLAY_B_DIGITAL_PORT, (read32(INTEL_DISPLAY_B_DIGITAL_PORT)
122 			& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
123 			| monitorMode | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
124 	}
125 
126 	if (mode != B_DPMS_ON) {
127 		enable_display_plane(false);
128 		wait_for_vblank();
129 		enable_display_pipe(false);
130 	}
131 
132 	if (mode == B_DPMS_OFF) {
133 		write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL) | DISPLAY_PLL_ENABLED);
134 		read32(INTEL_DISPLAY_A_PLL);
135 		spin(150);
136 	}
137 
138 	read32(INTEL_DISPLAY_A_BASE);
139 		// flush the eventually cached PCI bus writes
140 }
141 
142 
143 //	#pragma mark -
144 
145 
146 uint32
147 intel_dpms_capabilities(void)
148 {
149 	TRACE(("intel_dpms_capabilities()\n"));
150 	return B_DPMS_ON | B_DPMS_SUSPEND | B_DPMS_STAND_BY | B_DPMS_OFF;
151 }
152 
153 
154 uint32
155 intel_dpms_mode(void)
156 {
157 	TRACE(("intel_dpms_mode()\n"));
158 	return gInfo->shared_info->dpms_mode;
159 }
160 
161 
162 status_t
163 intel_set_dpms_mode(uint32 mode)
164 {
165 	TRACE(("intel_set_dpms_mode()\n"));
166 	gInfo->shared_info->dpms_mode = mode;
167 	set_display_power_mode(mode);
168 
169 	return B_OK;
170 }
171 
172