linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration
@ 2019-06-14 12:13 Maxime Ripard
  2019-06-14 12:13 ` [PATCH v4 01/12] drm/connector: Add documentation for drm_cmdline_mode Maxime Ripard
                   ` (11 more replies)
  0 siblings, 12 replies; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

Hi,

The proprietary stack for the RaspberryPi allows for a number of video
parameters widely used by their users, but yet don't have any equivalents
in the mainline kernel.

Those options are detailed here:
https://www.raspberrypi.org/documentation/configuration/config-txt/video.md

While not all of them are desirable to have in the mainline kernel, some of
them still have value, such as properties to initialise the overscan or
rotation parameters.

This series is an attempt to support those, and is based on a rewrite of
the command line parser I did a couple of years ago that never reached
upstream (due to a lack of time on my side). While this parser was
initially made to deal with named modes (in order to support TV modes), it
also allowed to extend it more easily, which is why it's resurrected.

It relies on the series "drm/fb-helper: Move modesetting code to
drm_client" by Noralf Trønnes found here:
https://patchwork.freedesktop.org/series/58598/

Let me know what you think,
Maxime

Changes from v3:
  - Add documentation for drm_cmdline_mode and the new variables
  - Move the TV properties reset to a helper
  - Fix a missing X resolution or a missing Y resolution
  - Add more tests
  - Add the rotation to the orientation
  - Fix the reflection
  - Change the name of the drm_client_panel_rotation function
  - Rebased on top of current next

Changes from v2:
  - Fixed some sparse warnings
  - Rebased on top of next and Noralf series
  - Moved the property initialisation to vc4 reset hook
  - Added documentation for the new drm_cmdline_mode
  - Renamed overscan to tv_margins to be consistent with the APIs

Changes from v1:
  - Dropped the patches to deal with EDID
  - Added the unit test as selftest
  - Rebased on next

Maxime Ripard (12):
  drm/connector: Add documentation for drm_cmdline_mode
  drm/client: Restrict the plane_state scope
  drm/client: Restrict the rotation check to the rotation itself
  drm/client: Change drm_client_panel_rotation name
  drm/modes: Rewrite the command line parser
  drm/modes: Support modes names on the command line
  drm/modes: Allow to specify rotation and reflection on the commandline
  drm/connector: Introduce a TV margins structure
  drm/atomic: Add a function to reset connector TV properties
  drm/modes: Parse overscan properties
  drm/selftests: Add command line parser selftests
  drm/vc4: hdmi: Set default state margin at reset

 drivers/gpu/drm/drm_atomic_state_helper.c           |  18 +-
 drivers/gpu/drm/drm_client_modeset.c                |  44 +-
 drivers/gpu/drm/drm_connector.c                     |   3 +-
 drivers/gpu/drm/drm_fb_helper.c                     |   2 +-
 drivers/gpu/drm/drm_modes.c                         | 469 +++++--
 drivers/gpu/drm/selftests/Makefile                  |   2 +-
 drivers/gpu/drm/selftests/drm_cmdline_selftests.h   |  55 +-
 drivers/gpu/drm/selftests/test-drm_cmdline_parser.c | 918 +++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.c                      |   8 +-
 include/drm/drm_atomic_state_helper.h               |   1 +-
 include/drm/drm_client.h                            |   2 +-
 include/drm/drm_connector.h                         | 148 +-
 12 files changed, 1529 insertions(+), 141 deletions(-)
 create mode 100644 drivers/gpu/drm/selftests/drm_cmdline_selftests.h
 create mode 100644 drivers/gpu/drm/selftests/test-drm_cmdline_parser.c

base-commit: 1123a3310ed6ad290be0fa4f2e995a7d68e108e2
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v4 01/12] drm/connector: Add documentation for drm_cmdline_mode
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15  8:51   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 02/12] drm/client: Restrict the plane_state scope Maxime Ripard
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

The struct drm_cmdline_mode holds the result of the command line parsers.
However, it wasn't documented so far, so let's do that.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 include/drm/drm_connector.h | 86 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 84 insertions(+), 2 deletions(-)

diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 47e749b74e5f..f9cfa96f5d7e 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -904,18 +904,100 @@ struct drm_connector_funcs {
 				   const struct drm_connector_state *state);
 };
 
