1/*
2 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * This file contains the DPMS functions required by the extension.
30 */
31
32#ifdef HAVE_XORG_CONFIG_H
33#include <xorg-config.h>
34#endif
35
36#include <X11/X.h>
37#include "os.h"
38#include "globals.h"
39#include "xf86.h"
40#include "xf86Priv.h"
41#ifdef DPMSExtension
42#include <X11/extensions/dpmsconst.h>
43#include "dpmsproc.h"
44#endif
45#include "xf86VGAarbiter.h"
46
47
48#ifdef DPMSExtension
49static DevPrivateKeyRec DPMSKeyRec;
50static DevPrivateKey DPMSKey;
51static Bool DPMSClose(int i, ScreenPtr pScreen);
52static int DPMSCount = 0;
53#endif
54
55
56Bool
57xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags)
58{
59#ifdef DPMSExtension
60    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
61    DPMSPtr pDPMS;
62    pointer DPMSOpt;
63    MessageType enabled_from;
64
65    DPMSKey = &DPMSKeyRec;
66
67    if (!dixRegisterPrivateKey(&DPMSKeyRec, PRIVATE_SCREEN, sizeof (DPMSRec)))
68	return FALSE;
69
70    pDPMS = dixLookupPrivate(&pScreen->devPrivates, DPMSKey);
71    pScrn->DPMSSet = set;
72    pDPMS->Flags = flags;
73    DPMSOpt = xf86FindOption(pScrn->options, "dpms");
74    if (DPMSDisabledSwitch) {
75	enabled_from = X_CMDLINE;
76	DPMSEnabled = FALSE;
77    }
78    else if (DPMSOpt) {
79	enabled_from = X_CONFIG;
80	DPMSEnabled = xf86CheckBoolOption(pScrn->options, "dpms", FALSE);
81	xf86MarkOptionUsed(DPMSOpt);
82    }
83    else {
84	enabled_from = X_DEFAULT;
85	DPMSEnabled = TRUE;
86    }
87    if (DPMSEnabled)
88	xf86DrvMsg(pScreen->myNum, enabled_from, "DPMS enabled\n");
89    pDPMS->Enabled = DPMSEnabled;
90    pDPMS->CloseScreen = pScreen->CloseScreen;
91    pScreen->CloseScreen = DPMSClose;
92    DPMSCount++;
93    return TRUE;
94#else
95    return FALSE;
96#endif
97}
98
99
100#ifdef DPMSExtension
101
102static Bool
103DPMSClose(int i, ScreenPtr pScreen)
104{
105    DPMSPtr pDPMS;
106
107    /* This shouldn't happen */
108    if (DPMSKey == NULL)
109	return FALSE;
110
111    pDPMS = dixLookupPrivate(&pScreen->devPrivates, DPMSKey);
112
113    /* This shouldn't happen */
114    if (!pDPMS)
115	return FALSE;
116
117    pScreen->CloseScreen = pDPMS->CloseScreen;
118
119    /*
120     * Turn on DPMS when shutting down. If this function can be used
121     * depends on the order the driver wraps things. If this is called
122     * after the driver has shut down everything the driver will have
123     * to deal with this internally.
124     */
125    if (xf86Screens[i]->vtSema && xf86Screens[i]->DPMSSet) {
126 	xf86Screens[i]->DPMSSet(xf86Screens[i],DPMSModeOn,0);
127    }
128
129    if (--DPMSCount == 0)
130	DPMSKey = NULL;
131    return pScreen->CloseScreen(i, pScreen);
132}
133
134
135/*
136 * DPMSSet --
137 *	Device dependent DPMS mode setting hook.  This is called whenever
138 *	the DPMS mode is to be changed.
139 */
140int
141DPMSSet(ClientPtr client, int level)
142{
143    int rc, i;
144    DPMSPtr pDPMS;
145    ScrnInfoPtr pScrn;
146
147    DPMSPowerLevel = level;
148
149    if (DPMSKey == NULL)
150	return Success;
151
152    if (level != DPMSModeOn) {
153	rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive);
154	if (rc != Success)
155	    return rc;
156    }
157
158    /* For each screen, set the DPMS level */
159    for (i = 0; i < xf86NumScreens; i++) {
160    	pScrn = xf86Screens[i];
161	pDPMS = dixLookupPrivate(&screenInfo.screens[i]->devPrivates, DPMSKey);
162	if (pDPMS && pScrn->DPMSSet && pDPMS->Enabled && pScrn->vtSema) {
163	    xf86VGAarbiterLock(pScrn);
164	    pScrn->DPMSSet(pScrn, level, 0);
165	    xf86VGAarbiterUnlock(pScrn);
166	}
167    }
168    return Success;
169}
170
171
172/*
173 * DPMSSupported --
174 *	Return TRUE if any screen supports DPMS.
175 */
176Bool
177DPMSSupported(void)
178{
179    int i;
180    DPMSPtr pDPMS;
181    ScrnInfoPtr pScrn;
182
183    if (DPMSKey == NULL) {
184	return FALSE;
185    }
186
187    /* For each screen, check if DPMS is supported */
188    for (i = 0; i < xf86NumScreens; i++) {
189    	pScrn = xf86Screens[i];
190	pDPMS = dixLookupPrivate(&screenInfo.screens[i]->devPrivates, DPMSKey);
191	if (pDPMS && pScrn->DPMSSet)
192	    return TRUE;
193    }
194    return FALSE;
195}
196
197#endif /* DPMSExtension */
198