Hello Adam, On Fri, Jul 20, 2012 at 12:34:21PM +1000, Dave Airlie wrote: > > Samsung 2443BW is 1920x1200 but reports 1920x1080 in the EDID. Attached > > is a proof-of-concept implementation of a quirk. It works on my i686 PC. ... > > This implementation matches the wrong mode by size. Other approaches are > > possible. > > > > I'd appreciate feedback. > > ajax, seem sane? Ping? With kind regards, Baurzhan.
>From b6c7a43e8b8fa0b6b39ed4a99c463071269d1a50 Mon Sep 17 00:00:00 2001 From: Baurzhan Ismagulov <ibr@xxxxxxxxxxx> Date: Sat, 14 Jul 2012 22:27:18 +0200 Subject: [PATCH 1/2] drm: Make edid_quirk_list const Signed-off-by: Baurzhan Ismagulov <ibr@xxxxxxxxxxx> --- drivers/gpu/drm/drm_edid.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a8743c3..09ff2bb 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -86,7 +86,7 @@ static struct edid_quirk { char vendor[4]; int product_id; u32 quirks; -} edid_quirk_list[] = { +} const edid_quirk_list[] = { /* Acer AL1706 */ { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, /* Acer F51 */ @@ -415,7 +415,7 @@ EXPORT_SYMBOL(drm_get_edid); * * Returns true if @vendor is in @edid, false otherwise */ -static bool edid_vendor(struct edid *edid, char *vendor) +static bool edid_vendor(struct edid *edid, const char *vendor) { char edid_vendor[3]; @@ -435,7 +435,7 @@ static bool edid_vendor(struct edid *edid, char *vendor) */ static u32 edid_get_quirks(struct edid *edid) { - struct edid_quirk *quirk; + const struct edid_quirk *quirk; int i; for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) { -- 1.7.2.5
>From ea4ca18f607c3829239ad602b0cb8d319fbcd75e Mon Sep 17 00:00:00 2001 From: Baurzhan Ismagulov <ibr@xxxxxxxxxxx> Date: Sat, 14 Jul 2012 22:23:33 +0200 Subject: [PATCH 2/2] drm: Add quirk for Samsung SyncMaster 2443BW Signed-off-by: Baurzhan Ismagulov <ibr@xxxxxxxxxxx> --- drivers/gpu/drm/drm_edid.c | 64 ++++++++++++++++++++++++++++++------------- 1 files changed, 44 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 09ff2bb..73dda54 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -68,12 +68,14 @@ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) /* Force reduced-blanking timings for detailed modes */ #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) +/* Force size */ +#define EDID_QUIRK_FORCE_SIZE (1 << 8) struct detailed_mode_closure { struct drm_connector *connector; struct edid *edid; bool preferred; - u32 quirks; + const struct edid_quirk *quirk; int modes; }; @@ -82,10 +84,23 @@ struct detailed_mode_closure { #define LEVEL_GTF2 2 #define LEVEL_CVT 3 +struct size { + int x; + int y; +}; + +struct force_size { + struct size bad; + struct size good; +}; + static struct edid_quirk { char vendor[4]; int product_id; u32 quirks; + union { + struct force_size size; + } u; } const edid_quirk_list[] = { /* Acer AL1706 */ { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 }, @@ -122,6 +137,9 @@ static struct edid_quirk { /* Samsung SyncMaster 22[5-6]BW */ { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, + /* Samsung SyncMaster 2443BW */ + { "SAM", 0x06b0, EDID_QUIRK_FORCE_SIZE, + .u.size = { { 1920, 1080 }, { 1920, 1200 } } }, /* ViewSonic VA2026w */ { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, @@ -428,12 +446,12 @@ static bool edid_vendor(struct edid *edid, const char *vendor) } /** - * edid_get_quirks - return quirk flags for a given EDID + * edid_get_quirk - return quirk data for a given EDID * @edid: EDID to process * * This tells subsequent routines what fixes they need to apply. */ -static u32 edid_get_quirks(struct edid *edid) +static const struct edid_quirk *edid_get_quirk(struct edid *edid) { const struct edid_quirk *quirk; int i; @@ -443,10 +461,10 @@ static u32 edid_get_quirks(struct edid *edid) if (edid_vendor(edid, quirk->vendor) && (EDID_PRODUCT_ID(edid) == quirk->product_id)) - return quirk->quirks; + return quirk; } - return 0; + return NULL; } #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) @@ -866,7 +884,7 @@ drm_mode_do_interlace_quirk(struct drm_display_mode *mode, static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, struct edid *edid, struct detailed_timing *timing, - u32 quirks) + const struct edid_quirk *quirk) { struct drm_display_mode *mode; struct detailed_pixel_timing *pt = &timing->data.pixel_data; @@ -898,7 +916,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, return NULL; } - if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) { + if (quirk && quirk->quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) { mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false); if (!mode) return NULL; @@ -906,11 +924,17 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, goto set_size; } + if (quirk && quirk->quirks & EDID_QUIRK_FORCE_SIZE && + hactive == quirk->u.size.bad.x && vactive == quirk->u.size.bad.y) { + hactive = quirk->u.size.good.x; + vactive = quirk->u.size.good.y; + } + mode = drm_mode_create(dev); if (!mode) return NULL; - if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) + if (quirk && quirk->quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) timing->pixel_clock = cpu_to_le16(1088); mode->clock = le16_to_cpu(timing->pixel_clock) * 10; @@ -933,9 +957,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, drm_mode_do_interlace_quirk(mode, pt); - if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { + if (quirk && quirk->quirks & EDID_QUIRK_DETAILED_SYNC_PP) pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; - } mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; @@ -946,12 +969,12 @@ set_size: mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; - if (quirks & EDID_QUIRK_DETAILED_IN_CM) { + if (quirk && quirk->quirks & EDID_QUIRK_DETAILED_IN_CM) { mode->width_mm *= 10; mode->height_mm *= 10; } - if (quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { + if (quirk && quirk->quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { mode->width_mm = edid->width_cm * 10; mode->height_mm = edid->height_cm * 10; } @@ -1421,7 +1444,7 @@ do_detailed_mode(struct detailed_timing *timing, void *c) if (timing->pixel_clock) { newmode = drm_mode_detailed(closure->connector->dev, closure->edid, timing, - closure->quirks); + closure->quirk); if (!newmode) return; @@ -1442,13 +1465,13 @@ do_detailed_mode(struct detailed_timing *timing, void *c) */ static int add_detailed_modes(struct drm_connector *connector, struct edid *edid, - u32 quirks) + const struct edid_quirk *quirk) { struct detailed_mode_closure closure = { connector, edid, 1, - quirks, + quirk, 0 }; @@ -1890,7 +1913,7 @@ static void drm_add_display_info(struct edid *edid, int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) { int num_modes = 0; - u32 quirks; + const struct edid_quirk *quirk; if (edid == NULL) { return 0; @@ -1901,7 +1924,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) return 0; } - quirks = edid_get_quirks(edid); + quirk = edid_get_quirk(edid); /* * EDID spec says modes should be preferred in this order: @@ -1917,15 +1940,16 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) * * XXX order for additional mode types in extension blocks? */ - num_modes += add_detailed_modes(connector, edid, quirks); + num_modes += add_detailed_modes(connector, edid, quirk); num_modes += add_cvt_modes(connector, edid); num_modes += add_standard_modes(connector, edid); num_modes += add_established_modes(connector, edid); num_modes += add_inferred_modes(connector, edid); num_modes += add_cea_modes(connector, edid); - if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) - edid_fixup_preferred(connector, quirks); + if (quirk && quirk->quirks & + (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) + edid_fixup_preferred(connector, quirk->quirks); drm_add_display_info(edid, &connector->display_info); -- 1.7.2.5
_______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel