2009/9/10 Csillag Kristof <[email protected]>: > Hi all, > > As I have mentioned a few days earlier, I have encountered a Samsung > 214T monitor, > which is unable to properly use DDC when connected via DVI, but works > fine via VGA. > > I could not get it to work with the Radeon driver, but the proprietary > NVIDIA driver > had an option to force-feed the driver with custom EDID data from a > file, instead of DDC, > so I could use the monitor with NVIDIA. > > However, I wanted the Radeon driver, so I have added the same option to > the radeon driver. > It works for me; if you consider this useful, please add to the official > branch. > > * * * > > Here is how I use it: > > 1. Connect the monitor to the PC using VGA > 2. get-edid > /root/Samsung_214T.edid > 3. add to xorg.conf: Option "CustomEDID" > "DVI-0:/root/Samsung_214T.edid" > 4. Connect the monitor to the PC using DVI > 5. Restart X > > > ... and it work.s > > As far as I can tell, there is no other way to make this monitor work > with this driver, > so this is very important to me; however, I am not sure how many people are > blessed with such broken hardware, so I can not estimate the real importance > of the problem. > > * * * > > Please let me know what do you think!
Great patch! thanks for doing this. I've made some small improvements to it. Please test this patch and let me know and I'll go ahead and commit it. Thanks, Alex
From 3a45ef378de0743349bf87409b422874813543a1 Mon Sep 17 00:00:00 2001 From: Csillag Kristof <[email protected]> Date: Thu, 10 Sep 2009 23:41:11 -0400 Subject: [PATCH] radeon: add support for Custom EDID Allows you to specify an edid per output from a file to override what is detected by DDC. Useful for problematic monitors or KVM switches that block DDC. Specifying an EDID that is not compatible with your monitor could damage your monitor so use with caution. agd5f: cache the custom edid at startup so we don't have to read it from file every time the output is queried. --- man/radeon.man | 28 +++++++++++++++++++++++ src/radeon.h | 1 + src/radeon_driver.c | 1 + src/radeon_output.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/radeon_probe.h | 3 ++ 5 files changed, 92 insertions(+), 1 deletions(-) diff --git a/man/radeon.man b/man/radeon.man index 703fe1d..62270fb 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -302,6 +302,34 @@ for monitor detection. This is different from NoDDC option. The default value is .B off. .TP +.BI "Option \*qCustomEDID\*q \*q" string \*q +Forces the X driver to use the EDID data specified in a file rather +than the display's EDID. Also overrides DDC monitor detection. +.br +You may specify a semicolon separated list of output name and filename pairs. +The output name is something like "VGA-0" or "DVI-0"; +consult the Xorg log for the supported output names of any given system. +.br +The file must contain a raw 128-byte EDID block, as captured by +.B +get-edid. +.br +For example: +.B +Option \*qCustomEDID\*q \*qVGA-0:/tmp/edid1.bin; DVI-0:/tmp/edid2.bin\*q +will assign the EDID from the file /tmp/edid1.bin to the output device +VGA-0, and the EDID from the file /tmp/edid2.bin to the output device +DVI-0. +.br +Note that a output name must always be specified, +even if only one EDID is specified. +.br +.B +Caution: +Specifying an EDID that doesn't exactly match your display may +damage your hardware, as it allows the driver to specify timings beyond +the capabilities of your display. Use with care. +.TP .BI "Option \*qPanelSize\*q \*q" "string" \*q Should only be used when driver cannot detect the correct panel size. Apply to both desktop (TMDS) and laptop (LVDS) digital panels. diff --git a/src/radeon.h b/src/radeon.h index fc9614e..dbc2e11 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -176,6 +176,7 @@ typedef enum { #endif #endif OPTION_IGNORE_EDID, + OPTION_CUSTOM_EDID, OPTION_DISP_PRIORITY, OPTION_PANEL_SIZE, OPTION_MIN_DOTCLOCK, diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 67fb9b7..ea77319 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -161,6 +161,7 @@ static const OptionInfoRec RADEONOptions[] = { #endif #endif { OPTION_IGNORE_EDID, "IgnoreEDID", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CUSTOM_EDID, "CustomEDID", OPTV_ANYSTR, {0}, FALSE }, { OPTION_DISP_PRIORITY, "DisplayPriority", OPTV_ANYSTR, {0}, FALSE }, { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, { OPTION_MIN_DOTCLOCK, "ForceMinDotClock", OPTV_FREQ, {0}, FALSE }, diff --git a/src/radeon_output.c b/src/radeon_output.c index 30f6f3b..fba36af 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -32,6 +32,7 @@ #include <string.h> #include <stdio.h> +#include <fcntl.h> /* X and server generic header files */ #include "xf86.h" @@ -215,6 +216,59 @@ monitor_is_digital(xf86MonPtr MonInfo) return (MonInfo->rawData[0x14] & 0x80) != 0; } +static void +RADEONGetHardCodedEDIDFromFile(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + char *EDIDlist = (char *)xf86GetOptValString(info->Options, OPTION_CUSTOM_EDID); + + if (EDIDlist != NULL) { + unsigned char edid[128]; + char *name = output->name; + char *outputEDID = strstr(EDIDlist, name); + + if (outputEDID != NULL) { + char *end; + int fd; + + outputEDID += strlen(name) + 1; + end = strstr(outputEDID, ";"); + if (end != NULL) + *end = 0; + + fd = open (outputEDID, O_RDONLY); + if (fd >= 0) { + read(fd, edid, 128); + close(fd); + if (edid[1] == 0xff) { + radeon_output->custom_mon = xf86InterpretEDID(output->scrn->scrnIndex, edid); + radeon_output->custom_edid = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Successfully read Custom EDID data for output %s from %s.\n", + name, outputEDID); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Custom EDID data for %s read from %s was invalid.\n", + name, outputEDID); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not read custom EDID for output %s from file %s.\n", + name, outputEDID); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Could not find EDID file name for output %s; using auto detection.\n", + name); + } + } + radeon_output->custom_edid = FALSE; + radeon_output->custom_mon = NULL; +} + + static RADEONMonitorType radeon_ddc_connected(xf86OutputPtr output) { @@ -224,7 +278,10 @@ radeon_ddc_connected(xf86OutputPtr output) xf86MonPtr MonInfo = NULL; RADEONOutputPrivatePtr radeon_output = output->driver_private; - if (radeon_output->pI2CBus) { + if (radeon_output->custom_edid) { + MonInfo = xnfcalloc(sizeof(xf86Monitor), 1); + *MonInfo = *radeon_output->custom_mon; + } else if (radeon_output->pI2CBus) { if (info->get_hardcoded_edid_from_bios) MonInfo = RADEONGetHardCodedEDIDFromBIOS(output); if (MonInfo == NULL) { @@ -2802,6 +2859,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) xf86OutputPtr output = xf86_config->output[i]; output->possible_clones = radeon_output_clones(pScrn, output); + RADEONGetHardCodedEDIDFromFile(output); } return TRUE; diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 9cac15c..469f36a 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -261,6 +261,9 @@ typedef struct _RADEONOutputPrivateRec { I2CBusPtr pI2CBus; RADEONI2CBusRec ddc_i2c; Bool shared_ddc; + + Bool custom_edid; + xf86MonPtr custom_mon; // router info // HDP info -- 1.5.4.3
_______________________________________________ xorg mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/xorg
