From patchwork Thu Apr 18 12:41:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 10907219 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9BB951515 for ; Thu, 18 Apr 2019 12:42:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7D15628CA8 for ; Thu, 18 Apr 2019 12:42:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 713E528CAC; Thu, 18 Apr 2019 12:42:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C8B8B28CA8 for ; Thu, 18 Apr 2019 12:42:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=24hnpbtykSDgLrNAcHUFz0evT71wyAumdHWMvefEHM4=; b=sMY9EMCrEWA3PU 2psLjH0/x0yzhZYfsbjmeRlHERttqaf59I6ph89cU1IhfAWzV3mcoSn7AJ2L7aoNbhzOpWsOX4Itv hyZGTvQoZ5K9XCx284MyGV+nhzaK7aczVOCCHju546hf+665BnBS/71o1KWFHNi07tWeg0pLGW6TZ QLWN0PI2BSb5ipWgSixDFhBcKqXuru8SkRrdYIGpVL2lj+wPSt2YYa/XkGJ5Qo4u7Nkum5AoD17rF MqVLJ55foz8hVDpKg7i8332GRlgYLtHu0tP9yJ6+Aa99QSOOutA0TUZRFg7Zk8LmlcFo/JtQ9TL2c T6JB4yxRSYHdwbJkeQ1Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6N9-0000AB-Dv; Thu, 18 Apr 2019 12:42:35 +0000 Received: from relay9-d.mail.gandi.net ([217.70.183.199]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6Mu-0008H8-H0 for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2019 12:42:23 +0000 X-Originating-IP: 90.88.160.238 Received: from localhost (aaubervilliers-681-1-42-238.w90-88.abo.wanadoo.fr [90.88.160.238]) (Authenticated sender: maxime.ripard@bootlin.com) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 65844FF803; Thu, 18 Apr 2019 12:42:06 +0000 (UTC) From: Maxime Ripard To: Maarten Lankhorst , Sean Paul , Maxime Ripard , Daniel Vetter , David Airlie Subject: [PATCH v3 1/6] drm/modes: Rewrite the command line parser Date: Thu, 18 Apr 2019 14:41:54 +0200 Message-Id: <500140e56478f2b91c30ff7389a4444b427b1dfd.1555591281.git-series.maxime.ripard@bootlin.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190418_054221_431749_5700C4B5 X-CRM114-Status: GOOD ( 18.45 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eben@raspberrypi.org, dri-devel@lists.freedesktop.org, Paul Kocialkowski , Eric Anholt , noralf@tronnes.org, Thomas Petazzoni , Maxime Ripard , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Maxime Ripard Rewrite the command line parser in order to get away from the state machine parsing the video mode lines. Hopefully, this will allow to extend it more easily to support named modes and / or properties set directly on the command line. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_modes.c | 305 +++++++++++++++++++++++-------------- 1 file changed, 190 insertions(+), 115 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 56f92a0bba62..3f89198f0891 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -30,6 +30,7 @@ * authorization from the copyright holder(s) and author(s). */ +#include #include #include #include @@ -1405,6 +1406,131 @@ void drm_connector_list_update(struct drm_connector *connector) } EXPORT_SYMBOL(drm_connector_list_update); +static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr, + struct drm_cmdline_mode *mode) +{ + if (str[0] != '-') + return -EINVAL; + + mode->bpp = simple_strtol(str + 1, end_ptr, 10); + mode->bpp_specified = true; + + return 0; +} + +static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr, + struct drm_cmdline_mode *mode) +{ + if (str[0] != '@') + return -EINVAL; + + mode->refresh = simple_strtol(str + 1, end_ptr, 10); + mode->refresh_specified = true; + + return 0; +} + +static int drm_mode_parse_cmdline_extra(const char *str, int length, + struct drm_connector *connector, + struct drm_cmdline_mode *mode) +{ + int i; + + for (i = 0; i < length; i++) { + switch (str[i]) { + case 'i': + mode->interlace = true; + break; + case 'm': + mode->margins = true; + break; + case 'D': + if (mode->force != DRM_FORCE_UNSPECIFIED) + return -EINVAL; + + if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) && + (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB)) + mode->force = DRM_FORCE_ON; + else + mode->force = DRM_FORCE_ON_DIGITAL; + break; + case 'd': + if (mode->force != DRM_FORCE_UNSPECIFIED) + return -EINVAL; + + mode->force = DRM_FORCE_OFF; + break; + case 'e': + if (mode->force != DRM_FORCE_UNSPECIFIED) + return -EINVAL; + + mode->force = DRM_FORCE_ON; + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length, + bool extras, + struct drm_connector *connector, + struct drm_cmdline_mode *mode) +{ + bool rb = false, cvt = false; + int xres = 0, yres = 0; + int remaining, i; + char *end_ptr; + + xres = simple_strtol(str, &end_ptr, 10); + + if (end_ptr[0] != 'x') + return -EINVAL; + end_ptr++; + + yres = simple_strtol(end_ptr, &end_ptr, 10); + + remaining = length - (end_ptr - str); + if (remaining < 0) + return -EINVAL; + + for (i = 0; i < remaining; i++) { + switch (end_ptr[i]) { + case 'M': + cvt = true; + break; + case 'R': + rb = true; + break; + default: + /* + * Try to pass that to our extras parsing + * function to handle the case where the + * extras are directly after the resolution + */ + if (extras) { + int ret = drm_mode_parse_cmdline_extra(end_ptr + i, + 1, + connector, + mode); + if (ret) + return ret; + } else { + return -EINVAL; + } + } + } + + mode->xres = xres; + mode->yres = yres; + mode->cvt = cvt; + mode->rb = rb; + + return 0; +} + /** * drm_mode_parse_command_line_for_connector - parse command line modeline for connector * @mode_option: optional per connector mode option @@ -1431,13 +1557,12 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, struct drm_cmdline_mode *mode) { const char *name; - unsigned int namelen; - bool res_specified = false, bpp_specified = false, refresh_specified = false; - unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0; - bool yres_specified = false, cvt = false, rb = false; - bool interlace = false, margins = false, was_digit = false; - int i; - enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; + bool parse_extras = false; + unsigned int bpp_off = 0, refresh_off = 0; + unsigned int mode_end = 0; + char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; + char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; + int ret; #ifdef CONFIG_FB if (!mode_option) @@ -1450,127 +1575,77 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, } name = mode_option; - namelen = strlen(name); - for (i = namelen-1; i >= 0; i--) { - switch (name[i]) { - case '@': - if (!refresh_specified && !bpp_specified && - !yres_specified && !cvt && !rb && was_digit) { - refresh = simple_strtol(&name[i+1], NULL, 10); - refresh_specified = true; - was_digit = false; - } else - goto done; - break; - case '-': - if (!bpp_specified && !yres_specified && !cvt && - !rb && was_digit) { - bpp = simple_strtol(&name[i+1], NULL, 10); - bpp_specified = true; - was_digit = false; - } else - goto done; - break; - case 'x': - if (!yres_specified && was_digit) { - yres = simple_strtol(&name[i+1], NULL, 10); - yres_specified = true; - was_digit = false; - } else - goto done; - break; - case '0' ... '9': - was_digit = true; - break; - case 'M': - if (yres_specified || cvt || was_digit) - goto done; - cvt = true; - break; - case 'R': - if (yres_specified || cvt || rb || was_digit) - goto done; - rb = true; - break; - case 'm': - if (cvt || yres_specified || was_digit) - goto done; - margins = true; - break; - case 'i': - if (cvt || yres_specified || was_digit) - goto done; - interlace = true; - break; - case 'e': - if (yres_specified || bpp_specified || refresh_specified || - was_digit || (force != DRM_FORCE_UNSPECIFIED)) - goto done; - force = DRM_FORCE_ON; - break; - case 'D': - if (yres_specified || bpp_specified || refresh_specified || - was_digit || (force != DRM_FORCE_UNSPECIFIED)) - goto done; + if (!isdigit(name[0])) + return false; - if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) && - (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB)) - force = DRM_FORCE_ON; - else - force = DRM_FORCE_ON_DIGITAL; - break; - case 'd': - if (yres_specified || bpp_specified || refresh_specified || - was_digit || (force != DRM_FORCE_UNSPECIFIED)) - goto done; + /* Try to locate the bpp and refresh specifiers, if any */ + bpp_ptr = strchr(name, '-'); + if (bpp_ptr) { + bpp_off = bpp_ptr - name; + mode->bpp_specified = true; + } - force = DRM_FORCE_OFF; - break; - default: - goto done; - } + refresh_ptr = strchr(name, '@'); + if (refresh_ptr) { + refresh_off = refresh_ptr - name; + mode->refresh_specified = true; } - if (i < 0 && yres_specified) { - char *ch; - xres = simple_strtol(name, &ch, 10); - if ((ch != NULL) && (*ch == 'x')) - res_specified = true; - else - i = ch - name; - } else if (!yres_specified && was_digit) { - /* catch mode that begins with digits but has no 'x' */ - i = 0; + /* Locate the end of the name / resolution, and parse it */ + if (bpp_ptr && refresh_ptr) { + mode_end = min(bpp_off, refresh_off); + } else if (bpp_ptr) { + mode_end = bpp_off; + } else if (refresh_ptr) { + mode_end = refresh_off; + } else { + mode_end = strlen(name); + parse_extras = true; } -done: - if (i >= 0) { - pr_warn("[drm] parse error at position %i in video mode '%s'\n", - i, name); - mode->specified = false; + + ret = drm_mode_parse_cmdline_res_mode(name, mode_end, + parse_extras, + connector, + mode); + if (ret) return false; - } + mode->specified = true; - if (res_specified) { - mode->specified = true; - mode->xres = xres; - mode->yres = yres; + if (bpp_ptr) { + ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode); + if (ret) + return false; } - if (refresh_specified) { - mode->refresh_specified = true; - mode->refresh = refresh; + if (refresh_ptr) { + ret = drm_mode_parse_cmdline_refresh(refresh_ptr, + &refresh_end_ptr, mode); + if (ret) + return false; } - if (bpp_specified) { - mode->bpp_specified = true; - mode->bpp = bpp; + /* + * Locate the end of the bpp / refresh, and parse the extras + * if relevant + */ + if (bpp_ptr && refresh_ptr) + extra_ptr = max(bpp_end_ptr, refresh_end_ptr); + else if (bpp_ptr) + extra_ptr = bpp_end_ptr; + else if (refresh_ptr) + extra_ptr = refresh_end_ptr; + + if (extra_ptr) { + int remaining = strlen(name) - (extra_ptr - name); + + /* + * We still have characters to process, while + * we shouldn't have any + */ + if (remaining > 0) + return false; } - mode->rb = rb; - mode->cvt = cvt; - mode->interlace = interlace; - mode->margins = margins; - mode->force = force; return true; } From patchwork Thu Apr 18 12:41:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 10907217 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1C26C922 for ; Thu, 18 Apr 2019 12:42:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F17B028CA9 for ; Thu, 18 Apr 2019 12:42:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E54F328CB3; Thu, 18 Apr 2019 12:42:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7098D28CA9 for ; Thu, 18 Apr 2019 12:42:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=VrsWne6Rti9gddIACwvnNBqf0EmzJ1K7MoQLiXTPQrk=; b=SL+OZKA7szvxTt BBvssYzwVVBfgC0a5B3oekSC+B2e6kqSPSx0OHiGWIVOVUhx09mnHAs5tP0W4dP0mJBwF+iR7ihN5 JMkWWY2bkIL6UrEaM3H9MKmm1FIFY9Zc9puJgcxerAQr6ieFFqZzTcbfSK/8TKxuA95GT1qZCS+p4 4gy1Xwsv7+f8Wuu8YTIPzGXZx2wP7bVxXH/hEZkzQHJvLu8Ufnzx+t2fRfKjY9KCqV9PnIS5Ba0jz N0r2s/BqwTRWuwYoOFKOajSVtU0jWHEBGCvEkgq8DRn/E17zHaKLHf08s1JPo9/ZRwDM+X72sJU9R hy+9PUIVBPtVq2Mhf2/A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6N1-0008RF-HA; Thu, 18 Apr 2019 12:42:27 +0000 Received: from relay6-d.mail.gandi.net ([217.70.183.198]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6Mn-0008Dg-IB for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2019 12:42:15 +0000 X-Originating-IP: 90.88.160.238 Received: from localhost (aaubervilliers-681-1-42-238.w90-88.abo.wanadoo.fr [90.88.160.238]) (Authenticated sender: maxime.ripard@bootlin.com) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 3F7CBC0011; Thu, 18 Apr 2019 12:42:10 +0000 (UTC) From: Maxime Ripard To: Maarten Lankhorst , Sean Paul , Maxime Ripard , Daniel Vetter , David Airlie Subject: [PATCH v3 2/6] drm/modes: Support modes names on the command line Date: Thu, 18 Apr 2019 14:41:55 +0200 Message-Id: <791ec173cce4007a7eadf2e68877bb640bf8dd84.1555591281.git-series.maxime.ripard@bootlin.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190418_054213_897159_31E7BAD1 X-CRM114-Status: GOOD ( 21.60 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eben@raspberrypi.org, dri-devel@lists.freedesktop.org, Paul Kocialkowski , Eric Anholt , noralf@tronnes.org, Thomas Petazzoni , Maxime Ripard , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Maxime Ripard The drm subsystem also uses the video= kernel parameter, and in the documentation refers to the fbdev documentation for that parameter. However, that documentation also says that instead of giving the mode using its resolution we can also give a name. However, DRM doesn't handle that case at the moment. Even though in most case it shouldn't make any difference, it might be useful for analog modes, where different standards might have the same resolution, but still have a few different parameters that are not encoded in the modes (NTSC vs NTSC-J vs PAL-M for example). Signed-off-by: Maxime Ripard Reviewed-by: Noralf Trønnes --- drivers/gpu/drm/drm_client_modeset.c | 4 ++- drivers/gpu/drm/drm_connector.c | 3 +- drivers/gpu/drm/drm_modes.c | 52 ++++++++++++++++++++--------- include/drm/drm_connector.h | 1 +- 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 2a428ac00930..f2869c82510c 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -149,6 +149,10 @@ drm_connector_pick_cmdline_mode(struct drm_connector *connector) prefer_non_interlace = !cmdline_mode->interlace; again: list_for_each_entry(mode, &connector->modes, head) { + /* Check (optional) mode name first */ + if (!strcmp(mode->name, cmdline_mode->name)) + return mode; + /* check width/height */ if (mode->hdisplay != cmdline_mode->xres || mode->vdisplay != cmdline_mode->yres) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 2355124849db..e33814f5940e 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -139,8 +139,9 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector) connector->force = mode->force; } - DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", + DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n", connector->name, + mode->name ? mode->name : "", mode->xres, mode->yres, mode->refresh_specified ? mode->refresh : 60, mode->rb ? " reduced blanking" : "", diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 3f89198f0891..9613c1a28487 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1557,7 +1557,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, struct drm_cmdline_mode *mode) { const char *name; - bool parse_extras = false; + bool named_mode = false, parse_extras = false; unsigned int bpp_off = 0, refresh_off = 0; unsigned int mode_end = 0; char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; @@ -1576,8 +1576,14 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, name = mode_option; + /* + * If the first character is not a digit, then it means that + * we have a named mode. + */ if (!isdigit(name[0])) - return false; + named_mode = true; + else + named_mode = false; /* Try to locate the bpp and refresh specifiers, if any */ bpp_ptr = strchr(name, '-'); @@ -1588,6 +1594,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, refresh_ptr = strchr(name, '@'); if (refresh_ptr) { + if (named_mode) + return false; + refresh_off = refresh_ptr - name; mode->refresh_specified = true; } @@ -1604,12 +1613,16 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, parse_extras = true; } - ret = drm_mode_parse_cmdline_res_mode(name, mode_end, - parse_extras, - connector, - mode); - if (ret) - return false; + if (named_mode) { + strncpy(mode->name, name, mode_end); + } else { + ret = drm_mode_parse_cmdline_res_mode(name, mode_end, + parse_extras, + connector, + mode); + if (ret) + return false; + } mode->specified = true; if (bpp_ptr) { @@ -1637,14 +1650,23 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, extra_ptr = refresh_end_ptr; if (extra_ptr) { - int remaining = strlen(name) - (extra_ptr - name); + if (!named_mode) { + int len = strlen(name) - (extra_ptr - name); - /* - * We still have characters to process, while - * we shouldn't have any - */ - if (remaining > 0) - return false; + ret = drm_mode_parse_cmdline_extra(extra_ptr, len, + connector, mode); + if (ret) + return false; + } else { + int remaining = strlen(name) - (extra_ptr - name); + + /* + * We still have characters to process, while + * we shouldn't have any + */ + if (remaining > 0) + return false; + } } return true; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 02a131202add..06aa3b9cb920 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -896,6 +896,7 @@ struct drm_connector_funcs { /* mode specified on the command line */ struct drm_cmdline_mode { + char name[DRM_DISPLAY_MODE_LEN]; bool specified; bool refresh_specified; bool bpp_specified; From patchwork Thu Apr 18 12:41:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 10907225 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DC2A71850 for ; Thu, 18 Apr 2019 12:43:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BFE67289C4 for ; Thu, 18 Apr 2019 12:43:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B3C3D28CA8; Thu, 18 Apr 2019 12:43:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.7 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,URIBL_RHS_DOB autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3074728BDE for ; Thu, 18 Apr 2019 12:43:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=QYfekdctqYZqF2c78kabfcihawDyl25sNTWCSAaIycc=; b=UAKsO4Pwl/LQ3x LN11/mbyx2sN+tZwlqVB6luTbl9OVy4WjcxcYo2MMP74I07k3YMa60zl5L5FZxdRfAUEkiT1j1qL4 MOJ15YOGyxNNaFhNobNue9r1nFq0Ipn+nQSwcJbTvpa0enJUCOozoxVRdZLVN2YHFQ2Ypo4BqToFk /1bSXj/fOKMz32rMIO2oaMRcGtYn9bG9544j2S5NCwYa0HXKs5MrWyQQpSPjBoTIl/DaQpOgdxLNv db+3zLlzgoXs6BMHwp6MEXP8yJ/qfLwSlFQjTAtVbNuudP7WlTGVieR0hsjBNw8AytxPyVvue/6M/ dAdHcccRn8wakcVFETYA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6Ns-00010v-Us; Thu, 18 Apr 2019 12:43:20 +0000 Received: from relay4-d.mail.gandi.net ([217.70.183.196]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6Mz-0008NJ-8T for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2019 12:42:27 +0000 X-Originating-IP: 90.88.160.238 Received: from localhost (aaubervilliers-681-1-42-238.w90-88.abo.wanadoo.fr [90.88.160.238]) (Authenticated sender: maxime.ripard@bootlin.com) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 9F264E0002; Thu, 18 Apr 2019 12:42:12 +0000 (UTC) From: Maxime Ripard To: Maarten Lankhorst , Sean Paul , Maxime Ripard , Daniel Vetter , David Airlie Subject: [PATCH v3 3/6] drm/modes: Allow to specify rotation and reflection on the commandline Date: Thu, 18 Apr 2019 14:41:56 +0200 Message-Id: X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190418_054225_627489_900FACDF X-CRM114-Status: GOOD ( 20.82 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eben@raspberrypi.org, dri-devel@lists.freedesktop.org, Paul Kocialkowski , Eric Anholt , noralf@tronnes.org, Thomas Petazzoni , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Rotations and reflections setup are needed in some scenarios to initialise properly the initial framebuffer. Some drivers already had a bunch of quirks to deal with this, such as either a private kernel command line parameter (omapdss) or on the device tree (various panels). In order to accomodate this, let's create a video mode parameter to deal with the rotation and reflexion. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_client_modeset.c | 10 +++- drivers/gpu/drm/drm_modes.c | 110 ++++++++++++++++++++++------ include/drm/drm_connector.h | 9 ++- 3 files changed, 109 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index f2869c82510c..15145d2c86d5 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -823,6 +823,7 @@ EXPORT_SYMBOL(drm_client_modeset_probe); bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotation) { struct drm_connector *connector = modeset->connectors[0]; + struct drm_cmdline_mode *cmdline; struct drm_plane *plane = modeset->crtc->primary; u64 valid_mask = 0; unsigned int i; @@ -844,6 +845,15 @@ bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotat *rotation = DRM_MODE_ROTATE_0; } + /** + * We want the rotation on the command line to overwrite + * whatever comes from the panel. + */ + cmdline = &connector->cmdline_mode; + if (cmdline->specified && + cmdline->rotation != DRM_MODE_ROTATE_0) + *rotation = cmdline->rotation; + /* * TODO: support 90 / 270 degree hardware rotation, * depending on the hardware this may require the framebuffer diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 9613c1a28487..ac8d70b92b62 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1531,6 +1531,71 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length, return 0; } +static int drm_mode_parse_cmdline_options(char *str, size_t len, + struct drm_connector *connector, + struct drm_cmdline_mode *mode) +{ + unsigned int rotation = 0; + char *sep = str; + + while ((sep = strchr(sep, ','))) { + char *delim, *option; + + option = sep + 1; + delim = strchr(option, '='); + if (!delim) { + delim = strchr(option, ','); + + if (!delim) + delim = str + len; + } + + if (!strncmp(option, "rotate", delim - option)) { + const char *value = delim + 1; + unsigned int deg; + + deg = simple_strtol(value, &sep, 10); + + /* Make sure we have parsed something */ + if (sep == value) + return -EINVAL; + + switch (deg) { + case 0: + rotation |= DRM_MODE_ROTATE_0; + break; + + case 90: + rotation |= DRM_MODE_ROTATE_90; + break; + + case 180: + rotation |= DRM_MODE_ROTATE_180; + break; + + case 270: + rotation |= DRM_MODE_ROTATE_270; + break; + + default: + return -EINVAL; + } + } else if (!strncmp(option, "reflect_x", delim - option)) { + rotation |= DRM_MODE_REFLECT_X; + sep = delim; + } else if (!strncmp(option, "reflect_y", delim - option)) { + rotation |= DRM_MODE_REFLECT_Y; + sep = delim; + } else { + return -EINVAL; + } + } + + mode->rotation = rotation; + + return 0; +} + /** * drm_mode_parse_command_line_for_connector - parse command line modeline for connector * @mode_option: optional per connector mode option @@ -1558,9 +1623,10 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, { const char *name; bool named_mode = false, parse_extras = false; - unsigned int bpp_off = 0, refresh_off = 0; + unsigned int bpp_off = 0, refresh_off = 0, options_off = 0; unsigned int mode_end = 0; char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; + char *options_ptr = NULL; char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int ret; @@ -1601,13 +1667,18 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, mode->refresh_specified = true; } + /* Locate the start of named options */ + options_ptr = strchr(name, ','); + if (options_ptr) + options_off = options_ptr - name; + /* Locate the end of the name / resolution, and parse it */ - if (bpp_ptr && refresh_ptr) { - mode_end = min(bpp_off, refresh_off); - } else if (bpp_ptr) { + if (bpp_ptr) { mode_end = bpp_off; } else if (refresh_ptr) { mode_end = refresh_off; + } else if (options_ptr) { + mode_end = options_off; } else { mode_end = strlen(name); parse_extras = true; @@ -1649,24 +1720,23 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, else if (refresh_ptr) extra_ptr = refresh_end_ptr; - if (extra_ptr) { - if (!named_mode) { - int len = strlen(name) - (extra_ptr - name); + if (extra_ptr && + extra_ptr != options_ptr) { + int len = strlen(name) - (extra_ptr - name); - ret = drm_mode_parse_cmdline_extra(extra_ptr, len, - connector, mode); - if (ret) - return false; - } else { - int remaining = strlen(name) - (extra_ptr - name); + ret = drm_mode_parse_cmdline_extra(extra_ptr, len, + connector, mode); + if (ret) + return false; + } - /* - * We still have characters to process, while - * we shouldn't have any - */ - if (remaining > 0) - return false; - } + if (options_ptr) { + int len = strlen(name) - (options_ptr - name); + + ret = drm_mode_parse_cmdline_options(options_ptr, len, + connector, mode); + if (ret) + return false; } return true; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 06aa3b9cb920..6f57c1a3afff 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -908,6 +908,15 @@ struct drm_cmdline_mode { bool cvt; bool margins; enum drm_connector_force force; + + /** + * @rotation: + * + * Initial rotation of the mode setup from the command line. + * See DRM_MODE_ROTATE_*. Only DRM_MODE_ROTATE_0 and + * DRM_MODE_ROTATE_180 are supported at the moment. + */ + unsigned int rotation; }; /** From patchwork Thu Apr 18 12:41:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 10907223 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4F12F922 for ; Thu, 18 Apr 2019 12:43:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 342F5289C4 for ; Thu, 18 Apr 2019 12:43:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 27FC528BDE; Thu, 18 Apr 2019 12:43:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.7 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,URIBL_RHS_DOB autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E24EE28CA8 for ; Thu, 18 Apr 2019 12:43:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=y5ggHRBEW04FR+Y8tJlk2JznmFurghulNmbmMHtMPU4=; b=db210xEgpF9uhZ F2RTp2cv+q3MFeBEz20k3a1KzM4dLZfYHky94HGtFX6REQsQUf8VlRwq1hQ+RUJ3g2ykx/N1MSv5c 9dMlLCxIk2s5HHRq12fs6bMINMhlFMHr+lM3iISfWkN44Y8MWbbhTGLgDHdNrePqX6+33Z6596Yy0 N0b6m72dqyKk0rR8IX74I4nTqFPZLHgI9QSZhTgBBGlFAdupIgUxDk7cUqws3w1D4NBIzI00cM71t lR/X4DJ+bAsJHzW/Vq+m6o/48OIv85V3jrFJveUSGZ5MtP1Kt83obTFqxqHhSBIpYQ3FDyAhpTgvs 2WW3TCtQ4Ar2T1gMvIZA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6Nh-0000ks-Mz; Thu, 18 Apr 2019 12:43:09 +0000 Received: from relay5-d.mail.gandi.net ([217.70.183.197]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6N3-0008Sa-Jq for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2019 12:42:34 +0000 X-Originating-IP: 90.88.160.238 Received: from localhost (aaubervilliers-681-1-42-238.w90-88.abo.wanadoo.fr [90.88.160.238]) (Authenticated sender: maxime.ripard@bootlin.com) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 758FB1C0002; Thu, 18 Apr 2019 12:42:14 +0000 (UTC) From: Maxime Ripard To: Maarten Lankhorst , Sean Paul , Maxime Ripard , Daniel Vetter , David Airlie Subject: [PATCH v3 4/6] drm/modes: Parse overscan properties Date: Thu, 18 Apr 2019 14:41:57 +0200 Message-Id: <92e60e2aedee460f600eea91d2dafc801a52a9e3.1555591281.git-series.maxime.ripard@bootlin.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190418_054230_318573_84A16BF4 X-CRM114-Status: GOOD ( 12.39 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eben@raspberrypi.org, dri-devel@lists.freedesktop.org, Paul Kocialkowski , Eric Anholt , noralf@tronnes.org, Thomas Petazzoni , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Properly configuring the overscan properties might be needed for the initial setup of the framebuffer for display that still have overscan. Let's allow for more properties on the kernel command line to setup each margin. Signed-off-by: Maxime Ripard Reviewed-by: Noralf Trønnes --- drivers/gpu/drm/drm_modes.c | 44 ++++++++++++++++++++++++++++++++++++++- include/drm/drm_connector.h | 14 ++++++++++++- 2 files changed, 58 insertions(+) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index ac8d70b92b62..d93c44a97ce9 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1586,6 +1586,50 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len, } else if (!strncmp(option, "reflect_y", delim - option)) { rotation |= DRM_MODE_REFLECT_Y; sep = delim; + } else if (!strncmp(option, "margin_right", delim - option)) { + const char *value = delim + 1; + unsigned int margin; + + margin = simple_strtol(value, &sep, 10); + + /* Make sure we have parsed something */ + if (sep == value) + return -EINVAL; + + mode->tv_margins.right = margin; + } else if (!strncmp(option, "margin_left", delim - option)) { + const char *value = delim + 1; + unsigned int margin; + + margin = simple_strtol(value, &sep, 10); + + /* Make sure we have parsed something */ + if (sep == value) + return -EINVAL; + + mode->tv_margins.left = margin; + } else if (!strncmp(option, "margin_top", delim - option)) { + const char *value = delim + 1; + unsigned int margin; + + margin = simple_strtol(value, &sep, 10); + + /* Make sure we have parsed something */ + if (sep == value) + return -EINVAL; + + mode->tv_margins.top = margin; + } else if (!strncmp(option, "margin_bottom", delim - option)) { + const char *value = delim + 1; + unsigned int margin; + + margin = simple_strtol(value, &sep, 10); + + /* Make sure we have parsed something */ + if (sep == value) + return -EINVAL; + + mode->tv_margins.bottom = margin; } else { return -EINVAL; } diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 6f57c1a3afff..89bc6ac38043 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -917,6 +917,20 @@ struct drm_cmdline_mode { * DRM_MODE_ROTATE_180 are supported at the moment. */ unsigned int rotation; + + /** + * @tv_margins: TV margins (in pixels) + * @tv_margins.left: left margin + * @tv_margins.right: right margin + * @tv_margins.top: top margin + * @tv_margins.bottom: bottom margin + */ + struct { + unsigned int left; + unsigned int right; + unsigned int top; + unsigned int bottom; + } tv_margins; }; /** From patchwork Thu Apr 18 12:41:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 10907221 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 42948922 for ; Thu, 18 Apr 2019 12:43:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23D4028CA8 for ; Thu, 18 Apr 2019 12:43:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 17FFA28CAC; Thu, 18 Apr 2019 12:43:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.7 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,URIBL_RHS_DOB autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B757128CA9 for ; Thu, 18 Apr 2019 12:43:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=asYclA0X5oM/GoyoGOKlfA8Dt8xeYUGQA0PL2B29LZ0=; b=krQ4OQa0uylZZw k25QFBuzfL6LEp8eUO1q8+PHZHJen4N+PxswX2c0vJ2Ng2dDjjJDo75j+AC6mBA6c767HdhER+5Io V37bzTwyIhQRbJs1J5gSYY/WxC2VdeIthdY/Aj13KBLvnIKso9zzDTN/Sf4CSN+sDIT0Ntw0GIpRK PZK2sGQsynyNfkZ902z4OpR6fIxlB6f9kaqrC7B/iTr6FvlK/eNY1/QJhL245k4tw6r5hHjgQ7KQO TGh8Vbc30iW3hu6Dt0yKoa39EgiWHVpRsdvUsDkn8t3sboPONMx8G43KbvRAdziVfdXqdrLm3qjhV DdY+t7cmDLyoTGKamhhA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6Nb-0000cT-6r; Thu, 18 Apr 2019 12:43:03 +0000 Received: from relay4-d.mail.gandi.net ([217.70.183.196]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6Mz-0008NK-8T for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2019 12:42:31 +0000 X-Originating-IP: 90.88.160.238 Received: from localhost (aaubervilliers-681-1-42-238.w90-88.abo.wanadoo.fr [90.88.160.238]) (Authenticated sender: maxime.ripard@bootlin.com) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 5F610E0003; Thu, 18 Apr 2019 12:42:20 +0000 (UTC) From: Maxime Ripard To: Maarten Lankhorst , Sean Paul , Maxime Ripard , Daniel Vetter , David Airlie Subject: [PATCH v3 5/6] drm/selftests: Add command line parser selftests Date: Thu, 18 Apr 2019 14:41:58 +0200 Message-Id: <2aac1939a5fb99922b4b552295db41ea4bc99329.1555591281.git-series.maxime.ripard@bootlin.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190418_054225_644696_CC212D69 X-CRM114-Status: GOOD ( 14.21 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eben@raspberrypi.org, dri-devel@lists.freedesktop.org, Paul Kocialkowski , Eric Anholt , noralf@tronnes.org, Thomas Petazzoni , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The command line parser is pretty tough to get right and very error prone, so let's add a selftest to try to catch any regression. Signed-off-by: Maxime Ripard Reviewed-by: Noralf Trønnes --- drivers/gpu/drm/selftests/Makefile | 2 +- drivers/gpu/drm/selftests/drm_cmdline_selftests.h | 49 +- drivers/gpu/drm/selftests/test-drm_cmdline_parser.c | 846 +++++++++++++- 3 files changed, 896 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/selftests/drm_cmdline_selftests.h create mode 100644 drivers/gpu/drm/selftests/test-drm_cmdline_parser.c diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index 1bb73dc4c88c..fdd4238cb34a 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -2,4 +2,4 @@ test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \ test-drm_format.o test-drm_framebuffer.o \ test-drm_damage_helper.o -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h new file mode 100644 index 000000000000..6f9ba9459bec --- /dev/null +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* List each unit test as selftest(function) + * + * The name is used as both an enum and expanded as igt__name to create + * a module parameter. It must be unique and legal for a C identifier. + * + * Tests are executed in order by igt/drm_mm + */ + +#define cmdline_test(test) selftest(test, test) + +cmdline_test(drm_cmdline_test_res) +cmdline_test(drm_cmdline_test_res_vesa) +cmdline_test(drm_cmdline_test_res_vesa_rblank) +cmdline_test(drm_cmdline_test_res_rblank) +cmdline_test(drm_cmdline_test_res_bpp) +cmdline_test(drm_cmdline_test_res_refresh) +cmdline_test(drm_cmdline_test_res_bpp_refresh) +cmdline_test(drm_cmdline_test_res_bpp_refresh_interlaced) +cmdline_test(drm_cmdline_test_res_bpp_refresh_margins) +cmdline_test(drm_cmdline_test_res_bpp_refresh_force_off) +cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_off) +cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on) +cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_analog) +cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_digital) +cmdline_test(drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on) +cmdline_test(drm_cmdline_test_res_margins_force_on) +cmdline_test(drm_cmdline_test_res_vesa_margins) +cmdline_test(drm_cmdline_test_res_invalid_mode) +cmdline_test(drm_cmdline_test_res_bpp_wrong_place_mode) +cmdline_test(drm_cmdline_test_name) +cmdline_test(drm_cmdline_test_name_bpp) +cmdline_test(drm_cmdline_test_name_refresh) +cmdline_test(drm_cmdline_test_name_bpp_refresh) +cmdline_test(drm_cmdline_test_name_refresh_wrong_mode) +cmdline_test(drm_cmdline_test_name_refresh_invalid_mode) +cmdline_test(drm_cmdline_test_name_option) +cmdline_test(drm_cmdline_test_name_bpp_option) +cmdline_test(drm_cmdline_test_rotate_0) +cmdline_test(drm_cmdline_test_rotate_90) +cmdline_test(drm_cmdline_test_rotate_180) +cmdline_test(drm_cmdline_test_rotate_270) +cmdline_test(drm_cmdline_test_rotate_invalid_val) +cmdline_test(drm_cmdline_test_rotate_truncated) +cmdline_test(drm_cmdline_test_hmirror) +cmdline_test(drm_cmdline_test_vmirror) +cmdline_test(drm_cmdline_test_margin_options) +cmdline_test(drm_cmdline_test_multiple_options) +cmdline_test(drm_cmdline_test_invalid_option) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c new file mode 100644 index 000000000000..290d32cd9a07 --- /dev/null +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c @@ -0,0 +1,846 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Bootlin + */ + +#define pr_fmt(fmt) "drm_cmdline: " fmt + +#include +#include + +#include +#include + +#define TESTS "drm_cmdline_selftests.h" +#include "drm_selftest.h" +#include "test-drm_modeset_common.h" + +static int drm_cmdline_test_res(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_vesa(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480M", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(!mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_vesa_rblank(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480MR", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(!mode.rb); + FAIL_ON(!mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_rblank(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480R", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(!mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_bpp(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_refresh(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480@60", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh_interlaced(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60i", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(!mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh_margins(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60m", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(!mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh_force_off(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60d", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_OFF); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh_force_on_off(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("720x480-24@60de", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh_force_on(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60e", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_ON); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh_force_on_analog(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60D", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_ON); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh_force_on_digital(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + connector.connector_type = DRM_MODE_CONNECTOR_DVII; + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60D", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL); + + return 0; +} + +static int drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60ime", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(!mode.refresh_specified); + FAIL_ON(mode.refresh != 60); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(!mode.interlace); + FAIL_ON(!mode.margins); + FAIL_ON(mode.force != DRM_FORCE_ON); + + return 0; +} + +static int drm_cmdline_test_res_margins_force_on(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480me", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(!mode.margins); + FAIL_ON(mode.force != DRM_FORCE_ON); + + return 0; +} + +static int drm_cmdline_test_res_vesa_margins(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480Mm", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(!mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(!mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_res_invalid_mode(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("720x480f", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_res_bpp_wrong_place_mode(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("720x480e-24", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_name(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC", + &connector, + &mode)); + FAIL_ON(strcmp(mode.name, "NTSC")); + FAIL_ON(mode.refresh_specified); + FAIL_ON(mode.bpp_specified); + + return 0; +} + +static int drm_cmdline_test_name_bpp(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC-24", + &connector, + &mode)); + FAIL_ON(strcmp(mode.name, "NTSC")); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + return 0; +} + +static int drm_cmdline_test_name_bpp_refresh(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC-24@60", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_name_refresh(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_name_refresh_wrong_mode(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60m", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_name_refresh_invalid_mode(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60f", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_name_option(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC,rotate=180", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(strcmp(mode.name, "NTSC")); + FAIL_ON(mode.rotation != DRM_MODE_ROTATE_180); + + return 0; +} + +static int drm_cmdline_test_name_bpp_option(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC-24,rotate=180", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(strcmp(mode.name, "NTSC")); + FAIL_ON(mode.rotation != DRM_MODE_ROTATE_180); + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + return 0; +} + +static int drm_cmdline_test_rotate_0(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=0", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation != DRM_MODE_ROTATE_0); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_rotate_90(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=90", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation != DRM_MODE_ROTATE_90); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_rotate_180(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=180", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation != DRM_MODE_ROTATE_180); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_rotate_270(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=270", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation != DRM_MODE_ROTATE_270); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_rotate_invalid_val(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=42", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_rotate_truncated(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=", + &connector, + &mode)); + + return 0; +} + +static int drm_cmdline_test_hmirror(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,reflect_x", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation != DRM_MODE_REFLECT_X); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_vmirror(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,reflect_y", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation != DRM_MODE_REFLECT_Y); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_margin_options(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.tv_margins.right != 14); + FAIL_ON(mode.tv_margins.left != 24); + FAIL_ON(mode.tv_margins.bottom != 36); + FAIL_ON(mode.tv_margins.top != 42); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_multiple_options(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=270,reflect_x", + &connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation != (DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X)); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_invalid_option(void *ignored) +{ + struct drm_connector connector = { }; + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,test=42", + &connector, + &mode)); + + return 0; +} + +#include "drm_selftest.c" + +static int __init test_drm_cmdline_init(void) +{ + int err; + + err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL); + + return err > 0 ? 0 : err; +} +module_init(test_drm_cmdline_init); + +MODULE_AUTHOR("Maxime Ripard "); +MODULE_LICENSE("GPL"); From patchwork Thu Apr 18 12:41:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 10907227 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5CA921515 for ; Thu, 18 Apr 2019 12:43:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3FBA428BDE for ; Thu, 18 Apr 2019 12:43:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 33B8E289C4; Thu, 18 Apr 2019 12:43:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.7 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,URIBL_RHS_DOB autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D3B9F289C4 for ; Thu, 18 Apr 2019 12:43:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=3zrqC/PPbJf6dPdbNZPns5xzxSxubHIUh+2dAzYb0OM=; b=lc3Xrp9/mY/v1K 6rWFQEOjPs1LuI+EHTxXS3vlLJdVtWhw/UoYNlbMU6Z9xKE38jAn7aJVEtacVQ7f76/gJ+11Up7eL Fuk3SqrggfrhVy2/GkrFZWiwPRS/4by5njj28bNqA0BCBets59rIGaMR2LhDmSGhzeCIaYvhP9zbH /ZYjn7c3LA3p0vD8kXjt+6zoF4v4EAsaBNnHTIS96OKvxgFjV3FgNOneNh7hP9AGmAe4WdKsxdSSZ KQlMSzqSfQfoF28NRxuUn93IWx7AmNPcnvQQvDImt7r1KMk0Wk1wG3eaW24npEWbLAkYRV9HrpNri h71jWaqU7V0TlloCQUNA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6O3-0001EF-Ni; Thu, 18 Apr 2019 12:43:31 +0000 Received: from relay2-d.mail.gandi.net ([217.70.183.194]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hH6N5-0008V4-R8 for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2019 12:42:37 +0000 X-Originating-IP: 90.88.160.238 Received: from localhost (aaubervilliers-681-1-42-238.w90-88.abo.wanadoo.fr [90.88.160.238]) (Authenticated sender: maxime.ripard@bootlin.com) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 1ADBB40003; Thu, 18 Apr 2019 12:42:22 +0000 (UTC) From: Maxime Ripard To: Maarten Lankhorst , Sean Paul , Maxime Ripard , Daniel Vetter , David Airlie Subject: [PATCH v3 6/6] drm/vc4: hdmi: Set default state margin at reset Date: Thu, 18 Apr 2019 14:41:59 +0200 Message-Id: X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190418_054232_429882_EE7094A6 X-CRM114-Status: GOOD ( 11.40 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eben@raspberrypi.org, dri-devel@lists.freedesktop.org, Paul Kocialkowski , Eric Anholt , noralf@tronnes.org, Thomas Petazzoni , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Now that the TV margins are properly parsed and filled into drm_cmdline_mode, we just need to initialise the first state at reset to get those values and start using them. Signed-off-by: Maxime Ripard Acked-by: Noralf Trønnes --- drivers/gpu/drm/vc4/vc4_hdmi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 99fc8569e0f5..d86f154138f5 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -255,11 +255,25 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) return ret; } +static void vc4_hdmi_connector_reset(struct drm_connector *connector) +{ + struct drm_cmdline_mode *cmdline = &connector->cmdline_mode; + struct drm_connector_state *state; + + drm_atomic_helper_connector_reset(connector); + + state = connector->state; + state->tv.margins.left = cmdline->tv_margins.left; + state->tv.margins.right = cmdline->tv_margins.right; + state->tv.margins.top = cmdline->tv_margins.top; + state->tv.margins.bottom = cmdline->tv_margins.bottom; +} + static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { .detect = vc4_hdmi_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = vc4_hdmi_connector_destroy, - .reset = drm_atomic_helper_connector_reset, + .reset = vc4_hdmi_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };