From patchwork Fri Mar 22 23:08:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dylan Semler X-Patchwork-Id: 2323351 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 C4CD23FD8C for ; Fri, 22 Mar 2013 23:09:06 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D09EBE5FF1 for ; Fri, 22 Mar 2013 16:09:06 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-ve0-f169.google.com (mail-ve0-f169.google.com [209.85.128.169]) by gabe.freedesktop.org (Postfix) with ESMTP id 1A62EE5DF6 for ; Fri, 22 Mar 2013 16:08:11 -0700 (PDT) Received: by mail-ve0-f169.google.com with SMTP id d10so225664vea.0 for ; Fri, 22 Mar 2013 16:08:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=hmhERn1Y3qNvIzdYUAzAWL6qBg5hl5n+oWskyi/vX9g=; b=CubrSemP8djGbpUVQkOe7R3AFtDLebuaxA8QKVgFOYMPWC3wTS1+feHpiTp+8jc3HS EGk4MYnJQTsYkp1LwnKW2b0vI6yTApFCVKL9/fQmLVtXaq/AWmV2ToZXRFeX2ve7n2f6 WTMmbxu1b7IyUnaByGcVvXzoIa139mCko29DdKML9JZ92j7eF/VutiMteUjJhWhKDkDT bjtyWNASIKWC37iXmYxFs/rnn0/OfmG57+AHoiCCyNbPNMrQxztlZP3giJ8/RIl5pyL2 cBzvONNU/DnxDTvCFGziwJJNeSXIYuHRdm9vcrjQu8pbFQX0x6/Y/KGbAN1mEOhY+AJA bWWg== X-Received: by 10.220.153.2 with SMTP id i2mr4574442vcw.53.1363993690472; Fri, 22 Mar 2013 16:08:10 -0700 (PDT) Received: from localhost.localdomain (c-71-230-10-110.hsd1.pa.comcast.net. [71.230.10.110]) by mx.google.com with ESMTPS id h11sm5806574vdj.12.2013.03.22.16.08.09 (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 22 Mar 2013 16:08:09 -0700 (PDT) From: Dylan Semler To: dri-devel@lists.freedesktop.org Subject: [PATCH v3 1/2] drm: Enhance EDID quirks to explicitly set a mode Date: Fri, 22 Mar 2013 19:08:06 -0400 Message-Id: <1363993687-6935-2-git-send-email-dylan.semler@gmail.com> X-Mailer: git-send-email 1.7.11.7 In-Reply-To: <1363993687-6935-1-git-send-email-dylan.semler@gmail.com> References: <1363993687-6935-1-git-send-email-dylan.semler@gmail.com> 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: , MIME-Version: 1.0 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 There is at least one monitor that doesn't report its native resolution in its EDID block. This enhancement extends the EDID quirk logic to make monitors like this "just work". This patch sets up a new quirk list where monitors' correct width, height, refresh rate, and reduced blanking parameters are specified. When a matching monitor is attached the full mode is calculated with drm_cvt_mode() and added to the connector. The DRM_MODE_TYPE_PREFERRED bit is set on the new mode and unset from all other modes. The patch also defines a new quirk bit: EDID_QUIRK_FORCE_MODE. This bit needs to be set for the new quirk list discribed above to be checked. Signed-off-by: Dylan Semler --- drivers/gpu/drm/drm_edid.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index c194f4e..38b8641 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -68,6 +68,8 @@ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) /* Force reduced-blanking timings for detailed modes */ #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) +/* Force specific mode for monitors that don't report correct EDIDs */ +#define EDID_QUIRK_FORCE_MODE (1 << 8) struct detailed_mode_closure { struct drm_connector *connector; @@ -127,6 +129,16 @@ static struct edid_quirk { { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, }; +static struct edid_quirk_force_mode { + char vendor[4]; + int product_id; + int hdisplay; + int vdisplay; + int vrefresh; + bool reduced; +} edid_quirk_force_mode_list[] = { +}; + /* * Autogenerated from the DMT spec. * This table is copied from xfree86/modes/xf86EdidModes.c. @@ -2219,6 +2231,70 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, return closure.modes; } +/* Add an explicit mode based on a quirk + */ +static int +do_force_quirk_modes(struct drm_connector *connector, int hdisplay, + int vdisplay, int vrefresh, bool reduced) +{ + struct drm_display_mode *mode, *t, *cur_mode; + struct drm_device *dev = connector->dev; + int num_modes = 0; + + /* sanity check display parameters */ + if (hdisplay < 0) + return 0; + if (vdisplay < 0) + return 0; + if (vrefresh < 0) + return 0; + + /* loop through the probed modes and clear the preferred bit */ + list_for_each_entry_safe(cur_mode, t, &connector->probed_modes, head) + cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED; + + mode = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, reduced, 0, 0); + + if (mode) { + mode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + num_modes++; + } + return num_modes; +} + +/* + * add_force_quirk_modes - Add modes based on monitor's EDID quirks + * @connector: attached connector + * @edid: EDID block to scan + * @quirks: quirks to apply + * + * At least one monitor doesn't report its native resolution in its EDID block. + * Here we add the native mode according to this quirk + */ +static int +add_force_quirk_modes(struct drm_connector *connector, struct edid *edid, + u32 quirks) +{ + struct edid_quirk_force_mode *quirk_mode; + int i, num_modes = 0; + + for (i = 0; i < ARRAY_SIZE(edid_quirk_force_mode_list); i++) { + quirk_mode = &edid_quirk_force_mode_list[i]; + + if (edid_vendor(edid, quirk_mode->vendor) && + (EDID_PRODUCT_ID(edid) == quirk_mode->product_id)) { + num_modes = do_force_quirk_modes(connector, + quirk_mode->hdisplay, + quirk_mode->vdisplay, + quirk_mode->vrefresh, + quirk_mode->reduced); + } + } + return num_modes; + +} + #define HDMI_IDENTIFIER 0x000C03 #define AUDIO_BLOCK 0x01 #define VIDEO_BLOCK 0x02 @@ -2803,6 +2879,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) edid_fixup_preferred(connector, quirks); + if (quirks & EDID_QUIRK_FORCE_MODE) + num_modes += add_force_quirk_modes(connector, edid, quirks); drm_add_display_info(edid, &connector->display_info);