mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 18:47:06 +00:00
175 lines
5.5 KiB
Diff
175 lines
5.5 KiB
Diff
|
From aec195ba9d647eb9e70e77c68c04e073a7c0e75e Mon Sep 17 00:00:00 2001
|
||
|
From: Maxime Ripard <maxime.ripard@bootlin.com>
|
||
|
Date: Wed, 19 Jun 2019 12:17:50 +0200
|
||
|
Subject: [PATCH 735/773] drm/modes: Support modes names on the command line
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
commit 3aeeb13d899627fe2b86bdbdcd0927cf7192234f upstream.
|
||
|
Minor conflict resolution as upstream has moved functions
|
||
|
from drm_fb_helper.c to a new drm_client_modeset.c
|
||
|
|
||
|
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).
|
||
|
|
||
|
Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
|
||
|
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||
|
Link: https://patchwork.freedesktop.org/patch/msgid/18443e0c3bdbbd16cea4ec63bc7f2079b820b43b.1560783090.git-series.maxime.ripard@bootlin.com
|
||
|
---
|
||
|
drivers/gpu/drm/drm_connector.c | 3 +-
|
||
|
drivers/gpu/drm/drm_fb_helper.c | 4 +++
|
||
|
drivers/gpu/drm/drm_modes.c | 62 ++++++++++++++++++++++++---------
|
||
|
include/drm/drm_connector.h | 7 ++++
|
||
|
4 files changed, 59 insertions(+), 17 deletions(-)
|
||
|
|
||
|
--- a/drivers/gpu/drm/drm_connector.c
|
||
|
+++ b/drivers/gpu/drm/drm_connector.c
|
||
|
@@ -135,8 +135,9 @@ static void drm_connector_get_cmdline_mo
|
||
|
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" : "",
|
||
|
--- a/drivers/gpu/drm/drm_fb_helper.c
|
||
|
+++ b/drivers/gpu/drm/drm_fb_helper.c
|
||
|
@@ -2099,6 +2099,10 @@ struct drm_display_mode *drm_pick_cmdlin
|
||
|
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)
|
||
|
--- a/drivers/gpu/drm/drm_modes.c
|
||
|
+++ b/drivers/gpu/drm/drm_modes.c
|
||
|
@@ -1586,7 +1586,7 @@ bool drm_mode_parse_command_line_for_con
|
||
|
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;
|
||
|
@@ -1605,8 +1605,22 @@ bool drm_mode_parse_command_line_for_con
|
||
|
|
||
|
name = mode_option;
|
||
|
|
||
|
- if (!isdigit(name[0]))
|
||
|
- return false;
|
||
|
+ /*
|
||
|
+ * This is a bit convoluted. To differentiate between the
|
||
|
+ * named modes and poorly formatted resolutions, we need a
|
||
|
+ * bunch of things:
|
||
|
+ * - We need to make sure that the first character (which
|
||
|
+ * would be our resolution in X) is a digit.
|
||
|
+ * - However, if the X resolution is missing, then we end up
|
||
|
+ * with something like x<yres>, with our first character
|
||
|
+ * being an alpha-numerical character, which would be
|
||
|
+ * considered a named mode.
|
||
|
+ *
|
||
|
+ * If this isn't enough, we should add more heuristics here,
|
||
|
+ * and matching unit-tests.
|
||
|
+ */
|
||
|
+ if (!isdigit(name[0]) && name[0] != 'x')
|
||
|
+ named_mode = true;
|
||
|
|
||
|
/* Try to locate the bpp and refresh specifiers, if any */
|
||
|
bpp_ptr = strchr(name, '-');
|
||
|
@@ -1617,6 +1631,9 @@ bool drm_mode_parse_command_line_for_con
|
||
|
|
||
|
refresh_ptr = strchr(name, '@');
|
||
|
if (refresh_ptr) {
|
||
|
+ if (named_mode)
|
||
|
+ return false;
|
||
|
+
|
||
|
refresh_off = refresh_ptr - name;
|
||
|
mode->refresh_specified = true;
|
||
|
}
|
||
|
@@ -1633,12 +1650,16 @@ bool drm_mode_parse_command_line_for_con
|
||
|
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) {
|
||
|
@@ -1666,14 +1687,23 @@ bool drm_mode_parse_command_line_for_con
|
||
|
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;
|
||
|
--- a/include/drm/drm_connector.h
|
||
|
+++ b/include/drm/drm_connector.h
|
||
|
@@ -765,6 +765,13 @@ struct drm_connector_funcs {
|
||
|
*/
|
||
|
struct drm_cmdline_mode {
|
||
|
/**
|
||
|
+ * @name:
|
||
|
+ *
|
||
|
+ * Name of the mode.
|
||
|
+ */
|
||
|
+ char name[DRM_DISPLAY_MODE_LEN];
|
||
|
+
|
||
|
+ /**
|
||
|
* @specified:
|
||
|
*
|
||
|
* Has a mode been read from the command-line?
|