From patchwork Wed Dec 3 21:49:29 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ung X-Patchwork-Id: 5434001 Return-Path: X-Original-To: patchwork-linux-fbdev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6C668BEEA8 for ; Wed, 3 Dec 2014 21:49:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 831A22021A for ; Wed, 3 Dec 2014 21:49:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 71F0F20218 for ; Wed, 3 Dec 2014 21:49:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751854AbaLCVti (ORCPT ); Wed, 3 Dec 2014 16:49:38 -0500 Received: from hqemgate14.nvidia.com ([216.228.121.143]:9227 "EHLO hqemgate14.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751405AbaLCVth (ORCPT ); Wed, 3 Dec 2014 16:49:37 -0500 Received: from hqnvupgp07.nvidia.com (Not Verified[216.228.121.13]) by hqemgate14.nvidia.com id ; Wed, 03 Dec 2014 13:49:48 -0800 Received: from hqemhub02.nvidia.com ([172.20.12.94]) by hqnvupgp07.nvidia.com (PGP Universal service); Wed, 03 Dec 2014 13:47:14 -0800 X-PGP-Universal: processed; by hqnvupgp07.nvidia.com on Wed, 03 Dec 2014 13:47:14 -0800 Received: from dung-P9X79.nvidia.com (172.20.144.16) by hqemhub02.nvidia.com (172.20.150.31) with Microsoft SMTP Server (TLS) id 8.3.342.0; Wed, 3 Dec 2014 13:49:37 -0800 From: David Ung To: , CC: , David Ung Subject: [PATCH 3/3] video: fbdev: Validate mode timing against monspec Date: Wed, 3 Dec 2014 13:49:29 -0800 Message-ID: <1417643369-20603-3-git-send-email-davidu@nvidia.com> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1417643369-20603-1-git-send-email-davidu@nvidia.com> References: <1417643369-20603-1-git-send-email-davidu@nvidia.com> MIME-Version: 1.0 Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP fbmon may generate mode timings that are out of spec of the monitor. eg DELL U2410 has a max clock 170mhz but advertises a resolutions of 1920x1200@60 in its Standard Timings, fbmon creates a mode using the GTF timing calculation which gave it a 193mhz clock. This patch checks to see if the mode can be supported by the monitor by comparing against monspecs.dclkmax. Signed-off-by: David Ung --- drivers/video/fbdev/core/fbmon.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c index aa1110a..cc3ea6c8 100644 --- a/drivers/video/fbdev/core/fbmon.c +++ b/drivers/video/fbdev/core/fbmon.c @@ -496,7 +496,7 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) } static int get_std_timing(unsigned char *block, struct fb_videomode *mode, - int ver, int rev) + int ver, int rev, struct fb_monspecs *specs) { int xres, yres = 0, refresh, ratio, i; @@ -542,16 +542,23 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode, if (i == DMT_SIZE || !dmt_modes[i].mode) calc_mode_timings(xres, yres, refresh, mode); + /* Check the mode we got is within valid spec of the monitor */ + if (specs && specs->dclkmax + && PICOS2KHZ(mode->pixclock) * 1000 > specs->dclkmax) { + DPRINTK(" mode exceed max DCLK\n"); + return 0; + } + return 1; } -static int get_dst_timing(unsigned char *block, - struct fb_videomode *mode, int ver, int rev) +static int get_dst_timing(unsigned char *block, struct fb_videomode *mode, + int ver, int rev, struct fb_monspecs *specs) { int j, num = 0; for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) - num += get_std_timing(block, &mode[num], ver, rev); + num += get_std_timing(block, &mode[num], ver, rev, specs); return num; } @@ -607,7 +614,8 @@ static void get_detailed_timing(unsigned char *block, * This function builds a mode database using the contents of the EDID * data */ -static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) +static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize, + struct fb_monspecs *specs) { struct fb_videomode *mode, *m; unsigned char *block; @@ -649,12 +657,13 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) DPRINTK(" Standard Timings\n"); block = edid + STD_TIMING_DESCRIPTIONS_START; for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) - num += get_std_timing(block, &mode[num], ver, rev); + num += get_std_timing(block, &mode[num], ver, rev, specs); block = edid + DETAILED_TIMING_DESCRIPTIONS_START; for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) - num += get_dst_timing(block + 5, &mode[num], ver, rev); + num += get_dst_timing(block + 5, &mode[num], + ver, rev, specs); } /* Yikes, EDID data is totally useless */ @@ -713,7 +722,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs) int num_modes, hz, hscan, pixclock; int vtotal, htotal; - modes = fb_create_modedb(edid, &num_modes); + modes = fb_create_modedb(edid, &num_modes, specs); if (!modes) { DPRINTK("None Available\n"); return 1; @@ -970,7 +979,7 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) DPRINTK(" Display Characteristics:\n"); get_monspecs(edid, specs); - specs->modedb = fb_create_modedb(edid, &specs->modedb_len); + specs->modedb = fb_create_modedb(edid, &specs->modedb_len, specs); /* * Workaround for buggy EDIDs that sets that the first