diff options
Diffstat (limited to 'driver/xf86-video-nv/compat/modes/xf86Crtc.c')
-rw-r--r-- | driver/xf86-video-nv/compat/modes/xf86Crtc.c | 676 |
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 |