* [PATCH 0/1] drm-set-default-noedid-res.patch
@ 2010-05-16 23:38 Carsten Emde
2010-05-16 23:38 ` [PATCH 1/1] drm-set-default-noedid-res.patch Carsten Emde
2010-05-17 7:29 ` [PATCH 0/1] drm-set-default-noedid-res.patch Dave Airlie
0 siblings, 2 replies; 5+ messages in thread
From: Carsten Emde @ 2010-05-16 23:38 UTC (permalink / raw)
To: David Airlie; +Cc: DRI
Hi,
Some monitors and, more often, kvm switches do not provide working EDID
data. KMS based X configurations in recent server versions no longer
allow to override the screen resolution which makes it impossible to
correctly adapt the screen resolution to the monitor in use.
This patch allows to define the fallback screen resolution to something
else than the default 1024x768.
Carsten.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/1] drm-set-default-noedid-res.patch
2010-05-16 23:38 [PATCH 0/1] drm-set-default-noedid-res.patch Carsten Emde
@ 2010-05-16 23:38 ` Carsten Emde
2010-05-17 7:29 ` [PATCH 0/1] drm-set-default-noedid-res.patch Dave Airlie
1 sibling, 0 replies; 5+ messages in thread
From: Carsten Emde @ 2010-05-16 23:38 UTC (permalink / raw)
To: David Airlie; +Cc: DRI, Carsten Emde
[-- Attachment #1: drm-set-default-noedid-res.patch --]
[-- Type: text/plain, Size: 2618 bytes --]
A default resolution of 1024x768 is used, if there are no
EDID data. However, this may not always be appropriate.
This patch introduces the kernel parameter drm.noedidres
that has the format "<width>x<height>". If specified, it will
override the default.
Example: drm.noedidres=1280x1024
Signed-off-by: Carsten Emde <C.Emde@osadl.org>
---
drivers/gpu/drm/drm_crtc_helper.c | 14 +++++++++++++-
drivers/gpu/drm/drm_stub.c | 5 +++++
include/drm/drmP.h | 1 +
3 files changed, 19 insertions(+), 1 deletion(-)
Index: head/drivers/gpu/drm/drm_crtc_helper.c
===================================================================
--- head.orig/drivers/gpu/drm/drm_crtc_helper.c
+++ head/drivers/gpu/drm/drm_crtc_helper.c
@@ -110,9 +110,21 @@ int drm_helper_probe_single_connector_mo
count = (*connector_funcs->get_modes)(connector);
if (!count) {
- count = drm_add_modes_noedid(connector, 1024, 768);
+ unsigned long x = 1024, y = 768;
+
+ if (drm_noedidres != NULL) {
+ unsigned long nx, ny;
+
+ if (sscanf(drm_noedidres, "%lux%lu", &nx, &ny) == 2) {
+ x = nx;
+ y = ny;
+ }
+ }
+ count = drm_add_modes_noedid(connector, x, y);
if (!count)
return 0;
+ DRM_DEBUG_KMS("no EDID, added mode %lux%lu to connector %s\n",
+ x, y, drm_get_connector_name(connector));
}
drm_mode_connector_list_update(connector);
Index: head/drivers/gpu/drm/drm_stub.c
===================================================================
--- head.orig/drivers/gpu/drm/drm_stub.c
+++ head/drivers/gpu/drm/drm_stub.c
@@ -40,12 +40,17 @@
unsigned int drm_debug = 0; /* 1 to enable debug output */
EXPORT_SYMBOL(drm_debug);
+char *drm_noedidres; /* screen "<width>x<height>", if no EDID data */
+EXPORT_SYMBOL(drm_noedidres);
+
MODULE_AUTHOR(CORE_AUTHOR);
MODULE_DESCRIPTION(CORE_DESC);
MODULE_LICENSE("GPL and additional rights");
MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(noedidres, "Screen \"<width>x<height>\", if no EDID data");
module_param_named(debug, drm_debug, int, 0600);
+module_param_named(noedidres, drm_noedidres, charp, 0600);
struct idr drm_minors_idr;
Index: head/include/drm/drmP.h
===================================================================
--- head.orig/include/drm/drmP.h
+++ head/include/drm/drmP.h
@@ -1356,6 +1356,7 @@ extern int drm_get_dev(struct pci_dev *p
extern void drm_put_dev(struct drm_device *dev);
extern int drm_put_minor(struct drm_minor **minor);
extern unsigned int drm_debug;
+extern char *drm_noedidres;
extern struct class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/1] drm-set-default-noedid-res.patch
2010-05-16 23:38 [PATCH 0/1] drm-set-default-noedid-res.patch Carsten Emde
2010-05-16 23:38 ` [PATCH 1/1] drm-set-default-noedid-res.patch Carsten Emde
@ 2010-05-17 7:29 ` Dave Airlie
2010-05-17 10:52 ` Carsten Emde
2010-05-24 20:07 ` [RFC] " Carsten Emde
1 sibling, 2 replies; 5+ messages in thread
From: Dave Airlie @ 2010-05-17 7:29 UTC (permalink / raw)
To: Carsten Emde; +Cc: DRI
On Mon, May 17, 2010 at 9:38 AM, Carsten Emde <C.Emde@osadl.org> wrote:
> Hi,
>
> Some monitors and, more often, kvm switches do not provide working EDID
> data. KMS based X configurations in recent server versions no longer
> allow to override the screen resolution which makes it impossible to
> correctly adapt the screen resolution to the monitor in use.
>
> This patch allows to define the fallback screen resolution to something
> else than the default 1024x768.
Does video=800x600 not work for you?
Dave.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/1] drm-set-default-noedid-res.patch
2010-05-17 7:29 ` [PATCH 0/1] drm-set-default-noedid-res.patch Dave Airlie
@ 2010-05-17 10:52 ` Carsten Emde
2010-05-24 20:07 ` [RFC] " Carsten Emde
1 sibling, 0 replies; 5+ messages in thread
From: Carsten Emde @ 2010-05-17 10:52 UTC (permalink / raw)
To: Dave Airlie; +Cc: DRI
Dave,
>> Some monitors and, more often, kvm switches do not provide working
>> EDID data. KMS based X configurations in recent server versions no
>> longer allow to override the screen resolution which makes it
>> impossible to correctly adapt the screen resolution to the monitor
>> in use. This patch allows to define the fallback screen resolution
>> to something else than the default 1024x768.
> Does video=800x600 not work for you?
No, this only sets the tty resolution; the resolution of the X server
appears to be limited to the maximum as specified at line 123 in
drivers/gpu/drm/drm_crtc_helper.c:
drm_add_modes_noedid(connector, x, y);
kernel parameter TTY resolution Max. X resolution
- 640x480 1024x768
vga=0x31b 1280x1024 1024x768
video=1280x1024 1280x1024 1024x768
video=1280x1024 vga=0x31b 1280x1024 1024x768
drm.noedidres 1280x1024 1280x1024
drm.noedidres vga=0x31b 1280x1024 1280x1024
X.Org X Server 1.7.6
Build ID: xorg-x11-server 1.7.6-4.fc12
Carsten.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC] Re: [PATCH 0/1] drm-set-default-noedid-res.patch
2010-05-17 7:29 ` [PATCH 0/1] drm-set-default-noedid-res.patch Dave Airlie
2010-05-17 10:52 ` Carsten Emde
@ 2010-05-24 20:07 ` Carsten Emde
1 sibling, 0 replies; 5+ messages in thread
From: Carsten Emde @ 2010-05-24 20:07 UTC (permalink / raw)
To: Dave Airlie; +Cc: DRI
[-- Attachment #1: Type: text/plain, Size: 2697 bytes --]
Dave,
>> Some monitors and, more often, kvm switches do not provide working
>> EDID data. KMS based X configurations in recent server versions no
>> longer allow to override the screen resolution which makes it
>> impossible to correctly adapt the screen resolution to the monitor
>> in use. This patch allows to define the fallback screen resolution
>> to something else than the default 1024x768.
> Does video=800x600 not work for you?
I did a lot more tests; apparently, things are even more difficult than
expected.
These are my observations (all with Radeon X1950 and radeon driver):
- On the monitor side:
In addition to the known quirks, the EDID data may not be accessible or
erroneous. The original patch only solved the situation of unavailable
EDID data. A frequent reason of erroneous or unavailable EDID data is
the use of suboptimally designed KVM switches that are unable to probe
the connected monitor and send no or fantasy EDID data.
- On the Xorg side:
Older radeon drivers recognize the options "IgnoreEDID" and "NoDDC".
Using this trick, Xorg can be forced to disregard any EDID data and use
the resolution as specified in xorg.conf.
Less old radeon drivers still recognize the option "IgnoreEDID", but
this does not work any longer, since the option "NoDDC" has been
abandoned. Such drivers rely on correct EDID data.
Current radeon drivers should have the option "CustomEDID" to override
the probed EDID data (at least this is what the manual says), but I
couldn't get it working. The log file insists on saying that the option
"CustomEDID" is not used. These drivers also rely on correct EDID data.
My conclusion is, that the right place to solve the situation is in the
kernel. The attached patch makes the sysfs edid entry writable. If the
name of an existing binary EDID data file in /lib/firmware is supplied
such as
cd /sys/devices/pci0000:00/0000:00:07.0/0000:05:00.0/drm/card0
echo dvi_0.bin >card0-DVI-I-1/edid
the related connector will be set to these EDID data. Any probing is
then disabled. To restore the previous behavior and to re-enable monitor
probing, an empty string or a single line delimiter must be sent:
echo >card0-DVI-I-1/edid
I have tested the patch successfully in a number of different
configurations. When userspace setup tools such as
gnome-display-properties are used, the name and resolution data of the
provided (fake) EDID data are correctly decoded.
When compared to the various X hacks I tried, I find this solution
better, since it solves the problem at a place where it belongs. This is
in line with the observation that EDID related functionality appears to
fade out of X drivers.
Does this make sense?
Carsten.
[-- Attachment #2: drivers-gpu-drm-allow-to-load-edid-firmware.patch --]
[-- Type: text/x-patch, Size: 4333 bytes --]
Use the firmware interface to load binary EDID data from
a file and use them to assign monitor data to a video
connector.
Signed-off-by: Carsten Emde <C.Emde@osadl.org>
---
drivers/gpu/drm/drm_crtc_helper.c | 7 ++++
drivers/gpu/drm/drm_edid.c | 5 +++
drivers/gpu/drm/drm_sysfs.c | 63 +++++++++++++++++++++++++++++++++++++-
include/drm/drm_crtc.h | 1
4 files changed, 75 insertions(+), 1 deletion(-)
Index: linux-2.6.34/drivers/gpu/drm/drm_crtc_helper.c
===================================================================
--- linux-2.6.34.orig/drivers/gpu/drm/drm_crtc_helper.c
+++ linux-2.6.34/drivers/gpu/drm/drm_crtc_helper.c
@@ -87,6 +87,13 @@ int drm_helper_probe_single_connector_mo
int mode_flags = 0;
DRM_DEBUG_KMS("%s\n", drm_get_connector_name(connector));
+
+ if (connector->edid_pinned) {
+ list_for_each_entry(mode, &connector->modes, head)
+ count++;
+ return count;
+ }
+
/* set all modes to the unverified state */
list_for_each_entry_safe(mode, t, &connector->modes, head)
mode->status = MODE_UNVERIFIED;
Index: linux-2.6.34/drivers/gpu/drm/drm_edid.c
===================================================================
--- linux-2.6.34.orig/drivers/gpu/drm/drm_edid.c
+++ linux-2.6.34/drivers/gpu/drm/drm_edid.c
@@ -1214,6 +1214,11 @@ struct edid *drm_get_edid(struct drm_con
int ret;
struct edid *edid;
+ if (connector->edid_pinned) {
+ edid = (struct edid *) connector->display_info.raw_edid;
+ goto end;
+ }
+
edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1),
GFP_KERNEL);
if (edid == NULL) {
Index: linux-2.6.34/drivers/gpu/drm/drm_sysfs.c
===================================================================
--- linux-2.6.34.orig/drivers/gpu/drm/drm_sysfs.c
+++ linux-2.6.34/drivers/gpu/drm/drm_sysfs.c
@@ -16,9 +16,11 @@
#include <linux/kdev_t.h>
#include <linux/gfp.h>
#include <linux/err.h>
+#include <linux/firmware.h>
#include "drm_sysfs.h"
#include "drm_core.h"
+#include "drm_edid.h"
#include "drmP.h"
#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
@@ -219,6 +221,64 @@ static ssize_t edid_show(struct kobject
return count;
}
+static ssize_t edid_store(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *connector_dev = container_of(kobj, struct device, kobj);
+ struct drm_connector *connector = to_drm_connector(connector_dev);
+ const struct firmware *fw;
+ unsigned char *edid;
+ size_t size = EDID_LENGTH;
+ int status;
+ char *filename, *cr;
+
+ if (count == 0 || *buf == '\n' || *buf == '\0') {
+ connector->edid_pinned = 0;
+ return count;
+ }
+
+ filename = kmalloc(count+1, GFP_KERNEL);
+ if (!filename)
+ return -ENOMEM;
+ memcpy(filename, buf, count);
+ filename[count] = '\0';
+
+ cr = strchr(filename, '\n');
+ if (cr)
+ *cr = '\0';
+
+ status = request_firmware(&fw, filename, connector_dev);
+ kfree(filename);
+ if (status)
+ return status;
+
+ if (fw->size != size) {
+ release_firmware(fw);
+ return -EINVAL;
+ }
+
+ edid = kmalloc(size, GFP_KERNEL);
+ if (edid == NULL) {
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ edid = (unsigned char *) fw->data;
+
+ drm_mode_connector_update_edid_property(connector,
+ (struct edid *) edid);
+ drm_add_edid_modes(connector, (struct edid *) edid);
+ drm_mode_connector_list_update(connector);
+ drm_mode_sort(&connector->modes);
+
+ connector->display_info.raw_edid = edid;
+ connector->edid_pinned = 1;
+
+ release_firmware(fw);
+
+ return count;
+}
+
static ssize_t modes_show(struct device *device,
struct device_attribute *attr,
char *buf)
@@ -332,9 +392,10 @@ static struct device_attribute connector
static struct bin_attribute edid_attr = {
.attr.name = "edid",
- .attr.mode = 0444,
+ .attr.mode = 0644,
.size = 128,
.read = edid_show,
+ .write = edid_store,
};
/**
Index: linux-2.6.34/include/drm/drm_crtc.h
===================================================================
--- linux-2.6.34.orig/include/drm/drm_crtc.h
+++ linux-2.6.34/include/drm/drm_crtc.h
@@ -508,6 +508,7 @@ struct drm_connector {
struct list_head user_modes;
struct drm_property_blob *edid_blob_ptr;
+ int edid_pinned;
u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY];
uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY];
[-- Attachment #3: Type: text/plain, Size: 159 bytes --]
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-05-24 20:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-16 23:38 [PATCH 0/1] drm-set-default-noedid-res.patch Carsten Emde
2010-05-16 23:38 ` [PATCH 1/1] drm-set-default-noedid-res.patch Carsten Emde
2010-05-17 7:29 ` [PATCH 0/1] drm-set-default-noedid-res.patch Dave Airlie
2010-05-17 10:52 ` Carsten Emde
2010-05-24 20:07 ` [RFC] " Carsten Emde
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.