@@ -682,65 +682,48 @@ static void fill_detailed_lvds_block(struct detailed_monitor_section *det_mon,
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, struct fixed_panel_lvds *p_lvds)
{
- 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;
-
- 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;
- }
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr koutput = drmmode_output->mode_output;
+
+ xf86MonPtr edid_mon = output->MonInfo;
+ int i, j, flags;
+ DisplayModePtr pmode, m;
+ drmModeModeInfo *mode_ptr;
+ struct detailed_monitor_section *det_mon;
+
+ pmode = xnfalloc(sizeof(DisplayModeRec));
+ drmmode_ConvertFromKMode(output->scrn, &koutput->modes[j], pmode);
+
+ if (edid_mon) {
/*
- * 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
+ * when there exists the EDID, we will clear the GTF flag to avoid
+ * that the xf86GetDefaultModes will be called again in xserver
+ */
+ edid_mon->features.msc &= ~(0x01);
+ } else {
+ /*
+ * When there is no EDID, we will construct the bogus EDID and not
+ * set the GTF flag. This is also to avoid that the xf86GetDefaultModes
+ * will be called again in xserver
*/
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;
+ return modes;
}
- /* Find the fixed panel mode.
+ /*
+ * 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
+ * are added for the LVDS output device.
*/
j = 0;
for (i = 0; i < koutput->count_modes; i++) {
@@ -758,31 +741,38 @@ static int drmmode_output_lvds_edid(xf86OutputPtr output,
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
- */
+ /* construct bogus EDID and 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;
}
- /* 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;
+ if (pmode)
+ xfree(pmode);
+ }
+ /*
+ * Always add the default mode for LVDS and invalidate the mode which is
+ * beyond the range of hdisplay/vdisplay
+ */
+ m = xf86GetDefaultModes();
+ /* validate the default mode list by checking panel size */
+ xf86ValidateModesSize(output->scrn, m, p_lvds->hdisplay,
+ p_lvds->vdisplay, 0);
+
+ /* mark the invalid mode by checking flag(Interface/doublescan) */
+ flags = (output->interlaceAllowed ? V_INTERLACE : 0) |
+ (output->doubleScanAllowed ? V_DBLSCAN : 0);
+ xf86ValidateModesFlags(output->scrn, m, flags);
+ /* remove the invalid mode */
+ xf86PruneInvalidModes(output->scrn, &m, 1);
+ modes = xf86ModesAdd(modes, m);
+
+ return modes;
}
static DisplayModePtr
@@ -854,8 +844,9 @@ drmmode_output_get_modes(xf86OutputPtr output)
if (!p_lvds->hdisplay || !p_lvds->vdisplay)
xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
"Incorrect KMS mode.\n");
- drmmode_output_lvds_edid(output, p_lvds);
+ Modes = drmmode_output_lvds_edid(output, Modes, p_lvds);
}
+
return Modes;
}