Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / common / xf86VidMode.c
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
46 #ifdef XF86VIDMODE
47 #include "vidmodeproc.h"
48 #include "xf86cmap.h"
49
50 static DevPrivateKeyRec VidModeKeyRec;
51 static DevPrivateKey VidModeKey;
52 static int VidModeCount = 0;
53 static Bool VidModeClose(ScreenPtr pScreen);
54
55 #define VMPTR(p) ((VidModePtr)dixLookupPrivate(&(p)->devPrivates, VidModeKey))
56
57 #endif
58
59 Bool
60 VidModeExtensionInit(ScreenPtr pScreen)
61 {
62 #ifdef XF86VIDMODE
63 VidModePtr pVidMode;
64
65 if (!xf86GetVidModeEnabled()) {
66 DebugF("!xf86GetVidModeEnabled()\n");
67 return FALSE;
68 }
69
70 VidModeKey = &VidModeKeyRec;
71
72 if (!dixRegisterPrivateKey(&VidModeKeyRec, PRIVATE_SCREEN, 0))
73 return FALSE;
74
75 pVidMode = calloc(sizeof(VidModeRec), 1);
76 if (!pVidMode)
77 return FALSE;
78
79 dixSetPrivate(&pScreen->devPrivates, VidModeKey, pVidMode);
80
81 pVidMode->Flags = 0;
82 pVidMode->Next = NULL;
83 pVidMode->CloseScreen = pScreen->CloseScreen;
84 pScreen->CloseScreen = VidModeClose;
85 VidModeCount++;
86 return TRUE;
87 #else
88 DebugF("no vidmode extension\n");
89 return FALSE;
90 #endif
91 }
92
93 #ifdef XF86VIDMODE
94
95 static Bool
96 VidModeClose(ScreenPtr pScreen)
97 {
98 VidModePtr pVidMode = VMPTR(pScreen);
99
100 /* This shouldn't happen */
101 if (!pVidMode)
102 return FALSE;
103
104 pScreen->CloseScreen = pVidMode->CloseScreen;
105
106 if (--VidModeCount == 0) {
107 free(dixLookupPrivate(&pScreen->devPrivates, VidModeKey));
108 dixSetPrivate(&pScreen->devPrivates, VidModeKey, NULL);
109 VidModeKey = NULL;
110 }
111 return pScreen->CloseScreen(pScreen);
112 }
113
114 Bool
115 VidModeAvailable(int scrnIndex)
116 {
117 ScrnInfoPtr pScrn;
118 VidModePtr pVidMode;
119
120 if (VidModeKey == NULL) {
121 DebugF("VidModeKey == NULL\n");
122 return FALSE;
123 }
124
125 pScrn = xf86Screens[scrnIndex];
126 if (pScrn == NULL) {
127 DebugF("pScrn == NULL\n");
128 return FALSE;
129 }
130
131 pVidMode = VMPTR(pScrn->pScreen);
132 if (pVidMode)
133 return TRUE;
134 else {
135 DebugF("pVidMode == NULL\n");
136 return FALSE;
137 }
138 }
139
140 Bool
141 VidModeGetCurrentModeline(int scrnIndex, pointer *mode, int *dotClock)
142 {
143 ScrnInfoPtr pScrn;
144
145 if (!VidModeAvailable(scrnIndex))
146 return FALSE;
147
148 pScrn = xf86Screens[scrnIndex];
149
150 if (pScrn->currentMode) {
151 *mode = (pointer) (pScrn->currentMode);
152 *dotClock = pScrn->currentMode->Clock;
153
154 return TRUE;
155 }
156 return FALSE;
157 }
158
159 int
160 VidModeGetDotClock(int scrnIndex, int Clock)
161 {
162 ScrnInfoPtr pScrn;
163
164 if (!VidModeAvailable(scrnIndex))
165 return 0;
166
167 pScrn = xf86Screens[scrnIndex];
168 if ((pScrn->progClock) || (Clock >= MAXCLOCKS))
169 return Clock;
170 else
171 return pScrn->clock[Clock];
172 }
173
174 int
175 VidModeGetNumOfClocks(int scrnIndex, Bool *progClock)
176 {
177 ScrnInfoPtr pScrn;
178
179 if (!VidModeAvailable(scrnIndex))
180 return 0;
181
182 pScrn = xf86Screens[scrnIndex];
183 if (pScrn->progClock) {
184 *progClock = TRUE;
185 return 0;
186 }
187 else {
188 *progClock = FALSE;
189 return pScrn->numClocks;
190 }
191 }
192
193 Bool
194 VidModeGetClocks(int scrnIndex, int *Clocks)
195 {
196 ScrnInfoPtr pScrn;
197 int i;
198
199 if (!VidModeAvailable(scrnIndex))
200 return FALSE;
201
202 pScrn = xf86Screens[scrnIndex];
203
204 if (pScrn->progClock)
205 return FALSE;
206
207 for (i = 0; i < pScrn->numClocks; i++)
208 *Clocks++ = pScrn->clock[i];
209
210 return TRUE;
211 }
212
213 Bool
214 VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock)
215 {
216 ScrnInfoPtr pScrn;
217 VidModePtr pVidMode;
218
219 if (!VidModeAvailable(scrnIndex))
220 return FALSE;
221
222 pScrn = xf86Screens[scrnIndex];
223 if (pScrn->modes == NULL)
224 return FALSE;
225
226 pVidMode = VMPTR(pScrn->pScreen);
227 pVidMode->First = pScrn->modes;
228 pVidMode->Next = pVidMode->First->next;
229
230 if (pVidMode->First->status == MODE_OK) {
231 *mode = (pointer) (pVidMode->First);
232 *dotClock = VidModeGetDotClock(scrnIndex, pVidMode->First->Clock);
233 return TRUE;
234 }
235
236 return VidModeGetNextModeline(scrnIndex, mode, dotClock);
237 }
238
239 Bool
240 VidModeGetNextModeline(int scrnIndex, pointer *mode, int *dotClock)
241 {
242 ScrnInfoPtr pScrn;
243 VidModePtr pVidMode;
244 DisplayModePtr p;
245
246 if (!VidModeAvailable(scrnIndex))
247 return FALSE;
248
249 pScrn = xf86Screens[scrnIndex];
250 pVidMode = VMPTR(pScrn->pScreen);
251
252 for (p = pVidMode->Next; p != NULL && p != pVidMode->First; p = p->next) {
253 if (p->status == MODE_OK) {
254 pVidMode->Next = p->next;
255 *mode = (pointer) p;
256 *dotClock = VidModeGetDotClock(scrnIndex, p->Clock);
257 return TRUE;
258 }
259 }
260
261 return FALSE;
262 }
263
264 Bool
265 VidModeDeleteModeline(int scrnIndex, pointer mode)
266 {
267 ScrnInfoPtr pScrn;
268
269 if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
270 return FALSE;
271
272 pScrn = xf86Screens[scrnIndex];
273 xf86DeleteMode(&(pScrn->modes), (DisplayModePtr) mode);
274 return TRUE;
275 }
276
277 Bool
278 VidModeZoomViewport(int scrnIndex, int zoom)
279 {
280 ScrnInfoPtr pScrn;
281
282 if (!VidModeAvailable(scrnIndex))
283 return FALSE;
284
285 pScrn = xf86Screens[scrnIndex];
286 xf86ZoomViewport(pScrn->pScreen, zoom);
287 return TRUE;
288 }
289
290 Bool
291 VidModeSetViewPort(int scrnIndex, int x, int y)
292 {
293 ScrnInfoPtr pScrn;
294
295 if (!VidModeAvailable(scrnIndex))
296 return FALSE;
297
298 pScrn = xf86Screens[scrnIndex];
299 pScrn->frameX0 = min(max(x, 0),
300 pScrn->virtualX - pScrn->currentMode->HDisplay);
301 pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
302 pScrn->frameY0 = min(max(y, 0),
303 pScrn->virtualY - pScrn->currentMode->VDisplay);
304 pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
305 if (pScrn->AdjustFrame != NULL)
306 (pScrn->AdjustFrame) (pScrn, pScrn->frameX0, pScrn->frameY0);
307
308 return TRUE;
309 }
310
311 Bool
312 VidModeGetViewPort(int scrnIndex, int *x, int *y)
313 {
314 ScrnInfoPtr pScrn;
315
316 if (!VidModeAvailable(scrnIndex))
317 return FALSE;
318
319 pScrn = xf86Screens[scrnIndex];
320 *x = pScrn->frameX0;
321 *y = pScrn->frameY0;
322 return TRUE;
323 }
324
325 Bool
326 VidModeSwitchMode(int scrnIndex, pointer mode)
327 {
328 ScrnInfoPtr pScrn;
329 DisplayModePtr pTmpMode;
330 Bool retval;
331
332 if (!VidModeAvailable(scrnIndex))
333 return FALSE;
334
335 pScrn = xf86Screens[scrnIndex];
336 /* save in case we fail */
337 pTmpMode = pScrn->currentMode;
338 /* Force a mode switch */
339 pScrn->currentMode = NULL;
340 retval = xf86SwitchMode(pScrn->pScreen, mode);
341 /* we failed: restore it */
342 if (retval == FALSE)
343 pScrn->currentMode = pTmpMode;
344 return retval;
345 }
346
347 Bool
348 VidModeLockZoom(int scrnIndex, Bool lock)
349 {
350 ScrnInfoPtr pScrn;
351
352 if (!VidModeAvailable(scrnIndex))
353 return FALSE;
354
355 pScrn = xf86Screens[scrnIndex];
356
357 if (xf86Info.dontZoom)
358 return FALSE;
359
360 xf86LockZoom(pScrn->pScreen, lock);
361 return TRUE;
362 }
363
364 Bool
365 VidModeGetMonitor(int scrnIndex, pointer *monitor)
366 {
367 ScrnInfoPtr pScrn;
368
369 if (!VidModeAvailable(scrnIndex))
370 return FALSE;
371
372 pScrn = xf86Screens[scrnIndex];
373 *monitor = (pointer) (pScrn->monitor);
374
375 return TRUE;
376 }
377
378 ModeStatus
379 VidModeCheckModeForMonitor(int scrnIndex, pointer mode)
380 {
381 ScrnInfoPtr pScrn;
382
383 if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
384 return MODE_ERROR;
385
386 pScrn = xf86Screens[scrnIndex];
387
388 return xf86CheckModeForMonitor((DisplayModePtr) mode, pScrn->monitor);
389 }
390
391 ModeStatus
392 VidModeCheckModeForDriver(int scrnIndex, pointer mode)
393 {
394 ScrnInfoPtr pScrn;
395
396 if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
397 return MODE_ERROR;
398
399 pScrn = xf86Screens[scrnIndex];
400
401 return xf86CheckModeForDriver(pScrn, (DisplayModePtr) mode, 0);
402 }
403
404 void
405 VidModeSetCrtcForMode(int scrnIndex, pointer mode)
406 {
407 ScrnInfoPtr pScrn;
408 DisplayModePtr ScreenModes;
409
410 if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
411 return;
412
413 /* Ugly hack so that the xf86Mode.c function can be used without change */
414 pScrn = xf86Screens[scrnIndex];
415 ScreenModes = pScrn->modes;
416 pScrn->modes = (DisplayModePtr) mode;
417
418 xf86SetCrtcForModes(pScrn, pScrn->adjustFlags);
419 pScrn->modes = ScreenModes;
420 return;
421 }
422
423 Bool
424 VidModeAddModeline(int scrnIndex, pointer mode)
425 {
426 ScrnInfoPtr pScrn;
427
428 if ((mode == NULL) || (!VidModeAvailable(scrnIndex)))
429 return FALSE;
430
431 pScrn = xf86Screens[scrnIndex];
432
433 ((DisplayModePtr) mode)->name = strdup(""); /* freed by deletemode */
434 ((DisplayModePtr) mode)->status = MODE_OK;
435 ((DisplayModePtr) mode)->next = pScrn->modes->next;
436 ((DisplayModePtr) mode)->prev = pScrn->modes;
437 pScrn->modes->next = (DisplayModePtr) mode;
438 if (((DisplayModePtr) mode)->next != NULL)
439 ((DisplayModePtr) mode)->next->prev = (DisplayModePtr) mode;
440
441 return TRUE;
442 }
443
444 int
445 VidModeGetNumOfModes(int scrnIndex)
446 {
447 pointer mode = NULL;
448 int dotClock = 0, nummodes = 0;
449
450 if (!VidModeGetFirstModeline(scrnIndex, &mode, &dotClock))
451 return nummodes;
452
453 do {
454 nummodes++;
455 if (!VidModeGetNextModeline(scrnIndex, &mode, &dotClock))
456 return nummodes;
457 } while (TRUE);
458 }
459
460 Bool
461 VidModeSetGamma(int scrnIndex, float red, float green, float blue)
462 {
463 ScrnInfoPtr pScrn;
464 Gamma gamma;
465
466 if (!VidModeAvailable(scrnIndex))
467 return FALSE;
468
469 pScrn = xf86Screens[scrnIndex];
470 gamma.red = red;
471 gamma.green = green;
472 gamma.blue = blue;
473 if (xf86ChangeGamma(pScrn->pScreen, gamma) != Success)
474 return FALSE;
475 else
476 return TRUE;
477 }
478
479 Bool
480 VidModeGetGamma(int scrnIndex, float *red, float *green, float *blue)
481 {
482 ScrnInfoPtr pScrn;
483
484 if (!VidModeAvailable(scrnIndex))
485 return FALSE;
486
487 pScrn = xf86Screens[scrnIndex];
488 *red = pScrn->gamma.red;
489 *green = pScrn->gamma.green;
490 *blue = pScrn->gamma.blue;
491 return TRUE;
492 }
493
494 Bool
495 VidModeSetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b)
496 {
497 ScrnInfoPtr pScrn;
498
499 if (!VidModeAvailable(scrnIndex))
500 return FALSE;
501
502 pScrn = xf86Screens[scrnIndex];
503 xf86ChangeGammaRamp(pScrn->pScreen, size, r, g, b);
504 return TRUE;
505 }
506
507 Bool
508 VidModeGetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b)
509 {
510 ScrnInfoPtr pScrn;
511
512 if (!VidModeAvailable(scrnIndex))
513 return FALSE;
514
515 pScrn = xf86Screens[scrnIndex];
516 xf86GetGammaRamp(pScrn->pScreen, size, r, g, b);
517 return TRUE;
518 }
519
520 int
521 VidModeGetGammaRampSize(int scrnIndex)
522 {
523 if (!VidModeAvailable(scrnIndex))
524 return 0;
525
526 return xf86GetGammaRampSize(xf86Screens[scrnIndex]->pScreen);
527 }
528
529 pointer
530 VidModeCreateMode(void)
531 {
532 DisplayModePtr mode;
533
534 mode = malloc(sizeof(DisplayModeRec));
535 if (mode != NULL) {
536 mode->name = "";
537 mode->VScan = 1; /* divides refresh rate. default = 1 */
538 mode->Private = NULL;
539 mode->next = mode;
540 mode->prev = mode;
541 }
542 return mode;
543 }
544
545 void
546 VidModeCopyMode(pointer modefrom, pointer modeto)
547 {
548 memcpy(modeto, modefrom, sizeof(DisplayModeRec));
549 }
550
551 int
552 VidModeGetModeValue(pointer mode, int valtyp)
553 {
554 int ret = 0;
555
556 switch (valtyp) {
557 case VIDMODE_H_DISPLAY:
558 ret = ((DisplayModePtr) mode)->HDisplay;
559 break;
560 case VIDMODE_H_SYNCSTART:
561 ret = ((DisplayModePtr) mode)->HSyncStart;
562 break;
563 case VIDMODE_H_SYNCEND:
564 ret = ((DisplayModePtr) mode)->HSyncEnd;
565 break;
566 case VIDMODE_H_TOTAL:
567 ret = ((DisplayModePtr) mode)->HTotal;
568 break;
569 case VIDMODE_H_SKEW:
570 ret = ((DisplayModePtr) mode)->HSkew;
571 break;
572 case VIDMODE_V_DISPLAY:
573 ret = ((DisplayModePtr) mode)->VDisplay;
574 break;
575 case VIDMODE_V_SYNCSTART:
576 ret = ((DisplayModePtr) mode)->VSyncStart;
577 break;
578 case VIDMODE_V_SYNCEND:
579 ret = ((DisplayModePtr) mode)->VSyncEnd;
580 break;
581 case VIDMODE_V_TOTAL:
582 ret = ((DisplayModePtr) mode)->VTotal;
583 break;
584 case VIDMODE_FLAGS:
585 ret = ((DisplayModePtr) mode)->Flags;
586 break;
587 case VIDMODE_CLOCK:
588 ret = ((DisplayModePtr) mode)->Clock;
589 break;
590 }
591 return ret;
592 }
593
594 void
595 VidModeSetModeValue(pointer mode, int valtyp, int val)
596 {
597 switch (valtyp) {
598 case VIDMODE_H_DISPLAY:
599 ((DisplayModePtr) mode)->HDisplay = val;
600 break;
601 case VIDMODE_H_SYNCSTART:
602 ((DisplayModePtr) mode)->HSyncStart = val;
603 break;
604 case VIDMODE_H_SYNCEND:
605 ((DisplayModePtr) mode)->HSyncEnd = val;
606 break;
607 case VIDMODE_H_TOTAL:
608 ((DisplayModePtr) mode)->HTotal = val;
609 break;
610 case VIDMODE_H_SKEW:
611 ((DisplayModePtr) mode)->HSkew = val;
612 break;
613 case VIDMODE_V_DISPLAY:
614 ((DisplayModePtr) mode)->VDisplay = val;
615 break;
616 case VIDMODE_V_SYNCSTART:
617 ((DisplayModePtr) mode)->VSyncStart = val;
618 break;
619 case VIDMODE_V_SYNCEND:
620 ((DisplayModePtr) mode)->VSyncEnd = val;
621 break;
622 case VIDMODE_V_TOTAL:
623 ((DisplayModePtr) mode)->VTotal = val;
624 break;
625 case VIDMODE_FLAGS:
626 ((DisplayModePtr) mode)->Flags = val;
627 break;
628 case VIDMODE_CLOCK:
629 ((DisplayModePtr) mode)->Clock = val;
630 break;
631 }
632 return;
633 }
634
635 vidMonitorValue
636 VidModeGetMonitorValue(pointer monitor, int valtyp, int indx)
637 {
638 vidMonitorValue ret = { NULL, };
639
640 switch (valtyp) {
641 case VIDMODE_MON_VENDOR:
642 ret.ptr = (((MonPtr) monitor)->vendor);
643 break;
644 case VIDMODE_MON_MODEL:
645 ret.ptr = (((MonPtr) monitor)->model);
646 break;
647 case VIDMODE_MON_NHSYNC:
648 ret.i = ((MonPtr) monitor)->nHsync;
649 break;
650 case VIDMODE_MON_NVREFRESH:
651 ret.i = ((MonPtr) monitor)->nVrefresh;
652 break;
653 case VIDMODE_MON_HSYNC_LO:
654 ret.f = (100.0 * ((MonPtr) monitor)->hsync[indx].lo);
655 break;
656 case VIDMODE_MON_HSYNC_HI:
657 ret.f = (100.0 * ((MonPtr) monitor)->hsync[indx].hi);
658 break;
659 case VIDMODE_MON_VREFRESH_LO:
660 ret.f = (100.0 * ((MonPtr) monitor)->vrefresh[indx].lo);
661 break;
662 case VIDMODE_MON_VREFRESH_HI:
663 ret.f = (100.0 * ((MonPtr) monitor)->vrefresh[indx].hi);
664 break;
665 }
666 return ret;
667 }
668
669 #endif /* XF86VIDMODE */