1 From 7d395633947fa6595a117f40e0f27ba87be77d6c Mon Sep 17 00:00:00 2001
2 From: Hans de Goede <hdegoede@redhat.com>
3 Date: Mon, 18 Nov 2019 16:51:30 +0100
4 Subject: [PATCH] drm/modes: parse_cmdline: Add support for specifying
7 Commit 4e7a4a6fbdc669c44e6079f9d5eb25673749455f upstream.
9 Sometimes we want to override a connector's panel_orientation from the
10 kernel commandline. Either for testing and for special cases, e.g. a kiosk
11 like setup which uses a TV mounted in portrait mode.
13 Users can already specify a "rotate" option through a video= kernel cmdline
14 option. But that only supports 0/180 degrees (see drm_client_modeset TODO)
15 and only works for in kernel modeset clients, not for userspace kms users.
17 The "panel-orientation" connector property OTOH does support 90/270 degrees
18 as it leaves dealing with the rotation up to userspace and this does work
19 for userspace kms clients (at least those which support this property).
22 -Add missing ':' after @panel_orientation (reported by kbuild test robot)
24 BugLink: https://gitlab.freedesktop.org/plymouth/plymouth/merge_requests/83
25 Acked-by: Maxime Ripard <mripard@kernel.org>
26 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
27 Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-9-hdegoede@redhat.com
29 Documentation/fb/modedb.rst | 3 ++
30 drivers/gpu/drm/drm_modes.c | 32 +++++++++++++++++++
31 .../gpu/drm/selftests/drm_cmdline_selftests.h | 1 +
32 .../drm/selftests/test-drm_cmdline_parser.c | 22 +++++++++++++
33 include/drm/drm_connector.h | 8 +++++
34 5 files changed, 66 insertions(+)
36 --- a/Documentation/fb/modedb.rst
37 +++ b/Documentation/fb/modedb.rst
38 @@ -65,6 +65,9 @@ Valid options are::
39 - reflect_y (boolean): Perform an axial symmetry on the Y axis
40 - rotate (integer): Rotate the initial framebuffer by x
41 degrees. Valid values are 0, 90, 180 and 270.
42 + - panel_orientation, one of "normal", "upside_down", "left_side_up", or
43 + "right_side_up". For KMS drivers only, this sets the "panel orientation"
44 + property on the kms connector as hint for kms users.
47 -----------------------------------------------------------------------------
48 --- a/drivers/gpu/drm/drm_modes.c
49 +++ b/drivers/gpu/drm/drm_modes.c
50 @@ -1591,6 +1591,33 @@ static int drm_mode_parse_cmdline_int(co
54 +static int drm_mode_parse_panel_orientation(const char *delim,
55 + struct drm_cmdline_mode *mode)
63 + delim = strchr(value, ',');
65 + delim = value + strlen(value);
67 + if (!strncmp(value, "normal", delim - value))
68 + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
69 + else if (!strncmp(value, "upside_down", delim - value))
70 + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
71 + else if (!strncmp(value, "left_side_up", delim - value))
72 + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
73 + else if (!strncmp(value, "right_side_up", delim - value))
74 + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
81 static int drm_mode_parse_cmdline_options(const char *str,
83 const struct drm_connector *connector,
84 @@ -1657,6 +1684,9 @@ static int drm_mode_parse_cmdline_option
87 mode->tv_margins.bottom = margin;
88 + } else if (!strncmp(option, "panel_orientation", delim - option)) {
89 + if (drm_mode_parse_panel_orientation(delim, mode))
94 @@ -1715,6 +1745,8 @@ bool drm_mode_parse_command_line_for_con
95 char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
98 + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
102 mode_option = fb_mode_option;
103 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
104 +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
105 @@ -64,3 +64,4 @@ cmdline_test(drm_cmdline_test_bpp_extra_
106 cmdline_test(drm_cmdline_test_extra_and_option)
107 cmdline_test(drm_cmdline_test_freestanding_options)
108 cmdline_test(drm_cmdline_test_freestanding_force_e_and_options)
109 +cmdline_test(drm_cmdline_test_panel_orientation)
110 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
111 +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
112 @@ -1092,6 +1092,28 @@ static int drm_cmdline_test_freestanding
116 +static int drm_cmdline_test_panel_orientation(void *ignored)
118 + struct drm_cmdline_mode mode = { };
120 + FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down",
123 + FAIL_ON(mode.specified);
124 + FAIL_ON(mode.refresh_specified);
125 + FAIL_ON(mode.bpp_specified);
127 + FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP);
131 + FAIL_ON(mode.interlace);
132 + FAIL_ON(mode.margins);
133 + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
138 #include "drm_selftest.c"
140 static int __init test_drm_cmdline_init(void)
141 --- a/include/drm/drm_connector.h
142 +++ b/include/drm/drm_connector.h
143 @@ -1066,6 +1066,14 @@ struct drm_cmdline_mode {
144 unsigned int rotation_reflection;
147 + * @panel_orientation:
149 + * drm-connector "panel orientation" property override value,
150 + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN if not set.
152 + enum drm_panel_orientation panel_orientation;
155 * @tv_margins: TV margins to apply to the mode.
157 struct drm_connector_tv_margins tv_margins;