-/* mode specified on the command line */
+/**
+ * struct drm_cmdline_mode - DRM Mode passed through the kernel command-line
+ *
+ * Each connector can have an initial mode with additional options
+ * passed through the kernel command line. This structure allows to
+ * express those parameters and will be filled by the command-line
+ * parser.
+ */
 struct drm_cmdline_mode {
+	/**
+	 * @specified:
+	 *
+	 * Has a mode been read from the command-line?
+	 */
 	bool specified;
+
+	/**
+	 * @refresh_specified:
+	 *
+	 * Did the mode has a preferred refresh rate?
+	 */
 	bool refresh_specified;
+
+	/**
+	 * @bpp_specified:
+	 *
+	 * Did the mode has a preferred BPP?
+	 */
 	bool bpp_specified;
-	int xres, yres;
+
+	/**
+	 * @xres:
+	 *
+	 * Active resolution on the X axis, in pixels.
+	 */
+	int xres;
+
+	/**
+	 * @yres:
+	 *
+	 * Active resolution on the Y axis, in pixels.
+	 */
+	int yres;
+
+	/**
+	 * @bpp:
+	 *
+	 * Bits per pixels for the mode.
+	 */
 	int bpp;
+
+	/**
+	 * @refresh:
+	 *
+	 * Refresh rate, in Hertz.
+	 */
 	int refresh;
+
+	/**
+	 * @rb:
+	 *
+	 * Do we need to use reduced blanking?
+	 */
 	bool rb;
+
+	/**
+	 * @interlace:
+	 *
+	 * The mode is interlaced.
+	 */
 	bool interlace;
+
+	/**
+	 * @cvt:
+	 *
+	 * The timings will be calculated using the VESA Coordinated
+	 * Video Timings instead of looking up the mode from a table.
+	 */
 	bool cvt;
+
+	/**
+	 * @margins:
+	 *
+	 * Add margins to the mode calculation (1.8% of xres rounded
+	 * down to 8 pixels and 1.8% of yres).
+	 */
 	bool margins;
+
+	/**
+	 * @force:
+	 *
+	 * Ignore the hotplug state of the connector, and force its
+	 * state to one of the DRM_FORCE_* values.
+	 */
 	enum drm_connector_force force;
 };
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 02/12] drm/client: Restrict the plane_state scope
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
  2019-06-14 12:13 ` [PATCH v4 01/12] drm/connector: Add documentation for drm_cmdline_mode Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-14 12:28   ` Jani Nikula
  2019-06-15  8:52   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 03/12] drm/client: Restrict the rotation check to the rotation itself Maxime Ripard
                   ` (9 subsequent siblings)
  11 siblings, 2 replies; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

The drm_client_modeset_commit_atomic function uses two times the
plane_state variable in inner blocks of code, but the variable has a scope
global to this function.

This will lead to inadvertent devs to reuse the variable in the second
block with the value left by the first, without any warning from the
compiler since value would have been initialized.

Fix this by moving the variable declaration to the proper scope.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/gpu/drm/drm_client_modeset.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index 006bf7390e7d..8264c3a732b0 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -861,7 +861,6 @@ EXPORT_SYMBOL(drm_client_panel_rotation);
 static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active)
 {
 	struct drm_device *dev = client->dev;
-	struct drm_plane_state *plane_state;
 	struct drm_plane *plane;
 	struct drm_atomic_state *state;
 	struct drm_modeset_acquire_ctx ctx;
@@ -879,6 +878,8 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool 
 	state->acquire_ctx = &ctx;
 retry:
 	drm_for_each_plane(plane, dev) {
+		struct drm_plane_state *plane_state;
+
 		plane_state = drm_atomic_get_plane_state(state, plane);
 		if (IS_ERR(plane_state)) {
 			ret = PTR_ERR(plane_state);
@@ -901,6 +902,8 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool 
 		unsigned int rotation;
 
 		if (drm_client_panel_rotation(mode_set, &rotation)) {
+			struct drm_plane_state *plane_state;
+
 			/* Cannot fail as we've already gotten the plane state above */
 			plane_state = drm_atomic_get_new_plane_state(state, primary);
 			plane_state->rotation = rotation;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 03/12] drm/client: Restrict the rotation check to the rotation itself
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
  2019-06-14 12:13 ` [PATCH v4 01/12] drm/connector: Add documentation for drm_cmdline_mode Maxime Ripard
  2019-06-14 12:13 ` [PATCH v4 02/12] drm/client: Restrict the plane_state scope Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15  8:59   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 04/12] drm/client: Change drm_client_panel_rotation name Maxime Ripard
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

The drm_client_rotation has a check on the rotation value, but the
reflections are also stored in the same variable, and the check doesn't
take this into account.

Therefore, even though we might have a valid rotation, if we're also using
a reflection parameter, the test will fail for no particular reason.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/gpu/drm/drm_client_modeset.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index 8264c3a732b0..b4e5fb0a17cf 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -845,7 +845,8 @@ bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotat
 	 * depending on the hardware this may require the framebuffer
 	 * to be in a specific tiling format.
 	 */
-	if (*rotation != DRM_MODE_ROTATE_180 || !plane->rotation_property)
+	if ((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180 ||
+	    !plane->rotation_property)
 		return false;
 
 	for (i = 0; i < plane->rotation_property->num_values; i++)
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 04/12] drm/client: Change drm_client_panel_rotation name
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (2 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 03/12] drm/client: Restrict the rotation check to the rotation itself Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15  9:01   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 05/12] drm/modes: Rewrite the command line parser Maxime Ripard
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

The drm_client_panel_rotation function has been used so far to set the
default rotation based on the panel orientation.

However, we can have more sources of information to make that decision,
starting with the command line that we will introduce later in this series.

Change the name to remove the panel mention.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/gpu/drm/drm_client_modeset.c | 12 ++++++------
 drivers/gpu/drm/drm_fb_helper.c      |  2 +-
 include/drm/drm_client.h             |  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index b4e5fb0a17cf..4869a0170bec 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -804,19 +804,19 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, 
 EXPORT_SYMBOL(drm_client_modeset_probe);
 
 /**
- * drm_client_panel_rotation() - Check panel orientation
+ * drm_client_rotation() - Check the initial rotation value
  * @modeset: DRM modeset
  * @rotation: Returned rotation value
  *
- * This function checks if the primary plane in @modeset can hw rotate to match
- * the panel orientation on its connector.
+ * This function checks if the primary plane in @modeset can hw rotate
+ * to match the rotation needed on its connector.
  *
  * Note: Currently only 0 and 180 degrees are supported.
  *
  * Return:
  * True if the plane can do the rotation, false otherwise.
  */
-bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
+bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
 {
 	struct drm_connector *connector = modeset->connectors[0];
 	struct drm_plane *plane = modeset->crtc->primary;
@@ -857,7 +857,7 @@ bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotat
 
 	return true;
 }
-EXPORT_SYMBOL(drm_client_panel_rotation);
+EXPORT_SYMBOL(drm_client_rotation);
 
 static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active)
 {
@@ -902,7 +902,7 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool 
 		struct drm_plane *primary = mode_set->crtc->primary;
 		unsigned int rotation;
 
-		if (drm_client_panel_rotation(mode_set, &rotation)) {
+		if (drm_client_rotation(mode_set, &rotation)) {
 			struct drm_plane_state *plane_state;
 
 			/* Cannot fail as we've already gotten the plane state above */
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 946cae196475..c19b92d4c7e3 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1722,7 +1722,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
 
 		modeset->fb = fb_helper->fb;
 
-		if (drm_client_panel_rotation(modeset, &rotation))
+		if (drm_client_rotation(modeset, &rotation))
 			/* Rotating in hardware, fbcon should not rotate */
 			sw_rotations |= DRM_MODE_ROTATE_0;
 		else
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index f2d5ed745733..72d51d1e9dd9 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -153,7 +153,7 @@ void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
 int drm_client_modeset_create(struct drm_client_dev *client);
 void drm_client_modeset_free(struct drm_client_dev *client);
 int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int height);
-bool drm_client_panel_rotation(struct drm_mode_set *modeset, unsigned int *rotation);
+bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation);
 int drm_client_modeset_commit_force(struct drm_client_dev *client);
 int drm_client_modeset_commit(struct drm_client_dev *client);
 int drm_client_modeset_dpms(struct drm_client_dev *client, int mode);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 05/12] drm/modes: Rewrite the command line parser
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (3 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 04/12] drm/client: Change drm_client_panel_rotation name Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15  9:11   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 06/12] drm/modes: Support modes names on the command line Maxime Ripard
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, Maxime Ripard, linux-arm-kernel

From: Maxime Ripard <maxime.ripard@free-electrons.com>

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 <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/drm_modes.c | 325 +++++++++++++++++++++++--------------
 1 file changed, 210 insertions(+), 115 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 5a07a28fec6d..6debbd6c1763 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 <linux/ctype.h>
 #include <linux/list.h>
 #include <linux/list_sort.h>
 #include <linux/export.h>
@@ -1408,6 +1409,151 @@ 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)
+{
+	unsigned int bpp;
+
+	if (str[0] != '-')
+		return -EINVAL;
+
+	str++;
+	bpp = simple_strtol(str, end_ptr, 10);
+	if (*end_ptr == str)
+		return -EINVAL;
+
+	mode->bpp = bpp;
+	mode->bpp_specified = true;
+
+	return 0;
+}
+
+static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
+					  struct drm_cmdline_mode *mode)
+{
+	unsigned int refresh;
+
+	if (str[0] != '@')
+		return -EINVAL;
+
+	str++;
+	refresh = simple_strtol(str, end_ptr, 10);
+	if (*end_ptr == str)
+		return -EINVAL;
+
+	mode->refresh = refresh;
+	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)
+{
+	const char *str_start = str;
+	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 == str)
+		return -EINVAL;
+
+	if (end_ptr[0] != 'x')
+		return -EINVAL;
+	end_ptr++;
+
+	str = end_ptr;
+	yres = simple_strtol(str, &end_ptr, 10);
+	if (end_ptr == str)
+		return -EINVAL;
+
+	remaining = length - (end_ptr - str_start);
+	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
@@ -1434,13 +1580,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)
@@ -1453,127 +1598,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;
 }
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 06/12] drm/modes: Support modes names on the command line
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (4 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 05/12] drm/modes: Rewrite the command line parser Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-14 12:13 ` [PATCH v4 07/12] drm/modes: Allow to specify rotation and reflection on the commandline Maxime Ripard
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, Maxime Ripard, linux-arm-kernel

