2 * Copyright © 2006 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 #ifdef HAVE_XORG_CONFIG_H
24 #include <xorg-config.h>
38 #include "xf86Modes.h"
39 #include "xf86RandR12.h"
40 #include "X11/extensions/render.h"
42 #include "X11/extensions/dpms.h"
43 #include "X11/Xatom.h"
45 #include "picturestr.h"
51 * Initialize xf86CrtcConfig structure
54 int xf86CrtcConfigPrivateIndex
= -1;
57 xf86CrtcConfigInit (ScrnInfoPtr scrn
,
58 const xf86CrtcConfigFuncsRec
*funcs
)
60 xf86CrtcConfigPtr config
;
62 if (xf86CrtcConfigPrivateIndex
== -1)
63 xf86CrtcConfigPrivateIndex
= xf86AllocateScrnInfoPrivateIndex();
64 config
= xnfcalloc (1, sizeof (xf86CrtcConfigRec
));
66 config
->funcs
= funcs
;
68 scrn
->privates
[xf86CrtcConfigPrivateIndex
].ptr
= config
;
72 xf86CrtcSetSizeRange (ScrnInfoPtr scrn
,
73 int minWidth
, int minHeight
,
74 int maxWidth
, int maxHeight
)
76 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
78 config
->minWidth
= minWidth
;
79 config
->minHeight
= minHeight
;
80 config
->maxWidth
= maxWidth
;
81 config
->maxHeight
= maxHeight
;
88 xf86CrtcCreate (ScrnInfoPtr scrn
,
89 const xf86CrtcFuncsRec
*funcs
)
91 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
92 xf86CrtcPtr crtc
, *crtcs
;
94 crtc
= xcalloc (sizeof (xf86CrtcRec
), 1);
99 #ifdef RANDR_12_INTERFACE
100 crtc
->randr_crtc
= NULL
;
102 crtc
->rotation
= RR_Rotate_0
;
103 crtc
->desiredRotation
= RR_Rotate_0
;
104 if (xf86_config
->crtc
)
105 crtcs
= xrealloc (xf86_config
->crtc
,
106 (xf86_config
->num_crtc
+ 1) * sizeof (xf86CrtcPtr
));
108 crtcs
= xalloc ((xf86_config
->num_crtc
+ 1) * sizeof (xf86CrtcPtr
));
114 xf86_config
->crtc
= crtcs
;
115 xf86_config
->crtc
[xf86_config
->num_crtc
++] = crtc
;
120 xf86CrtcDestroy (xf86CrtcPtr crtc
)
122 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(crtc
->scrn
);
125 (*crtc
->funcs
->destroy
) (crtc
);
126 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
127 if (xf86_config
->crtc
[c
] == crtc
)
129 memmove (&xf86_config
->crtc
[c
],
130 &xf86_config
->crtc
[c
+1],
131 ((xf86_config
->num_crtc
- (c
+ 1)) * sizeof(void*)));
132 xf86_config
->num_crtc
--;
140 * Return whether any outputs are connected to the specified pipe
144 xf86CrtcInUse (xf86CrtcPtr crtc
)
146 ScrnInfoPtr pScrn
= crtc
->scrn
;
147 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
150 for (o
= 0; o
< xf86_config
->num_output
; o
++)
151 if (xf86_config
->output
[o
]->crtc
== crtc
)
157 xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen
)
160 int subpixel_order
= SubPixelUnknown
;
161 Bool has_none
= FALSE
;
162 ScrnInfoPtr scrn
= xf86Screens
[pScreen
->myNum
];
163 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
166 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
168 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
170 for (o
= 0; o
< xf86_config
->num_output
; o
++)
172 xf86OutputPtr output
= xf86_config
->output
[o
];
174 if (output
->crtc
== crtc
)
176 switch (output
->subpixel_order
) {
180 case SubPixelUnknown
:
183 subpixel_order
= output
->subpixel_order
;
187 if (subpixel_order
!= SubPixelUnknown
)
190 if (subpixel_order
!= SubPixelUnknown
)
192 static const int circle
[4] = {
193 SubPixelHorizontalRGB
,
195 SubPixelHorizontalBGR
,
200 for (rotate
= 0; rotate
< 4; rotate
++)
201 if (crtc
->rotation
& (1 << rotate
))
203 for (c
= 0; c
< 4; c
++)
204 if (circle
[c
] == subpixel_order
)
206 c
= (c
+ rotate
) & 0x3;
207 if ((crtc
->rotation
& RR_Reflect_X
) && !(c
& 1))
209 if ((crtc
->rotation
& RR_Reflect_Y
) && (c
& 1))
211 subpixel_order
= circle
[c
];
215 if (subpixel_order
== SubPixelUnknown
&& has_none
)
216 subpixel_order
= SubPixelNone
;
217 PictureSetSubpixelOrder (pScreen
, subpixel_order
);
222 * Sets the given video mode on the given crtc
225 xf86CrtcSetMode (xf86CrtcPtr crtc
, DisplayModePtr mode
, Rotation rotation
,
228 ScrnInfoPtr scrn
= crtc
->scrn
;
229 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
232 Bool didLock
= FALSE
;
233 DisplayModePtr adjusted_mode
;
234 DisplayModeRec saved_mode
;
235 int saved_x
, saved_y
;
236 Rotation saved_rotation
;
238 crtc
->enabled
= xf86CrtcInUse (crtc
);
242 /* XXX disable crtc? */
246 adjusted_mode
= xf86DuplicateMode(mode
);
248 didLock
= crtc
->funcs
->lock (crtc
);
250 saved_mode
= crtc
->mode
;
253 saved_rotation
= crtc
->rotation
;
254 /* Update crtc values up front so the driver can rely on them for mode
260 crtc
->rotation
= rotation
;
262 /* XXX short-circuit changes to base location only */
264 /* Pass our mode to the outputs and the CRTC to give them a chance to
265 * adjust it according to limitations or output properties, and also
266 * a chance to reject the mode entirely.
268 for (i
= 0; i
< xf86_config
->num_output
; i
++) {
269 xf86OutputPtr output
= xf86_config
->output
[i
];
271 if (output
->crtc
!= crtc
)
274 if (!output
->funcs
->mode_fixup(output
, mode
, adjusted_mode
)) {
279 if (!crtc
->funcs
->mode_fixup(crtc
, mode
, adjusted_mode
)) {
283 if (!xf86CrtcRotate (crtc
, mode
, rotation
)) {
287 /* Prepare the outputs and CRTCs before setting the mode. */
288 for (i
= 0; i
< xf86_config
->num_output
; i
++) {
289 xf86OutputPtr output
= xf86_config
->output
[i
];
291 if (output
->crtc
!= crtc
)
294 /* Disable the output as the first thing we do. */
295 output
->funcs
->prepare(output
);
298 crtc
->funcs
->prepare(crtc
);
300 /* Set up the DPLL and any output state that needs to adjust or depend
303 crtc
->funcs
->mode_set(crtc
, mode
, adjusted_mode
, x
, y
);
304 for (i
= 0; i
< xf86_config
->num_output
; i
++)
306 xf86OutputPtr output
= xf86_config
->output
[i
];
307 if (output
->crtc
== crtc
)
308 output
->funcs
->mode_set(output
, mode
, adjusted_mode
);
311 /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
312 crtc
->funcs
->commit(crtc
);
313 for (i
= 0; i
< xf86_config
->num_output
; i
++)
315 xf86OutputPtr output
= xf86_config
->output
[i
];
316 if (output
->crtc
== crtc
)
318 output
->funcs
->commit(output
);
319 #ifdef RANDR_12_INTERFACE
320 if (output
->randr_output
)
321 RRPostPendingProperties (output
->randr_output
);
326 /* XXX free adjustedmode */
329 xf86CrtcSetScreenSubpixelOrder (scrn
->pScreen
);
335 crtc
->rotation
= saved_rotation
;
336 crtc
->mode
= saved_mode
;
340 crtc
->funcs
->unlock (crtc
);
349 extern XF86ConfigPtr xf86configptr
;
352 OPTION_PREFERRED_MODE
,
366 static OptionInfoRec xf86OutputOptions
[] = {
367 {OPTION_PREFERRED_MODE
, "PreferredMode", OPTV_STRING
, {0}, FALSE
},
368 {OPTION_POSITION
, "Position", OPTV_STRING
, {0}, FALSE
},
369 {OPTION_BELOW
, "Below", OPTV_STRING
, {0}, FALSE
},
370 {OPTION_RIGHT_OF
, "RightOf", OPTV_STRING
, {0}, FALSE
},
371 {OPTION_ABOVE
, "Above", OPTV_STRING
, {0}, FALSE
},
372 {OPTION_LEFT_OF
, "LeftOf", OPTV_STRING
, {0}, FALSE
},
373 {OPTION_ENABLE
, "Enable", OPTV_BOOLEAN
, {0}, FALSE
},
374 {OPTION_DISABLE
, "Disable", OPTV_BOOLEAN
, {0}, FALSE
},
375 {OPTION_MIN_CLOCK
, "MinClock", OPTV_FREQ
, {0}, FALSE
},
376 {OPTION_MAX_CLOCK
, "MaxClock", OPTV_FREQ
, {0}, FALSE
},
377 {OPTION_IGNORE
, "Ignore", OPTV_BOOLEAN
, {0}, FALSE
},
378 {OPTION_ROTATE
, "Rotate", OPTV_STRING
, {0}, FALSE
},
379 {-1, NULL
, OPTV_NONE
, {0}, FALSE
},
386 static OptionInfoRec xf86DeviceOptions
[] = {
387 {OPTION_MODEDEBUG
, "ModeDebug", OPTV_STRING
, {0}, FALSE
},
388 {-1, NULL
, OPTV_NONE
, {0}, FALSE
},
392 xf86OutputSetMonitor (xf86OutputPtr output
)
395 static const char monitor_prefix
[] = "monitor-";
402 xfree (output
->options
);
404 output
->options
= xnfalloc (sizeof (xf86OutputOptions
));
405 memcpy (output
->options
, xf86OutputOptions
, sizeof (xf86OutputOptions
));
407 option_name
= xnfalloc (strlen (monitor_prefix
) +
408 strlen (output
->name
) + 1);
409 strcpy (option_name
, monitor_prefix
);
410 strcat (option_name
, output
->name
);
411 monitor
= xf86findOptionValue (output
->scrn
->options
, option_name
);
413 monitor
= output
->name
;
415 xf86MarkOptionUsedByName (output
->scrn
->options
, option_name
);
417 output
->conf_monitor
= xf86findMonitor (monitor
,
418 xf86configptr
->conf_monitor_lst
);
420 * Find the monitor section of the screen and use that
422 if (!output
->conf_monitor
&& output
->use_screen_monitor
)
423 output
->conf_monitor
= xf86findMonitor (output
->scrn
->monitor
->id
,
424 xf86configptr
->conf_monitor_lst
);
425 if (output
->conf_monitor
)
427 xf86DrvMsg (output
->scrn
->scrnIndex
, X_INFO
,
428 "Output %s using monitor section %s\n",
429 output
->name
, output
->conf_monitor
->mon_identifier
);
430 xf86ProcessOptions (output
->scrn
->scrnIndex
,
431 output
->conf_monitor
->mon_option_lst
,
435 xf86DrvMsg (output
->scrn
->scrnIndex
, X_INFO
,
436 "Output %s has no monitor section\n",
441 xf86OutputEnabled (xf86OutputPtr output
)
443 Bool enable
, disable
;
445 /* check to see if this output was enabled in the config file */
446 if (xf86GetOptValBool (output
->options
, OPTION_ENABLE
, &enable
) && enable
)
448 xf86DrvMsg (output
->scrn
->scrnIndex
, X_INFO
,
449 "Output %s enabled by config file\n", output
->name
);
452 /* or if this output was disabled in the config file */
453 if (xf86GetOptValBool (output
->options
, OPTION_DISABLE
, &disable
) && disable
)
455 xf86DrvMsg (output
->scrn
->scrnIndex
, X_INFO
,
456 "Output %s disabled by config file\n", output
->name
);
459 /* otherwise, enable if it is not disconnected */
460 enable
= output
->status
!= XF86OutputStatusDisconnected
;
461 xf86DrvMsg (output
->scrn
->scrnIndex
, X_INFO
,
462 "Output %s %sconnected\n", output
->name
, enable
? "" : "dis");
467 xf86OutputIgnored (xf86OutputPtr output
)
469 return xf86ReturnOptValBool (output
->options
, OPTION_IGNORE
, FALSE
);
472 static char *direction
[4] = {
480 xf86OutputInitialRotation (xf86OutputPtr output
)
482 char *rotate_name
= xf86GetOptValString (output
->options
,
489 for (i
= 0; i
< 4; i
++)
490 if (xf86nameCompare (direction
[i
], rotate_name
) == 0)
495 _X_EXPORT xf86OutputPtr
496 xf86OutputCreate (ScrnInfoPtr scrn
,
497 const xf86OutputFuncsRec
*funcs
,
500 xf86OutputPtr output
, *outputs
;
501 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
505 len
= strlen (name
) + 1;
509 output
= xcalloc (sizeof (xf86OutputRec
) + len
, 1);
513 output
->funcs
= funcs
;
516 output
->name
= (char *) (output
+ 1);
517 strcpy (output
->name
, name
);
519 output
->subpixel_order
= SubPixelUnknown
;
521 * Use the old per-screen monitor section for the first output
523 output
->use_screen_monitor
= (xf86_config
->num_output
== 0);
524 #ifdef RANDR_12_INTERFACE
525 output
->randr_output
= NULL
;
529 xf86OutputSetMonitor (output
);
530 if (xf86OutputIgnored (output
))
538 if (xf86_config
->output
)
539 outputs
= xrealloc (xf86_config
->output
,
540 (xf86_config
->num_output
+ 1) * sizeof (xf86OutputPtr
));
542 outputs
= xalloc ((xf86_config
->num_output
+ 1) * sizeof (xf86OutputPtr
));
549 xf86_config
->output
= outputs
;
550 xf86_config
->output
[xf86_config
->num_output
++] = output
;
556 xf86OutputRename (xf86OutputPtr output
, const char *name
)
558 int len
= strlen(name
) + 1;
559 char *newname
= xalloc (len
);
562 return FALSE
; /* so sorry... */
564 strcpy (newname
, name
);
565 if (output
->name
&& output
->name
!= (char *) (output
+ 1))
566 xfree (output
->name
);
567 output
->name
= newname
;
568 xf86OutputSetMonitor (output
);
569 if (xf86OutputIgnored (output
))
575 xf86OutputUseScreenMonitor (xf86OutputPtr output
, Bool use_screen_monitor
)
577 if (use_screen_monitor
!= output
->use_screen_monitor
)
579 output
->use_screen_monitor
= use_screen_monitor
;
580 xf86OutputSetMonitor (output
);
585 xf86OutputDestroy (xf86OutputPtr output
)
587 ScrnInfoPtr scrn
= output
->scrn
;
588 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
591 (*output
->funcs
->destroy
) (output
);
592 while (output
->probed_modes
)
593 xf86DeleteMode (&output
->probed_modes
, output
->probed_modes
);
594 for (o
= 0; o
< xf86_config
->num_output
; o
++)
595 if (xf86_config
->output
[o
] == output
)
597 memmove (&xf86_config
->output
[o
],
598 &xf86_config
->output
[o
+1],
599 ((xf86_config
->num_output
- (o
+ 1)) * sizeof(void*)));
600 xf86_config
->num_output
--;
603 if (output
->name
&& output
->name
!= (char *) (output
+ 1))
604 xfree (output
->name
);
609 * Called during CreateScreenResources to hook up RandR
612 xf86CrtcCreateScreenResources (ScreenPtr screen
)
614 ScrnInfoPtr scrn
= xf86Screens
[screen
->myNum
];
615 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
617 screen
->CreateScreenResources
= config
->CreateScreenResources
;
619 if (!(*screen
->CreateScreenResources
)(screen
))
622 if (!xf86RandR12CreateScreenResources (screen
))
629 * Clean up config on server reset
632 xf86CrtcCloseScreen (int index
, ScreenPtr screen
)
634 ScrnInfoPtr scrn
= xf86Screens
[screen
->myNum
];
635 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
638 screen
->CloseScreen
= config
->CloseScreen
;
640 xf86RotateCloseScreen (screen
);
642 for (o
= 0; o
< config
->num_output
; o
++)
644 xf86OutputPtr output
= config
->output
[o
];
646 output
->randr_output
= NULL
;
648 for (c
= 0; c
< config
->num_crtc
; c
++)
650 xf86CrtcPtr crtc
= config
->crtc
[c
];
652 crtc
->randr_crtc
= NULL
;
654 return screen
->CloseScreen (index
, screen
);
658 * Called at ScreenInit time to set up
661 xf86CrtcScreenInit (ScreenPtr screen
)
663 ScrnInfoPtr scrn
= xf86Screens
[screen
->myNum
];
664 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
668 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
, "RandR 1.2 enabled, ignore the following RandR disabled message.\n");
669 xf86DisableRandR(); /* Disable old RandR extension support */
670 xf86RandR12Init (screen
);
672 /* support all rotations if every crtc has the shadow alloc funcs */
673 for (c
= 0; c
< config
->num_crtc
; c
++)
675 xf86CrtcPtr crtc
= config
->crtc
[c
];
676 if (!crtc
->funcs
->shadow_allocate
|| !crtc
->funcs
->shadow_create
)
679 if (c
== config
->num_crtc
)
680 xf86RandR12SetRotations (screen
, RR_Rotate_0
| RR_Rotate_90
|
681 RR_Rotate_180
| RR_Rotate_270
|
682 RR_Reflect_X
| RR_Reflect_Y
);
684 xf86RandR12SetRotations (screen
, RR_Rotate_0
);
686 /* Wrap CreateScreenResources so we can initialize the RandR code */
687 config
->CreateScreenResources
= screen
->CreateScreenResources
;
688 screen
->CreateScreenResources
= xf86CrtcCreateScreenResources
;
690 config
->CloseScreen
= screen
->CloseScreen
;
691 screen
->CloseScreen
= xf86CrtcCloseScreen
;
696 static DisplayModePtr
697 xf86DefaultMode (xf86OutputPtr output
, int width
, int height
)
699 DisplayModePtr target_mode
= NULL
;
702 int target_preferred
= 0;
705 mm_height
= output
->mm_height
;
707 mm_height
= 203; /* 768 pixels at 96dpi */
709 * Pick a mode closest to 96dpi
711 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
)
714 int preferred
= (mode
->type
& M_T_PREFERRED
) != 0;
717 if (xf86ModeWidth (mode
, output
->initial_rotation
) > width
||
718 xf86ModeHeight (mode
, output
->initial_rotation
) > height
)
721 /* yes, use VDisplay here, not xf86ModeHeight */
722 dpi
= (mode
->VDisplay
* 254) / (mm_height
* 10);
724 diff
= diff
< 0 ? -diff
: diff
;
725 if (target_mode
== NULL
|| (preferred
> target_preferred
) ||
726 (preferred
== target_preferred
&& diff
< target_diff
))
730 target_preferred
= preferred
;
736 static DisplayModePtr
737 xf86ClosestMode (xf86OutputPtr output
,
738 DisplayModePtr match
, Rotation match_rotation
,
739 int width
, int height
)
741 DisplayModePtr target_mode
= NULL
;
746 * Pick a mode closest to the specified mode
748 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
)
753 if (xf86ModeWidth (mode
, output
->initial_rotation
) > width
||
754 xf86ModeHeight (mode
, output
->initial_rotation
) > height
)
757 /* exact matches are preferred */
758 if (output
->initial_rotation
== match_rotation
&&
759 xf86ModesEqual (mode
, match
))
762 dx
= xf86ModeWidth (match
, match_rotation
) - xf86ModeWidth (mode
, output
->initial_rotation
);
763 dy
= xf86ModeHeight (match
, match_rotation
) - xf86ModeHeight (mode
, output
->initial_rotation
);
764 diff
= dx
* dx
+ dy
* dy
;
765 if (target_mode
== NULL
|| diff
< target_diff
)
775 xf86OutputHasPreferredMode (xf86OutputPtr output
, int width
, int height
)
779 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
)
781 if (xf86ModeWidth (mode
, output
->initial_rotation
) > width
||
782 xf86ModeHeight (mode
, output
->initial_rotation
) > height
)
785 if (mode
->type
& M_T_PREFERRED
)
792 xf86PickCrtcs (ScrnInfoPtr scrn
,
793 xf86CrtcPtr
*best_crtcs
,
794 DisplayModePtr
*modes
,
799 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
801 xf86OutputPtr output
;
804 xf86CrtcPtr best_crtc
;
809 if (n
== config
->num_output
)
811 output
= config
->output
[n
];
814 * Compute score with this output disabled
816 best_crtcs
[n
] = NULL
;
818 best_score
= xf86PickCrtcs (scrn
, best_crtcs
, modes
, n
+1, width
, height
);
819 if (modes
[n
] == NULL
)
822 crtcs
= xalloc (config
->num_output
* sizeof (xf86CrtcPtr
));
827 /* Score outputs that are known to be connected higher */
828 if (output
->status
== XF86OutputStatusConnected
)
830 /* Score outputs with preferred modes higher */
831 if (xf86OutputHasPreferredMode (output
, width
, height
))
834 * Select a crtc for this output and
835 * then attempt to configure the remaining
838 for (c
= 0; c
< config
->num_crtc
; c
++)
840 if ((output
->possible_crtcs
& (1 << c
)) == 0)
843 crtc
= config
->crtc
[c
];
845 * Check to see if some other output is
848 for (o
= 0; o
< n
; o
++)
849 if (best_crtcs
[o
] == crtc
)
854 * If the two outputs desire the same mode,
855 * see if they can be cloned
857 if (xf86ModesEqual (modes
[o
], modes
[n
]) &&
858 config
->output
[0]->initial_rotation
== config
->output
[n
]->initial_rotation
&&
859 config
->output
[o
]->initial_x
== config
->output
[n
]->initial_x
&&
860 config
->output
[o
]->initial_y
== config
->output
[n
]->initial_y
)
862 if ((output
->possible_clones
& (1 << o
)) == 0)
863 continue; /* nope, try next CRTC */
866 continue; /* different modes, can't clone */
869 memcpy (crtcs
, best_crtcs
, n
* sizeof (xf86CrtcPtr
));
870 score
= my_score
+ xf86PickCrtcs (scrn
, crtcs
, modes
, n
+1, width
, height
);
871 if (score
> best_score
)
875 memcpy (best_crtcs
, crtcs
, config
->num_output
* sizeof (xf86CrtcPtr
));
884 * Compute the virtual size necessary to place all of the available
885 * crtcs in the specified configuration.
887 * canGrow indicates that the driver can make the screen larger than its initial
888 * configuration. If FALSE, this function will enlarge the screen to include
889 * the largest available mode.
893 xf86DefaultScreenLimits (ScrnInfoPtr scrn
, int *widthp
, int *heightp
,
896 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
897 int width
= 0, height
= 0;
902 for (c
= 0; c
< config
->num_crtc
; c
++)
904 int crtc_width
= 0, crtc_height
= 0;
905 xf86CrtcPtr crtc
= config
->crtc
[c
];
909 crtc_width
= crtc
->x
+ xf86ModeWidth (&crtc
->desiredMode
, crtc
->desiredRotation
);
910 crtc_height
= crtc
->y
+ xf86ModeHeight (&crtc
->desiredMode
, crtc
->desiredRotation
);
913 for (o
= 0; o
< config
->num_output
; o
++)
915 xf86OutputPtr output
= config
->output
[o
];
917 for (s
= 0; s
< config
->num_crtc
; s
++)
918 if (output
->possible_crtcs
& (1 << s
))
921 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
)
923 if (mode
->HDisplay
> crtc_width
)
924 crtc_width
= mode
->HDisplay
;
925 if (mode
->VDisplay
> crtc_width
)
926 crtc_width
= mode
->VDisplay
;
927 if (mode
->VDisplay
> crtc_height
)
928 crtc_height
= mode
->VDisplay
;
929 if (mode
->HDisplay
> crtc_height
)
930 crtc_height
= mode
->HDisplay
;
935 if (crtc_width
> width
)
937 if (crtc_height
> height
)
938 height
= crtc_height
;
940 if (config
->maxWidth
&& width
> config
->maxWidth
) width
= config
->maxWidth
;
941 if (config
->maxHeight
&& height
> config
->maxHeight
) height
= config
->maxHeight
;
942 if (config
->minWidth
&& width
< config
->minWidth
) width
= config
->minWidth
;
943 if (config
->minHeight
&& height
< config
->minHeight
) height
= config
->minHeight
;
948 #define POSITION_UNSET -100000
951 xf86InitialOutputPositions (ScrnInfoPtr scrn
, DisplayModePtr
*modes
)
953 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
957 for (o
= 0; o
< config
->num_output
; o
++)
959 xf86OutputPtr output
= config
->output
[o
];
961 output
->initial_x
= output
->initial_y
= POSITION_UNSET
;
965 * Loop until all outputs are set
969 Bool any_set
= FALSE
;
970 Bool keep_going
= FALSE
;
972 for (o
= 0; o
< config
->num_output
; o
++)
974 static const OutputOpts relations
[] = {
975 OPTION_BELOW
, OPTION_RIGHT_OF
, OPTION_ABOVE
, OPTION_LEFT_OF
977 xf86OutputPtr output
= config
->output
[o
];
978 xf86OutputPtr relative
;
984 if (output
->initial_x
!= POSITION_UNSET
)
986 position
= xf86GetOptValString (output
->options
,
989 * Absolute position wins
994 if (sscanf (position
, "%d %d", &x
, &y
) == 2)
996 output
->initial_x
= x
;
997 output
->initial_y
= y
;
1001 xf86DrvMsg (scrn
->scrnIndex
, X_ERROR
,
1002 "Output %s position not of form \"x y\"\n",
1004 output
->initial_x
= output
->initial_y
= 0;
1010 * Next comes relative positions
1013 relative_name
= NULL
;
1014 for (r
= 0; r
< 4; r
++)
1016 relation
= relations
[r
];
1017 relative_name
= xf86GetOptValString (output
->options
,
1026 for (or = 0; or < config
->num_output
; or++)
1028 xf86OutputPtr out_rel
= config
->output
[or];
1029 XF86ConfMonitorPtr rel_mon
= out_rel
->conf_monitor
;
1033 if (xf86nameCompare (rel_mon
->mon_identifier
,
1034 relative_name
) == 0)
1036 relative
= config
->output
[or];
1040 if (strcmp (out_rel
->name
, relative_name
) == 0)
1042 relative
= config
->output
[or];
1048 xf86DrvMsg (scrn
->scrnIndex
, X_ERROR
,
1049 "Cannot position output %s relative to unknown output %s\n",
1050 output
->name
, relative_name
);
1051 output
->initial_x
= 0;
1052 output
->initial_y
= 0;
1056 if (relative
->initial_x
== POSITION_UNSET
)
1061 output
->initial_x
= relative
->initial_x
;
1062 output
->initial_y
= relative
->initial_y
;
1065 output
->initial_y
+= xf86ModeHeight (modes
[or], relative
->initial_rotation
);
1067 case OPTION_RIGHT_OF
:
1068 output
->initial_x
+= xf86ModeWidth (modes
[or], relative
->initial_rotation
);
1071 output
->initial_y
-= xf86ModeHeight (modes
[or], relative
->initial_rotation
);
1073 case OPTION_LEFT_OF
:
1074 output
->initial_x
-= xf86ModeWidth (modes
[or], relative
->initial_rotation
);
1083 /* Nothing set, just stick them at 0,0 */
1084 output
->initial_x
= 0;
1085 output
->initial_y
= 0;
1092 for (o
= 0; o
< config
->num_output
; o
++)
1094 xf86OutputPtr output
= config
->output
[o
];
1095 if (output
->initial_x
== POSITION_UNSET
)
1097 xf86DrvMsg (scrn
->scrnIndex
, X_ERROR
,
1098 "Output position loop. Moving %s to 0,0\n",
1100 output
->initial_x
= output
->initial_y
= 0;
1108 * normalize positions
1112 for (o
= 0; o
< config
->num_output
; o
++)
1114 xf86OutputPtr output
= config
->output
[o
];
1116 if (output
->initial_x
< min_x
)
1117 min_x
= output
->initial_x
;
1118 if (output
->initial_y
< min_y
)
1119 min_y
= output
->initial_y
;
1122 for (o
= 0; o
< config
->num_output
; o
++)
1124 xf86OutputPtr output
= config
->output
[o
];
1126 output
->initial_x
-= min_x
;
1127 output
->initial_y
-= min_y
;
1133 * XXX walk the monitor mode list and prune out duplicates that
1134 * are inserted by xf86DDCMonitorSet. In an ideal world, that
1135 * function would do this work by itself.
1139 xf86PruneDuplicateMonitorModes (MonPtr Monitor
)
1141 DisplayModePtr master
, clone
, next
;
1143 for (master
= Monitor
->Modes
;
1144 master
&& master
!= Monitor
->Last
;
1145 master
= master
->next
)
1147 for (clone
= master
->next
; clone
&& clone
!= Monitor
->Modes
; clone
= next
)
1150 if (xf86ModesEqual (master
, clone
))
1152 if (Monitor
->Last
== clone
)
1153 Monitor
->Last
= clone
->prev
;
1154 xf86DeleteMode (&Monitor
->Modes
, clone
);
1160 /** Return - 0 + if a should be earlier, same or later than b in list
1163 xf86ModeCompare (DisplayModePtr a
, DisplayModePtr b
)
1167 diff
= ((b
->type
& M_T_PREFERRED
) != 0) - ((a
->type
& M_T_PREFERRED
) != 0);
1170 diff
= b
->HDisplay
* b
->VDisplay
- a
->HDisplay
* a
->VDisplay
;
1173 diff
= b
->Clock
- a
->Clock
;
1178 * Insertion sort input in-place and return the resulting head
1180 static DisplayModePtr
1181 xf86SortModes (DisplayModePtr input
)
1183 DisplayModePtr output
= NULL
, i
, o
, n
, *op
, prev
;
1185 /* sort by preferred status and pixel area */
1189 input
= input
->next
;
1190 for (op
= &output
; (o
= *op
); op
= &o
->next
)
1191 if (xf86ModeCompare (o
, i
) > 0)
1196 /* prune identical modes */
1197 for (o
= output
; o
&& (n
= o
->next
); o
= n
)
1199 if (!strcmp (o
->name
, n
->name
) && xf86ModesEqual (o
, n
))
1207 /* hook up backward links */
1209 for (o
= output
; o
; o
= o
->next
)
1218 xf86ProbeOutputModes (ScrnInfoPtr scrn
, int maxX
, int maxY
)
1220 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1223 /* When canGrow was TRUE in the initial configuration we have to
1224 * compare against the maximum values so that we don't drop modes.
1225 * When canGrow was FALSE, the maximum values would have been clamped
1228 if (maxX
== 0 || maxY
== 0) {
1229 maxX
= config
->maxWidth
;
1230 maxY
= config
->maxHeight
;
1233 /* Elide duplicate modes before defaulting code uses them */
1234 xf86PruneDuplicateMonitorModes (scrn
->monitor
);
1236 /* Probe the list of modes for each output. */
1237 for (o
= 0; o
< config
->num_output
; o
++)
1239 xf86OutputPtr output
= config
->output
[o
];
1240 DisplayModePtr mode
;
1241 DisplayModePtr config_modes
= NULL
, output_modes
, default_modes
;
1242 char *preferred_mode
;
1243 xf86MonPtr edid_monitor
;
1244 XF86ConfMonitorPtr conf_monitor
;
1249 enum { sync_config
, sync_edid
, sync_default
} sync_source
= sync_default
;
1251 while (output
->probed_modes
!= NULL
)
1252 xf86DeleteMode(&output
->probed_modes
, output
->probed_modes
);
1255 * Check connection status
1257 output
->status
= (*output
->funcs
->detect
)(output
);
1259 if (output
->status
== XF86OutputStatusDisconnected
)
1261 xf86OutputSetEDID (output
, NULL
);
1265 memset (&mon_rec
, '\0', sizeof (mon_rec
));
1267 conf_monitor
= output
->conf_monitor
;
1273 for (i
= 0; i
< conf_monitor
->mon_n_hsync
; i
++)
1275 mon_rec
.hsync
[mon_rec
.nHsync
].lo
= conf_monitor
->mon_hsync
[i
].lo
;
1276 mon_rec
.hsync
[mon_rec
.nHsync
].hi
= conf_monitor
->mon_hsync
[i
].hi
;
1278 sync_source
= sync_config
;
1280 for (i
= 0; i
< conf_monitor
->mon_n_vrefresh
; i
++)
1282 mon_rec
.vrefresh
[mon_rec
.nVrefresh
].lo
= conf_monitor
->mon_vrefresh
[i
].lo
;
1283 mon_rec
.vrefresh
[mon_rec
.nVrefresh
].hi
= conf_monitor
->mon_vrefresh
[i
].hi
;
1284 mon_rec
.nVrefresh
++;
1285 sync_source
= sync_config
;
1287 config_modes
= xf86GetMonitorModes (scrn
, conf_monitor
);
1290 output_modes
= (*output
->funcs
->get_modes
) (output
);
1292 edid_monitor
= output
->MonInfo
;
1297 Bool set_hsync
= mon_rec
.nHsync
== 0;
1298 Bool set_vrefresh
= mon_rec
.nVrefresh
== 0;
1300 for (i
= 0; i
< sizeof (edid_monitor
->det_mon
) / sizeof (edid_monitor
->det_mon
[0]); i
++)
1302 if (edid_monitor
->det_mon
[i
].type
== DS_RANGES
)
1304 struct monitor_ranges
*ranges
= &edid_monitor
->det_mon
[i
].section
.ranges
;
1305 if (set_hsync
&& ranges
->max_h
)
1307 mon_rec
.hsync
[mon_rec
.nHsync
].lo
= ranges
->min_h
;
1308 mon_rec
.hsync
[mon_rec
.nHsync
].hi
= ranges
->max_h
;
1310 if (sync_source
== sync_default
)
1311 sync_source
= sync_edid
;
1313 if (set_vrefresh
&& ranges
->max_v
)
1315 mon_rec
.vrefresh
[mon_rec
.nVrefresh
].lo
= ranges
->min_v
;
1316 mon_rec
.vrefresh
[mon_rec
.nVrefresh
].hi
= ranges
->max_v
;
1317 mon_rec
.nVrefresh
++;
1318 if (sync_source
== sync_default
)
1319 sync_source
= sync_edid
;
1321 if (ranges
->max_clock
> max_clock
)
1322 max_clock
= ranges
->max_clock
;
1327 if (xf86GetOptValFreq (output
->options
, OPTION_MIN_CLOCK
,
1328 OPTUNITS_KHZ
, &clock
))
1329 min_clock
= (int) clock
;
1330 if (xf86GetOptValFreq (output
->options
, OPTION_MAX_CLOCK
,
1331 OPTUNITS_KHZ
, &clock
))
1332 max_clock
= (int) clock
;
1335 * These limits will end up setting a 1024x768@60Hz mode by default,
1336 * which seems like a fairly good mode to use when nothing else is
1339 if (mon_rec
.nHsync
== 0)
1341 mon_rec
.hsync
[0].lo
= 31.0;
1342 mon_rec
.hsync
[0].hi
= 55.0;
1345 if (mon_rec
.nVrefresh
== 0)
1347 mon_rec
.vrefresh
[0].lo
= 58.0;
1348 mon_rec
.vrefresh
[0].hi
= 62.0;
1349 mon_rec
.nVrefresh
= 1;
1351 default_modes
= xf86GetDefaultModes (output
->interlaceAllowed
,
1352 output
->doubleScanAllowed
);
1354 if (sync_source
== sync_config
)
1357 * Check output and config modes against sync range from config file
1359 xf86ValidateModesSync (scrn
, output_modes
, &mon_rec
);
1360 xf86ValidateModesSync (scrn
, config_modes
, &mon_rec
);
1363 * Check default modes against sync range
1365 xf86ValidateModesSync (scrn
, default_modes
, &mon_rec
);
1367 * Check default modes against monitor max clock
1370 xf86ValidateModesClocks(scrn
, default_modes
,
1371 &min_clock
, &max_clock
, 1);
1373 output
->probed_modes
= NULL
;
1374 output
->probed_modes
= xf86ModesAdd (output
->probed_modes
, config_modes
);
1375 output
->probed_modes
= xf86ModesAdd (output
->probed_modes
, output_modes
);
1376 output
->probed_modes
= xf86ModesAdd (output
->probed_modes
, default_modes
);
1379 * Check all modes against max size
1382 xf86ValidateModesSize (scrn
, output
->probed_modes
,
1386 * Check all modes against output
1388 for (mode
= output
->probed_modes
; mode
!= NULL
; mode
= mode
->next
)
1389 if (mode
->status
== MODE_OK
)
1390 mode
->status
= (*output
->funcs
->mode_valid
)(output
, mode
);
1392 xf86PruneInvalidModes(scrn
, &output
->probed_modes
,
1393 config
->debug_modes
);
1395 output
->probed_modes
= xf86SortModes (output
->probed_modes
);
1397 /* Check for a configured preference for a particular mode */
1398 preferred_mode
= xf86GetOptValString (output
->options
,
1399 OPTION_PREFERRED_MODE
);
1403 for (mode
= output
->probed_modes
; mode
; mode
= mode
->next
)
1405 if (!strcmp (preferred_mode
, mode
->name
))
1407 if (mode
!= output
->probed_modes
)
1410 mode
->prev
->next
= mode
->next
;
1412 mode
->next
->prev
= mode
->prev
;
1413 mode
->next
= output
->probed_modes
;
1414 output
->probed_modes
->prev
= mode
;
1416 output
->probed_modes
= mode
;
1418 mode
->type
|= M_T_PREFERRED
;
1421 mode
->type
&= ~M_T_PREFERRED
;
1425 output
->initial_rotation
= xf86OutputInitialRotation (output
);
1427 if (config
->debug_modes
) {
1428 if (output
->probed_modes
!= NULL
) {
1429 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
,
1430 "Printing probed modes for output %s\n",
1433 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
,
1434 "No remaining probed modes for output %s\n",
1438 for (mode
= output
->probed_modes
; mode
!= NULL
; mode
= mode
->next
)
1440 /* The code to choose the best mode per pipe later on will require
1441 * VRefresh to be set.
1443 mode
->VRefresh
= xf86ModeVRefresh(mode
);
1444 xf86SetModeCrtc(mode
, INTERLACE_HALVE_V
);
1446 if (config
->debug_modes
)
1447 xf86PrintModeline(scrn
->scrnIndex
, mode
);
1454 * Copy one of the output mode lists to the ScrnInfo record
1457 /* XXX where does this function belong? Here? */
1459 xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn
, int *x
, int *y
);
1462 xf86SetScrnInfoModes (ScrnInfoPtr scrn
)
1464 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1465 xf86OutputPtr output
;
1467 DisplayModePtr last
, mode
;
1469 output
= config
->output
[config
->compat_output
];
1475 for (o
= 0; o
< config
->num_output
; o
++)
1476 if (config
->output
[o
]->crtc
)
1478 config
->compat_output
= o
;
1479 output
= config
->output
[o
];
1482 /* no outputs are active, punt and leave things as they are */
1486 crtc
= output
->crtc
;
1488 /* Clear any existing modes from scrn->modes */
1489 while (scrn
->modes
!= NULL
)
1490 xf86DeleteMode(&scrn
->modes
, scrn
->modes
);
1492 /* Set scrn->modes to the mode list for the 'compat' output */
1493 scrn
->modes
= xf86DuplicateModes(scrn
, output
->probed_modes
);
1495 for (mode
= scrn
->modes
; mode
; mode
= mode
->next
)
1496 if (xf86ModesEqual (mode
, &crtc
->desiredMode
))
1499 if (scrn
->modes
!= NULL
) {
1500 /* For some reason, scrn->modes is circular, unlike the other mode
1501 * lists. How great is that?
1503 for (last
= scrn
->modes
; last
&& last
->next
; last
= last
->next
)
1505 last
->next
= scrn
->modes
;
1506 scrn
->modes
->prev
= last
;
1508 while (scrn
->modes
!= mode
)
1509 scrn
->modes
= scrn
->modes
->next
;
1512 scrn
->currentMode
= scrn
->modes
;
1516 * Construct default screen configuration
1518 * Given auto-detected (and, eventually, configured) values,
1519 * construct a usable configuration for the system
1521 * canGrow indicates that the driver can resize the screen to larger than its
1522 * initially configured size via the config->funcs->resize hook. If TRUE, this
1523 * function will set virtualX and virtualY to match the initial configuration
1524 * and leave config->max{Width,Height} alone. If FALSE, it will bloat
1525 * virtual[XY] to include the largest modes and set config->max{Width,Height}
1530 xf86InitialConfiguration (ScrnInfoPtr scrn
, Bool canGrow
)
1532 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1534 DisplayModePtr target_mode
= NULL
;
1535 Rotation target_rotation
= RR_Rotate_0
;
1537 DisplayModePtr
*modes
;
1542 /* Set up the device options */
1543 config
->options
= xnfalloc (sizeof (xf86DeviceOptions
));
1544 memcpy (config
->options
, xf86DeviceOptions
, sizeof (xf86DeviceOptions
));
1545 xf86ProcessOptions (scrn
->scrnIndex
,
1548 config
->debug_modes
= xf86ReturnOptValBool (config
->options
,
1549 OPTION_MODEDEBUG
, FALSE
);
1551 if (scrn
->display
->virtualX
)
1552 width
= scrn
->display
->virtualX
;
1554 width
= config
->maxWidth
;
1555 if (scrn
->display
->virtualY
)
1556 height
= scrn
->display
->virtualY
;
1558 height
= config
->maxHeight
;
1560 xf86ProbeOutputModes (scrn
, width
, height
);
1562 crtcs
= xnfcalloc (config
->num_output
, sizeof (xf86CrtcPtr
));
1563 modes
= xnfcalloc (config
->num_output
, sizeof (DisplayModePtr
));
1564 enabled
= xnfcalloc (config
->num_output
, sizeof (Bool
));
1566 for (o
= 0; o
< config
->num_output
; o
++)
1568 xf86OutputPtr output
= config
->output
[o
];
1571 enabled
[o
] = xf86OutputEnabled (output
);
1575 * Let outputs with preferred modes drive screen size
1577 for (o
= 0; o
< config
->num_output
; o
++)
1579 xf86OutputPtr output
= config
->output
[o
];
1582 xf86OutputHasPreferredMode (output
, width
, height
))
1584 target_mode
= xf86DefaultMode (output
, width
, height
);
1585 target_rotation
= output
->initial_rotation
;
1588 modes
[o
] = target_mode
;
1589 config
->compat_output
= o
;
1596 for (o
= 0; o
< config
->num_output
; o
++)
1598 xf86OutputPtr output
= config
->output
[o
];
1601 target_mode
= xf86DefaultMode (output
, width
, height
);
1602 target_rotation
= output
->initial_rotation
;
1605 modes
[o
] = target_mode
;
1606 config
->compat_output
= o
;
1612 for (o
= 0; o
< config
->num_output
; o
++)
1614 xf86OutputPtr output
= config
->output
[o
];
1619 modes
[o
] = xf86ClosestMode (output
, target_mode
,
1620 target_rotation
, width
, height
);
1622 xf86DrvMsg (scrn
->scrnIndex
, X_ERROR
,
1623 "Output %s enabled but has no modes\n",
1626 xf86DrvMsg (scrn
->scrnIndex
, X_INFO
,
1627 "Output %s using initial mode %s\n",
1628 output
->name
, modes
[o
]->name
);
1633 * Set the position of each output
1635 if (!xf86InitialOutputPositions (scrn
, modes
))
1643 * Assign CRTCs to fit output configuration
1645 if (!xf86PickCrtcs (scrn
, crtcs
, modes
, 0, width
, height
))
1652 /* XXX override xf86 common frame computation code */
1654 scrn
->display
->frameX0
= 0;
1655 scrn
->display
->frameY0
= 0;
1657 for (c
= 0; c
< config
->num_crtc
; c
++)
1659 xf86CrtcPtr crtc
= config
->crtc
[c
];
1661 crtc
->enabled
= FALSE
;
1662 memset (&crtc
->desiredMode
, '\0', sizeof (crtc
->desiredMode
));
1666 * Set initial configuration
1668 for (o
= 0; o
< config
->num_output
; o
++)
1670 xf86OutputPtr output
= config
->output
[o
];
1671 DisplayModePtr mode
= modes
[o
];
1672 xf86CrtcPtr crtc
= crtcs
[o
];
1676 crtc
->desiredMode
= *mode
;
1677 crtc
->desiredRotation
= output
->initial_rotation
;
1678 crtc
->desiredX
= output
->initial_x
;
1679 crtc
->desiredY
= output
->initial_y
;
1680 crtc
->enabled
= TRUE
;
1681 crtc
->x
= output
->initial_x
;
1682 crtc
->y
= output
->initial_y
;
1683 output
->crtc
= crtc
;
1687 if (scrn
->display
->virtualX
== 0)
1690 * Expand virtual size to cover the current config and potential mode
1691 * switches, if the driver can't enlarge the screen later.
1693 xf86DefaultScreenLimits (scrn
, &width
, &height
, canGrow
);
1695 scrn
->display
->virtualX
= width
;
1696 scrn
->display
->virtualY
= height
;
1699 if (width
> scrn
->virtualX
)
1700 scrn
->virtualX
= width
;
1701 if (height
> scrn
->virtualY
)
1702 scrn
->virtualY
= height
;
1705 * Make sure the configuration isn't too small.
1707 if (width
< config
->minWidth
|| height
< config
->minHeight
)
1711 * Limit the crtc config to virtual[XY] if the driver can't grow the
1716 xf86CrtcSetSizeRange (scrn
, config
->minWidth
, config
->minHeight
,
1720 /* Mirror output modes to scrn mode list */
1721 xf86SetScrnInfoModes (scrn
);
1729 * Using the desired mode information in each crtc, set
1730 * modes (used in EnterVT functions, or at server startup)
1734 xf86SetDesiredModes (ScrnInfoPtr scrn
)
1736 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1740 * Turn off everything so mode setting is done
1741 * with hardware in a consistent state
1743 for (o
= 0; o
< config
->num_output
; o
++)
1745 xf86OutputPtr output
= config
->output
[o
];
1746 (*output
->funcs
->dpms
)(output
, DPMSModeOff
);
1749 for (c
= 0; c
< config
->num_crtc
; c
++)
1751 xf86CrtcPtr crtc
= config
->crtc
[c
];
1753 crtc
->funcs
->dpms(crtc
, DPMSModeOff
);
1754 memset(&crtc
->mode
, 0, sizeof(crtc
->mode
));
1757 for (c
= 0; c
< config
->num_crtc
; c
++)
1759 xf86CrtcPtr crtc
= config
->crtc
[c
];
1760 xf86OutputPtr output
= NULL
;
1763 if (config
->output
[config
->compat_output
]->crtc
== crtc
)
1764 output
= config
->output
[config
->compat_output
];
1767 for (o
= 0; o
< config
->num_output
; o
++)
1768 if (config
->output
[o
]->crtc
== crtc
)
1770 output
= config
->output
[o
];
1775 * Skip disabled crtcs
1780 /* Mark that we'll need to re-set the mode for sure */
1781 memset(&crtc
->mode
, 0, sizeof(crtc
->mode
));
1782 if (!crtc
->desiredMode
.CrtcHDisplay
)
1784 DisplayModePtr mode
= xf86OutputFindClosestMode (output
, scrn
->currentMode
);
1788 crtc
->desiredMode
= *mode
;
1789 crtc
->desiredRotation
= RR_Rotate_0
;
1794 if (!xf86CrtcSetMode (crtc
, &crtc
->desiredMode
, crtc
->desiredRotation
,
1795 crtc
->desiredX
, crtc
->desiredY
))
1799 xf86DisableUnusedFunctions(scrn
);
1804 * In the current world order, there are lists of modes per output, which may
1805 * or may not include the mode that was asked to be set by XFree86's mode
1806 * selection. Find the closest one, in the following preference order:
1809 * - Closer in size to the requested mode, but no larger
1810 * - Closer in refresh rate to the requested mode.
1813 _X_EXPORT DisplayModePtr
1814 xf86OutputFindClosestMode (xf86OutputPtr output
, DisplayModePtr desired
)
1816 DisplayModePtr best
= NULL
, scan
= NULL
;
1818 for (scan
= output
->probed_modes
; scan
!= NULL
; scan
= scan
->next
)
1820 /* If there's an exact match, we're done. */
1821 if (xf86ModesEqual(scan
, desired
)) {
1826 /* Reject if it's larger than the desired mode. */
1827 if (scan
->HDisplay
> desired
->HDisplay
||
1828 scan
->VDisplay
> desired
->VDisplay
)
1834 * If we haven't picked a best mode yet, use the first
1835 * one in the size range
1843 /* Find if it's closer to the right size than the current best
1846 if ((scan
->HDisplay
> best
->HDisplay
&&
1847 scan
->VDisplay
>= best
->VDisplay
) ||
1848 (scan
->HDisplay
>= best
->HDisplay
&&
1849 scan
->VDisplay
> best
->VDisplay
))
1855 /* Find if it's still closer to the right refresh than the current
1858 if (scan
->HDisplay
== best
->HDisplay
&&
1859 scan
->VDisplay
== best
->VDisplay
&&
1860 (fabs(scan
->VRefresh
- desired
->VRefresh
) <
1861 fabs(best
->VRefresh
- desired
->VRefresh
))) {
1869 * When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
1870 * take the specified mode and apply it to the crtc connected to the compat
1871 * output. Then, find similar modes for the other outputs, as with the
1872 * InitialConfiguration code above. The goal is to clone the desired
1873 * mode across all outputs that are currently active.
1877 xf86SetSingleMode (ScrnInfoPtr pScrn
, DisplayModePtr desired
, Rotation rotation
)
1879 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1881 xf86OutputPtr compat_output
= config
->output
[config
->compat_output
];
1882 DisplayModePtr compat_mode
;
1886 * Let the compat output drive the final mode selection
1888 compat_mode
= xf86OutputFindClosestMode (compat_output
, desired
);
1890 desired
= compat_mode
;
1892 for (c
= 0; c
< config
->num_crtc
; c
++)
1894 xf86CrtcPtr crtc
= config
->crtc
[c
];
1895 DisplayModePtr crtc_mode
= NULL
;
1901 for (o
= 0; o
< config
->num_output
; o
++)
1903 xf86OutputPtr output
= config
->output
[o
];
1904 DisplayModePtr output_mode
;
1906 /* skip outputs not on this crtc */
1907 if (output
->crtc
!= crtc
)
1912 output_mode
= xf86OutputFindClosestMode (output
, crtc_mode
);
1913 if (output_mode
!= crtc_mode
)
1914 output
->crtc
= NULL
;
1917 crtc_mode
= xf86OutputFindClosestMode (output
, desired
);
1921 crtc
->enabled
= FALSE
;
1924 if (!xf86CrtcSetMode (crtc
, crtc_mode
, rotation
, 0, 0))
1928 crtc
->desiredMode
= *crtc_mode
;
1929 crtc
->desiredRotation
= rotation
;
1934 xf86DisableUnusedFunctions(pScrn
);
1935 #if RANDR_12_INTERFACE
1936 xf86RandR12TellChanged (pScrn
->pScreen
);
1943 * Set the DPMS power mode of all outputs and CRTCs.
1945 * If the new mode is off, it will turn off outputs and then CRTCs.
1946 * Otherwise, it will affect CRTCs before outputs.
1949 xf86DPMSSet(ScrnInfoPtr scrn
, int mode
, int flags
)
1951 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1957 if (mode
== DPMSModeOff
) {
1958 for (i
= 0; i
< config
->num_output
; i
++) {
1959 xf86OutputPtr output
= config
->output
[i
];
1960 if (output
->crtc
!= NULL
)
1961 (*output
->funcs
->dpms
) (output
, mode
);
1965 for (i
= 0; i
< config
->num_crtc
; i
++) {
1966 xf86CrtcPtr crtc
= config
->crtc
[i
];
1968 (*crtc
->funcs
->dpms
) (crtc
, mode
);
1971 if (mode
!= DPMSModeOff
) {
1972 for (i
= 0; i
< config
->num_output
; i
++) {
1973 xf86OutputPtr output
= config
->output
[i
];
1974 if (output
->crtc
!= NULL
)
1975 (*output
->funcs
->dpms
) (output
, mode
);
1981 * Implement the screensaver by just calling down into the driver DPMS hooks.
1983 * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
1984 * the outputs will still get disabled (blanked).
1987 xf86SaveScreen(ScreenPtr pScreen
, int mode
)
1989 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
1991 if (xf86IsUnblank(mode
))
1992 xf86DPMSSet(pScrn
, DPMSModeOn
, 0);
1994 xf86DPMSSet(pScrn
, DPMSModeOff
, 0);
2000 * Disable all inactive crtcs and outputs
2003 xf86DisableUnusedFunctions(ScrnInfoPtr pScrn
)
2005 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
2008 for (o
= 0; o
< xf86_config
->num_output
; o
++)
2010 xf86OutputPtr output
= xf86_config
->output
[o
];
2012 (*output
->funcs
->dpms
)(output
, DPMSModeOff
);
2015 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
2017 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
2021 crtc
->funcs
->dpms(crtc
, DPMSModeOff
);
2022 memset(&crtc
->mode
, 0, sizeof(crtc
->mode
));
2027 #ifdef RANDR_12_INTERFACE
2029 #define EDID_ATOM_NAME "EDID_DATA"
2032 * Set the RandR EDID property
2035 xf86OutputSetEDIDProperty (xf86OutputPtr output
, void *data
, int data_len
)
2037 Atom edid_atom
= MakeAtom(EDID_ATOM_NAME
, sizeof(EDID_ATOM_NAME
) - 1, TRUE
);
2039 /* This may get called before the RandR resources have been created */
2040 if (output
->randr_output
== NULL
)
2043 if (data_len
!= 0) {
2044 RRChangeOutputProperty(output
->randr_output
, edid_atom
, XA_INTEGER
, 8,
2045 PropModeReplace
, data_len
, data
, FALSE
, TRUE
);
2047 RRDeleteOutputProperty(output
->randr_output
, edid_atom
);
2054 * Set the EDID information for the specified output
2057 xf86OutputSetEDID (xf86OutputPtr output
, xf86MonPtr edid_mon
)
2059 ScrnInfoPtr scrn
= output
->scrn
;
2060 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
2062 #ifdef RANDR_12_INTERFACE
2066 if (output
->MonInfo
!= NULL
)
2067 xfree(output
->MonInfo
);
2069 output
->MonInfo
= edid_mon
;
2071 if (config
->debug_modes
) {
2072 xf86DrvMsg(scrn
->scrnIndex
, X_INFO
, "EDID for output %s\n",
2074 xf86PrintEDID(edid_mon
);
2077 /* Set the DDC properties for the 'compat' output */
2078 if (output
== config
->output
[config
->compat_output
])
2079 xf86SetDDCproperties(scrn
, edid_mon
);
2081 #ifdef RANDR_12_INTERFACE
2082 /* Set the RandR output properties */
2086 if (edid_mon
->ver
.version
== 1)
2088 else if (edid_mon
->ver
.version
== 2)
2091 xf86OutputSetEDIDProperty (output
, edid_mon
? edid_mon
->rawData
: NULL
, size
);
2096 /* Pull out a phyiscal size from a detailed timing if available. */
2097 for (i
= 0; i
< 4; i
++) {
2098 if (edid_mon
->det_mon
[i
].type
== DT
&&
2099 edid_mon
->det_mon
[i
].section
.d_timings
.h_size
!= 0 &&
2100 edid_mon
->det_mon
[i
].section
.d_timings
.v_size
!= 0)
2102 output
->mm_width
= edid_mon
->det_mon
[i
].section
.d_timings
.h_size
;
2103 output
->mm_height
= edid_mon
->det_mon
[i
].section
.d_timings
.v_size
;
2108 /* if no mm size is available from a detailed timing, check the max size field */
2109 if ((!output
->mm_width
|| !output
->mm_height
) &&
2110 (edid_mon
->features
.hsize
&& edid_mon
->features
.vsize
))
2112 output
->mm_width
= edid_mon
->features
.hsize
* 10;
2113 output
->mm_height
= edid_mon
->features
.vsize
* 10;
2119 * Return the list of modes supported by the EDID information
2120 * stored in 'output'
2122 _X_EXPORT DisplayModePtr
2123 xf86OutputGetEDIDModes (xf86OutputPtr output
)
2125 ScrnInfoPtr scrn
= output
->scrn
;
2126 xf86MonPtr edid_mon
= output
->MonInfo
;
2130 return xf86DDCGetModes(scrn
->scrnIndex
, edid_mon
);
2133 _X_EXPORT xf86MonPtr
2134 xf86OutputGetEDID (xf86OutputPtr output
, I2CBusPtr pDDCBus
)
2136 ScrnInfoPtr scrn
= output
->scrn
;
2138 return xf86DoEDID_DDC2 (scrn
->scrnIndex
, pDDCBus
);
2141 static char *_xf86ConnectorNames
[] = { "None", "VGA", "DVI-I", "DVI-D",
2142 "DVI-A", "Composite", "S-Video",
2143 "Component", "LFP", "Proprietary" };
2145 xf86ConnectorGetName(xf86ConnectorType connector
)
2147 return _xf86ConnectorNames
[connector
];
2151 x86_crtc_box_intersect(BoxPtr dest
, BoxPtr a
, BoxPtr b
)
2153 dest
->x1
= a
->x1
> b
->x1
? a
->x1
: b
->x1
;
2154 dest
->x2
= a
->x2
< b
->x2
? a
->x2
: b
->x2
;
2155 dest
->y1
= a
->y1
> b
->y1
? a
->y1
: b
->y1
;
2156 dest
->y2
= a
->y2
< b
->y2
? a
->y2
: b
->y2
;
2158 if (dest
->x1
>= dest
->x2
|| dest
->y1
>= dest
->y2
)
2159 dest
->x1
= dest
->x2
= dest
->y1
= dest
->y2
= 0;
2163 x86_crtc_box(xf86CrtcPtr crtc
, BoxPtr crtc_box
)
2165 if (crtc
->enabled
) {
2166 crtc_box
->x1
= crtc
->x
;
2167 crtc_box
->x2
= crtc
->x
+ xf86ModeWidth(&crtc
->mode
, crtc
->rotation
);
2168 crtc_box
->y1
= crtc
->y
;
2169 crtc_box
->y2
= crtc
->y
+ xf86ModeHeight(&crtc
->mode
, crtc
->rotation
);
2171 crtc_box
->x1
= crtc_box
->x2
= crtc_box
->y1
= crtc_box
->y2
= 0;
2175 xf86_crtc_box_area(BoxPtr box
)
2177 return (int) (box
->x2
- box
->x1
) * (int) (box
->y2
- box
->y1
);
2181 * Return the crtc covering 'box'. If two crtcs cover a portion of
2182 * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
2183 * with greater coverage
2187 xf86_covering_crtc(ScrnInfoPtr pScrn
,
2189 xf86CrtcPtr desired
,
2190 BoxPtr crtc_box_ret
)
2192 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(pScrn
);
2193 xf86CrtcPtr crtc
, best_crtc
;
2194 int coverage
, best_coverage
;
2196 BoxRec crtc_box
, cover_box
;
2200 crtc_box_ret
->x1
= 0;
2201 crtc_box_ret
->x2
= 0;
2202 crtc_box_ret
->y1
= 0;
2203 crtc_box_ret
->y2
= 0;
2204 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
2205 crtc
= xf86_config
->crtc
[c
];
2206 x86_crtc_box(crtc
, &crtc_box
);
2207 x86_crtc_box_intersect(&cover_box
, &crtc_box
, box
);
2208 coverage
= xf86_crtc_box_area(&cover_box
);
2209 if (coverage
&& crtc
== desired
) {
2210 *crtc_box_ret
= crtc_box
;
2212 } else if (coverage
> best_coverage
) {
2213 *crtc_box_ret
= crtc_box
;
2215 best_coverage
= coverage
;
2222 * For overlay video, compute the relevant CRTC and
2223 * clip video to that
2227 xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn
,
2228 xf86CrtcPtr
*crtc_ret
,
2229 xf86CrtcPtr desired_crtc
,
2240 RegionRec crtc_region_local
;
2241 RegionPtr crtc_region
= reg
;
2245 xf86CrtcPtr crtc
= xf86_covering_crtc(pScrn
, dst
,
2250 REGION_INIT (pScreen
, &crtc_region_local
, &crtc_box
, 1);
2251 crtc_region
= &crtc_region_local
;
2252 REGION_INTERSECT (pScreen
, crtc_region
, crtc_region
, reg
);
2257 ret
= xf86XVClipVideoHelper(dst
, xa
, xb
, ya
, yb
,
2258 crtc_region
, width
, height
);
2260 if (crtc_region
!= reg
)
2261 REGION_UNINIT (pScreen
, &crtc_region_local
);