From patchwork Sat Jul 14 21:42:36 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baurzhan Ismagulov X-Patchwork-Id: 1198251 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 90DC63FC4C for ; Sat, 14 Jul 2012 21:57:44 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 3D92D9E9BA for ; Sat, 14 Jul 2012 14:57:44 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org X-Greylist: delayed 879 seconds by postgrey-1.32 at gabe; Sat, 14 Jul 2012 23:57:32 CEST Received: from almaty.kz-easy.com (almaty.radix50.net [85.214.25.173]) by gabe.freedesktop.org (Postfix) with ESMTP id 3DE019E78C for ; Sat, 14 Jul 2012 14:57:32 -0700 (PDT) Received: from alatau.radix50.net (dslb-088-065-252-033.pools.arcor-ip.net [88.65.252.33]) (authenticated bits=0) by almaty.kz-easy.com (8.14.3/8.14.3/Debian-5+lenny1) with ESMTP id q6ELgflj017758 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT); Sat, 14 Jul 2012 23:42:43 +0200 Received: from medeu.radix50.net (root@medeu [192.168.0.3]) by alatau.radix50.net (8.14.3/8.14.3/Debian-5) with ESMTP id q6ELgaW6013651 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT); Sat, 14 Jul 2012 23:42:36 +0200 Received: from medeu.radix50.net (ibr@localhost [127.0.0.1]) by medeu.radix50.net (8.14.3/8.14.3/Debian-9.4) with ESMTP id q6ELgaY2003808 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT); Sat, 14 Jul 2012 23:42:36 +0200 Received: (from ibr@localhost) by medeu.radix50.net (8.14.3/8.14.3/Submit) id q6ELgax9003807; Sat, 14 Jul 2012 23:42:36 +0200 Date: Sat, 14 Jul 2012 23:42:36 +0200 From: Baurzhan Ismagulov To: airlied@linux.ie Subject: quirk for Samsung 2443BW Message-ID: <20120714214231.GC3451@radix50.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) X-Spam-Status: No, score=4.9 required=5.0 tests=BAYES_00, RCVD_IN_BRBL_LASTEXT, RCVD_IN_PBL, RCVD_IN_SORBS_DUL, RDNS_DYNAMIC, TO_NO_BRKTS_DYNIP autolearn=no version=3.3.1 X-Spam-Level: **** X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on almaty.kz-easy.com Cc: dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Hello David, 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. The patch is against the latest linux-2.6. An attempt to clone git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git (as listed in MAINTAINERS) resulted in "fatal: The remote end hung up unexpectedly". This implementation matches the wrong mode by size. Other approaches are possible. I'd appreciate feedback. With kind regards, Baurzhan. From ea4ca18f607c3829239ad602b0cb8d319fbcd75e Mon Sep 17 00:00:00 2001 From: Baurzhan Ismagulov 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 --- 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