xref: /haiku/src/add-ons/accelerants/intel_extreme/dpms.cpp (revision 2f470aec1c92ce6917b8a903e343795dc77af41f)
1 /*
2  * Copyright 2006, 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 	} else {
36 		// when disabling it, we have to trigger the update using a write to
37 		// the display base address
38 		if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
39 			write32(INTEL_DISPLAY_A_CONTROL, planeAControl & ~DISPLAY_CONTROL_ENABLED);
40 			write32(INTEL_DISPLAY_A_BASE, gInfo->shared_info->frame_buffer_offset);
41 		}
42 		if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
43 			write32(INTEL_DISPLAY_B_CONTROL, planeBControl & ~DISPLAY_CONTROL_ENABLED);
44 			write32(INTEL_DISPLAY_B_BASE, gInfo->shared_info->frame_buffer_offset);
45 		}
46 	}
47 }
48 
49 
50 static void
51 enable_display_pipe(bool enable)
52 {
53 	uint32 pipeAControl = read32(INTEL_DISPLAY_A_PIPE_CONTROL);
54 	uint32 pipeBControl = read32(INTEL_DISPLAY_B_PIPE_CONTROL);
55 
56 	if (enable) {
57 		if (gInfo->head_mode & HEAD_MODE_A_ANALOG)
58 			write32(INTEL_DISPLAY_A_PIPE_CONTROL, pipeAControl | DISPLAY_PIPE_ENABLED);
59 		if (gInfo->head_mode & HEAD_MODE_B_DIGITAL)
60 			write32(INTEL_DISPLAY_B_PIPE_CONTROL, pipeBControl | DISPLAY_PIPE_ENABLED);
61 	} else {
62 		if (gInfo->head_mode & HEAD_MODE_A_ANALOG)
63 			write32(INTEL_DISPLAY_A_PIPE_CONTROL, pipeAControl & ~DISPLAY_PIPE_ENABLED);
64 		if (gInfo->head_mode & HEAD_MODE_B_DIGITAL)
65 			write32(INTEL_DISPLAY_B_PIPE_CONTROL, pipeBControl & ~DISPLAY_PIPE_ENABLED);
66 	}
67 }
68 
69 
70 void
71 set_display_power_mode(uint32 mode)
72 {
73 	uint32 monitorMode = 0;
74 
75 	if (mode == B_DPMS_ON) {
76 		enable_display_pipe(true);
77 		enable_display_plane(true);
78 	}
79 
80 	wait_for_vblank();
81 
82 	switch (mode) {
83 		case B_DPMS_ON:
84 			monitorMode = DISPLAY_MONITOR_ON;
85 			break;
86 		case B_DPMS_SUSPEND:
87 			monitorMode = DISPLAY_MONITOR_SUSPEND;
88 			break;
89 		case B_DPMS_STAND_BY:
90 			monitorMode = DISPLAY_MONITOR_STAND_BY;
91 			break;
92 		case B_DPMS_OFF:
93 			monitorMode = DISPLAY_MONITOR_OFF;
94 			break;
95 	}
96 
97 	if (gInfo->head_mode & HEAD_MODE_A_ANALOG) {
98 		write32(INTEL_DISPLAY_A_ANALOG_PORT, (read32(INTEL_DISPLAY_A_ANALOG_PORT)
99 			& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
100 			| monitorMode | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
101 	}
102 	if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) {
103 		write32(INTEL_DISPLAY_B_DIGITAL_PORT, (read32(INTEL_DISPLAY_B_DIGITAL_PORT)
104 			& ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED))
105 			| monitorMode | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0));
106 	}
107 
108 	if (mode != B_DPMS_ON) {
109 		enable_display_plane(false);
110 		enable_display_pipe(false);
111 	}
112 }
113 
114 
115 //	#pragma mark -
116 
117 
118 uint32
119 intel_dpms_capabilities(void)
120 {
121 	TRACE(("intel_dpms_capabilities()\n"));
122 	return B_DPMS_ON | B_DPMS_SUSPEND | B_DPMS_STAND_BY | B_DPMS_OFF;
123 }
124 
125 
126 uint32
127 intel_dpms_mode(void)
128 {
129 	TRACE(("intel_dpms_mode()\n"));
130 	return gInfo->shared_info->dpms_mode;
131 }
132 
133 
134 status_t
135 intel_set_dpms_mode(uint32 mode)
136 {
137 	TRACE(("intel_set_dpms_mode()\n"));
138 	gInfo->shared_info->dpms_mode = mode;
139 	set_display_power_mode(mode);
140 
141 	return B_OK;
142 }
143 
144