xref: /haiku/src/add-ons/accelerants/ati/rage128_dpms.cpp (revision 82a8a20999118b748396cf16a33c47c3b0c0222d)
1 /*
2 	Haiku ATI video driver adapted from the X.org ATI driver.
3 
4 	Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
5 						 Precision Insight, Inc., Cedar Park, Texas, and
6 						 VA Linux Systems Inc., Fremont, California.
7 
8 	Copyright 2009 Haiku, Inc.  All rights reserved.
9 	Distributed under the terms of the MIT license.
10 
11 	Authors:
12 	Gerald Zajac 2009
13 */
14 
15 
16 #include "accelerant.h"
17 #include "rage128.h"
18 
19 
20 
21 uint32
22 Rage128_DPMSCapabilities(void)
23 {
24 	// Return DPMS modes supported by this device.
25 
26 	return B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF;
27 }
28 
29 
30 uint32
31 Rage128_GetDPMSMode(void)
32 {
33 	// Return the current DPMS mode.
34 
35 	uint32 tmp = INREG(R128_CRTC_EXT_CNTL);
36 	uint32 mode;
37 
38 	if( (tmp & R128_CRTC_DISPLAY_DIS) == 0 )
39 		mode = B_DPMS_ON;
40 	else if( (tmp & R128_CRTC_VSYNC_DIS) == 0 )
41 		mode = B_DPMS_STAND_BY;
42 	else if( (tmp & R128_CRTC_HSYNC_DIS) == 0 )
43 		mode = B_DPMS_SUSPEND;
44 	else
45 		mode = B_DPMS_OFF;
46 
47 	TRACE("Rage128_DPMSMode() mode: %d\n", mode);
48 	return mode;
49 }
50 
51 
52 status_t
53 Rage128_SetDPMSMode(uint32 dpmsMode)
54 {
55 	// Set the display into one of the Display Power Management modes,
56 	// and return B_OK if successful, else return B_ERROR.
57 
58 	SharedInfo& si = *gInfo.sharedInfo;
59 
60 	TRACE("Rage128_SetDPMSMode() mode: %d, display type: %d\n", dpmsMode, si.displayType);
61 
62 	int mask = (R128_CRTC_DISPLAY_DIS
63 				| R128_CRTC_HSYNC_DIS
64 				| R128_CRTC_VSYNC_DIS);
65 
66 	switch (dpmsMode) {
67 		case B_DPMS_ON:
68 			// Screen: On; HSync: On, VSync: On.
69 			OUTREGM(R128_CRTC_EXT_CNTL, 0, mask);
70 			break;
71 
72 		case B_DPMS_STAND_BY:
73 			// Screen: Off; HSync: Off, VSync: On.
74 			OUTREGM(R128_CRTC_EXT_CNTL,
75 				R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, mask);
76 			break;
77 
78 		case B_DPMS_SUSPEND:
79 			// Screen: Off; HSync: On, VSync: Off.
80 			OUTREGM(R128_CRTC_EXT_CNTL,
81 				R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, mask);
82 			break;
83 
84 		case B_DPMS_OFF:
85 			// Screen: Off; HSync: Off, VSync: Off.
86 			OUTREGM(R128_CRTC_EXT_CNTL, mask, mask);
87 			break;
88 
89 		default:
90 			TRACE("Invalid DPMS mode %d\n", dpmsMode);
91 			return B_ERROR;
92 	}
93 
94 	if (si.displayType == MT_LAPTOP) {
95 		uint32 genCtrl;
96 
97 		switch (dpmsMode) {
98 			case B_DPMS_ON:
99 				genCtrl = INREG(R128_LVDS_GEN_CNTL);
100 				genCtrl |= R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON | R128_LVDS_DIGON;
101 				genCtrl &= ~R128_LVDS_DISPLAY_DIS;
102 				OUTREG(R128_LVDS_GEN_CNTL, genCtrl);
103 				break;
104 
105 			case B_DPMS_STAND_BY:
106 			case B_DPMS_SUSPEND:
107 			case B_DPMS_OFF:
108 				genCtrl = INREG(R128_LVDS_GEN_CNTL);
109 				genCtrl |= R128_LVDS_DISPLAY_DIS;
110 				OUTREG(R128_LVDS_GEN_CNTL, genCtrl);
111 				snooze(10);
112 				genCtrl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON | R128_LVDS_DIGON);
113 				OUTREG(R128_LVDS_GEN_CNTL, genCtrl);
114 				break;
115 
116 			default:
117 				TRACE("Invalid DPMS mode %d\n", dpmsMode);
118 				return B_ERROR;
119 		}
120 	}
121 
122 	if (gInfo.sharedInfo->displayType == MT_DVI) {
123 		switch (dpmsMode) {
124 			case B_DPMS_ON:
125 				OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL)
126 					| (R128_FP_FPON | R128_FP_TDMS_EN));
127 				break;
128 
129 			case B_DPMS_STAND_BY:
130 			case B_DPMS_SUSPEND:
131 			case B_DPMS_OFF:
132 				OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL)
133 					& ~(R128_FP_FPON | R128_FP_TDMS_EN));
134 				break;
135 
136 			default:
137 				TRACE("Invalid DPMS mode %d\n", dpmsMode);
138 				return B_ERROR;
139 		}
140 	}
141 
142 	return B_OK;
143 }
144 
145