From patchwork Mon Mar 25 21:58:02 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dylan Semler X-Patchwork-Id: 2333801 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 02B2F3FD8C for ; Mon, 25 Mar 2013 21:59:11 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EB625E641B for ; Mon, 25 Mar 2013 14:59:10 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-ve0-f170.google.com (mail-ve0-f170.google.com [209.85.128.170]) by gabe.freedesktop.org (Postfix) with ESMTP id D3EF3E63C0 for ; Mon, 25 Mar 2013 14:58:06 -0700 (PDT) Received: by mail-ve0-f170.google.com with SMTP id 14so5393478vea.1 for ; Mon, 25 Mar 2013 14:58:06 -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=KJGsTa9FyOlVh6Eo9A5aDob2QTSdGRW48dRabRDXMMs=; b=QjNJdXiar0vOagJIEyh7q+MUQpXBwqTyHNpacTvI/gwi9zNWnX/KKYwHnlP9RF2v7i Guzo6+BXmgPk5qEGa8NaE3jdLEsqbRhbFNDHdOGWs8qq/karbtRnvLLz2oJAMXcOiX5N +esyPFZxPzSGWOoUftWDExN4OioijHIZZ9XUZOnnDLE5ApTXlSBeXS52tGyt/+ms4UOG hRO1SpAksqe5y6nOohAXtKM9WTEoiucYZJRr/CnXnKga/b4VBrzqBweCTEKAJFd/qi/8 MaRCORf6h6obUl/VTwhivpXTBkpheq0GfWravvtKPlMDqumpUUkDtVt+HMih2WZWR+nu R+xg== X-Received: by 10.58.154.229 with SMTP id vr5mr17988150veb.11.1364248686251; Mon, 25 Mar 2013 14:58:06 -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 tp10sm22662071vec.1.2013.03.25.14.58.05 (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 25 Mar 2013 14:58:05 -0700 (PDT) From: Dylan Semler To: dri-devel@lists.freedesktop.org Subject: [PATCH v4 1/2] drm: Enhance EDID quirks to explicitly set a mode Date: Mon, 25 Mar 2013 17:58:02 -0400 Message-Id: <1364248683-3426-2-git-send-email-dylan.semler@gmail.com> X-Mailer: git-send-email 1.7.11.7 In-Reply-To: <1364248683-3426-1-git-send-email-dylan.semler@gmail.com> References: <1364248683-3426-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 | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index c194f4e..f8f3a4a 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; @@ -128,6 +130,22 @@ static struct edid_quirk { }; /* + * Displays that don't report a desired mode in their EDID block that cannot be + * resolved with a quirk from above are specified here. If multiple modes need + * to be forced for the same display, the most preferred should be last; that + * is what the display will be initialized with. + */ +static struct edid_quirk_force_mode { + char vendor[4]; /* vendor ID */ + int product_id; /* product ID */ + int hdisplay; /* horizontal resolution */ + int vdisplay; /* vertical resolution */ + int vrefresh; /* refresh rate */ + bool reduced; /* reduce blanking */ +} edid_quirk_force_mode_list[] = { +}; + +/* * Autogenerated from the DMT spec. * This table is copied from xfree86/modes/xf86EdidModes.c. */ @@ -2219,6 +2237,63 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, return closure.modes; } +/* + * Add forced mode according to the matching quirk, set it as preferred, + * and remove the preferred bit from all other modes. + */ +static int +do_force_quirk_mode(struct drm_connector *connector, int hdisplay, + int vdisplay, int vrefresh, bool reduced) +{ + struct drm_display_mode *mode, *cur_mode; + struct drm_device *dev = connector->dev; + + if (hdisplay < 0) + return 0; + if (vdisplay < 0) + return 0; + if (vrefresh < 0) + return 0; + + list_for_each_entry(cur_mode, &connector->probed_modes, head) + cur_mode->type &= ~DRM_MODE_TYPE_PREFERRED; + + mode = drm_cvt_mode(dev, hdisplay, vdisplay, vrefresh, reduced, 0, 0); + + if (!mode) + return 0; + + mode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + return 1; +} + +/* + * add_force_quirk_modes - Add modes based on monitor's EDID force mode quirks + * @connector: attached connector + * @edid: EDID block to scan + */ +static int +add_force_quirk_modes(struct drm_connector *connector, struct edid *edid) +{ + 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_mode(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 +2878,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 (EDID_QUIRK_FORCE_MODE) + num_modes += add_force_quirk_modes(connector, edid); drm_add_display_info(edid, &connector->display_info);