From: Maxime Ripard <maxime.ripard@free-electrons.com>

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@free-electrons.com>
---
 drivers/gpu/drm/drm_client_modeset.c |  4 ++-
 drivers/gpu/drm/drm_connector.c      |  3 +-
 drivers/gpu/drm/drm_modes.c          | 62 +++++++++++++++++++++--------
 include/drm/drm_connector.h          |  7 +++-
 4 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index 4869a0170bec..33d4988f22ae 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 e17586aaa80f..ff0f86a79799 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 6debbd6c1763..429d3be17800 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1580,7 +1580,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;
@@ -1599,8 +1599,22 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 
 	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, '-');
@@ -1611,6 +1625,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;
 	}
@@ -1627,12 +1644,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) {
@@ -1660,14 +1681,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 f9cfa96f5d7e..f46a53e86d75 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -914,6 +914,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?
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 07/12] drm/modes: Allow to specify rotation and reflection on the commandline
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (5 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 06/12] drm/modes: Support modes names on the command line Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15  9:21   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 08/12] drm/connector: Introduce a TV margins structure Maxime Ripard
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

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 <maxime.ripard@bootlin.com>
---
 drivers/gpu/drm/drm_client_modeset.c |  20 +++++-
 drivers/gpu/drm/drm_modes.c          | 110 ++++++++++++++++++++++------
 include/drm/drm_connector.h          |   9 ++-
 3 files changed, 119 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index 33d4988f22ae..57937e38492c 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -824,6 +824,7 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
 {
 	struct drm_connector *connector = modeset->connectors[0];
 	struct drm_plane *plane = modeset->crtc->primary;
+	struct drm_cmdline_mode *cmdline;
 	u64 valid_mask = 0;
 	unsigned int i;
 
@@ -844,6 +845,25 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
 		*rotation = DRM_MODE_ROTATE_0;
 	}
 
