From patchwork Wed Jan 30 05:28:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chiluk X-Patchwork-Id: 216788 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 6DCBB2C0094 for ; Wed, 30 Jan 2013 20:13:46 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1U0TjX-0005YQ-Ve; Wed, 30 Jan 2013 09:13:32 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1U0QE4-0004ll-Rg for kernel-team@lists.ubuntu.com; Wed, 30 Jan 2013 05:28:48 +0000 Received: from cpe-70-124-70-187.austin.res.rr.com ([70.124.70.187] helo=localhost.localdomain) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1U0QE4-0001aM-HG for kernel-team@lists.ubuntu.com; Wed, 30 Jan 2013 05:28:48 +0000 From: Dave Chiluk To: kernel-team@lists.ubuntu.com Subject: [PATCH 07/10] drm: edid: Don't add inferred modes with higher resolution Date: Tue, 29 Jan 2013 23:28:28 -0600 Message-Id: <1359523711-5875-8-git-send-email-chiluk@canonical.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1359523711-5875-1-git-send-email-chiluk@canonical.com> References: <1359523711-5875-1-git-send-email-chiluk@canonical.com> X-Mailman-Approved-At: Wed, 30 Jan 2013 09:13:30 +0000 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Takashi Iwai BugLink: http://bugs.launchpad.net/bugs/1109112 When a monitor EDID doesn't give the preferred bit, driver assumes that the mode with the higest resolution and rate is the preferred mode. Meanwhile the recent changes for allowing more modes in the GFT/CVT ranges give actually more modes, and some modes may be over the native size. Thus such a mode would be picked up as the preferred mode although it's no native resolution. For avoiding such a problem, this patch limits the addition of inferred modes by checking not to be greater than other modes. Also, it checks the duplicated mode entry at the same time. Reviewed-by: Adam Jackson Signed-off-by: Takashi Iwai Signed-off-by: Dave Airlie (cherry picked from commit 7b668ebe2fce517873b0c28dd70c10fef1d3dc2f) Signed-off-by: David Chiluk --- drivers/gpu/drm/drm_edid.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 8b72d9e..a0666f0 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1027,6 +1027,24 @@ mode_in_range(const struct drm_display_mode *mode, struct edid *edid, return true; } +static bool valid_inferred_mode(const struct drm_connector *connector, + const struct drm_display_mode *mode) +{ + struct drm_display_mode *m; + bool ok = false; + + list_for_each_entry(m, &connector->probed_modes, head) { + if (mode->hdisplay == m->hdisplay && + mode->vdisplay == m->vdisplay && + drm_mode_vrefresh(mode) == drm_mode_vrefresh(m)) + return false; /* duplicated */ + if (mode->hdisplay <= m->hdisplay && + mode->vdisplay <= m->vdisplay) + ok = true; + } + return ok; +} + /* * XXX If drm_dmt_modes ever regrows the CVT-R modes (and it will) this will * need to account for them. @@ -1040,7 +1058,8 @@ drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid, struct drm_device *dev = connector->dev; for (i = 0; i < drm_num_dmt_modes; i++) { - if (mode_in_range(drm_dmt_modes + i, edid, timing)) { + if (mode_in_range(drm_dmt_modes + i, edid, timing) && + valid_inferred_mode(connector, drm_dmt_modes + i)) { newmode = drm_mode_duplicate(dev, &drm_dmt_modes[i]); if (newmode) { drm_mode_probed_add(connector, newmode); @@ -1078,7 +1097,8 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, newmode = drm_gtf_mode(dev, m->w, m->h, m->r, 0, 0); fixup_mode_1366x768(newmode); - if (!mode_in_range(newmode, edid, timing)) { + if (!mode_in_range(newmode, edid, timing) || + !valid_inferred_mode(connector, newmode)) { drm_mode_destroy(dev, newmode); continue; } @@ -1104,7 +1124,8 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid, newmode = drm_cvt_mode(dev, m->w, m->h, m->r, rb, 0, 0); fixup_mode_1366x768(newmode); - if (!mode_in_range(newmode, edid, timing)) { + if (!mode_in_range(newmode, edid, timing) || + !valid_inferred_mode(connector, newmode)) { drm_mode_destroy(dev, newmode); continue; }