From patchwork Mon Mar 4 14:52:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 159548 Delivered-To: patch@linaro.org Received: by 2002:a02:5cc1:0:0:0:0:0 with SMTP id w62csp3859380jad; Mon, 4 Mar 2019 06:53:05 -0800 (PST) X-Google-Smtp-Source: APXvYqxCLgGjh0lPAuAJOoLZpsz+v+kfqCUtnuJuACs2gFRrtYfy+hH8JIuwXfAKX1+1IskDKOU5 X-Received: by 2002:a63:e447:: with SMTP id i7mr18682688pgk.70.1551711185064; Mon, 04 Mar 2019 06:53:05 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551711185; cv=none; d=google.com; s=arc-20160816; b=UyLmeuxd2y3EJezf7IelXoIw05KgkdrMLr8VvKfMLkssJM6sn2Ljh3qQB2bcwEecBz wfrMZYMdkv2yJlU65BOJBgs89ZdQy7oikhU5D6N+8QCysDVu5GkL2yk3xUKyUB2PZW5G a966CaoB6LT8v2Q1oRUFnaShdlQZ84Lfy5r1eVsVkTYEOxVjadYGNBDlSUhurCfis9Fw VwWSjE3HJJAzQkoz8GILHPBEX5FVnbPSPs+0gNQiMfru0I/hUztGiOwxrgsmNK8/Ewa2 KBYcBKNLAEjxUPig2o+y7kJ4bQbPWY5rHwLzpNs0eS96J25nzBXyBrHBGIzPK84orKj1 uoUw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:mime-version:references:in-reply-to:message-id:date :subject:to:from:delivered-to; bh=h0+aQMHM07j3P0X9noHD3/WN6aLvfInDZDxTsZTxWug=; b=kHUtkdx3wCHQdWF8ZrRlaqqwDywmLB9/tMHZgojC34AOV0OgyS7ARUurIbG8YjszkR KKIipPKRpyjYWiroYDbema1kJR4NWsJFLKmi9l3atU3n487oCb1NnLTu3eLVVTpH6ePi Tv+b+4pjT8x0TvW68iT+pgikuFhHFu2y2Ua8FXaE1IS7apundT/DdyrpekAoEcw0c1Vg med0k4GM8BGV2K6YipYytnejlKdLBJC8pHPP0Ae+BgfxSveTkqhISQlFoaReylkh6pcM jiWDmHCs2S5rvkncaMN2TL1vAYP2kmMM/lBJfXo155cscGZiH7KDUl6d7TM7plizeuED 6GYA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [131.252.210.177]) by mx.google.com with ESMTPS id m10si5420006pgk.386.2019.03.04.06.53.04 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Mar 2019 06:53:05 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) client-ip=131.252.210.177; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D00B089D46; Mon, 4 Mar 2019 14:53:03 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by gabe.freedesktop.org (Postfix) with ESMTPS id 92DF389D46 for ; Mon, 4 Mar 2019 14:53:02 +0000 (UTC) X-Originating-IP: 185.94.189.188 Received: from localhost (unknown [185.94.189.188]) (Authenticated sender: maxime.ripard@bootlin.com) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 29AE8C000A; Mon, 4 Mar 2019 14:52:56 +0000 (UTC) From: Maxime Ripard To: Maarten Lankhorst , Sean Paul , Maxime Ripard , Daniel Vetter , David Airlie Subject: [PATCH 4/7] drm/modes: Rewrite the command line parser Date: Mon, 4 Mar 2019 15:52:37 +0100 Message-Id: X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eben@raspberrypi.org, dri-devel@lists.freedesktop.org, Paul Kocialkowski , Thomas Petazzoni , Maxime Ripard , linux-arm-kernel@lists.infradead.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" 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 | 308 +++++++++++++++++++++++-------------- 1 file changed, 193 insertions(+), 115 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 869ac6f4671e..31d61940c007 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,80 @@ 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) { + if (named_mode) + return false; + + 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 Mon Mar 4 14:52:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 159549 Delivered-To: patch@linaro.org Received: by 2002:a02:5cc1:0:0:0:0:0 with SMTP id w62csp3859435jad; Mon, 4 Mar 2019 06:53:08 -0800 (PST) X-Google-Smtp-Source: APXvYqxRx0HJuvEoseys4EOuWpGuj1KfF8e4Lv8JrmekvJCCAGDjk9xjF/UUXjJa7pzpXiBQoSAR X-Received: by 2002:a63:6605:: with SMTP id a5mr18911887pgc.372.1551711188377; Mon, 04 Mar 2019 06:53:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551711188; cv=none; d=google.com; s=arc-20160816; b=P2gNUvTV7t6viGXG04cxlq3T0D/f9wrTDtHxuYGqcVt54AAH6bxlW/K/+DeAwsLH+u KBk90F9+gYdHeAHkjaUnL47FVLyI4HNFsubd/zY+BVgtkV2xAHAObM/3RYBPkMEPUUSO Y+IebZIffuepHfsY6IKiGwE0gw6AAtjPTOR3av3Ek/iiSJeLCM3nKA1uWyZeLuJnRz1A ZktiKRTFW7IEjKsjgzcGSUHeHTHxYPkcz2OBQb8y52M8N2L3ldD27WsbArkqXEBx1LdU Nsqx8leA4+5vwCpimfvmrlcdN8u8VIrh3RPq2/lljJD98MZ16U04JqEMT4elgJPLemof kKEw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:mime-version:references:in-reply-to:message-id:date :subject:to:from:delivered-to; bh=qQQB/1pMHWl6t1IgUQrW1kmea8HNxUaBri1rXCoVqcY=; b=Ou11Og5zLhk7clK7uZw0uK4XIL95yJ/CPPMr6nhFGF+OrjuOtFI6a4OereG/tbykNN ZAvdPvKvLRSvkVnqSQKyw0uCACFF42QDDkBW8k4mCbI9jK8v0M590lkihctIoV4w93Vl wNFdirYdfbPyKQwISBZG/4HdF7gzsmmZy65NinsUW4aveUYK2bN55gqleDvxKX7/EI2K rZy8G5ys8MzpLpsISAaUI3WF8h1GH/gLaPvgSc2KcSVXMiKcyklqhE1/FzUPXBQnkkJ2 At8JqbTcSCSdB1LFYcuGS/k4fugmtBnY3zR3TNCFTmoEeYrL1WulnvJ0IgP3UNCq/35l V8Pg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [2610:10:20:722:a800:ff:fe36:1795]) by mx.google.com with ESMTPS id d23si5248520plr.333.2019.03.04.06.53.07 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 04 Mar 2019 06:53:08 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) client-ip=2610:10:20:722:a800:ff:fe36:1795; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 2610:10:20:722:a800:ff:fe36:1795 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 19DF189D49; Mon, 4 Mar 2019 14:53:06 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net [217.70.183.199]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6D49489CF5 for ; Mon, 4 Mar 2019 14:53:03 +0000 (UTC) X-Originating-IP: 185.94.189.188 Received: from localhost (unknown [185.94.189.188]) (Authenticated sender: maxime.ripard@bootlin.com) by relay9-d.mail.gandi.net (Postfix) with ESMTPSA id 6F569FF805; Mon, 4 Mar 2019 14:53:00 +0000 (UTC) From: Maxime Ripard To: Maarten Lankhorst , Sean Paul , Maxime Ripard , Daniel Vetter , David Airlie Subject: [PATCH 5/7] drm/modes: Support modes names on the command line Date: Mon, 4 Mar 2019 15:52:38 +0100 Message-Id: <84e1fb2ff08ad3a5ba3707bc937ba7fe6be15adc.1551711042.git-series.maxime.ripard@bootlin.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eben@raspberrypi.org, dri-devel@lists.freedesktop.org, Paul Kocialkowski , Thomas Petazzoni , Maxime Ripard , linux-arm-kernel@lists.infradead.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" 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 --- drivers/gpu/drm/drm_connector.c | 3 +- drivers/gpu/drm/drm_fb_helper.c | 4 +++- drivers/gpu/drm/drm_modes.c | 49 +++++++++++++++++++++++----------- include/drm/drm_connector.h | 1 +- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index dd40eff0911c..799e932c114d 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_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 0e9349ff2d16..cacc4b56344e 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -2158,6 +2158,10 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f prefer_non_interlace = !cmdline_mode->interlace; again: list_for_each_entry(mode, &fb_helper_conn->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_modes.c b/drivers/gpu/drm/drm_modes.c index 31d61940c007..3d843d17370a 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, '-'); @@ -1607,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) { @@ -1640,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 8fe22abb1e10..215761153245 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -823,6 +823,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;