1 /*
2  * Copyright (c) 1999-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 VidMode functions required by the extension.
30  * These have been added to avoid the need for the higher level extension
31  * code to access the private XFree86 data structures directly. Wherever
32  * possible this code uses the functions in xf86Mode.c to do the work,
33  * so that two version of code that do similar things don't have to be
34  * maintained.
35  */
36 
37 #ifdef HAVE_XORG_CONFIG_H
38 #include <xorg-config.h>
39 #endif
40 
41 #include <X11/X.h>
42 #include "os.h"
43 #include "xf86.h"
44 #include "xf86Priv.h"
45 #include "extinit.h"
46 
47 #ifdef XF86VIDMODE
48 #include "vidmodestr.h"
49 #include "xf86Privstr.h"
50 #include "xf86Extensions.h"
51 #include "xf86cmap.h"
52 
53 static vidMonitorValue
xf86VidModeGetMonitorValue(ScreenPtr pScreen,int valtyp,int indx)54 xf86VidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
55 {
56     vidMonitorValue ret = { NULL, };
57     MonPtr monitor;
58     ScrnInfoPtr pScrn;
59 
60     pScrn = xf86ScreenToScrn(pScreen);
61     monitor = pScrn->monitor;
62 
63     switch (valtyp) {
64     case VIDMODE_MON_VENDOR:
65         ret.ptr = monitor->vendor;
66         break;
67     case VIDMODE_MON_MODEL:
68         ret.ptr = monitor->model;
69         break;
70     case VIDMODE_MON_NHSYNC:
71         ret.i = monitor->nHsync;
72         break;
73     case VIDMODE_MON_NVREFRESH:
74         ret.i = monitor->nVrefresh;
75         break;
76     case VIDMODE_MON_HSYNC_LO:
77         ret.f = (100.0 * monitor->hsync[indx].lo);
78         break;
79     case VIDMODE_MON_HSYNC_HI:
80         ret.f = (100.0 * monitor->hsync[indx].hi);
81         break;
82     case VIDMODE_MON_VREFRESH_LO:
83         ret.f = (100.0 * monitor->vrefresh[indx].lo);
84         break;
85     case VIDMODE_MON_VREFRESH_HI:
86         ret.f = (100.0 * monitor->vrefresh[indx].hi);
87         break;
88     }
89     return ret;
90 }
91 
92 static Bool
xf86VidModeGetCurrentModeline(ScreenPtr pScreen,DisplayModePtr * mode,int * dotClock)93 xf86VidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
94 {
95     ScrnInfoPtr pScrn;
96 
97     pScrn = xf86ScreenToScrn(pScreen);
98 
99     if (pScrn->currentMode) {
100         *mode = pScrn->currentMode;
101         *dotClock = pScrn->currentMode->Clock;
102 
103         return TRUE;
104     }
105     return FALSE;
106 }
107 
108 static int
xf86VidModeGetDotClock(ScreenPtr pScreen,int Clock)109 xf86VidModeGetDotClock(ScreenPtr pScreen, int Clock)
110 {
111     ScrnInfoPtr pScrn;
112 
113     pScrn = xf86ScreenToScrn(pScreen);
114     if ((pScrn->progClock) || (Clock >= MAXCLOCKS))
115         return Clock;
116     else
117         return pScrn->clock[Clock];
118 }
119 
120 static int
xf86VidModeGetNumOfClocks(ScreenPtr pScreen,Bool * progClock)121 xf86VidModeGetNumOfClocks(ScreenPtr pScreen, Bool *progClock)
122 {
123     ScrnInfoPtr pScrn;
124 
125     pScrn = xf86ScreenToScrn(pScreen);
126     if (pScrn->progClock) {
127         *progClock = TRUE;
128         return 0;
129     }
130     else {
131         *progClock = FALSE;
132         return pScrn->numClocks;
133     }
134 }
135 
136 static Bool
xf86VidModeGetClocks(ScreenPtr pScreen,int * Clocks)137 xf86VidModeGetClocks(ScreenPtr pScreen, int *Clocks)
138 {
139     ScrnInfoPtr pScrn;
140     int i;
141 
142     pScrn = xf86ScreenToScrn(pScreen);
143 
144     if (pScrn->progClock)
145         return FALSE;
146 
147     for (i = 0; i < pScrn->numClocks; i++)
148         *Clocks++ = pScrn->clock[i];
149 
150     return TRUE;
151 }
152 
153 static Bool
xf86VidModeGetNextModeline(ScreenPtr pScreen,DisplayModePtr * mode,int * dotClock)154 xf86VidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
155 {
156     VidModePtr pVidMode;
157     DisplayModePtr p;
158 
159     pVidMode = VidModeGetPtr(pScreen);
160 
161     for (p = pVidMode->Next; p != NULL && p != pVidMode->First; p = p->next) {
162         if (p->status == MODE_OK) {
163             pVidMode->Next = p->next;
164             *mode = p;
165             *dotClock = xf86VidModeGetDotClock(pScreen, p->Clock);
166             return TRUE;
167         }
168     }
169 
170     return FALSE;
171 }
172 
173 static Bool
xf86VidModeGetFirstModeline(ScreenPtr pScreen,DisplayModePtr * mode,int * dotClock)174 xf86VidModeGetFirstModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
175 {
176     ScrnInfoPtr pScrn;
177     VidModePtr pVidMode;
178 
179     pScrn = xf86ScreenToScrn(pScreen);
180     if (pScrn->modes == NULL)
181         return FALSE;
182 
183     pVidMode = VidModeGetPtr(pScreen);
184     pVidMode->First = pScrn->modes;
185     pVidMode->Next = pVidMode->First->next;
186 
187     if (pVidMode->First->status == MODE_OK) {
188         *mode = pVidMode->First;
189         *dotClock = xf86VidModeGetDotClock(pScreen, pVidMode->First->Clock);
190         return TRUE;
191     }
192 
193     return xf86VidModeGetNextModeline(pScreen, mode, dotClock);
194 }
195 
196 static Bool
xf86VidModeDeleteModeline(ScreenPtr pScreen,DisplayModePtr mode)197 xf86VidModeDeleteModeline(ScreenPtr pScreen, DisplayModePtr mode)
198 {
199     ScrnInfoPtr pScrn;
200 
201     if (mode == NULL)
202         return FALSE;
203 
204     pScrn = xf86ScreenToScrn(pScreen);
205     xf86DeleteMode(&(pScrn->modes), mode);
206     return TRUE;
207 }
208 
209 static Bool
xf86VidModeZoomViewport(ScreenPtr pScreen,int zoom)210 xf86VidModeZoomViewport(ScreenPtr pScreen, int zoom)
211 {
212     xf86ZoomViewport(pScreen, zoom);
213     return TRUE;
214 }
215 
216 static Bool
xf86VidModeSetViewPort(ScreenPtr pScreen,int x,int y)217 xf86VidModeSetViewPort(ScreenPtr pScreen, int x, int y)
218 {
219     ScrnInfoPtr pScrn;
220 
221     pScrn = xf86ScreenToScrn(pScreen);
222     pScrn->frameX0 = min(max(x, 0),
223                          pScrn->virtualX - pScrn->currentMode->HDisplay);
224     pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
225     pScrn->frameY0 = min(max(y, 0),
226                          pScrn->virtualY - pScrn->currentMode->VDisplay);
227     pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
228     if (pScrn->AdjustFrame != NULL)
229         (pScrn->AdjustFrame) (pScrn, pScrn->frameX0, pScrn->frameY0);
230 
231     return TRUE;
232 }
233 
234 static Bool
xf86VidModeGetViewPort(ScreenPtr pScreen,int * x,int * y)235 xf86VidModeGetViewPort(ScreenPtr pScreen, int *x, int *y)
236 {
237     ScrnInfoPtr pScrn;
238 
239     pScrn = xf86ScreenToScrn(pScreen);
240     *x = pScrn->frameX0;
241     *y = pScrn->frameY0;
242     return TRUE;
243 }
244 
245 static Bool
xf86VidModeSwitchMode(ScreenPtr pScreen,DisplayModePtr mode)246 xf86VidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
247 {
248     ScrnInfoPtr pScrn;
249     DisplayModePtr pTmpMode;
250     Bool retval;
251 
252     pScrn = xf86ScreenToScrn(pScreen);
253     /* save in case we fail */
254     pTmpMode = pScrn->currentMode;
255     /* Force a mode switch */
256     pScrn->currentMode = NULL;
257     retval = xf86SwitchMode(pScrn->pScreen, mode);
258     /* we failed: restore it */
259     if (retval == FALSE)
260         pScrn->currentMode = pTmpMode;
261     return retval;
262 }
263 
264 static Bool
xf86VidModeLockZoom(ScreenPtr pScreen,Bool lock)265 xf86VidModeLockZoom(ScreenPtr pScreen, Bool lock)
266 {
267     if (xf86Info.dontZoom)
268         return FALSE;
269 
270     xf86LockZoom(pScreen, lock);
271     return TRUE;
272 }
273 
274 static ModeStatus
xf86VidModeCheckModeForMonitor(ScreenPtr pScreen,DisplayModePtr mode)275 xf86VidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode)
276 {
277     ScrnInfoPtr pScrn;
278 
279     if (mode == NULL)
280         return MODE_ERROR;
281 
282     pScrn = xf86ScreenToScrn(pScreen);
283 
284     return xf86CheckModeForMonitor(mode, pScrn->monitor);
285 }
286 
287 static ModeStatus
xf86VidModeCheckModeForDriver(ScreenPtr pScreen,DisplayModePtr mode)288 xf86VidModeCheckModeForDriver(ScreenPtr pScreen, DisplayModePtr mode)
289 {
290     ScrnInfoPtr pScrn;
291 
292     if (mode == NULL)
293         return MODE_ERROR;
294 
295     pScrn = xf86ScreenToScrn(pScreen);
296 
297     return xf86CheckModeForDriver(pScrn, mode, 0);
298 }
299 
300 static void
xf86VidModeSetCrtcForMode(ScreenPtr pScreen,DisplayModePtr mode)301 xf86VidModeSetCrtcForMode(ScreenPtr pScreen, DisplayModePtr mode)
302 {
303     ScrnInfoPtr pScrn;
304     DisplayModePtr ScreenModes;
305 
306     if (mode == NULL)
307         return;
308 
309     /* Ugly hack so that the xf86Mode.c function can be used without change */
310     pScrn = xf86ScreenToScrn(pScreen);
311     ScreenModes = pScrn->modes;
312     pScrn->modes = mode;
313 
314     xf86SetCrtcForModes(pScrn, pScrn->adjustFlags);
315     pScrn->modes = ScreenModes;
316     return;
317 }
318 
319 static Bool
xf86VidModeAddModeline(ScreenPtr pScreen,DisplayModePtr mode)320 xf86VidModeAddModeline(ScreenPtr pScreen, DisplayModePtr mode)
321 {
322     ScrnInfoPtr pScrn;
323 
324     if (mode == NULL)
325         return FALSE;
326 
327     pScrn = xf86ScreenToScrn(pScreen);
328 
329     mode->name = strdup(""); /* freed by deletemode */
330     mode->status = MODE_OK;
331     mode->next = pScrn->modes->next;
332     mode->prev = pScrn->modes;
333     pScrn->modes->next = mode;
334     if (mode->next != NULL)
335         mode->next->prev = mode;
336 
337     return TRUE;
338 }
339 
340 static int
xf86VidModeGetNumOfModes(ScreenPtr pScreen)341 xf86VidModeGetNumOfModes(ScreenPtr pScreen)
342 {
343     DisplayModePtr mode = NULL;
344     int dotClock = 0, nummodes = 0;
345 
346     if (!xf86VidModeGetFirstModeline(pScreen, &mode, &dotClock))
347         return nummodes;
348 
349     do {
350         nummodes++;
351         if (!xf86VidModeGetNextModeline(pScreen, &mode, &dotClock))
352             return nummodes;
353     } while (TRUE);
354 }
355 
356 static Bool
xf86VidModeSetGamma(ScreenPtr pScreen,float red,float green,float blue)357 xf86VidModeSetGamma(ScreenPtr pScreen, float red, float green, float blue)
358 {
359     Gamma gamma;
360 
361     gamma.red = red;
362     gamma.green = green;
363     gamma.blue = blue;
364     if (xf86ChangeGamma(pScreen, gamma) != Success)
365         return FALSE;
366     else
367         return TRUE;
368 }
369 
370 static Bool
xf86VidModeGetGamma(ScreenPtr pScreen,float * red,float * green,float * blue)371 xf86VidModeGetGamma(ScreenPtr pScreen, float *red, float *green, float *blue)
372 {
373     ScrnInfoPtr pScrn;
374 
375     pScrn = xf86ScreenToScrn(pScreen);
376     *red = pScrn->gamma.red;
377     *green = pScrn->gamma.green;
378     *blue = pScrn->gamma.blue;
379     return TRUE;
380 }
381 
382 static Bool
xf86VidModeSetGammaRamp(ScreenPtr pScreen,int size,CARD16 * r,CARD16 * g,CARD16 * b)383 xf86VidModeSetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b)
384 {
385     xf86ChangeGammaRamp(pScreen, size, r, g, b);
386     return TRUE;
387 }
388 
389 static Bool
xf86VidModeGetGammaRamp(ScreenPtr pScreen,int size,CARD16 * r,CARD16 * g,CARD16 * b)390 xf86VidModeGetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b)
391 {
392     xf86GetGammaRamp(pScreen, size, r, g, b);
393     return TRUE;
394 }
395 
396 static Bool
xf86VidModeInit(ScreenPtr pScreen)397 xf86VidModeInit(ScreenPtr pScreen)
398 {
399     VidModePtr pVidMode;
400 
401     if (!xf86GetVidModeEnabled()) {
402         DebugF("!xf86GetVidModeEnabled()\n");
403         return FALSE;
404     }
405 
406     pVidMode = VidModeInit(pScreen);
407     if (!pVidMode)
408         return FALSE;
409 
410     pVidMode->Flags = 0;
411     pVidMode->Next = NULL;
412 
413     pVidMode->GetMonitorValue = xf86VidModeGetMonitorValue;
414     pVidMode->GetCurrentModeline = xf86VidModeGetCurrentModeline;
415     pVidMode->GetFirstModeline = xf86VidModeGetFirstModeline;
416     pVidMode->GetNextModeline = xf86VidModeGetNextModeline;
417     pVidMode->DeleteModeline = xf86VidModeDeleteModeline;
418     pVidMode->ZoomViewport = xf86VidModeZoomViewport;
419     pVidMode->GetViewPort = xf86VidModeGetViewPort;
420     pVidMode->SetViewPort = xf86VidModeSetViewPort;
421     pVidMode->SwitchMode = xf86VidModeSwitchMode;
422     pVidMode->LockZoom = xf86VidModeLockZoom;
423     pVidMode->GetNumOfClocks = xf86VidModeGetNumOfClocks;
424     pVidMode->GetClocks = xf86VidModeGetClocks;
425     pVidMode->CheckModeForMonitor = xf86VidModeCheckModeForMonitor;
426     pVidMode->CheckModeForDriver = xf86VidModeCheckModeForDriver;
427     pVidMode->SetCrtcForMode = xf86VidModeSetCrtcForMode;
428     pVidMode->AddModeline = xf86VidModeAddModeline;
429     pVidMode->GetDotClock = xf86VidModeGetDotClock;
430     pVidMode->GetNumOfModes = xf86VidModeGetNumOfModes;
431     pVidMode->SetGamma = xf86VidModeSetGamma;
432     pVidMode->GetGamma = xf86VidModeGetGamma;
433     pVidMode->SetGammaRamp = xf86VidModeSetGammaRamp;
434     pVidMode->GetGammaRamp = xf86VidModeGetGammaRamp;
435     pVidMode->GetGammaRampSize = xf86GetGammaRampSize; /* use xf86cmap API directly */
436 
437     return TRUE;
438 }
439 
440 void
XFree86VidModeExtensionInit(void)441 XFree86VidModeExtensionInit(void)
442 {
443     int i;
444     Bool enabled = FALSE;
445 
446     DebugF("XFree86VidModeExtensionInit");
447 
448     /* This means that the DDX doesn't want the vidmode extension enabled */
449     if (!xf86GetVidModeEnabled())
450         return;
451 
452     for (i = 0; i < screenInfo.numScreens; i++) {
453         if (xf86VidModeInit (screenInfo.screens[i]))
454             enabled = TRUE;
455     }
456     /* This means that the DDX doesn't want the vidmode extension enabled */
457     if (!enabled)
458         return;
459 
460    VidModeAddExtension(xf86GetVidModeAllowNonLocal());
461 }
462 
463 #endif                          /* XF86VIDMODE */
464