+	/**
+	 * The panel already defined the default rotation
+	 * through its orientation. Whatever has been provided
+	 * on the command line needs to be added to that.
+	 *
+	 * Unfortunately, the rotations are at different bit
+	 * indices, so the math to add them up are not as
+	 * trivial as they could.
+	 */
+	cmdline = &connector->cmdline_mode;
+	if (cmdline->specified) {
+		unsigned int panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
+		unsigned int cmdline_rot = ilog2(cmdline->rotation & DRM_MODE_ROTATE_MASK);
+		unsigned int sum_rot;
+
+		sum_rot = (panel_rot + cmdline_rot) % 4;
+		*rotation = 1 << sum_rot;
+	}
+
 	/*
 	 * 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 429d3be17800..b92b7df6784a 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1554,6 +1554,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
@@ -1581,9 +1646,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;
 
@@ -1632,13 +1698,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;
@@ -1680,24 +1751,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 f46a53e86d75..68a04169ea36 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1006,6 +1006,15 @@ struct drm_cmdline_mode {
 	 * state to one of the DRM_FORCE_* values.
 	 */
 	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;
 };
 
 /**
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 08/12] drm/connector: Introduce a TV margins structure
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (6 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 07/12] drm/modes: Allow to specify rotation and reflection on the commandline Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15 14:54   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 09/12] drm/atomic: Add a function to reset connector TV properties Maxime Ripard
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

The TV margins has been defined as a structure inside the
drm_connector_state structure so far. However, we will need it in other
structures as well, so let's move that structure definition so that it can
be reused.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 include/drm/drm_connector.h | 34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 68a04169ea36..c58a35b34c1a 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -464,13 +464,37 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
 				     unsigned int num_formats);
 
 /**
+ * struct drm_connector_tv_margins - TV connector related margins
+ *
+ * Describes the margins in pixels to put around the image on TV
+ * connectors to deal with overscan.
+ */
+struct drm_connector_tv_margins {
+	/**
+	 * @bottom: Bottom margin in pixels.
+	 */
+	unsigned int bottom;
+
+	/**
+	 * @left: Left margin in pixels.
+	 */
+	unsigned int left;
+
+	/**
+	 * @right: Right margin in pixels.
+	 */
+	unsigned int right;
+
+	/**
+	 * @top: Top margin in pixels.
+	 */
+	unsigned int top;
+};
+
+/**
  * struct drm_tv_connector_state - TV connector related states
  * @subconnector: selected subconnector
- * @margins: margins (all margins are expressed in pixels)
- * @margins.left: left margin
- * @margins.right: right margin
- * @margins.top: top margin
- * @margins.bottom: bottom margin
+ * @margins: TV margins
  * @mode: TV mode
  * @brightness: brightness in percent
  * @contrast: contrast in percent
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 09/12] drm/atomic: Add a function to reset connector TV properties
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (7 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 08/12] drm/connector: Introduce a TV margins structure Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15 15:30   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 10/12] drm/modes: Parse overscan properties Maxime Ripard
                   ` (2 subsequent siblings)
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

During the connector reset, if that connector has a TV property, it needs
to be reset to the value provided on the command line.

Provide a helper to do that.

Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/gpu/drm/drm_atomic_state_helper.c | 18 ++++++++++++++++++
 include/drm/drm_atomic_state_helper.h     |  1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 97ab26679b96..f4f0ada9c152 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -376,6 +376,24 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector)
 EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
 
 /**
+ * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
+ * @connector: DRM connector
+ *
+ * Resets the TV-related properties attached to a connector.
+ */
+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
+{
+	struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
+	struct drm_connector_state *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;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
+
+/**
  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
  * @connector: connector object
  * @state: atomic connector state
diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h
index 4e6d2e7a40b8..e4577cc11689 100644
--- a/include/drm/drm_atomic_state_helper.h
+++ b/include/drm/drm_atomic_state_helper.h
@@ -62,6 +62,7 @@ void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
 void __drm_atomic_helper_connector_reset(struct drm_connector *connector,
 					 struct drm_connector_state *conn_state);
 void drm_atomic_helper_connector_reset(struct drm_connector *connector);
+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector);
 void
 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
 					   struct drm_connector_state *state);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 10/12] drm/modes: Parse overscan properties
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (8 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 09/12] drm/atomic: Add a function to reset connector TV properties Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15 15:40   ` Noralf Trønnes
  2019-06-14 12:13 ` [PATCH v4 11/12] drm/selftests: Add command line parser selftests Maxime Ripard
  2019-06-14 12:13 ` [PATCH v4 12/12] drm/vc4: hdmi: Set default state margin at reset Maxime Ripard
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

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.

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/gpu/drm/drm_modes.c | 44 ++++++++++++++++++++++++++++++++++++++-
 include/drm/drm_connector.h | 12 +++++-----
 2 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index b92b7df6784a..25d2ba595750 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1609,6 +1609,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 c58a35b34c1a..6841c46e6781 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -505,12 +505,7 @@ struct drm_connector_tv_margins {
  */
 struct drm_tv_connector_state {
 	enum drm_mode_subconnector subconnector;
-	struct {
-		unsigned int left;
-		unsigned int right;
-		unsigned int top;
-		unsigned int bottom;
-	} margins;
+	struct drm_connector_tv_margins margins;
 	unsigned int mode;
 	unsigned int brightness;
 	unsigned int contrast;
@@ -1039,6 +1034,11 @@ struct drm_cmdline_mode {
 	 * DRM_MODE_ROTATE_180 are supported at the moment.
 	 */
 	unsigned int rotation;
+
+	/**
+	 * @tv_margins: TV margins to apply to the mode.
+	 */
+	struct drm_connector_tv_margins tv_margins;
 };
 
 /**
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 11/12] drm/selftests: Add command line parser selftests
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (9 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 10/12] drm/modes: Parse overscan properties Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-14 12:13 ` [PATCH v4 12/12] drm/vc4: hdmi: Set default state margin at reset Maxime Ripard
  11 siblings, 0 replies; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

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.

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/gpu/drm/selftests/Makefile                  |   2 +-
 drivers/gpu/drm/selftests/drm_cmdline_selftests.h   |  55 +-
 drivers/gpu/drm/selftests/test-drm_cmdline_parser.c | 918 +++++++++++++-
 3 files changed, 974 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 8ec64ecf0e36..aae88f8a016c 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -3,4 +3,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..b45824ec7c8f
--- /dev/null
+++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
@@ -0,0 +1,55 @@
+/* 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_missing_x)
+cmdline_test(drm_cmdline_test_res_missing_y)
+cmdline_test(drm_cmdline_test_res_bad_y)
+cmdline_test(drm_cmdline_test_res_missing_y_bpp)
+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_bad_bpp)
+cmdline_test(drm_cmdline_test_res_refresh)
+cmdline_test(drm_cmdline_test_res_bad_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..d7e54154e988
--- /dev/null
+++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
@@ -0,0 +1,918 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Bootlin
+ */
+
+#define pr_fmt(fmt) "drm_cmdline: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_modes.h>
+
+#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_missing_x(void *ignored)
+{
+	struct drm_connector connector = { };
+	struct drm_cmdline_mode mode = { };
+
+	FAIL_ON(drm_mode_parse_command_line_for_connector("x480",
+							  &connector,
+							  &mode));
+
+	return 0;
+}
+
+static int drm_cmdline_test_res_missing_y(void *ignored)
+{
+	struct drm_connector connector = { };
+	struct drm_cmdline_mode mode = { };
+
+	FAIL_ON(drm_mode_parse_command_line_for_connector("1024x",
+							  &connector,
+							  &mode));
+
+	return 0;
+}
+
+static int drm_cmdline_test_res_bad_y(void *ignored)
+{
+	struct drm_connector connector = { };
+	struct drm_cmdline_mode mode = { };
+
+	FAIL_ON(drm_mode_parse_command_line_for_connector("1024xtest",
+							  &connector,
+							  &mode));
+
+	return 0;
+}
+
+static int drm_cmdline_test_res_missing_y_bpp(void *ignored)
+{
+	struct drm_connector connector = { };
+	struct drm_cmdline_mode mode = { };
+
+	FAIL_ON(drm_mode_parse_command_line_for_connector("1024x-24",
+							  &connector,
+							  &mode));
+
+	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_bad_bpp(void *ignored)
+{
+	struct drm_connector connector = { };
+	struct drm_cmdline_mode mode = { };
+
+	FAIL_ON(drm_mode_parse_command_line_for_connector("720x480-test",
+							  &connector,
+							  &mode));
+
+	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_bad_refresh(void *ignored)
+{
+	struct drm_connector connector = { };
+	struct drm_cmdline_mode mode = { };
+
+	FAIL_ON(drm_mode_parse_command_line_for_connector("720x480@refresh",
+							  &connector,
+							  &mode));
+
+	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 <maxime.ripard@bootlin.com>");
+MODULE_LICENSE("GPL");
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 12/12] drm/vc4: hdmi: Set default state margin at reset
  2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
                   ` (10 preceding siblings ...)
  2019-06-14 12:13 ` [PATCH v4 11/12] drm/selftests: Add command line parser selftests Maxime Ripard
@ 2019-06-14 12:13 ` Maxime Ripard
  2019-06-15 15:43   ` Noralf Trønnes
  11 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 12:13 UTC (permalink / raw)
  To: Maarten Lankhorst, Sean Paul, Maxime Ripard, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt, noralf,
	Thomas Petazzoni, linux-arm-kernel

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 <maxime.ripard@bootlin.com>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 99fc8569e0f5..43442c5619a3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -255,11 +255,17 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 	return ret;
 }
 
+static void vc4_hdmi_connector_reset(struct drm_connector *connector)
+{
+	drm_atomic_helper_connector_reset(connector);
+	drm_atomic_helper_connector_tv_reset(connector);
+}
+
 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,
 };
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 02/12] drm/client: Restrict the plane_state scope
  2019-06-14 12:13 ` [PATCH v4 02/12] drm/client: Restrict the plane_state scope Maxime Ripard
@ 2019-06-14 12:28   ` Jani Nikula
  2019-06-14 14:12     ` Maxime Ripard
  2019-06-15  8:52   ` Noralf Trønnes
  1 sibling, 1 reply; 27+ messages in thread
From: Jani Nikula @ 2019-06-14 12:28 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Maxime Ripard,
	Daniel Vetter, David Airlie
  Cc: Paul Kocialkowski, linux-arm-kernel, Thomas Petazzoni, dri-devel, eben

On Fri, 14 Jun 2019, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> The drm_client_modeset_commit_atomic function uses two times the
> plane_state variable in inner blocks of code, but the variable has a scope
> global to this function.
>
> This will lead to inadvertent devs to reuse the variable in the second
> block with the value left by the first, without any warning from the
> compiler since value would have been initialized.
>
> Fix this by moving the variable declaration to the proper scope.

This is an improvement, but I'd consider renaming also to not shadow
variables.

BR,
Jani.

>
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
>  drivers/gpu/drm/drm_client_modeset.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
> index 006bf7390e7d..8264c3a732b0 100644
> --- a/drivers/gpu/drm/drm_client_modeset.c
> +++ b/drivers/gpu/drm/drm_client_modeset.c
> @@ -861,7 +861,6 @@ EXPORT_SYMBOL(drm_client_panel_rotation);
>  static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active)
>  {
>  	struct drm_device *dev = client->dev;
> -	struct drm_plane_state *plane_state;
>  	struct drm_plane *plane;
>  	struct drm_atomic_state *state;
>  	struct drm_modeset_acquire_ctx ctx;
> @@ -879,6 +878,8 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool 
>  	state->acquire_ctx = &ctx;
>  retry:
>  	drm_for_each_plane(plane, dev) {
> +		struct drm_plane_state *plane_state;
> +
>  		plane_state = drm_atomic_get_plane_state(state, plane);
>  		if (IS_ERR(plane_state)) {
>  			ret = PTR_ERR(plane_state);
> @@ -901,6 +902,8 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool 
>  		unsigned int rotation;
>  
>  		if (drm_client_panel_rotation(mode_set, &rotation)) {
> +			struct drm_plane_state *plane_state;
> +
>  			/* Cannot fail as we've already gotten the plane state above */
>  			plane_state = drm_atomic_get_new_plane_state(state, primary);
>  			plane_state->rotation = rotation;

-- 
Jani Nikula, Intel Open Source Graphics Center

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 02/12] drm/client: Restrict the plane_state scope
  2019-06-14 12:28   ` Jani Nikula
@ 2019-06-14 14:12     ` Maxime Ripard
  2019-06-17  9:27       ` Jani Nikula
  0 siblings, 1 reply; 27+ messages in thread
From: Maxime Ripard @ 2019-06-14 14:12 UTC (permalink / raw)
  To: Jani Nikula
  Cc: eben, David Airlie, Maarten Lankhorst, dri-devel,
	Paul Kocialkowski, Sean Paul, Thomas Petazzoni, Daniel Vetter,
	linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 2479 bytes --]

Hi Jani,

On Fri, Jun 14, 2019 at 03:28:59PM +0300, Jani Nikula wrote:
> On Fri, 14 Jun 2019, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > The drm_client_modeset_commit_atomic function uses two times the
> > plane_state variable in inner blocks of code, but the variable has a scope
> > global to this function.
> >
> > This will lead to inadvertent devs to reuse the variable in the second
> > block with the value left by the first, without any warning from the
> > compiler since value would have been initialized.
> >
> > Fix this by moving the variable declaration to the proper scope.
>
> This is an improvement, but I'd consider renaming also to not shadow
> variables.
>
> > Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> > ---
> >  drivers/gpu/drm/drm_client_modeset.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
> > index 006bf7390e7d..8264c3a732b0 100644
> > --- a/drivers/gpu/drm/drm_client_modeset.c
> > +++ b/drivers/gpu/drm/drm_client_modeset.c
> > @@ -861,7 +861,6 @@ EXPORT_SYMBOL(drm_client_panel_rotation);
> >  static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active)
> >  {
> >  	struct drm_device *dev = client->dev;
> > -	struct drm_plane_state *plane_state;
> >  	struct drm_plane *plane;
> >  	struct drm_atomic_state *state;
> >  	struct drm_modeset_acquire_ctx ctx;
> > @@ -879,6 +878,8 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool
> >  	state->acquire_ctx = &ctx;
> >  retry:
> >  	drm_for_each_plane(plane, dev) {
> > +		struct drm_plane_state *plane_state;
> > +
> >  		plane_state = drm_atomic_get_plane_state(state, plane);
> >  		if (IS_ERR(plane_state)) {
> >  			ret = PTR_ERR(plane_state);
> > @@ -901,6 +902,8 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool
> >  		unsigned int rotation;
> >
> >  		if (drm_client_panel_rotation(mode_set, &rotation)) {
> > +			struct drm_plane_state *plane_state;
> > +

That's not super clear from that patch, but this variable will not
shadow the first one.

The code layout is pretty much this one:

loop () {
  struct drm_plane_state *plane_state;

  [...]
}

loop () {
  loop () {
    struct drm_plane_state *plane_state;

    [...]
  }
}

so the shadowing doesn't exist

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 01/12] drm/connector: Add documentation for drm_cmdline_mode
  2019-06-14 12:13 ` [PATCH v4 01/12] drm/connector: Add documentation for drm_cmdline_mode Maxime Ripard
@ 2019-06-15  8:51   ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15  8:51 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> The struct drm_cmdline_mode holds the result of the command line parsers.
> However, it wasn't documented so far, so let's do that.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
>  include/drm/drm_connector.h | 86 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 84 insertions(+), 2 deletions(-)
> 
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 47e749b74e5f..f9cfa96f5d7e 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -904,18 +904,100 @@ struct drm_connector_funcs {
>  				   const struct drm_connector_state *state);
>  };
>  
> -/* mode specified on the command line */
> +/**
> + * struct drm_cmdline_mode - DRM Mode passed through the kernel command-line
> + *
> + * Each connector can have an initial mode with additional options
> + * passed through the kernel command line. This structure allows to
> + * express those parameters and will be filled by the command-line
> + * parser.
> + */
>  struct drm_cmdline_mode {
> +	/**
> +	 * @specified:
> +	 *
> +	 * Has a mode been read from the command-line?
> +	 */
>  	bool specified;
> +
> +	/**
> +	 * @refresh_specified:
> +	 *
> +	 * Did the mode has a preferred refresh rate?

s/has/have/ or Does the mode have

> +	 */
>  	bool refresh_specified;
> +
> +	/**
> +	 * @bpp_specified:
> +	 *
> +	 * Did the mode has a preferred BPP?

s/has/have/

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

> +	 */
>  	bool bpp_specified;
> -	int xres, yres;
> +
> +	/**
> +	 * @xres:
> +	 *
> +	 * Active resolution on the X axis, in pixels.
> +	 */
> +	int xres;
> +
> +	/**
> +	 * @yres:
> +	 *
> +	 * Active resolution on the Y axis, in pixels.
> +	 */
> +	int yres;
> +
> +	/**
> +	 * @bpp:
> +	 *
> +	 * Bits per pixels for the mode.
> +	 */
>  	int bpp;
> +
> +	/**
> +	 * @refresh:
> +	 *
> +	 * Refresh rate, in Hertz.
> +	 */
>  	int refresh;
> +
> +	/**
> +	 * @rb:
> +	 *
> +	 * Do we need to use reduced blanking?
> +	 */
>  	bool rb;
> +
> +	/**
> +	 * @interlace:
> +	 *
> +	 * The mode is interlaced.
> +	 */
>  	bool interlace;
> +
> +	/**
> +	 * @cvt:
> +	 *
> +	 * The timings will be calculated using the VESA Coordinated
> +	 * Video Timings instead of looking up the mode from a table.
> +	 */
>  	bool cvt;
> +
> +	/**
> +	 * @margins:
> +	 *
> +	 * Add margins to the mode calculation (1.8% of xres rounded
> +	 * down to 8 pixels and 1.8% of yres).
> +	 */
>  	bool margins;
> +
> +	/**
> +	 * @force:
> +	 *
> +	 * Ignore the hotplug state of the connector, and force its
> +	 * state to one of the DRM_FORCE_* values.
> +	 */
>  	enum drm_connector_force force;
>  };
>  
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 02/12] drm/client: Restrict the plane_state scope
  2019-06-14 12:13 ` [PATCH v4 02/12] drm/client: Restrict the plane_state scope Maxime Ripard
  2019-06-14 12:28   ` Jani Nikula
@ 2019-06-15  8:52   ` Noralf Trønnes
  1 sibling, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15  8:52 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> The drm_client_modeset_commit_atomic function uses two times the
> plane_state variable in inner blocks of code, but the variable has a scope
> global to this function.
> 
> This will lead to inadvertent devs to reuse the variable in the second
> block with the value left by the first, without any warning from the
> compiler since value would have been initialized.
> 
> Fix this by moving the variable declaration to the proper scope.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 03/12] drm/client: Restrict the rotation check to the rotation itself
  2019-06-14 12:13 ` [PATCH v4 03/12] drm/client: Restrict the rotation check to the rotation itself Maxime Ripard
@ 2019-06-15  8:59   ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15  8:59 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> The drm_client_rotation has a check on the rotation value, but the
> reflections are also stored in the same variable, and the check doesn't
> take this into account.
> 
> Therefore, even though we might have a valid rotation, if we're also using
> a reflection parameter, the test will fail for no particular reason.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 04/12] drm/client: Change drm_client_panel_rotation name
  2019-06-14 12:13 ` [PATCH v4 04/12] drm/client: Change drm_client_panel_rotation name Maxime Ripard
@ 2019-06-15  9:01   ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15  9:01 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> The drm_client_panel_rotation function has been used so far to set the
> default rotation based on the panel orientation.
> 
> However, we can have more sources of information to make that decision,
> starting with the command line that we will introduce later in this series.
> 
> Change the name to remove the panel mention.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 05/12] drm/modes: Rewrite the command line parser
  2019-06-14 12:13 ` [PATCH v4 05/12] drm/modes: Rewrite the command line parser Maxime Ripard
