xf86-video-intel: 3 commits - src/drmmode_display.c
Zhenyu Wang
zhen at kemper.freedesktop.org
Mon Jun 15 20:28:48 PDT 2009
src/drmmode_display.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 188 insertions(+), 1 deletion(-)
New commits:
commit 246cec965958e94babf5377e6f221522b05fb458
Author: Zhao Yakui <yakui.zhao at intel.com>
Date: Wed Jun 10 11:17:28 2009 +0800
Fix EDID for LVDS output device to add the default modes
Fix the EDID for the LVDS output device to add the default modes.This is
similar to what we have done in UMS mode.
a. When there exists the EDID, either find the DS_RANGES block or replace
a DS_VENDOR block, smashing it into a DS_RANGES block with open refresh
to match all the defaults modes.
b. When there is no EDID, we will construct a bogus EDID and add a DS_RANGES
block with the open refresh to match all the default modes.
http://bugs.freedesktop.org/show_bug.cgi?id=20801
http://bugs.freedesktop.org/show_bug.cgi?id=21094
http://bugs.freedesktop.org/show_bug.cgi?id=21346
http://bugs.freedesktop.org/show_bug.cgi?id=21417
http://bugs.freedesktop.org/show_bug.cgi?id=21671
Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index aee885a..02a71ae 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -489,6 +489,132 @@ drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
return MODE_OK;
}
+static void fill_detailed_lvds_block(struct detailed_monitor_section *det_mon,
+ DisplayModePtr mode)
+{
+ struct detailed_timings *timing = &det_mon->section.d_timings;
+
+ det_mon->type = DT;
+ timing->clock = mode->Clock * 1000;
+ timing->h_active = mode->HDisplay;
+ timing->h_blanking = mode->HTotal - mode->HDisplay;
+ timing->v_active = mode->VDisplay;
+ timing->v_blanking = mode->VTotal - mode->VDisplay;
+ timing->h_sync_off = mode->HSyncStart - mode->HDisplay;
+ timing->h_sync_width = mode->HSyncEnd - mode->HSyncStart;
+ timing->v_sync_off = mode->VSyncStart - mode->VDisplay;
+ timing->v_sync_width = mode->VSyncEnd - mode->VSyncStart;
+
+ if (mode->Flags & V_PVSYNC)
+ timing->misc |= 0x02;
+
+ if (mode->Flags & V_PHSYNC)
+ timing->misc |= 0x01;
+}
+
+static int drmmode_output_lvds_edid(xf86OutputPtr output,
+ 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;
+ }
+ /*
+ * 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;
+ }
+ }
+ 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;
+ }
+ /* 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;
+}
+
static DisplayModePtr
drmmode_output_get_modes(xf86OutputPtr output)
{
@@ -555,6 +681,7 @@ 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);
}
return Modes;
}
commit 5d1dc7677004d445a7a781decd8c1ef9747c14fb
Author: Zhao Yakui <yakui.zhao at intel.com>
Date: Wed Jun 10 11:17:27 2009 +0800
Get the LVDS panel limit and check whether the given modeline is valid
When the connector type is LVDS, it will traverse the mode list returned by
KMS kernel to get the LVDS panel limit. Then it will use the panel limit to
check whether the given modeline is valid. If the given modeline exceeds
the LVDS panel limit, it will be invalid.
http://bugs.freedesktop.org/show_bug.cgi?id=20801
http://bugs.freedesktop.org/show_bug.cgi?id=21094
http://bugs.freedesktop.org/show_bug.cgi?id=21346
http://bugs.freedesktop.org/show_bug.cgi?id=21417
http://bugs.freedesktop.org/show_bug.cgi?id=21671
Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index c9e15a4..aee885a 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -471,6 +471,21 @@ drmmode_output_detect(xf86OutputPtr output)
static Bool
drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr koutput = drmmode_output->mode_output;
+ struct fixed_panel_lvds *p_lvds = drmmode_output->private_data;
+
+ /*
+ * If the connector type is LVDS, we will use the panel limit to
+ * verfiy whether the mode is valid.
+ */
+ if ((koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) && p_lvds) {
+ if (pModes->HDisplay > p_lvds->hdisplay ||
+ pModes->VDisplay > p_lvds->vdisplay)
+ return MODE_PANEL;
+ else
+ return MODE_OK;
+ }
return MODE_OK;
}
@@ -483,6 +498,8 @@ drmmode_output_get_modes(xf86OutputPtr output)
int i;
DisplayModePtr Modes = NULL, Mode;
drmModePropertyPtr props;
+ struct fixed_panel_lvds *p_lvds;
+ drmModeModeInfo *mode_ptr;
/* look for an EDID property */
for (i = 0; i < koutput->count_props; i++) {
@@ -518,6 +535,27 @@ drmmode_output_get_modes(xf86OutputPtr output)
Modes = xf86ModesAdd(Modes, Mode);
}
+ p_lvds = drmmode_output->private_data;
+ /*
+ * If the connector type is LVDS, we will traverse the kernel mode to
+ * get the panel limit.
+ * If it is incorrect, please fix me.
+ */
+ if ((koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) && p_lvds) {
+ p_lvds->hdisplay = 0;
+ p_lvds->vdisplay = 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)) {
+ p_lvds->hdisplay = mode_ptr->hdisplay;
+ p_lvds->vdisplay = mode_ptr->vdisplay;
+ }
+ }
+ if (!p_lvds->hdisplay || !p_lvds->vdisplay)
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "Incorrect KMS mode.\n");
+ }
return Modes;
}
commit 115e28639fbf6a1eba636dafac02fadd83036c75
Author: Zhao Yakui <yakui.zhao at intel.com>
Date: Wed Jun 10 11:17:26 2009 +0800
Add the private data for the LVDS connector
Add the private data when the connector type is LVDS.
We can use the private_data to store the LVDS panel limit.
For example: Hdisplay, Vdisplay.
http://bugs.freedesktop.org/show_bug.cgi?id=20801
http://bugs.freedesktop.org/show_bug.cgi?id=21094
http://bugs.freedesktop.org/show_bug.cgi?id=21346
http://bugs.freedesktop.org/show_bug.cgi?id=21417
http://bugs.freedesktop.org/show_bug.cgi?id=21671
Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 24e0e26..c9e15a4 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -58,6 +58,10 @@ typedef struct {
Atom *atoms;
} drmmode_prop_rec, *drmmode_prop_ptr;
+struct fixed_panel_lvds {
+ int hdisplay;
+ int vdisplay;
+};
typedef struct {
drmmode_ptr drmmode;
int output_id;
@@ -66,6 +70,8 @@ typedef struct {
drmModePropertyBlobPtr edid_blob;
int num_props;
drmmode_prop_ptr props;
+ void *private_data;
+ /* this is used to store private data */
} drmmode_output_private_rec, *drmmode_output_private_ptr;
static void
@@ -529,6 +535,10 @@ drmmode_output_destroy(xf86OutputPtr output)
}
xfree(drmmode_output->props);
drmModeFreeConnector(drmmode_output->mode_output);
+ if (drmmode_output->private_data) {
+ xfree(drmmode_output->private_data);
+ drmmode_output->private_data = NULL;
+ }
xfree(drmmode_output);
output->driver_private = NULL;
}
@@ -792,7 +802,19 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
drmModeFreeEncoder(kencoder);
return;
}
-
+ /*
+ * If the connector type of the output device is LVDS, we will
+ * allocate the private_data to store the panel limit.
+ * For example: hdisplay, vdisplay
+ */
+ drmmode_output->private_data = NULL;
+ if (koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) {
+ drmmode_output->private_data = xcalloc(
+ sizeof(struct fixed_panel_lvds), 1);
+ if (!drmmode_output->private_data)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Can't allocate private memory for LVDS.\n");
+ }
drmmode_output->output_id = drmmode->mode_res->connectors[num];
drmmode_output->mode_output = koutput;
drmmode_output->mode_encoder = kencoder;
More information about the xorg-commit
mailing list