diff options
author | Hans de Goede <hdegoede@redhat.com> | 2019-11-18 18:51:30 +0300 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2019-12-16 14:13:18 +0300 |
commit | 4e7a4a6fbdc669c44e6079f9d5eb25673749455f (patch) | |
tree | a57a8b9358aacedc5b4ad7d07519c4fef882f666 | |
parent | 7b1cce760afe38b40f0989cdf10b2190dccf9815 (diff) | |
download | linux-4e7a4a6fbdc669c44e6079f9d5eb25673749455f.tar.xz |
drm/modes: parse_cmdline: Add support for specifying panel_orientation (v2)
Sometimes we want to override a connector's panel_orientation from the
kernel commandline. Either for testing and for special cases, e.g. a kiosk
like setup which uses a TV mounted in portrait mode.
Users can already specify a "rotate" option through a video= kernel cmdline
option. But that only supports 0/180 degrees (see drm_client_modeset TODO)
and only works for in kernel modeset clients, not for userspace kms users.
The "panel-orientation" connector property OTOH does support 90/270 degrees
as it leaves dealing with the rotation up to userspace and this does work
for userspace kms clients (at least those which support this property).
Changes in v2:
-Add missing ':' after @panel_orientation (reported by kbuild test robot)
BugLink: https://gitlab.freedesktop.org/plymouth/plymouth/merge_requests/83
Acked-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-9-hdegoede@redhat.com
-rw-r--r-- | Documentation/fb/modedb.rst | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/selftests/drm_cmdline_selftests.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/selftests/test-drm_cmdline_parser.c | 22 | ||||
-rw-r--r-- | include/drm/drm_connector.h | 8 |
5 files changed, 66 insertions, 0 deletions
diff --git a/Documentation/fb/modedb.rst b/Documentation/fb/modedb.rst index 9c4e3fd39e6d..624d08fd2856 100644 --- a/Documentation/fb/modedb.rst +++ b/Documentation/fb/modedb.rst @@ -65,6 +65,9 @@ Valid options are:: - reflect_y (boolean): Perform an axial symmetry on the Y axis - rotate (integer): Rotate the initial framebuffer by x degrees. Valid values are 0, 90, 180 and 270. + - panel_orientation, one of "normal", "upside_down", "left_side_up", or + "right_side_up". For KMS drivers only, this sets the "panel orientation" + property on the kms connector as hint for kms users. ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 2e82603f5d0a..119fed7ab815 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1591,6 +1591,33 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) return 0; } +static int drm_mode_parse_panel_orientation(const char *delim, + struct drm_cmdline_mode *mode) +{ + const char *value; + + if (*delim != '=') + return -EINVAL; + + value = delim + 1; + delim = strchr(value, ','); + if (!delim) + delim = value + strlen(value); + + if (!strncmp(value, "normal", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (!strncmp(value, "upside_down", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (!strncmp(value, "left_side_up", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else if (!strncmp(value, "right_side_up", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else + return -EINVAL; + + return 0; +} + static int drm_mode_parse_cmdline_options(const char *str, bool freestanding, const struct drm_connector *connector, @@ -1657,6 +1684,9 @@ static int drm_mode_parse_cmdline_options(const char *str, return -EINVAL; mode->tv_margins.bottom = margin; + } else if (!strncmp(option, "panel_orientation", delim - option)) { + if (drm_mode_parse_panel_orientation(delim, mode)) + return -EINVAL; } else { return -EINVAL; } @@ -1715,6 +1745,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int i, len, ret; + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + #ifdef CONFIG_FB if (!mode_option) mode_option = fb_mode_option; diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h index aee92ac2cc21..ceac7af9a172 100644 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h @@ -64,3 +64,4 @@ cmdline_test(drm_cmdline_test_bpp_extra_and_option) cmdline_test(drm_cmdline_test_extra_and_option) cmdline_test(drm_cmdline_test_freestanding_options) cmdline_test(drm_cmdline_test_freestanding_force_e_and_options) +cmdline_test(drm_cmdline_test_panel_orientation) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c index 8248d4aa5aaa..520f3e66a384 100644 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c @@ -1092,6 +1092,28 @@ static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored) return 0; } +static int drm_cmdline_test_panel_orientation(void *ignored) +{ + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down", + &no_connector, + &mode)); + FAIL_ON(mode.specified); + FAIL_ON(mode.refresh_specified); + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP); + + 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; +} + #include "drm_selftest.c" static int __init test_drm_cmdline_init(void) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 17b728d9c73d..221910948b37 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1070,6 +1070,14 @@ struct drm_cmdline_mode { unsigned int rotation_reflection; /** + * @panel_orientation: + * + * drm-connector "panel orientation" property override value, + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN if not set. + */ + enum drm_panel_orientation panel_orientation; + + /** * @tv_margins: TV margins to apply to the mode. */ struct drm_connector_tv_margins tv_margins; |