diff -up xf86-video-intel-20090909/src/drmmode_display.c.lvds-modes xf86-video-intel-20090909/src/drmmode_display.c --- xf86-video-intel-20090909/src/drmmode_display.c.lvds-modes 2009-09-18 14:45:51.000000000 -0400 +++ xf86-video-intel-20090909/src/drmmode_display.c 2009-09-18 14:55:06.000000000 -0400 @@ -701,107 +701,46 @@ static void fill_detailed_lvds_block(str timing->misc |= 0x01; } -static int drmmode_output_lvds_edid(xf86OutputPtr output, - struct fixed_panel_lvds *p_lvds) +static DisplayModePtr +drmmode_output_lvds_edid(xf86OutputPtr output, DisplayModePtr modes) { - drmmode_output_private_ptr drmmode_output = output->driver_private; - drmModeConnectorPtr koutput = drmmode_output->mode_output; - int i, j; - DisplayModePtr pmode; - xf86MonPtr edid_mon; - drmModeModeInfo *mode_ptr; - struct detailed_monitor_section *det_mon; + xf86MonPtr mon = output->MonInfo; - if (output->MonInfo) { - /* - * If there exists the EDID, we will either find a DS_RANGES - * or replace a DS_VENDOR block, smashing it into a DS_RANGES - * block with opern refresh to match all the default modes. - */ - int edid_det_block_num; - edid_mon = output->MonInfo; - edid_mon->features.msc |= 0x01; - j = -1; - edid_det_block_num = sizeof(edid_mon->det_mon) / - sizeof(edid_mon->det_mon[0]); - for (i = 0; i < edid_det_block_num; i++) { - if (edid_mon->det_mon[i].type >= DS_VENDOR && j == -1) - j = i; - if (edid_mon->det_mon[i].type == DS_RANGES) { - j = i; - break; - } - } - if (j != -1) { - struct monitor_ranges *ranges = - &edid_mon->det_mon[j].section.ranges; - edid_mon->det_mon[j].type = DS_RANGES; - ranges->min_v = 0; - ranges->max_v = 200; - ranges->min_h = 0; - ranges->max_h = 200; - } - return 0; - } - /* - * If there is no EDID, we will construct a bogus EDID for LVDS output - * device. This is similar to what we have done in i830_lvds.c - */ - edid_mon = NULL; - edid_mon = xcalloc(1, sizeof(xf86Monitor)); - if (!edid_mon) { - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "Can't allocate memory for edid_mon.\n"); - return 0; - } - /* Find the fixed panel mode. - * In theory when there is no EDID, KMS kernel will return only one - * mode. And this can be regarded as fixed lvds panel mode. - * But it will be better to traverse the mode list to get the fixed - * lvds panel mode again as we don't know whether some new modes - * are added for the LVDS output device - */ - j = 0; - for (i = 0; i < koutput->count_modes; i++) { - mode_ptr = &koutput->modes[i]; - if ((mode_ptr->hdisplay == p_lvds->hdisplay) && - (mode_ptr->vdisplay == p_lvds->vdisplay)) { - /* find the fixed panel mode */ - j = i; - break; - } + if (!mon || !GTF_SUPPORTED(mon->features.msc)) { + DisplayModePtr i, m, p = NULL; + int max_x = 0, max_y = 0; + float max_vrefresh = 0.0; + + for (m = modes; m; m = m->next) { + if (m->type & M_T_PREFERRED) + p = m; + max_x = max(max_x, m->HDisplay); + max_y = max(max_y, m->VDisplay); + max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m)); } - pmode = xnfalloc(sizeof(DisplayModeRec)); - drmmode_ConvertFromKMode(output->scrn, &koutput->modes[j], pmode); - /*support DPM, instead of DPMS*/ - edid_mon->features.dpms |= 0x1; - /*defaultly support RGB color display*/ - edid_mon->features.display_type |= 0x1; - /*defaultly display support continuous-freqencey*/ - edid_mon->features.msc |= 0x1; - /*defaultly the EDID version is 1.4 */ - edid_mon->ver.version = 1; - edid_mon->ver.revision = 4; - det_mon = edid_mon->det_mon; - if (pmode) { - /* now we construct new EDID monitor, - * so filled one detailed timing block - */ - fill_detailed_lvds_block(det_mon, pmode); - /* the filed timing block should be set preferred*/ - edid_mon->features.msc |= 0x2; - det_mon = det_mon + 1; + + max_vrefresh = max(max_vrefresh, 60.0); + max_vrefresh *= (1 + SYNC_TOLERANCE); + + m = xf86GetDefaultModes(); + + xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0); + + for (i = m; i; i = i->next) { + if (xf86ModeVRefresh(i) > max_vrefresh) + i->status = MODE_VSYNC; + if (p && i->HDisplay >= p->HDisplay && + i->VDisplay >= p->VDisplay && + xf86ModeVRefresh(i) >= xf86ModeVRefresh(p)) + i->status = MODE_VSYNC; } - /* Set wide sync ranges so we get all modes - * handed to valid_mode for checking - */ - det_mon->type = DS_RANGES; - det_mon->section.ranges.min_v = 0; - det_mon->section.ranges.max_v = 200; - det_mon->section.ranges.min_h = 0; - det_mon->section.ranges.max_h = 200; - output->MonInfo = edid_mon; - return 0; + + xf86PruneInvalidModes(output->scrn, &m, FALSE); + + modes = xf86ModesAdd(modes, m); + } + + return modes; } static DisplayModePtr @@ -869,8 +808,11 @@ drmmode_output_get_modes(xf86OutputPtr o if (!p_lvds->hdisplay || !p_lvds->vdisplay) xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "Incorrect KMS mode.\n"); - drmmode_output_lvds_edid(output, p_lvds); } + + if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) + Modes = drmmode_output_lvds_edid(output, Modes); + return Modes; }