@ 2019-06-15  9:11   ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15  9:11 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, Maxime Ripard, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> From: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> 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 <maxime.ripard@free-electrons.com>
> ---

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 07/12] drm/modes: Allow to specify rotation and reflection on the commandline
  2019-06-14 12:13 ` [PATCH v4 07/12] drm/modes: Allow to specify rotation and reflection on the commandline Maxime Ripard
@ 2019-06-15  9:21   ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15  9:21 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> 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.
> 

This needs to be documented in Documentation/fb/modedb.txt

> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
>  drivers/gpu/drm/drm_client_modeset.c |  20 +++++-
>  drivers/gpu/drm/drm_modes.c          | 110 ++++++++++++++++++++++------
>  include/drm/drm_connector.h          |   9 ++-
>  3 files changed, 119 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
> index 33d4988f22ae..57937e38492c 100644
> --- a/drivers/gpu/drm/drm_client_modeset.c
> +++ b/drivers/gpu/drm/drm_client_modeset.c
> @@ -824,6 +824,7 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
>  {
>  	struct drm_connector *connector = modeset->connectors[0];
>  	struct drm_plane *plane = modeset->crtc->primary;
> +	struct drm_cmdline_mode *cmdline;
>  	u64 valid_mask = 0;
>  	unsigned int i;
>  
> @@ -844,6 +845,25 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
>  		*rotation = DRM_MODE_ROTATE_0;
>  	}
>  
> +	/**
> +	 * The panel already defined the default rotation
> +	 * through its orientation. Whatever has been provided
> +	 * on the command line needs to be added to that.
> +	 *
> +	 * Unfortunately, the rotations are at different bit
> +	 * indices, so the math to add them up are not as
> +	 * trivial as they could.
> +	 */
> +	cmdline = &connector->cmdline_mode;
> +	if (cmdline->specified) {
> +		unsigned int panel_rot = ilog2(*rotation & DRM_MODE_ROTATE_MASK);
> +		unsigned int cmdline_rot = ilog2(cmdline->rotation & DRM_MODE_ROTATE_MASK);
> +		unsigned int sum_rot;
> +
> +		sum_rot = (panel_rot + cmdline_rot) % 4;
> +		*rotation = 1 << sum_rot;
> +	}

Looks like reflect_* will be thrown away here?

> +
>  	/*
>  	 * 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 429d3be17800..b92b7df6784a 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1554,6 +1554,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
> @@ -1581,9 +1646,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;
>  
> @@ -1632,13 +1698,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;
> @@ -1680,24 +1751,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 f46a53e86d75..68a04169ea36 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -1006,6 +1006,15 @@ struct drm_cmdline_mode {
>  	 * state to one of the DRM_FORCE_* values.
>  	 */
>  	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.
> +	 */

Reflect is also supported?

Noralf.

> +	unsigned int rotation;
>  };
>  
>  /**
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 08/12] drm/connector: Introduce a TV margins structure
  2019-06-14 12:13 ` [PATCH v4 08/12] drm/connector: Introduce a TV margins structure Maxime Ripard
