summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-03-03 20:21:17 -0500
committerAlex Deucher <alexdeucher@gmail.com>2009-03-03 20:21:17 -0500
commit1a2b16561d19ec9c027c562902f5fc086c856994 (patch)
tree09478fb580837e104063f8dc6abe359163a63ac2
parent71117970df36cbe689ef15e9a6cca24439b4cd62 (diff)
radeon: adjust LVDS so that default modes get added
we can scale, so add the default modes. for panels with an EDID, set the continous freq bit. for panels without and EDID, add a FAKE edid with the continous freq bit set. Based on similar code in the Intel driver.
-rw-r--r--src/radeon_modes.c87
-rw-r--r--src/radeon_output.c32
2 files changed, 117 insertions, 2 deletions
diff --git a/src/radeon_modes.c b/src/radeon_modes.c
index 0a8fa001..662071b4 100644
--- a/src/radeon_modes.c
+++ b/src/radeon_modes.c
@@ -415,6 +415,83 @@ RADEONUpdatePanelSize(xf86OutputPtr output)
}
}
+static void fill_detailed_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 void
+radeon_lvds_add_fake_edid(xf86OutputPtr output, DisplayModePtr mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ xf86MonPtr edid_mon = NULL;
+
+ if (!output->MonInfo) {
+ edid_mon = xcalloc (1, sizeof (xf86Monitor));
+ if (edid_mon) {
+ struct detailed_monitor_section *det_mon = edid_mon->det_mon;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Adding fake EDID for LVDS\n");
+
+ /*support DPM, instead of DPMS*/
+ edid_mon->features.dpms |= 0x1;
+ /*default support RGB color display*/
+ edid_mon->features.display_type |= 0x1;
+ /*default display support continuous-freqencey*/
+ edid_mon->features.msc |= 0x1;
+ /*default the EDID version is 1.4 */
+ edid_mon->ver.version = 1;
+ edid_mon->ver.revision = 4;
+
+ if (mode) {
+ /* now we construct new EDID monitor,
+ * so filled one detailed timing block
+ */
+ fill_detailed_block(det_mon, mode);
+ /* 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;
+
+ /* empty edid */
+ edid_mon->rawData = xcalloc (1, 128);
+
+ edid_mon->vendor.name[0] = 70;
+ edid_mon->vendor.name[1] = 65;
+ edid_mon->vendor.name[2] = 75;
+ edid_mon->vendor.name[3] = 69;
+
+ output->MonInfo = edid_mon;
+ }
+ }
+}
+
DisplayModePtr
RADEONProbeOutputModes(xf86OutputPtr output)
{
@@ -460,10 +537,16 @@ RADEONProbeOutputModes(xf86OutputPtr output)
}
}
if (modes == NULL) {
- if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT))
+ if (radeon_output->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
modes = RADEONFPNativeMode(output);
+ radeon_lvds_add_fake_edid(output, modes);
+ xfree(modes);
+ modes = xf86OutputGetEDIDModes (output);
+ }
+
/* add the screen modes */
- RADEONAddScreenModes(output, &modes);
+ if (modes == NULL)
+ RADEONAddScreenModes(output, &modes);
}
}
}
diff --git a/src/radeon_output.c b/src/radeon_output.c
index 6bbe9abc..cded74be 100644
--- a/src/radeon_output.c
+++ b/src/radeon_output.c
@@ -208,6 +208,37 @@ radeon_set_active_device(xf86OutputPtr output)
}
}
+/* X Server pre-1.5 compatibility */
+#ifndef DS_VENDOR
+#define DS_VENDOR 0x101
+#endif
+
+static void radeon_fixup_edid_for_panel(xf86MonPtr edid_mon)
+{
+ int i, j = -1;
+
+ if (edid_mon) {
+ /* mark it to support continous timing so we can add default modes */
+ edid_mon->features.msc |= 0x1;
+ for (i = 0; i < sizeof (edid_mon->det_mon) / sizeof (edid_mon->det_mon[0]); 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;
+ }
+ }
+}
+
static RADEONMonitorType
radeon_ddc_connected(xf86OutputPtr output)
{
@@ -242,6 +273,7 @@ radeon_ddc_connected(xf86OutputPtr output)
switch (radeon_output->ConnectorType) {
case CONNECTOR_LVDS:
MonType = MT_LCD;
+ radeon_fixup_edid_for_panel(MonInfo);
break;
case CONNECTOR_DVI_D:
case CONNECTOR_HDMI_TYPE_A: