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
21uint32
22Rage128_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
30uint32
31Rage128_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
52status_t
53Rage128_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