@ 2019-06-15 14:54   ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15 14:54 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> The TV margins has been defined as a structure inside the
> drm_connector_state structure so far. However, we will need it in other
> structures as well, so let's move that structure definition so that it can
> be reused.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
>  include/drm/drm_connector.h | 34 +++++++++++++++++++++++++++++-----
>  1 file changed, 29 insertions(+), 5 deletions(-)
> 
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 68a04169ea36..c58a35b34c1a 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -464,13 +464,37 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
>  				     unsigned int num_formats);
>  
>  /**
> + * struct drm_connector_tv_margins - TV connector related margins
> + *
> + * Describes the margins in pixels to put around the image on TV
> + * connectors to deal with overscan.
> + */
> +struct drm_connector_tv_margins {
> +	/**
> +	 * @bottom: Bottom margin in pixels.
> +	 */
> +	unsigned int bottom;
> +
> +	/**
> +	 * @left: Left margin in pixels.
> +	 */
> +	unsigned int left;
> +
> +	/**
> +	 * @right: Right margin in pixels.
> +	 */
> +	unsigned int right;
> +
> +	/**
> +	 * @top: Top margin in pixels.
> +	 */
> +	unsigned int top;
> +};
> +
> +/**
>   * struct drm_tv_connector_state - TV connector related states
>   * @subconnector: selected subconnector
> - * @margins: margins (all margins are expressed in pixels)
> - * @margins.left: left margin
> - * @margins.right: right margin
> - * @margins.top: top margin
> - * @margins.bottom: bottom margin
> + * @margins: TV margins
>   * @mode: TV mode
>   * @brightness: brightness in percent
>   * @contrast: contrast in percent
> 

The actual struct conversion is missing here, it has ended up in:

[PATCH v4 10/12] drm/modes: Parse overscan properties

With that moved in here:

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 09/12] drm/atomic: Add a function to reset connector TV properties
  2019-06-14 12:13 ` [PATCH v4 09/12] drm/atomic: Add a function to reset connector TV properties Maxime Ripard
@ 2019-06-15 15:30   ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15 15:30 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> During the connector reset, if that connector has a TV property, it needs
> to be reset to the value provided on the command line.
> 
> Provide a helper to do that.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---

This patch uses drm_cmdline_mode->tv_margins before it is added, so it
needs to be moved after the patch that adds it.

With that fixed:

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 10/12] drm/modes: Parse overscan properties
  2019-06-14 12:13 ` [PATCH v4 10/12] drm/modes: Parse overscan properties Maxime Ripard
@ 2019-06-15 15:40   ` Noralf Trønnes
  2019-06-16  9:54     ` Noralf Trønnes
  0 siblings, 1 reply; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15 15:40 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> 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.

This also needs to be documented in Documentation/fb/modedb.txt

> 
> Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
>  drivers/gpu/drm/drm_modes.c | 44 ++++++++++++++++++++++++++++++++++++++-
>  include/drm/drm_connector.h | 12 +++++-----
>  2 files changed, 50 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index b92b7df6784a..25d2ba595750 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1609,6 +1609,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)) {

I wonder if this should be called tv_margin_right to distinguish it from
'm' (the mode specifier) which also is a margin? Or can these margins be
reused on other display types later on? A little stupid to have both
'tv_margin_right' and 'margin_right'.

> +			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 c58a35b34c1a..6841c46e6781 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -505,12 +505,7 @@ struct drm_connector_tv_margins {
>   */
>  struct drm_tv_connector_state {
>  	enum drm_mode_subconnector subconnector;
> -	struct {
> -		unsigned int left;
> -		unsigned int right;
> -		unsigned int top;
> -		unsigned int bottom;
> -	} margins;
> +	struct drm_connector_tv_margins margins;
>  	unsigned int mode;
>  	unsigned int brightness;
>  	unsigned int contrast;

As mentioned this needs moving to patch 8.

Noralf.

> @@ -1039,6 +1034,11 @@ struct drm_cmdline_mode {
>  	 * DRM_MODE_ROTATE_180 are supported at the moment.
>  	 */
>  	unsigned int rotation;
> +
> +	/**
> +	 * @tv_margins: TV margins to apply to the mode.
> +	 */
> +	struct drm_connector_tv_margins tv_margins;
>  };
>  
>  /**
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 12/12] drm/vc4: hdmi: Set default state margin at reset
  2019-06-14 12:13 ` [PATCH v4 12/12] drm/vc4: hdmi: Set default state margin at reset Maxime Ripard
@ 2019-06-15 15:43   ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-15 15:43 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: eben, dri-devel, Paul Kocialkowski, Eric Anholt,
	Thomas Petazzoni, linux-arm-kernel



Den 14.06.2019 14.13, skrev Maxime Ripard:
> 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 <maxime.ripard@bootlin.com>
> ---

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 10/12] drm/modes: Parse overscan properties
  2019-06-15 15:40   ` Noralf Trønnes
@ 2019-06-16  9:54     ` Noralf Trønnes
  0 siblings, 0 replies; 27+ messages in thread
From: Noralf Trønnes @ 2019-06-16  9:54 UTC (permalink / raw)
  To: Maxime Ripard, Maarten Lankhorst, Sean Paul, Daniel Vetter, David Airlie
  Cc: Paul Kocialkowski, linux-arm-kernel, Thomas Petazzoni, dri-devel, eben



Den 15.06.2019 17.40, skrev Noralf Trønnes:
> 
> 
> Den 14.06.2019 14.13, skrev Maxime Ripard:
>> 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.
> 
> This also needs to be documented in Documentation/fb/modedb.txt
> 
>>
>> Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
>> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
>> ---
>>  drivers/gpu/drm/drm_modes.c | 44 ++++++++++++++++++++++++++++++++++++++-
>>  include/drm/drm_connector.h | 12 +++++-----
>>  2 files changed, 50 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
>> index b92b7df6784a..25d2ba595750 100644
>> --- a/drivers/gpu/drm/drm_modes.c
>> +++ b/drivers/gpu/drm/drm_modes.c
>> @@ -1609,6 +1609,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)) {
> 
> I wonder if this should be called tv_margin_right to distinguish it from
> 'm' (the mode specifier) which also is a margin? Or can these margins be
> reused on other display types later on? A little stupid to have both
> 'tv_margin_right' and 'margin_right'.

And after a nights sleep I think 'margin_right' is just fine as long as
it's documented in modedb.txt as TV margins.

So with an modedb.txt entry and the struct change moved to patch 8:

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>

> 
>> +			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 c58a35b34c1a..6841c46e6781 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -505,12 +505,7 @@ struct drm_connector_tv_margins {
>>   */
>>  struct drm_tv_connector_state {
>>  	enum drm_mode_subconnector subconnector;
>> -	struct {
>> -		unsigned int left;
>> -		unsigned int right;
>> -		unsigned int top;
>> -		unsigned int bottom;
>> -	} margins;
>> +	struct drm_connector_tv_margins margins;
>>  	unsigned int mode;
>>  	unsigned int brightness;
>>  	unsigned int contrast;
> 
> As mentioned this needs moving to patch 8.
> 
> Noralf.
> 
>> @@ -1039,6 +1034,11 @@ struct drm_cmdline_mode {
>>  	 * DRM_MODE_ROTATE_180 are supported at the moment.
>>  	 */
>>  	unsigned int rotation;
>> +
>> +	/**
>> +	 * @tv_margins: TV margins to apply to the mode.
>> +	 */
>> +	struct drm_connector_tv_margins tv_margins;
>>  };
>>  
>>  /**
>>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 02/12] drm/client: Restrict the plane_state scope
  2019-06-14 14:12     ` Maxime Ripard
@ 2019-06-17  9:27       ` Jani Nikula
  0 siblings, 0 replies; 27+ messages in thread
From: Jani Nikula @ 2019-06-17  9:27 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: eben, David Airlie, Maarten Lankhorst, dri-devel,
	Paul Kocialkowski, Sean Paul, Thomas Petazzoni, Daniel Vetter,
	linux-arm-kernel

On Fri, 14 Jun 2019, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> Hi Jani,
>
> On Fri, Jun 14, 2019 at 03:28:59PM +0300, Jani Nikula wrote:
>> On Fri, 14 Jun 2019, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>> > The drm_client_modeset_commit_atomic function uses two times the
>> > plane_state variable in inner blocks of code, but the variable has a scope
>> > global to this function.
>> >
>> > This will lead to inadvertent devs to reuse the variable in the second
>> > block with the value left by the first, without any warning from the
>> > compiler since value would have been initialized.
>> >
>> > Fix this by moving the variable declaration to the proper scope.
>>
>> This is an improvement, but I'd consider renaming also to not shadow
>> variables.
>>
>> > Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
>> > ---
>> >  drivers/gpu/drm/drm_client_modeset.c | 5 ++++-
>> >  1 file changed, 4 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
>> > index 006bf7390e7d..8264c3a732b0 100644
>> > --- a/drivers/gpu/drm/drm_client_modeset.c
>> > +++ b/drivers/gpu/drm/drm_client_modeset.c
>> > @@ -861,7 +861,6 @@ EXPORT_SYMBOL(drm_client_panel_rotation);
>> >  static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active)
>> >  {
>> >  	struct drm_device *dev = client->dev;
>> > -	struct drm_plane_state *plane_state;
>> >  	struct drm_plane *plane;
>> >  	struct drm_atomic_state *state;
>> >  	struct drm_modeset_acquire_ctx ctx;
>> > @@ -879,6 +878,8 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool
>> >  	state->acquire_ctx = &ctx;
>> >  retry:
>> >  	drm_for_each_plane(plane, dev) {
>> > +		struct drm_plane_state *plane_state;
>> > +
>> >  		plane_state = drm_atomic_get_plane_state(state, plane);
>> >  		if (IS_ERR(plane_state)) {
>> >  			ret = PTR_ERR(plane_state);
>> > @@ -901,6 +902,8 @@ static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool
>> >  		unsigned int rotation;
>> >
>> >  		if (drm_client_panel_rotation(mode_set, &rotation)) {
>> > +			struct drm_plane_state *plane_state;
>> > +
>
> That's not super clear from that patch, but this variable will not
> shadow the first one.
>
> The code layout is pretty much this one:
>
> loop () {
>   struct drm_plane_state *plane_state;
>
>   [...]
> }
>
> loop () {
>   loop () {
>     struct drm_plane_state *plane_state;
>
>     [...]
>   }
> }
>
> so the shadowing doesn't exist

Indeed, sorry for the noise.

BR,
Jani.



-- 
Jani Nikula, Intel Open Source Graphics Center

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2019-06-17  9:24 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-14 12:13 [PATCH v4 00/12] drm/vc4: Allow for more boot-time configuration Maxime Ripard
2019-06-14 12:13 ` [PATCH v4 01/12] drm/connector: Add documentation for drm_cmdline_mode Maxime Ripard
2019-06-15  8:51   ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 02/12] drm/client: Restrict the plane_state scope Maxime Ripard
2019-06-14 12:28   ` Jani Nikula
2019-06-14 14:12     ` Maxime Ripard
2019-06-17  9:27       ` Jani Nikula
2019-06-15  8:52   ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 03/12] drm/client: Restrict the rotation check to the rotation itself Maxime Ripard
2019-06-15  8:59   ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 04/12] drm/client: Change drm_client_panel_rotation name Maxime Ripard
2019-06-15  9:01   ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 05/12] drm/modes: Rewrite the command line parser Maxime Ripard
2019-06-15  9:11   ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 06/12] drm/modes: Support modes names on the command line Maxime Ripard
2019-06-14 12:13 ` [PATCH v4 07/12] drm/modes: Allow to specify rotation and reflection on the commandline Maxime Ripard
2019-06-15  9:21   ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 08/12] drm/connector: Introduce a TV margins structure Maxime Ripard
2019-06-15 14:54   ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 09/12] drm/atomic: Add a function to reset connector TV properties Maxime Ripard
2019-06-15 15:30   ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 10/12] drm/modes: Parse overscan properties Maxime Ripard
2019-06-15 15:40   ` Noralf Trønnes
2019-06-16  9:54     ` Noralf Trønnes
2019-06-14 12:13 ` [PATCH v4 11/12] drm/selftests: Add command line parser selftests Maxime Ripard
2019-06-14 12:13 ` [PATCH v4 12/12] drm/vc4: hdmi: Set default state margin at reset Maxime Ripard
2019-06-15 15:43   ` Noralf Trønnes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).