summaryrefslogtreecommitdiff
path: root/driver/xf86-video-nv/compat/modes/xf86Crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/xf86-video-nv/compat/modes/xf86Crtc.c')
-rw-r--r--driver/xf86-video-nv/compat/modes/xf86Crtc.c676
1 files changed, 562 insertions, 114 deletions
diff --git a/driver/xf86-video-nv/compat/modes/xf86Crtc.c b/driver/xf86-video-nv/compat/modes/xf86Crtc.c
index d375da897..855d646da 100644
--- a/driver/xf86-video-nv/compat/modes/xf86Crtc.c
+++ b/driver/xf86-video-nv/compat/modes/xf86Crtc.c
@@ -1,5 +1,6 @@
/*
* Copyright © 2006 Keith Packard
+ * Copyright © 2008 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -36,6 +37,7 @@
#include "xf86DDC.h"
#include "xf86Crtc.h"
#include "xf86Modes.h"
+#include "xf86Priv.h"
#include "xf86RandR12.h"
#include "X11/extensions/render.h"
#define DPMS_SERVER
@@ -235,6 +237,9 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
int saved_x, saved_y;
Rotation saved_rotation;
+ if (crtc->funcs->set_mode_major)
+ return crtc->funcs->set_mode_major(crtc, mode, rotation, x, y);
+
crtc->enabled = xf86CrtcInUse (crtc);
if (!crtc->enabled)
@@ -259,6 +264,30 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
crtc->y = y;
crtc->rotation = rotation;
+ /* Shift offsets that move us out of virtual size */
+ if (x + mode->HDisplay > xf86_config->maxWidth ||
+ y + mode->VDisplay > xf86_config->maxHeight)
+ {
+ if (x + mode->HDisplay > xf86_config->maxWidth)
+ crtc->x = xf86_config->maxWidth - mode->HDisplay;
+ if (y + mode->VDisplay > xf86_config->maxHeight)
+ crtc->y = xf86_config->maxHeight - mode->VDisplay;
+ if (crtc->x < 0 || crtc->y < 0)
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Mode %dx%d does not fit virtual size %dx%d - "
+ "internal error\n", mode->HDisplay, mode->VDisplay,
+ xf86_config->maxWidth, xf86_config->maxHeight);
+ goto done;
+ }
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Mode %dx%d+%d+%d does not fit virtual size %dx%d - "
+ "offset updated to +%d+%d\n",
+ mode->HDisplay, mode->VDisplay, x, y,
+ xf86_config->maxWidth, xf86_config->maxHeight,
+ crtc->x, crtc->y);
+ }
+
/* XXX short-circuit changes to base location only */
/* Pass our mode to the outputs and the CRTC to give them a chance to
@@ -300,7 +329,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
/* Set up the DPLL and any output state that needs to adjust or depend
* on the DPLL.
*/
- crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
+ crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y);
for (i = 0; i < xf86_config->num_output; i++)
{
xf86OutputPtr output = xf86_config->output[i];
@@ -438,7 +467,7 @@ xf86OutputSetMonitor (xf86OutputPtr output)
}
static Bool
-xf86OutputEnabled (xf86OutputPtr output)
+xf86OutputEnabled (xf86OutputPtr output, Bool strict)
{
Bool enable, disable;
@@ -456,8 +485,16 @@ xf86OutputEnabled (xf86OutputPtr output)
"Output %s disabled by config file\n", output->name);
return FALSE;
}
- /* otherwise, enable if it is not disconnected */
- enable = output->status != XF86OutputStatusDisconnected;
+
+ /* If not, try to only light up the ones we know are connected */
+ if (strict) {
+ enable = output->status == XF86OutputStatusConnected;
+ }
+ /* But if that fails, try to light up even outputs we're unsure of */
+ else {
+ enable = output->status != XF86OutputStatusDisconnected;
+ }
+
xf86DrvMsg (output->scrn->scrnIndex, X_INFO,
"Output %s %sconnected\n", output->name, enable ? "" : "dis");
return enable;
@@ -704,14 +741,15 @@ xf86DefaultMode (xf86OutputPtr output, int width, int height)
mm_height = output->mm_height;
if (!mm_height)
- mm_height = 203; /* 768 pixels at 96dpi */
+ mm_height = (768 * 25.4) / DEFAULT_DPI;
/*
- * Pick a mode closest to 96dpi
+ * Pick a mode closest to DEFAULT_DPI
*/
for (mode = output->probed_modes; mode; mode = mode->next)
{
int dpi;
- int preferred = (mode->type & M_T_PREFERRED) != 0;
+ int preferred = (((mode->type & M_T_PREFERRED) != 0) +
+ ((mode->type & M_T_USERPREF) != 0));
int diff;
if (xf86ModeWidth (mode, output->initial_rotation) > width ||
@@ -720,7 +758,7 @@ xf86DefaultMode (xf86OutputPtr output, int width, int height)
/* yes, use VDisplay here, not xf86ModeHeight */
dpi = (mode->VDisplay * 254) / (mm_height * 10);
- diff = dpi - 96;
+ diff = dpi - DEFAULT_DPI;
diff = diff < 0 ? -diff : diff;
if (target_mode == NULL || (preferred > target_preferred) ||
(preferred == target_preferred && diff < target_diff))
@@ -771,7 +809,7 @@ xf86ClosestMode (xf86OutputPtr output,
return target_mode;
}
-static Bool
+static DisplayModePtr
xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
{
DisplayModePtr mode;
@@ -783,9 +821,21 @@ xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
continue;
if (mode->type & M_T_PREFERRED)
- return TRUE;
+ return mode;
}
- return FALSE;
+ return NULL;
+}
+
+static DisplayModePtr
+xf86OutputHasUserPreferredMode (xf86OutputPtr output)
+{
+ DisplayModePtr mode, first = output->probed_modes;
+
+ for (mode = first; mode && mode->next != first; mode = mode->next)
+ if (mode->type & M_T_USERPREF)
+ return mode;
+
+ return NULL;
}
static int
@@ -1053,6 +1103,16 @@ xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
any_set = TRUE;
continue;
}
+ if (!modes[or])
+ {
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Cannot position output %s relative to output %s without modes\n",
+ output->name, relative_name);
+ output->initial_x = 0;
+ output->initial_y = 0;
+ any_set = TRUE;
+ continue;
+ }
if (relative->initial_x == POSITION_UNSET)
{
keep_going = TRUE;
@@ -1068,10 +1128,10 @@ xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation);
break;
case OPTION_ABOVE:
- output->initial_y -= xf86ModeHeight (modes[or], relative->initial_rotation);
+ output->initial_y -= xf86ModeHeight (modes[o], relative->initial_rotation);
break;
case OPTION_LEFT_OF:
- output->initial_x -= xf86ModeWidth (modes[or], relative->initial_rotation);
+ output->initial_x -= xf86ModeWidth (modes[o], relative->initial_rotation);
break;
default:
break;
@@ -1214,6 +1274,67 @@ xf86SortModes (DisplayModePtr input)
return output;
}
+static char *
+preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output)
+{
+ char *preferred_mode = NULL;
+
+ /* Check for a configured preference for a particular mode */
+ preferred_mode = xf86GetOptValString (output->options,
+ OPTION_PREFERRED_MODE);
+ if (preferred_mode)
+ return preferred_mode;
+
+ if (pScrn->display->modes && *pScrn->display->modes)
+ preferred_mode = *pScrn->display->modes;
+
+ return preferred_mode;
+}
+
+static void
+GuessRangeFromModes(MonPtr mon, DisplayModePtr mode)
+{
+ if (!mon || !mode)
+ return;
+
+ mon->nHsync = 1;
+ mon->hsync[0].lo = 1024.0;
+ mon->hsync[0].hi = 0.0;
+
+ mon->nVrefresh = 1;
+ mon->vrefresh[0].lo = 1024.0;
+ mon->vrefresh[0].hi = 0.0;
+
+ while (mode) {
+ if (!mode->HSync)
+ mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal);
+
+ if (!mode->VRefresh)
+ mode->VRefresh = (1000.0 * ((float) mode->Clock)) /
+ ((float) (mode->HTotal * mode->VTotal));
+
+ if (mode->HSync < mon->hsync[0].lo)
+ mon->hsync[0].lo = mode->HSync;
+
+ if (mode->HSync > mon->hsync[0].hi)
+ mon->hsync[0].hi = mode->HSync;
+
+ if (mode->VRefresh < mon->vrefresh[0].lo)
+ mon->vrefresh[0].lo = mode->VRefresh;
+
+ if (mode->VRefresh > mon->vrefresh[0].hi)
+ mon->vrefresh[0].hi = mode->VRefresh;
+
+ mode = mode->next;
+ }
+
+ /* stretch out the bottom to fit 640x480@60 */
+ if (mon->hsync[0].lo > 31.0)
+ mon->hsync[0].lo = 31.0;
+ if (mon->vrefresh[0].lo > 58.0)
+ mon->vrefresh[0].lo = 58.0;
+}
+
_X_EXPORT void
xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
{
@@ -1318,8 +1439,8 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
if (sync_source == sync_default)
sync_source = sync_edid;
}
- if (ranges->max_clock > max_clock)
- max_clock = ranges->max_clock;
+ if (ranges->max_clock * 1000 > max_clock)
+ max_clock = ranges->max_clock * 1000;
}
}
}
@@ -1331,6 +1452,10 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
OPTUNITS_KHZ, &clock))
max_clock = (int) clock;
+ /* If we still don't have a sync range, guess wildly */
+ if (!mon_rec.nHsync || !mon_rec.nVrefresh)
+ GuessRangeFromModes(&mon_rec, output_modes);
+
/*
* These limits will end up setting a 1024x768@60Hz mode by default,
* which seems like a fairly good mode to use when nothing else is
@@ -1350,7 +1475,14 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
}
default_modes = xf86GetDefaultModes (output->interlaceAllowed,
output->doubleScanAllowed);
-
+
+ /*
+ * If this is not an RB monitor, remove RB modes from the default
+ * pool. RB modes from the config or the monitor itself are fine.
+ */
+ if (!mon_rec.reducedblanking)
+ xf86ValidateModesReducedBlanking (scrn, default_modes);
+
if (sync_source == sync_config)
{
/*
@@ -1366,9 +1498,12 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
/*
* Check default modes against monitor max clock
*/
- if (max_clock)
+ if (max_clock) {
xf86ValidateModesClocks(scrn, default_modes,
&min_clock, &max_clock, 1);
+ xf86ValidateModesClocks(scrn, output_modes,
+ &min_clock, &max_clock, 1);
+ }
output->probed_modes = NULL;
output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
@@ -1395,8 +1530,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
output->probed_modes = xf86SortModes (output->probed_modes);
/* Check for a configured preference for a particular mode */
- preferred_mode = xf86GetOptValString (output->options,
- OPTION_PREFERRED_MODE);
+ preferred_mode = preferredMode(scrn, output);
if (preferred_mode)
{
@@ -1415,10 +1549,9 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
mode->prev = NULL;
output->probed_modes = mode;
}
- mode->type |= M_T_PREFERRED;
+ mode->type |= (M_T_PREFERRED|M_T_USERPREF);
+ break;
}
- else
- mode->type &= ~M_T_PREFERRED;
}
}
@@ -1458,7 +1591,98 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
_X_EXPORT void
xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);
-_X_EXPORT void
+static DisplayModePtr
+biggestMode(DisplayModePtr a, DisplayModePtr b)
+{
+ int A, B;
+
+ if (!a)
+ return b;
+ if (!b)
+ return a;
+
+ A = a->HDisplay * a->VDisplay;
+ B = b->HDisplay * b->VDisplay;
+
+ if (A > B)
+ return a;
+
+ return b;
+}
+
+static xf86OutputPtr
+SetCompatOutput(xf86CrtcConfigPtr config)
+{
+ xf86OutputPtr output = NULL, test = NULL;
+ DisplayModePtr maxmode = NULL, testmode, mode;
+ int o, compat = -1, count, mincount = 0;
+
+ /* Look for one that's definitely connected */
+ for (o = 0; o < config->num_output; o++)
+ {
+ test = config->output[o];
+ if (!test->crtc)
+ continue;
+ if (test->status != XF86OutputStatusConnected)
+ continue;
+ if (!test->probed_modes)
+ continue;
+
+ testmode = mode = test->probed_modes;
+ for (count = 0; mode; mode = mode->next, count++)
+ testmode = biggestMode(testmode, mode);
+
+ if (!output) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ } else if (maxmode == biggestMode(maxmode, testmode)) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ } else if ((maxmode->HDisplay == testmode->HDisplay) &&
+ (maxmode->VDisplay == testmode->VDisplay) &&
+ count <= mincount) {
+ output = test;
+ compat = o;
+ maxmode = testmode;
+ mincount = count;
+ }
+ }
+
+ /* If we didn't find one, take anything we can get */
+ if (!output)
+ {
+ for (o = 0; o < config->num_output; o++)
+ {
+ test = config->output[o];
+ if (!test->crtc)
+ continue;
+ if (!test->probed_modes)
+ continue;
+
+ if (!output) {
+ output = test;
+ compat = o;
+ } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) {
+ output = test;
+ compat = o;
+ }
+ }
+ }
+
+ if (compat >= 0) {
+ config->compat_output = compat;
+ } else {
+ /* Don't change the compat output when no valid outputs found */
+ output = config->output[config->compat_output];
+ }
+
+ return output;
+}
+
xf86SetScrnInfoModes (ScrnInfoPtr scrn)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1466,23 +1690,11 @@ xf86SetScrnInfoModes (ScrnInfoPtr scrn)
xf86CrtcPtr crtc;
DisplayModePtr last, mode;
- output = config->output[config->compat_output];
- if (!output->crtc)
- {
- int o;
+ output = SetCompatOutput(config);
+
+ if (!output)
+ return; /* punt */
- output = NULL;
- for (o = 0; o < config->num_output; o++)
- if (config->output[o]->crtc)
- {
- config->compat_output = o;
- output = config->output[o];
- break;
- }
- /* no outputs are active, punt and leave things as they are */
- if (!output)
- return;
- }
crtc = output->crtc;
/* Clear any existing modes from scrn->modes */
@@ -1512,6 +1724,271 @@ xf86SetScrnInfoModes (ScrnInfoPtr scrn)
scrn->currentMode = scrn->modes;
}
+static void
+xf86EnableOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, Bool *enabled)
+{
+ Bool any_enabled = FALSE;
+ int o;
+
+ for (o = 0; o < config->num_output; o++)
+ any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE);
+
+ if (!any_enabled) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "No outputs definitely connected, trying again...\n");
+
+ for (o = 0; o < config->num_output; o++)
+ enabled[o] = xf86OutputEnabled(config->output[o], FALSE);
+ }
+}
+
+static Bool
+nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index)
+{
+ int o = *index;
+
+ for (o++; o < config->num_output; o++) {
+ if (enabled[o]) {
+ *index = o;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static Bool
+xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o, p;
+ int max_pref_width = 0, max_pref_height = 0;
+ DisplayModePtr *preferred, *preferred_match;
+ Bool ret = FALSE;
+
+ preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
+ preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr));
+
+ /* Check if the preferred mode is available on all outputs */
+ for (p = -1; nextEnabledOutput(config, enabled, &p); ) {
+ Rotation r = config->output[p]->initial_rotation;
+ DisplayModePtr mode;
+ if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p],
+ width, height))) {
+ int pref_width = xf86ModeWidth(preferred[p], r);
+ int pref_height = xf86ModeHeight(preferred[p], r);
+ Bool all_match = TRUE;
+
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ Bool match = FALSE;
+ xf86OutputPtr output = config->output[o];
+ if (o == p)
+ continue;
+
+ for (mode = output->probed_modes; mode; mode = mode->next) {
+ Rotation r = output->initial_rotation;
+ if (xf86ModeWidth(mode, r) == pref_width &&
+ xf86ModeHeight(mode, r) == pref_height) {
+ preferred[o] = mode;
+ match = TRUE;
+ }
+ }
+
+ all_match &= match;
+ }
+
+ if (all_match &&
+ (pref_width*pref_height > max_pref_width*max_pref_height)) {
+ for (o = -1; nextEnabledOutput(config, enabled, &o); )
+ preferred_match[o] = preferred[o];
+ max_pref_width = pref_width;
+ max_pref_height = pref_height;
+ ret = TRUE;
+ }
+ }
+ }
+
+ if (ret) {
+ /* oh good, there is a match. stash the selected modes and return. */
+ memcpy(modes, preferred_match,
+ config->num_output * sizeof(DisplayModePtr));
+ }
+
+ xfree(preferred);
+ xfree(preferred_match);
+ return ret;
+}
+
+static Bool
+aspectMatch(float a, float b)
+{
+ return fabs(1 - (a / b)) < 0.05;
+}
+
+static DisplayModePtr
+nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect)
+{
+ DisplayModePtr m = NULL;
+
+ if (!o)
+ return NULL;
+
+ if (!last)
+ m = o->probed_modes;
+ else
+ m = last->next;
+
+ for (; m; m = m->next)
+ if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay))
+ return m;
+
+ return NULL;
+}
+
+static DisplayModePtr
+bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect)
+{
+ int o = -1, p;
+ DisplayModePtr mode = NULL, test = NULL, match = NULL;
+
+ nextEnabledOutput(config, enabled, &o);
+ while ((mode = nextAspectMode(config->output[o], mode, aspect))) {
+ for (p = o; nextEnabledOutput(config, enabled, &p); ) {
+ test = xf86OutputFindClosestMode(config->output[p], mode);
+ if (!test)
+ break;
+ if (test->HDisplay != mode->HDisplay ||
+ test->VDisplay != mode->VDisplay) {
+ test = NULL;
+ break;
+ }
+ }
+
+ /* if we didn't match it on all outputs, try the next one */
+ if (!test)
+ continue;
+
+ /* if it's bigger than the last one, save it */
+ if (!match || (test->HDisplay > match->HDisplay))
+ match = test;
+ }
+
+ /* return the biggest one found */
+ return match;
+}
+
+static Bool
+xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o;
+ float aspect = 0.0, *aspects;
+ xf86OutputPtr output;
+ Bool ret = FALSE;
+ DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL;
+
+ aspects = xnfcalloc(config->num_output, sizeof(float));
+
+ /* collect the aspect ratios */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ output = config->output[o];
+ if (output->mm_height)
+ aspects[o] = (float)output->mm_width / (float)output->mm_height;
+ else
+ aspects[o] = 4.0 / 3.0;
+ }
+
+ /* check that they're all the same */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ output = config->output[o];
+ if (!aspect) {
+ aspect = aspects[o];
+ } else if (!aspectMatch(aspect, aspects[o])) {
+ goto no_aspect_match;
+ }
+ }
+
+ /* if they're all 4:3, just skip ahead and save effort */
+ if (!aspectMatch(aspect, 4.0/3.0))
+ aspect_guess = bestModeForAspect(config, enabled, aspect);
+
+no_aspect_match:
+ base_guess = bestModeForAspect(config, enabled, 4.0/3.0);
+
+ guess = biggestMode(base_guess, aspect_guess);
+
+ if (!guess)
+ goto out;
+
+ /* found a mode that works everywhere, now apply it */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ modes[o] = xf86OutputFindClosestMode(config->output[o], guess);
+ }
+ ret = TRUE;
+
+out:
+ xfree(aspects);
+ return ret;
+}
+
+static Bool
+xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ DisplayModePtr target_mode = NULL;
+ Rotation target_rotation = RR_Rotate_0;
+ DisplayModePtr default_mode;
+ int default_preferred, target_preferred = 0, o;
+
+ /* User preferred > preferred > other modes */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ default_mode = xf86DefaultMode (config->output[o], width, height);
+ if (!default_mode)
+ continue;
+
+ default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) +
+ ((default_mode->type & M_T_USERPREF) != 0));
+
+ if (default_preferred > target_preferred || !target_mode) {
+ target_mode = default_mode;
+ target_preferred = default_preferred;
+ target_rotation = config->output[o]->initial_rotation;
+ config->compat_output = o;
+ }
+ }
+
+ if (target_mode)
+ modes[config->compat_output] = target_mode;
+
+ /* Fill in other output modes */
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ if (!modes[o])
+ modes[o] = xf86ClosestMode(config->output[o], target_mode,
+ target_rotation, width, height);
+ }
+
+ return (target_mode != NULL);
+}
+
+static Bool
+xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config,
+ DisplayModePtr *modes, Bool *enabled,
+ int width, int height)
+{
+ int o;
+
+ for (o = -1; nextEnabledOutput(config, enabled, &o); )
+ if (xf86OutputHasUserPreferredMode(config->output[o]))
+ return
+ xf86TargetFallback(scrn, config, modes, enabled, width, height);
+
+ return FALSE;
+}
+
+
/**
* Construct default screen configuration
*
@@ -1531,13 +2008,11 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
int o, c;
- DisplayModePtr target_mode = NULL;
- Rotation target_rotation = RR_Rotate_0;
xf86CrtcPtr *crtcs;
DisplayModePtr *modes;
Bool *enabled;
- int width;
- int height;
+ int width, height;
+ int i = scrn->scrnIndex;
/* Set up the device options */
config->options = xnfalloc (sizeof (xf86DeviceOptions));
@@ -1563,70 +2038,28 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
enabled = xnfcalloc (config->num_output, sizeof (Bool));
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
-
- modes[o] = NULL;
- enabled[o] = xf86OutputEnabled (output);
- }
-
- /*
- * Let outputs with preferred modes drive screen size
- */
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
+ xf86EnableOutputs(scrn, config, enabled);
+
+ if (xf86TargetUserpref(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n");
+ else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n");
+ else if (xf86TargetAspect(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n");
+ else if (xf86TargetFallback(scrn, config, modes, enabled, width, height))
+ xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n");
+ else
+ xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n");
- if (enabled[o] &&
- xf86OutputHasPreferredMode (output, width, height))
- {
- target_mode = xf86DefaultMode (output, width, height);
- target_rotation = output->initial_rotation;
- if (target_mode)
- {
- modes[o] = target_mode;
- config->compat_output = o;
- break;
- }
- }
- }
- if (!target_mode)
- {
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
- if (enabled[o])
- {
- target_mode = xf86DefaultMode (output, width, height);
- target_rotation = output->initial_rotation;
- if (target_mode)
- {
- modes[o] = target_mode;
- config->compat_output = o;
- break;
- }
- }
- }
- }
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
-
- if (enabled[o])
- {
- if (!modes[o])
- modes[o] = xf86ClosestMode (output, target_mode,
- target_rotation, width, height);
- if (!modes[o])
- xf86DrvMsg (scrn->scrnIndex, X_ERROR,
- "Output %s enabled but has no modes\n",
- output->name);
- else
- xf86DrvMsg (scrn->scrnIndex, X_INFO,
- "Output %s using initial mode %s\n",
- output->name, modes[o]->name);
- }
+ for (o = -1; nextEnabledOutput(config, enabled, &o); ) {
+ if (!modes[o])
+ xf86DrvMsg (scrn->scrnIndex, X_ERROR,
+ "Output %s enabled but has no modes\n",
+ config->output[o]->name);
+ else
+ xf86DrvMsg (scrn->scrnIndex, X_INFO,
+ "Output %s using initial mode %s\n",
+ config->output[o]->name, modes[o]->name);
}
/*
@@ -1681,6 +2114,8 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
crtc->x = output->initial_x;
crtc->y = output->initial_y;
output->crtc = crtc;
+ } else {
+ output->crtc = NULL;
}
}
@@ -1760,6 +2195,10 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
xf86OutputPtr output = NULL;
int o;
+ /* Skip disabled CRTCs */
+ if (!crtc->enabled)
+ continue;
+
if (config->output[config->compat_output]->crtc == crtc)
output = config->output[config->compat_output];
else
@@ -1771,9 +2210,7 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
break;
}
}
- /*
- * Skip disabled crtcs
- */
+ /* paranoia */
if (!output)
continue;
@@ -2134,13 +2571,21 @@ _X_EXPORT xf86MonPtr
xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
{
ScrnInfoPtr scrn = output->scrn;
+ xf86MonPtr mon;
+
+ mon = xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
+ if (mon)
+ xf86DDCApplyQuirks (scrn->scrnIndex, mon);
- return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
+ return mon;
}
-static char *_xf86ConnectorNames[] = { "None", "VGA", "DVI-I", "DVI-D",
- "DVI-A", "Composite", "S-Video",
- "Component", "LFP", "Proprietary" };
+static char *_xf86ConnectorNames[] = {
+ "None", "VGA", "DVI-I", "DVI-D",
+ "DVI-A", "Composite", "S-Video",
+ "Component", "LFP", "Proprietary",
+ "HDMI", "DisplayPort",
+ };
_X_EXPORT char *
xf86ConnectorGetName(xf86ConnectorType connector)
{
@@ -2220,7 +2665,10 @@ xf86_covering_crtc(ScrnInfoPtr pScrn,
/*
* For overlay video, compute the relevant CRTC and
- * clip video to that
+ * clip video to that.
+ *
+ * returning FALSE means there was a memory failure of some kind,
+ * not that the video shouldn't be displayed
*/
_X_EXPORT Bool