nouveau.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements
@ 2022-09-22 14:25 Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile Maxime Ripard
                   ` (34 more replies)
  0 siblings, 35 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

Hi,

Here's a series aiming at improving the command line named modes support,
and more importantly how we deal with all the analog TV variants.

The named modes support were initially introduced to allow to specify the
analog TV mode to be used.

However, this was causing multiple issues:

  * The mode name parsed on the command line was passed directly to the
    driver, which had to figure out which mode it was suppose to match;

  * Figuring that out wasn't really easy, since the video= argument or what
    the userspace might not even have a name in the first place, but
    instead could have passed a mode with the same timings;

  * The fallback to matching on the timings was mostly working as long as
    we were supporting one 525 lines (most likely NSTC) and one 625 lines
    (PAL), but couldn't differentiate between two modes with the same
    timings (NTSC vs PAL-M vs NSTC-J for example);

  * There was also some overlap with the tv mode property registered by
    drm_mode_create_tv_properties(), but named modes weren't interacting
    with that property at all.

  * Even though that property was generic, its possible values were
    specific to each drivers, which made some generic support difficult.

Thus, I chose to tackle in multiple steps:

  * A new TV mode property was introduced, with generic values, each driver
    reporting through a bitmask what standard it supports to the userspace;

  * This option was added to the command line parsing code to be able to
    specify it on the kernel command line, and new atomic_check and reset
    helpers were created to integrate properly into atomic KMS;

  * The named mode parsing code is now creating a proper display mode for
    the given named mode, and the TV standard will thus be part of the
    connector state;

  * Two drivers were converted and tested for now (vc4 and sun4i), with
    some backward compatibility code to translate the old TV mode to the
    new TV mode;

Unit tests were created along the way.

One can switch from NTSC to PAL now using (on vc4)

modetest -M vc4  -s 53:720x480i -w 53:'TV mode':1 # NTSC
modetest -M vc4  -s 53:720x576i -w 53:'TV mode':4 # PAL

Let me know what you think,
Maxime

To: David Airlie <airlied@linux.ie>
To: Daniel Vetter <daniel@ffwll.ch>
To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
To: Maxime Ripard <mripard@kernel.org>
To: Thomas Zimmermann <tzimmermann@suse.de>
To: Emma Anholt <emma@anholt.net>
To: Jani Nikula <jani.nikula@linux.intel.com>
To: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
To: Rodrigo Vivi <rodrigo.vivi@intel.com>
To: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Ben Skeggs <bskeggs@redhat.com>
To: Karol Herbst <kherbst@redhat.com>
To: Lyude Paul <lyude@redhat.com>
To: Chen-Yu Tsai <wens@csie.org>
To: Jernej Skrabec <jernej.skrabec@gmail.com>
To: Samuel Holland <samuel@sholland.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Cc: "Noralf Trønnes" <noralf@tronnes.org>
Cc: Dave Stevenson <dave.stevenson@raspberrypi.com>
Cc: Dom Cobley <dom@raspberrypi.com>
Cc: Phil Elwell <phil@raspberrypi.com>
Cc: <dri-devel@lists.freedesktop.org>
Cc: linux-kernel@vger.kernel.org
Cc: intel-gfx@lists.freedesktop.org
Cc: nouveau@lists.freedesktop.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-sunxi@lists.linux.dev
Cc: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

---
Changes in v3:
- Applied some of the fixes to vc4 and sun4i
- Renamed the old TV mode property to legacy_mode
- Fixed a bunch of bisection errors
- Removed most of the redundant TV modes
- Added a new None TV mode to not fall back on NTSC by mistake
- Fixed the mode generation function to match better what is expected
- Added some logging to the mode generation function
- Split the improvements to the named mode parsing logic into separate patches
- Added more checks to the TV atomic_check helper
- Link to v2: https://lore.kernel.org/dri-devel/20220728-rpi-analog-tv-properties-v2-0-459522d653a7@cerno.tech/

Changes in v2:
- Kept the older TV mode property as legacy so we can keep the old drivers functional
- Renamed the tv_norm property to tv_mode
- Added a function to create PAL and NTSC compatible display modes
- Added some helpers to instantiate a mock DRM device in Kunit
- More Kunit tests
- Removed the HD analog TV modes
- Renamed some of the tests
- Renamed some of the named modes
- Fixed typos in commit logs
- Added the various tags
- Link to v1: https://lore.kernel.org/dri-devel/20220728-rpi-analog-tv-properties-v1-0-3d53ae722097@cerno.tech/

---
Geert Uytterhoeven (1):
      drm/modes: parse_cmdline: Add support for named modes containing dashes

Mateusz Kwiatkowski (3):
      drm/vc4: vec: Fix definition of PAL-M mode
      drm/vc4: vec: Check for VEC output constraints
      drm/vc4: vec: Add support for more analog TV standards

Maxime Ripard (29):
      drm/tests: Order Kunit tests in Makefile
      drm/tests: Add Kunit Helpers
      drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid ambiguity
      drm/connector: Rename subconnector state variable
      drm/atomic: Add TV subconnector property to get/set_property
      drm/connector: Rename legacy TV property
      drm/connector: Only register TV mode property if present
      drm/connector: Rename drm_mode_create_tv_properties
      drm/connector: Add TV standard property
      drm/modes: Add a function to generate analog display modes
      drm/modes: Only consider bpp and refresh before options
      drm/client: Add some tests for drm_connector_pick_cmdline_mode()
      drm/modes: Move named modes parsing to a separate function
      drm/modes: Bail out of named mode parsing if empty
      drm/modes: Bail out of named mode parsing early if it's a number
      drm/modes: Bail out of named mode parsing early if it's an option
      drm/modes: Bail out of named mode parsing early if it's a status
      drm/modes: Switch to named mode descriptors
      drm/modes: Fill drm_cmdline mode from named modes
      drm/connector: Add pixel clock to cmdline mode
      drm/connector: Add a function to lookup a TV mode by its name
      drm/modes: Introduce the tv_mode property as a command-line option
      drm/modes: Properly generate a drm_display_mode from a named mode
      drm/modes: Introduce more named modes
      drm/atomic-helper: Add a TV properties reset helper
      drm/atomic-helper: Add an analog TV atomic_check implementation
      drm/vc4: vec: Use TV Reset implementation
      drm/vc4: vec: Convert to the new TV mode property
      drm/sun4i: tv: Convert to the new TV mode property

 drivers/gpu/drm/drm_atomic_state_helper.c       | 128 ++++-
 drivers/gpu/drm/drm_atomic_uapi.c               |   8 +
 drivers/gpu/drm/drm_client_modeset.c            |   4 +
 drivers/gpu/drm/drm_connector.c                 | 111 +++-
 drivers/gpu/drm/drm_modes.c                     | 658 +++++++++++++++++++++++-
 drivers/gpu/drm/gud/gud_connector.c             |  12 +-
 drivers/gpu/drm/i2c/ch7006_drv.c                |   6 +-
 drivers/gpu/drm/i915/display/intel_tv.c         |   5 +-
 drivers/gpu/drm/nouveau/dispnv04/tvnv17.c       |   6 +-
 drivers/gpu/drm/sun4i/sun4i_tv.c                | 148 ++----
 drivers/gpu/drm/tests/Makefile                  |  16 +-
 drivers/gpu/drm/tests/drm_client_modeset_test.c | 239 +++++++++
 drivers/gpu/drm/tests/drm_cmdline_parser_test.c |  67 +++
 drivers/gpu/drm/tests/drm_kunit_helpers.c       |  54 ++
 drivers/gpu/drm/tests/drm_kunit_helpers.h       |   9 +
 drivers/gpu/drm/tests/drm_modes_test.c          | 136 +++++
 drivers/gpu/drm/vc4/vc4_hdmi.c                  |   2 +-
 drivers/gpu/drm/vc4/vc4_vec.c                   | 339 ++++++++++--
 include/drm/drm_atomic_state_helper.h           |   4 +
 include/drm/drm_connector.h                     |  92 +++-
 include/drm/drm_mode_config.h                   |  12 +-
 include/drm/drm_modes.h                         |  17 +
 22 files changed, 1866 insertions(+), 207 deletions(-)
---
base-commit: 9f5ef9111a4c973a69f9ba22ac73f1f9c634baf6
change-id: 20220728-rpi-analog-tv-properties-0914dfcee460

Best regards,
-- 
Maxime Ripard <maxime@cerno.tech>

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

* [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-23  8:06   ` Thomas Zimmermann
  2022-09-24 17:33   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers Maxime Ripard
                   ` (33 subsequent siblings)
  34 siblings, 2 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

Since we've recently added a ton of tests, the list starts to be a bit
of a mess and creates unneeded conflicts.

Let's order it alphabetically.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index 91b70f7d2769..2d9f49b62ecb 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -1,5 +1,13 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \
-	drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \
-	drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o drm_mm_test.o
+obj-$(CONFIG_DRM_KUNIT_TEST) += \
+	drm_buddy_test.o \
+	drm_cmdline_parser_test.o \
+	drm_damage_helper_test.o \
+	drm_dp_mst_helper_test.o \
+	drm_format_helper_test.o \
+	drm_format_test.o \
+	drm_framebuffer_test.o \
+	drm_mm_test.o \
+	drm_plane_helper_test.o \
+	drm_rect_test.o

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-24 17:56   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 03/33] drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid ambiguity Maxime Ripard
                   ` (32 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

As the number of kunit tests in KMS grows further, we start to have
multiple test suites that, for example, need to register a mock DRM
driver to interact with the KMS function they are supposed to test.

Let's add a file meant to provide those kind of helpers to avoid
duplication.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index 2d9f49b62ecb..b29ef1085cad 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
 	drm_format_helper_test.o \
 	drm_format_test.o \
 	drm_framebuffer_test.o \
+	drm_kunit_helpers.o \
 	drm_mm_test.o \
 	drm_plane_helper_test.o \
 	drm_rect_test.o
diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
new file mode 100644
index 000000000000..7ebd620481c1
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
@@ -0,0 +1,54 @@
+#include <drm/drm_drv.h>
+#include <drm/drm_managed.h>
+
+#include <linux/device.h>
+
+static const struct drm_mode_config_funcs drm_mode_config_funcs = {
+};
+
+static const struct drm_driver drm_mode_driver = {
+};
+
+static void drm_kunit_free_device(struct drm_device *drm, void *ptr)
+{
+	struct device *dev = ptr;
+
+	root_device_unregister(dev);
+}
+
+struct drm_device *drm_kunit_device_init(const char *name)
+{
+	struct drm_device *drm;
+	struct device *dev;
+	int ret;
+
+	dev = root_device_register(name);
+	if (IS_ERR(dev))
+		return ERR_CAST(dev);
+
+	drm = drm_dev_alloc(&drm_mode_driver, dev);
+	if (IS_ERR(drm)) {
+		root_device_unregister(dev);
+		return ERR_CAST(drm);
+	}
+	drm->mode_config.funcs = &drm_mode_config_funcs;
+
+	ret = drmm_add_action_or_reset(drm, drm_kunit_free_device, dev);
+	if (ret)
+		goto err_put_device;
+
+	ret = drmm_mode_config_init(drm);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return drm;
+
+err_put_device:
+	drm_dev_put(drm);
+	return ERR_PTR(ret);
+}
+
+void drm_kunit_device_exit(struct drm_device *drm)
+{
+	drm_dev_put(drm);
+}
diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.h b/drivers/gpu/drm/tests/drm_kunit_helpers.h
new file mode 100644
index 000000000000..5015a327a8c1
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_kunit_helpers.h
@@ -0,0 +1,9 @@
+#ifndef DRM_KUNIT_HELPERS_H_
+#define DRM_KUNIT_HELPERS_H_
+
+struct drm_device;
+
+struct drm_device *drm_kunit_device_init(const char *name);
+void drm_kunit_device_exit(struct drm_device *drm);
+
+#endif // DRM_KUNIT_HELPERS_H_

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 03/33] drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid ambiguity
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-23  8:09   ` Thomas Zimmermann
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 04/33] drm/connector: Rename subconnector state variable Maxime Ripard
                   ` (31 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

We currently have two sets of TV properties.

The first one is there to deal with analog TV properties, creating
properties such as the TV mode, subconnectors, saturation, hue and so on.
It's created by calling the drm_mode_create_tv_properties() function.

The second one is there to deal with properties that might be useful on a
TV, creating the overscan margins for example. It's created by calling the
drm_mode_create_tv_margin_properties().

However, we also have a drm_atomic_helper_connector_tv_reset() function
that will reset the TV margin properties to their default values, and thus
is supposed to be called for the latter set. This creates an ambiguity due
to the inconsistent naming.

We can thus rename the drm_atomic_helper_connector_tv_reset() function to
drm_atomic_helper_connector_tv_margins_reset() to remove that ambiguity
and hopefully make it more obvious.

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index bf31b9d92094..dfb57217253b 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -464,12 +464,12 @@ 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
+ * drm_atomic_helper_connector_tv_margins_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)
+void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector)
 {
 	struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
 	struct drm_connector_state *state = connector->state;
@@ -479,7 +479,7 @@ void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
 	state->tv.margins.top = cmdline->tv_margins.top;
 	state->tv.margins.bottom = cmdline->tv_margins.bottom;
 }
-EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
 
 /**
  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
index d0addd478815..fa636206f232 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -355,7 +355,7 @@ static void gud_connector_reset(struct drm_connector *connector)
 	drm_atomic_helper_connector_reset(connector);
 	connector->state->tv = gconn->initial_tv_state;
 	/* Set margins from command line */
-	drm_atomic_helper_connector_tv_reset(connector);
+	drm_atomic_helper_connector_tv_margins_reset(connector);
 	if (gconn->initial_brightness >= 0)
 		connector->state->tv.brightness = gconn->initial_brightness;
 }
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 4d3ff51ad2a8..fe01ca5a07d3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -396,7 +396,7 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
 	new_state->base.max_bpc = 8;
 	new_state->base.max_requested_bpc = 8;
 	new_state->output_format = VC4_HDMI_OUTPUT_RGB;
-	drm_atomic_helper_connector_tv_reset(connector);
+	drm_atomic_helper_connector_tv_margins_reset(connector);
 }
 
 static struct drm_connector_state *
diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h
index 3f8f1d627f7c..192766656b88 100644
--- a/include/drm/drm_atomic_state_helper.h
+++ b/include/drm/drm_atomic_state_helper.h
@@ -70,7 +70,7 @@ void __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_
 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_tv_margins_reset(struct drm_connector *connector);
 void
 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
 					   struct drm_connector_state *state);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 248206bbd975..23112f0c11cf 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -692,7 +692,7 @@ struct drm_connector_tv_margins {
 
 /**
  * struct drm_tv_connector_state - TV connector related states
- * @subconnector: selected subconnector
+ * @select_subconnector: selected subconnector
  * @margins: TV margins
  * @mode: TV mode
  * @brightness: brightness in percent

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 04/33] drm/connector: Rename subconnector state variable
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (2 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 03/33] drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid ambiguity Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-23  8:14   ` Thomas Zimmermann
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 05/33] drm/atomic: Add TV subconnector property to get/set_property Maxime Ripard
                   ` (30 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

There is two TV subconnector related properties registered by
drm_mode_create_tv_properties(): subconnector and select subconnector.

While the select subconnector property is stored in the kernel by the
drm_tv_connector_state structure, the subconnector property isn't stored
anywhere.

Worse, the select subconnector property is stored in a field called
subconnector, creating some ambiguity about which property content we're
accessing.

Let's rename that field to one called select_subconnector to make it move
obvious what it's about.

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 79730fa1dd8e..c74c78a28171 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -687,7 +687,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		 */
 		return -EINVAL;
 	} else if (property == config->tv_select_subconnector_property) {
-		state->tv.subconnector = val;
+		state->tv.select_subconnector = val;
 	} else if (property == config->tv_left_margin_property) {
 		state->tv.margins.left = val;
 	} else if (property == config->tv_right_margin_property) {
@@ -795,7 +795,7 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
 		else
 			*val = connector->dpms;
 	} else if (property == config->tv_select_subconnector_property) {
-		*val = state->tv.subconnector;
+		*val = state->tv.select_subconnector;
 	} else if (property == config->tv_left_margin_property) {
 		*val = state->tv.margins.left;
 	} else if (property == config->tv_right_margin_property) {
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 23112f0c11cf..60b5662dec7c 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -703,7 +703,7 @@ struct drm_connector_tv_margins {
  * @hue: hue in percent
  */
 struct drm_tv_connector_state {
-	enum drm_mode_subconnector subconnector;
+	enum drm_mode_subconnector select_subconnector;
 	struct drm_connector_tv_margins margins;
 	unsigned int mode;
 	unsigned int brightness;

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 05/33] drm/atomic: Add TV subconnector property to get/set_property
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (3 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 04/33] drm/connector: Rename subconnector state variable Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property Maxime Ripard
                   ` (29 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The subconnector property was created by drm_mode_create_tv_properties(),
but wasn't exposed to the userspace through the generic
atomic_get/set_property implementation, and wasn't stored in any generic
state structure.

Let's solve this.

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index c74c78a28171..c06d0639d552 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -688,6 +688,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		return -EINVAL;
 	} else if (property == config->tv_select_subconnector_property) {
 		state->tv.select_subconnector = val;
+	} else if (property == config->tv_subconnector_property) {
+		state->tv.subconnector = val;
 	} else if (property == config->tv_left_margin_property) {
 		state->tv.margins.left = val;
 	} else if (property == config->tv_right_margin_property) {
@@ -796,6 +798,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
 			*val = connector->dpms;
 	} else if (property == config->tv_select_subconnector_property) {
 		*val = state->tv.select_subconnector;
+	} else if (property == config->tv_subconnector_property) {
+		*val = state->tv.subconnector;
 	} else if (property == config->tv_left_margin_property) {
 		*val = state->tv.margins.left;
 	} else if (property == config->tv_right_margin_property) {
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 60b5662dec7c..1d5e3cccb9e3 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -693,6 +693,7 @@ struct drm_connector_tv_margins {
 /**
  * struct drm_tv_connector_state - TV connector related states
  * @select_subconnector: selected subconnector
+ * @subconnector: detected subconnector
  * @margins: TV margins
  * @mode: TV mode
  * @brightness: brightness in percent
@@ -704,6 +705,7 @@ struct drm_connector_tv_margins {
  */
 struct drm_tv_connector_state {
 	enum drm_mode_subconnector select_subconnector;
+	enum drm_mode_subconnector subconnector;
 	struct drm_connector_tv_margins margins;
 	unsigned int mode;
 	unsigned int brightness;

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (4 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 05/33] drm/atomic: Add TV subconnector property to get/set_property Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 20:44   ` Lyude Paul
                     ` (2 more replies)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 07/33] drm/connector: Only register TV mode property if present Maxime Ripard
                   ` (28 subsequent siblings)
  34 siblings, 3 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The current tv_mode has driver-specific values that don't allow to
easily share code using it, either at the userspace or kernel level.

Since we're going to introduce a new, generic, property that fit the
same purpose, let's rename this one to legacy_tv_mode to make it
obvious we should move away from it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index c06d0639d552..7f2b9a07fbdf 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -698,8 +698,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		state->tv.margins.top = val;
 	} else if (property == config->tv_bottom_margin_property) {
 		state->tv.margins.bottom = val;
-	} else if (property == config->tv_mode_property) {
-		state->tv.mode = val;
+	} else if (property == config->legacy_tv_mode_property) {
+		state->tv.legacy_mode = val;
 	} else if (property == config->tv_brightness_property) {
 		state->tv.brightness = val;
 	} else if (property == config->tv_contrast_property) {
@@ -808,8 +808,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
 		*val = state->tv.margins.top;
 	} else if (property == config->tv_bottom_margin_property) {
 		*val = state->tv.margins.bottom;
-	} else if (property == config->tv_mode_property) {
-		*val = state->tv.mode;
+	} else if (property == config->legacy_tv_mode_property) {
+		*val = state->tv.legacy_mode;
 	} else if (property == config->tv_brightness_property) {
 		*val = state->tv.brightness;
 	} else if (property == config->tv_contrast_property) {
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index e3142c8142b3..ede6025638d7 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1686,14 +1686,14 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
 	if (drm_mode_create_tv_margin_properties(dev))
 		goto nomem;
 
-	dev->mode_config.tv_mode_property =
+	dev->mode_config.legacy_tv_mode_property =
 		drm_property_create(dev, DRM_MODE_PROP_ENUM,
 				    "mode", num_modes);
-	if (!dev->mode_config.tv_mode_property)
+	if (!dev->mode_config.legacy_tv_mode_property)
 		goto nomem;
 
 	for (i = 0; i < num_modes; i++)
-		drm_property_add_enum(dev->mode_config.tv_mode_property,
+		drm_property_add_enum(dev->mode_config.legacy_tv_mode_property,
 				      i, modes[i]);
 
 	dev->mode_config.tv_brightness_property =
diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
index fa636206f232..86e992b2108b 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -303,7 +303,7 @@ static int gud_connector_atomic_check(struct drm_connector *connector,
 	    old_state->tv.margins.right != new_state->tv.margins.right ||
 	    old_state->tv.margins.top != new_state->tv.margins.top ||
 	    old_state->tv.margins.bottom != new_state->tv.margins.bottom ||
-	    old_state->tv.mode != new_state->tv.mode ||
+	    old_state->tv.legacy_mode != new_state->tv.legacy_mode ||
 	    old_state->tv.brightness != new_state->tv.brightness ||
 	    old_state->tv.contrast != new_state->tv.contrast ||
 	    old_state->tv.flicker_reduction != new_state->tv.flicker_reduction ||
@@ -424,7 +424,7 @@ gud_connector_property_lookup(struct drm_connector *connector, u16 prop)
 	case GUD_PROPERTY_TV_BOTTOM_MARGIN:
 		return config->tv_bottom_margin_property;
 	case GUD_PROPERTY_TV_MODE:
-		return config->tv_mode_property;
+		return config->legacy_tv_mode_property;
 	case GUD_PROPERTY_TV_BRIGHTNESS:
 		return config->tv_brightness_property;
 	case GUD_PROPERTY_TV_CONTRAST:
@@ -454,7 +454,7 @@ static unsigned int *gud_connector_tv_state_val(u16 prop, struct drm_tv_connecto
 	case GUD_PROPERTY_TV_BOTTOM_MARGIN:
 		return &state->margins.bottom;
 	case GUD_PROPERTY_TV_MODE:
-		return &state->mode;
+		return &state->legacy_mode;
 	case GUD_PROPERTY_TV_BRIGHTNESS:
 		return &state->brightness;
 	case GUD_PROPERTY_TV_CONTRAST:
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index b91e48d2190d..d29b63fd6178 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -264,7 +264,7 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder,
 				      priv->hmargin);
 	drm_object_attach_property(&connector->base, conf->tv_bottom_margin_property,
 				      priv->vmargin);
-	drm_object_attach_property(&connector->base, conf->tv_mode_property,
+	drm_object_attach_property(&connector->base, conf->legacy_tv_mode_property,
 				      priv->norm);
 	drm_object_attach_property(&connector->base, conf->tv_brightness_property,
 				      priv->brightness);
@@ -315,7 +315,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder,
 		ch7006_load_reg(client, state, CH7006_POV);
 		ch7006_load_reg(client, state, CH7006_VPOS);
 
-	} else if (property == conf->tv_mode_property) {
+	} else if (property == conf->legacy_tv_mode_property) {
 		if (connector->dpms != DRM_MODE_DPMS_OFF)
 			return -EINVAL;
 
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
index 9379f3463344..abaf9ded942d 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -1986,7 +1986,8 @@ intel_tv_init(struct drm_i915_private *dev_priv)
 	}
 	drm_mode_create_tv_properties(dev, i, tv_format_names);
 
-	drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
+	drm_object_attach_property(&connector->base,
+				   dev->mode_config.legacy_tv_mode_property,
 				   state->tv.mode);
 	drm_object_attach_property(&connector->base,
 				   dev->mode_config.tv_left_margin_property,
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index be28e7bd7490..1a15534adc60 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -662,7 +662,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder,
 					conf->tv_subconnector_property,
 					tv_enc->subconnector);
 	drm_object_attach_property(&connector->base,
-					conf->tv_mode_property,
+					conf->legacy_tv_mode_property,
 					tv_enc->tv_norm);
 	drm_object_attach_property(&connector->base,
 					conf->tv_flicker_reduction_property,
@@ -722,7 +722,7 @@ static int nv17_tv_set_property(struct drm_encoder *encoder,
 		if (encoder->crtc)
 			nv17_tv_update_rescaler(encoder);
 
-	} else if (property == conf->tv_mode_property) {
+	} else if (property == conf->legacy_tv_mode_property) {
 		if (connector->dpms != DRM_MODE_DPMS_OFF)
 			return -EINVAL;
 
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 0b3333865702..77c50ecb0309 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -274,7 +274,7 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 	struct drm_display_mode *mode;
 
 	mode = drm_mode_duplicate(connector->dev,
-				  vc4_vec_tv_modes[state->tv.mode].mode);
+				  vc4_vec_tv_modes[state->tv.legacy_mode].mode);
 	if (!mode) {
 		DRM_ERROR("Failed to create a new display mode\n");
 		return -ENOMEM;
@@ -312,7 +312,7 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
 	drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
 
 	drm_object_attach_property(&connector->base,
-				   dev->mode_config.tv_mode_property,
+				   dev->mode_config.legacy_tv_mode_property,
 				   VC4_VEC_TV_MODE_NTSC);
 
 	drm_connector_attach_encoder(connector, &vec->encoder.base);
@@ -449,7 +449,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
 {
 	const struct vc4_vec_tv_mode *vec_mode;
 
-	vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
+	vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode];
 
 	if (conn_state->crtc &&
 	    !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 1d5e3cccb9e3..5cfad8b6ad83 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -695,7 +695,7 @@ struct drm_connector_tv_margins {
  * @select_subconnector: selected subconnector
  * @subconnector: detected subconnector
  * @margins: TV margins
- * @mode: TV mode
+ * @legacy_mode: Legacy TV mode, driver specific value
  * @brightness: brightness in percent
  * @contrast: contrast in percent
  * @flicker_reduction: flicker reduction in percent
@@ -707,7 +707,7 @@ struct drm_tv_connector_state {
 	enum drm_mode_subconnector select_subconnector;
 	enum drm_mode_subconnector subconnector;
 	struct drm_connector_tv_margins margins;
-	unsigned int mode;
+	unsigned int legacy_mode;
 	unsigned int brightness;
 	unsigned int contrast;
 	unsigned int flicker_reduction;
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 6b5e01295348..35a827175c24 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -714,11 +714,13 @@ struct drm_mode_config {
 	 * between different TV connector types.
 	 */
 	struct drm_property *tv_select_subconnector_property;
+
 	/**
-	 * @tv_mode_property: Optional TV property to select
+	 * @legacy_tv_mode_property: Optional TV property to select
 	 * the output TV mode.
 	 */
-	struct drm_property *tv_mode_property;
+	struct drm_property *legacy_tv_mode_property;
+
 	/**
 	 * @tv_left_margin_property: Optional TV property to set the left
 	 * margin (expressed in pixels).

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 07/33] drm/connector: Only register TV mode property if present
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (5 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 08/33] drm/connector: Rename drm_mode_create_tv_properties Maxime Ripard
                   ` (27 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The drm_create_tv_properties() will create the TV mode property
unconditionally.

However, since we'll gradually phase it out, let's register it only if we
have a list passed as an argument. This will make the transition easier.

Acked-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index ede6025638d7..17a5913cefe3 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1686,15 +1686,18 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
 	if (drm_mode_create_tv_margin_properties(dev))
 		goto nomem;
 
-	dev->mode_config.legacy_tv_mode_property =
-		drm_property_create(dev, DRM_MODE_PROP_ENUM,
-				    "mode", num_modes);
-	if (!dev->mode_config.legacy_tv_mode_property)
-		goto nomem;
 
-	for (i = 0; i < num_modes; i++)
-		drm_property_add_enum(dev->mode_config.legacy_tv_mode_property,
-				      i, modes[i]);
+	if (num_modes) {
+		dev->mode_config.legacy_tv_mode_property =
+			drm_property_create(dev, DRM_MODE_PROP_ENUM,
+					    "mode", num_modes);
+		if (!dev->mode_config.legacy_tv_mode_property)
+			goto nomem;
+
+		for (i = 0; i < num_modes; i++)
+			drm_property_add_enum(dev->mode_config.legacy_tv_mode_property,
+					      i, modes[i]);
+	}
 
 	dev->mode_config.tv_brightness_property =
 		drm_property_create_range(dev, 0, "brightness", 0, 100);

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 08/33] drm/connector: Rename drm_mode_create_tv_properties
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (6 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 07/33] drm/connector: Only register TV mode property if present Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 20:45   ` Lyude Paul
  2022-09-24 15:43   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 09/33] drm/connector: Add TV standard property Maxime Ripard
                   ` (26 subsequent siblings)
  34 siblings, 2 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

drm_mode_create_tv_properties(), among other things, will create the
"mode" property that stores the analog TV mode that connector is
supposed to output.

However, that property is getting deprecated, so let's rename that
function to mention it's deprecated. We'll introduce a new variant of
that function creating the property superseeding it in a later patch.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 17a5913cefe3..4e4fbc9e0049 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1600,7 +1600,7 @@ EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
  * Called by a driver's HDMI connector initialization routine, this function
  * creates the TV margin properties for a given device. No need to call this
  * function for an SDTV connector, it's already called from
- * drm_mode_create_tv_properties().
+ * drm_mode_create_tv_properties_legacy().
  *
  * Returns:
  * 0 on success or a negative error code on failure.
@@ -1635,7 +1635,7 @@ int drm_mode_create_tv_margin_properties(struct drm_device *dev)
 EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
 
 /**
- * drm_mode_create_tv_properties - create TV specific connector properties
+ * drm_mode_create_tv_properties_legacy - create TV specific connector properties
  * @dev: DRM device
  * @num_modes: number of different TV formats (modes) supported
  * @modes: array of pointers to strings containing name of each format
@@ -1648,9 +1648,9 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
  * Returns:
  * 0 on success or a negative error code on failure.
  */
-int drm_mode_create_tv_properties(struct drm_device *dev,
-				  unsigned int num_modes,
-				  const char * const modes[])
+int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
+					 unsigned int num_modes,
+					 const char * const modes[])
 {
 	struct drm_property *tv_selector;
 	struct drm_property *tv_subconnector;
@@ -1733,7 +1733,7 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
 nomem:
 	return -ENOMEM;
 }
-EXPORT_SYMBOL(drm_mode_create_tv_properties);
+EXPORT_SYMBOL(drm_mode_create_tv_properties_legacy);
 
 /**
  * drm_mode_create_scaling_mode_property - create scaling mode property
diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
index 86e992b2108b..034e78360d4f 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -400,7 +400,7 @@ static int gud_connector_add_tv_mode(struct gud_device *gdrm, struct drm_connect
 	for (i = 0; i < num_modes; i++)
 		modes[i] = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN];
 
-	ret = drm_mode_create_tv_properties(connector->dev, num_modes, modes);
+	ret = drm_mode_create_tv_properties_legacy(connector->dev, num_modes, modes);
 free:
 	kfree(buf);
 	if (ret < 0)
@@ -539,7 +539,7 @@ static int gud_connector_add_properties(struct gud_device *gdrm, struct gud_conn
 			fallthrough;
 		case GUD_PROPERTY_TV_HUE:
 			/* This is a no-op if already added. */
-			ret = drm_mode_create_tv_properties(drm, 0, NULL);
+			ret = drm_mode_create_tv_properties_legacy(drm, 0, NULL);
 			if (ret)
 				goto out;
 			break;
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index d29b63fd6178..506f6f932518 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -250,7 +250,7 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder,
 	struct drm_device *dev = encoder->dev;
 	struct drm_mode_config *conf = &dev->mode_config;
 
-	drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names);
+	drm_mode_create_tv_properties_legacy(dev, NUM_TV_NORMS, ch7006_tv_norm_names);
 
 	priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2);
 	if (!priv->scale_property)
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
index abaf9ded942d..5e88da8185ee 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -1984,7 +1984,7 @@ intel_tv_init(struct drm_i915_private *dev_priv)
 
 		tv_format_names[i] = tv_modes[i].name;
 	}
-	drm_mode_create_tv_properties(dev, i, tv_format_names);
+	drm_mode_create_tv_properties_legacy(dev, i, tv_format_names);
 
 	drm_object_attach_property(&connector->base,
 				   dev->mode_config.legacy_tv_mode_property,
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index 1a15534adc60..e5480dab55e3 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -653,7 +653,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder,
 			tv_enc->tv_norm = i;
 	}
 
-	drm_mode_create_tv_properties(dev, num_tv_norms, nv17_tv_norm_names);
+	drm_mode_create_tv_properties_legacy(dev, num_tv_norms, nv17_tv_norm_names);
 
 	drm_object_attach_property(&connector->base,
 					conf->tv_select_subconnector_property,
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 77c50ecb0309..f31fef938f11 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -514,8 +514,9 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
 	struct vc4_vec *vec;
 	int ret;
 
-	ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names),
-					    tv_mode_names);
+	ret = drm_mode_create_tv_properties_legacy(drm,
+						   ARRAY_SIZE(tv_mode_names),
+						   tv_mode_names);
 	if (ret)
 		return ret;
 
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 5cfad8b6ad83..d566b4a4709c 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1799,9 +1799,9 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev);
 void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector);
 
 int drm_mode_create_tv_margin_properties(struct drm_device *dev);
-int drm_mode_create_tv_properties(struct drm_device *dev,
-				  unsigned int num_modes,
-				  const char * const modes[]);
+int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
+					 unsigned int num_modes,
+					 const char * const modes[]);
 void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
 int drm_mode_create_scaling_mode_property(struct drm_device *dev);
 int drm_connector_attach_content_type_property(struct drm_connector *dev);

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 09/33] drm/connector: Add TV standard property
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (7 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 08/33] drm/connector: Rename drm_mode_create_tv_properties Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-24 15:52   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes Maxime Ripard
                   ` (25 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The TV mode property has been around for a while now to select and get the
current TV mode output on an analog TV connector.

Despite that property name being generic, its content isn't and has been
driver-specific which makes it hard to build any generic behaviour on top
of it, both in kernel and user-space.

Let's create a new enum tv norm property, that can contain any of the
analog TV standards currently supported by kernel drivers. Each driver can
then pass in a bitmask of the modes it supports, and the property
creation function will filter out the modes not supported.

We'll then be able to phase out the older tv mode property.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 7f2b9a07fbdf..d867e7f9f2cd 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -700,6 +700,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		state->tv.margins.bottom = val;
 	} else if (property == config->legacy_tv_mode_property) {
 		state->tv.legacy_mode = val;
+	} else if (property == config->tv_mode_property) {
+		state->tv.mode = val;
 	} else if (property == config->tv_brightness_property) {
 		state->tv.brightness = val;
 	} else if (property == config->tv_contrast_property) {
@@ -810,6 +812,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
 		*val = state->tv.margins.bottom;
 	} else if (property == config->legacy_tv_mode_property) {
 		*val = state->tv.legacy_mode;
+	} else if (property == config->tv_mode_property) {
+		*val = state->tv.mode;
 	} else if (property == config->tv_brightness_property) {
 		*val = state->tv.brightness;
 	} else if (property == config->tv_contrast_property) {
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 4e4fbc9e0049..e7aa8de08f5b 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -980,6 +980,18 @@ static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = {
 DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
 		 drm_dvi_i_subconnector_enum_list)
 
+static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = {
+	{ DRM_MODE_TV_MODE_NONE, "None" },
+	{ DRM_MODE_TV_MODE_NTSC, "NTSC" },
+	{ DRM_MODE_TV_MODE_NTSC_443, "NTSC-443" },
+	{ DRM_MODE_TV_MODE_NTSC_J, "NTSC-J" },
+	{ DRM_MODE_TV_MODE_PAL, "PAL" },
+	{ DRM_MODE_TV_MODE_PAL_M, "PAL-M" },
+	{ DRM_MODE_TV_MODE_PAL_N, "PAL-N" },
+	{ DRM_MODE_TV_MODE_SECAM, "SECAM" },
+};
+DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list)
+
 static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
 	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
 	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
@@ -1645,6 +1657,10 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
  * responsible for allocating a list of format names and passing them to
  * this routine.
  *
+ * NOTE: This functions registers the deprecated "mode" connector
+ * property to select the analog TV mode (ie, NTSC, PAL, etc.). New
+ * drivers must use drm_mode_create_tv_properties() instead.
+ *
  * Returns:
  * 0 on success or a negative error code on failure.
  */
@@ -1686,7 +1702,6 @@ int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
 	if (drm_mode_create_tv_margin_properties(dev))
 		goto nomem;
 
-
 	if (num_modes) {
 		dev->mode_config.legacy_tv_mode_property =
 			drm_property_create(dev, DRM_MODE_PROP_ENUM,
@@ -1735,6 +1750,49 @@ int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_mode_create_tv_properties_legacy);
 
+/**
+ * drm_mode_create_tv_properties - create TV specific connector properties
+ * @dev: DRM device
+ * @supported_tv_modes: Bitmask of TV modes supported (See DRM_MODE_TV_MODE_*)
+
+ * Called by a driver's TV initialization routine, this function creates
+ * the TV specific connector properties for a given device.  Caller is
+ * responsible for allocating a list of format names and passing them to
+ * this routine.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_mode_create_tv_properties(struct drm_device *dev,
+				  unsigned int supported_tv_modes)
+{
+	struct drm_prop_enum_list tv_mode_list[DRM_MODE_TV_MODE_MAX];
+	struct drm_property *tv_mode;
+	unsigned int i, len = 0;
+
+	if (dev->mode_config.tv_mode_property)
+		return 0;
+
+	for (i = 0; i < DRM_MODE_TV_MODE_MAX; i++) {
+		if (!(supported_tv_modes & BIT(i)))
+			continue;
+
+		tv_mode_list[len].type = i;
+		tv_mode_list[len].name = drm_get_tv_mode_name(i);
+		len++;
+	}
+
+	tv_mode = drm_property_create_enum(dev, 0, "TV mode",
+					   tv_mode_list, len);
+	if (!tv_mode)
+		return -ENOMEM;
+
+	dev->mode_config.tv_mode_property = tv_mode;
+
+	return drm_mode_create_tv_properties_legacy(dev, 0, NULL);
+}
+EXPORT_SYMBOL(drm_mode_create_tv_properties);
+
 /**
  * drm_mode_create_scaling_mode_property - create scaling mode property
  * @dev: DRM device
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index d566b4a4709c..fffacbfd0a45 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -143,6 +143,71 @@ enum subpixel_order {
 
 };
 
+/**
+ * enum drm_connector_tv_mode - Analog TV output mode
+ *
+ * This enum is used to indicate the TV output mode used on an analog TV
+ * connector.
+ *
+ * WARNING: The values of this enum is uABI since they're exposed in the
+ * "TV mode" connector property.
+ */
+enum drm_connector_tv_mode {
+	/**
+	 * @DRM_MODE_TV_MODE_NONE: Placeholder to not default on one
+	 * variant or the other when nothing is set.
+	 */
+	DRM_MODE_TV_MODE_NONE = 0,
+
+	/**
+	 * @DRM_MODE_TV_MODE_NTSC: CCIR System M (aka 525-lines)
+	 * together with the NTSC Color Encoding.
+	 */
+	DRM_MODE_TV_MODE_NTSC,
+
+	/**
+	 * @DRM_MODE_TV_MODE_NTSC_443: Variant of
+	 * @DRM_MODE_TV_MODE_NTSC. Uses a color subcarrier frequency
+	 * of 4.43 MHz.
+	 */
+	DRM_MODE_TV_MODE_NTSC_443,
+
+	/**
+	 * @DRM_MODE_TV_MODE_NTSC_J: Variant of @DRM_MODE_TV_MODE_NTSC
+	 * used in Japan. Uses a black level equals to the blanking
+	 * level.
+	 */
+	DRM_MODE_TV_MODE_NTSC_J,
+
+	/**
+	 * @DRM_MODE_TV_MODE_PAL: CCIR System B together with the PAL
+	 * color system.
+	 */
+	DRM_MODE_TV_MODE_PAL,
+
+	/**
+	 * @DRM_MODE_TV_MODE_PAL_M: CCIR System M (aka 525-lines)
+	 * together with the PAL color encoding
+	 */
+	DRM_MODE_TV_MODE_PAL_M,
+
+	/**
+	 * @DRM_MODE_TV_MODE_PAL_N: CCIR System N together with the PAL
+	 * color encoding. It uses 625 lines, but has a color subcarrier
+	 * frequency of 3.58MHz, the SECAM color space, and narrower
+	 * channels compared to most of the other PAL variants.
+	 */
+	DRM_MODE_TV_MODE_PAL_N,
+
+	/**
+	 * @DRM_MODE_TV_MODE_SECAM: CCIR System B together with the
+	 * SECAM color system.
+	 */
+	DRM_MODE_TV_MODE_SECAM,
+
+	DRM_MODE_TV_MODE_MAX,
+};
+
 /**
  * struct drm_scrambling: sink's scrambling support.
  */
@@ -696,6 +761,7 @@ struct drm_connector_tv_margins {
  * @subconnector: detected subconnector
  * @margins: TV margins
  * @legacy_mode: Legacy TV mode, driver specific value
+ * @mode: TV mode
  * @brightness: brightness in percent
  * @contrast: contrast in percent
  * @flicker_reduction: flicker reduction in percent
@@ -708,6 +774,7 @@ struct drm_tv_connector_state {
 	enum drm_mode_subconnector subconnector;
 	struct drm_connector_tv_margins margins;
 	unsigned int legacy_mode;
+	unsigned int mode;
 	unsigned int brightness;
 	unsigned int contrast;
 	unsigned int flicker_reduction;
@@ -1789,6 +1856,7 @@ const char *drm_get_subpixel_order_name(enum subpixel_order order);
 const char *drm_get_dpms_name(int val);
 const char *drm_get_dvi_i_subconnector_name(int val);
 const char *drm_get_dvi_i_select_name(int val);
+const char *drm_get_tv_mode_name(int val);
 const char *drm_get_tv_subconnector_name(int val);
 const char *drm_get_tv_select_name(int val);
 const char *drm_get_dp_subconnector_name(int val);
@@ -1802,6 +1870,8 @@ int drm_mode_create_tv_margin_properties(struct drm_device *dev);
 int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
 					 unsigned int num_modes,
 					 const char * const modes[]);
+int drm_mode_create_tv_properties(struct drm_device *dev,
+				  unsigned int supported_tv_modes);
 void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
 int drm_mode_create_scaling_mode_property(struct drm_device *dev);
 int drm_connector_attach_content_type_property(struct drm_connector *dev);
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 35a827175c24..10a6f7d1df0d 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -718,9 +718,17 @@ struct drm_mode_config {
 	/**
 	 * @legacy_tv_mode_property: Optional TV property to select
 	 * the output TV mode.
+	 *
+	 * Superseeded by @tv_mode_property
 	 */
 	struct drm_property *legacy_tv_mode_property;
 
+	/**
+	 * @tv_mode_property: Optional TV property to select the TV
+	 * standard output on the connector.
+	 */
+	struct drm_property *tv_mode_property;
+
 	/**
 	 * @tv_left_margin_property: Optional TV property to set the left
 	 * margin (expressed in pixels).

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (8 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 09/33] drm/connector: Add TV standard property Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-23  9:05   ` Thomas Zimmermann
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 11/33] drm/modes: Only consider bpp and refresh before options Maxime Ripard
                   ` (24 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

Multiple drivers (meson, vc4, sun4i) define analog TV 525-lines and
625-lines modes in their drivers.

Since those modes are fairly standard, and that we'll need to use them
in more places in the future, it makes sense to move their definition
into the core framework.

However, analog display usually have fairly loose timings requirements,
the only discrete parameters being the total number of lines and pixel
clock frequency. Thus, we created a function that will create a display
mode from the standard, the pixel frequency and the active area.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 304004fb80aa..76ab700f56ff 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -116,6 +116,480 @@ void drm_mode_probed_add(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_probed_add);
 
+enum drm_mode_analog {
+	DRM_MODE_ANALOG_NTSC, /* 525 lines, 60Hz */
+	DRM_MODE_ANALOG_PAL, /* 625 lines, 50Hz */
+};
+
+/*
+ * The timings come from:
+ * - https://web.archive.org/web/20220406232708/http://www.kolumbus.fi/pami1/video/pal_ntsc.html
+ * - https://web.archive.org/web/20220406124914/http://martin.hinner.info/vga/pal.html
+ * - https://web.archive.org/web/20220609202433/http://www.batsocks.co.uk/readme/video_timing.htm
+ */
+#define NTSC_LINE_DURATION_NS		63556U
+#define NTSC_LINES_NUMBER		525
+
+#define NTSC_HBLK_DURATION_TYP_NS	10900U
+#define NTSC_HBLK_DURATION_MIN_NS	(NTSC_HBLK_DURATION_TYP_NS - 200)
+#define NTSC_HBLK_DURATION_MAX_NS	(NTSC_HBLK_DURATION_TYP_NS + 200)
+
+#define NTSC_HACT_DURATION_TYP_NS	(NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_TYP_NS)
+#define NTSC_HACT_DURATION_MIN_NS	(NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MAX_NS)
+#define NTSC_HACT_DURATION_MAX_NS	(NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MIN_NS)
+
+#define NTSC_HFP_DURATION_TYP_NS	1500
+#define NTSC_HFP_DURATION_MIN_NS	1270
+#define NTSC_HFP_DURATION_MAX_NS	2220
+
+#define NTSC_HSLEN_DURATION_TYP_NS	4700
+#define NTSC_HSLEN_DURATION_MIN_NS	(NTSC_HSLEN_DURATION_TYP_NS - 100)
+#define NTSC_HSLEN_DURATION_MAX_NS	(NTSC_HSLEN_DURATION_TYP_NS + 100)
+
+#define NTSC_HBP_DURATION_TYP_NS	4700
+
+/*
+ * I couldn't find the actual tolerance for the back porch, so let's
+ * just reuse the sync length ones.
+ */
+#define NTSC_HBP_DURATION_MIN_NS	(NTSC_HBP_DURATION_TYP_NS - 100)
+#define NTSC_HBP_DURATION_MAX_NS	(NTSC_HBP_DURATION_TYP_NS + 100)
+
+#define PAL_LINE_DURATION_NS		64000U
+#define PAL_LINES_NUMBER		625
+
+#define PAL_HACT_DURATION_TYP_NS	51950U
+#define PAL_HACT_DURATION_MIN_NS	(PAL_HACT_DURATION_TYP_NS - 100)
+#define PAL_HACT_DURATION_MAX_NS	(PAL_HACT_DURATION_TYP_NS + 400)
+
+#define PAL_HBLK_DURATION_TYP_NS	(PAL_LINE_DURATION_NS - PAL_HACT_DURATION_TYP_NS)
+#define PAL_HBLK_DURATION_MIN_NS	(PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MAX_NS)
+#define PAL_HBLK_DURATION_MAX_NS	(PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MIN_NS)
+
+#define PAL_HFP_DURATION_TYP_NS		1650
+#define PAL_HFP_DURATION_MIN_NS		(PAL_HFP_DURATION_TYP_NS - 100)
+#define PAL_HFP_DURATION_MAX_NS		(PAL_HFP_DURATION_TYP_NS + 400)
+
+#define PAL_HSLEN_DURATION_TYP_NS	4700
+#define PAL_HSLEN_DURATION_MIN_NS	(PAL_HSLEN_DURATION_TYP_NS - 200)
+#define PAL_HSLEN_DURATION_MAX_NS	(PAL_HSLEN_DURATION_TYP_NS + 200)
+
+#define PAL_HBP_DURATION_TYP_NS		5700
+#define PAL_HBP_DURATION_MIN_NS		(PAL_HBP_DURATION_TYP_NS - 200)
+#define PAL_HBP_DURATION_MAX_NS		(PAL_HBP_DURATION_TYP_NS + 200)
+
+struct analog_param_field {
+	unsigned int even, odd;
+};
+
+#define PARAM_FIELD(_odd, _even)		\
+	{ .even = _even, .odd = _odd }
+
+struct analog_param_range {
+	unsigned int	min, typ, max;
+};
+
+#define PARAM_RANGE(_min, _typ, _max)		\
+	{ .min = _min, .typ = _typ, .max = _max }
+
+struct analog_parameters {
+	unsigned int			num_lines;
+	unsigned int			line_duration_ns;
+
+	struct analog_param_range	hact_ns;
+	struct analog_param_range	hfp_ns;
+	struct analog_param_range	hslen_ns;
+	struct analog_param_range	hbp_ns;
+	struct analog_param_range	hblk_ns;
+
+	unsigned int			bt601_hfp;
+
+	struct analog_param_field	vfp_lines;
+	struct analog_param_field	vslen_lines;
+	struct analog_param_field	vbp_lines;
+};
+
+#define TV_MODE_PARAMETER(_mode, _lines, _line_dur, _hact, _hfp, _hslen, _hbp, _hblk, _bt601_hfp, _vfp, _vslen, _vbp) \
+	[_mode] = {							\
+		.num_lines = _lines,					\
+		.line_duration_ns = _line_dur,				\
+		.hact_ns = _hact,					\
+		.hfp_ns = _hfp,						\
+		.hslen_ns = _hslen,					\
+		.hbp_ns = _hbp,						\
+		.hblk_ns = _hblk,					\
+		.bt601_hfp = _bt601_hfp,				\
+		.vfp_lines = _vfp,					\
+		.vslen_lines = _vslen,					\
+		.vbp_lines = _vbp,					\
+	}
+
+const static struct analog_parameters tv_modes_parameters[] = {
+	TV_MODE_PARAMETER(DRM_MODE_ANALOG_NTSC,
+			  NTSC_LINES_NUMBER,
+			  NTSC_LINE_DURATION_NS,
+			  PARAM_RANGE(NTSC_HACT_DURATION_MIN_NS,
+				      NTSC_HACT_DURATION_TYP_NS,
+				      NTSC_HACT_DURATION_MAX_NS),
+			  PARAM_RANGE(NTSC_HFP_DURATION_MIN_NS,
+				      NTSC_HFP_DURATION_TYP_NS,
+				      NTSC_HFP_DURATION_MAX_NS),
+			  PARAM_RANGE(NTSC_HSLEN_DURATION_MIN_NS,
+				      NTSC_HSLEN_DURATION_TYP_NS,
+				      NTSC_HSLEN_DURATION_MAX_NS),
+			  PARAM_RANGE(NTSC_HBP_DURATION_MIN_NS,
+				      NTSC_HBP_DURATION_TYP_NS,
+				      NTSC_HBP_DURATION_MAX_NS),
+			  PARAM_RANGE(NTSC_HBLK_DURATION_MIN_NS,
+				      NTSC_HBLK_DURATION_TYP_NS,
+				      NTSC_HBLK_DURATION_MAX_NS),
+			  16,
+			  PARAM_FIELD(3, 3),
+			  PARAM_FIELD(3, 3),
+			  PARAM_FIELD(16, 17)),
+	TV_MODE_PARAMETER(DRM_MODE_ANALOG_PAL,
+			  PAL_LINES_NUMBER,
+			  PAL_LINE_DURATION_NS,
+			  PARAM_RANGE(PAL_HACT_DURATION_MIN_NS,
+				      PAL_HACT_DURATION_TYP_NS,
+				      PAL_HACT_DURATION_MAX_NS),
+			  PARAM_RANGE(PAL_HFP_DURATION_MIN_NS,
+				      PAL_HFP_DURATION_TYP_NS,
+				      PAL_HFP_DURATION_MAX_NS),
+			  PARAM_RANGE(PAL_HSLEN_DURATION_MIN_NS,
+				      PAL_HSLEN_DURATION_TYP_NS,
+				      PAL_HSLEN_DURATION_MAX_NS),
+			  PARAM_RANGE(PAL_HBP_DURATION_MIN_NS,
+				      PAL_HBP_DURATION_TYP_NS,
+				      PAL_HBP_DURATION_MAX_NS),
+			  PARAM_RANGE(PAL_HBLK_DURATION_MIN_NS,
+				      PAL_HBLK_DURATION_TYP_NS,
+				      PAL_HBLK_DURATION_MAX_NS),
+			  12,
+
+			  /*
+			   * The front porch is actually 6 short sync
+			   * pulses for the even field, and 5 for the
+			   * odd field. Each sync takes half a life so
+			   * the odd field front porch is shorter by
+			   * half a line.
+			   *
+			   * In progressive, we're supposed to use 6
+			   * pulses, so we're fine there
+			   */
+			  PARAM_FIELD(3, 2),
+
+			  /*
+			   * The vsync length is 5 long sync pulses,
+			   * each field taking half a line. We're
+			   * shorter for both fields by half a line.
+			   *
+			   * In progressive, we're supposed to use 5
+			   * pulses, so we're off by half
+			   * a line.
+			   *
+			   * In interlace, we're now off by half a line
+			   * for the even field and one line for the odd
+			   * field.
+			   */
+			  PARAM_FIELD(3, 3),
+
+			  /*
+			   * The back porch starts with post-equalizing
+			   * pulses, consisting in 5 short sync pulses
+			   * for the even field, 4 for the odd field. In
+			   * progressive, it's 5 short syncs.
+			   *
+			   * In progressive, we thus have 2.5 lines,
+			   * plus the 0.5 line we were missing
+			   * previously, so we should use 3 lines.
+			   *
+			   * In interlace, the even field is in the
+			   * exact same case than progressive. For the
+			   * odd field, we should be using 2 lines but
+			   * we're one line short, so we'll make up for
+			   * it here by using 3.
+			   *
+			   * The entire blanking area is supposed to
+			   * take 25 lines, so we also need to account
+			   * for the rest of the blanking area that
+			   * can't be in either the front porch or sync
+			   * period.
+			   */
+			  PARAM_FIELD(19, 20)),
+};
+
+static int fill_analog_mode(struct drm_device *dev,
+			    struct drm_display_mode *mode,
+			    const struct analog_parameters *params,
+			    unsigned long pixel_clock_hz,
+			    unsigned int hactive,
+			    unsigned int vactive,
+			    bool interlace)
+{
+	unsigned long pixel_duration_ns = NSEC_PER_SEC / pixel_clock_hz;
+	unsigned int htotal, vtotal;
+	unsigned int max_hact, hact_duration_ns;
+	unsigned int hblk, hblk_duration_ns;
+	unsigned int hfp, hfp_duration_ns;
+	unsigned int hslen, hslen_duration_ns;
+	unsigned int hbp, hbp_duration_ns;
+	unsigned int porches, porches_duration_ns;
+	unsigned int vfp, vfp_min;
+	unsigned int vbp, vbp_min;
+	unsigned int vslen;
+	bool bt601 = false;
+	int porches_rem;
+	u64 result;
+
+	drm_dbg_kms(dev,
+		    "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
+		    hactive, vactive,
+		    interlace ? 'i' : 'p',
+		    params->num_lines,
+		    pixel_clock_hz / 1000);
+
+	max_hact = params->hact_ns.max / pixel_duration_ns;
+	if (pixel_clock_hz == 13500000 && hactive > max_hact && hactive <= 720) {
+		drm_dbg_kms(dev, "Trying to generate a BT.601 mode. Disabling checks.\n");
+		bt601 = true;
+	}
+
+	/*
+	 * Our pixel duration is going to be round down by the division,
+	 * so rounding up is probably going to introduce even more
+	 * deviation.
+	 */
+	result = (u64)params->line_duration_ns * pixel_clock_hz;
+	do_div(result, NSEC_PER_SEC);
+	htotal = result;
+
+	drm_dbg_kms(dev, "Total Horizontal Number of Pixels: %u\n", htotal);
+
+	hact_duration_ns = hactive * pixel_duration_ns;
+	if (!bt601 &&
+	    (hact_duration_ns < params->hact_ns.min ||
+	     hact_duration_ns > params->hact_ns.max)) {
+		DRM_ERROR("Invalid horizontal active area duration: %uns (min: %u, max %u)\n",
+			  hact_duration_ns, params->hact_ns.min, params->hact_ns.max);
+		return -EINVAL;
+	}
+
+	hblk = htotal - hactive;
+	drm_dbg_kms(dev, "Horizontal Blanking Period: %u\n", hblk);
+
+	hblk_duration_ns = hblk * pixel_duration_ns;
+	if (!bt601 &&
+	    (hblk_duration_ns < params->hblk_ns.min ||
+	     hblk_duration_ns > params->hblk_ns.max)) {
+		DRM_ERROR("Invalid horizontal blanking duration: %uns (min: %u, max %u)\n",
+			  hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max);
+		return -EINVAL;
+	}
+
+	hslen = DIV_ROUND_UP(params->hslen_ns.typ, pixel_duration_ns);
+	drm_dbg_kms(dev, "Horizontal Sync Period: %u\n", hslen);
+
+	hslen_duration_ns = hslen * pixel_duration_ns;
+	if (!bt601 &&
+	    (hslen_duration_ns < params->hslen_ns.min ||
+	     hslen_duration_ns > params->hslen_ns.max)) {
+		DRM_ERROR("Invalid horizontal sync duration: %uns (min: %u, max %u)\n",
+			  hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max);
+		return -EINVAL;
+	}
+
+	porches = hblk - hslen;
+	drm_dbg_kms(dev, "Remaining horizontal pixels for both porches: %u\n", porches);
+
+	porches_duration_ns = porches * pixel_duration_ns;
+	if (!bt601 &&
+	    (porches_duration_ns > (params->hfp_ns.max + params->hbp_ns.max) ||
+	     porches_duration_ns < (params->hfp_ns.min + params->hbp_ns.min))) {
+		DRM_ERROR("Invalid horizontal porches duration: %uns\n", porches_duration_ns);
+		return -EINVAL;
+	}
+
+	if (bt601) {
+		hfp = params->bt601_hfp;
+	} else {
+		unsigned int hfp_min = DIV_ROUND_UP(params->hfp_ns.min,
+						    pixel_duration_ns);
+		unsigned int hbp_min = DIV_ROUND_UP(params->hbp_ns.min,
+						    pixel_duration_ns);
+		 int porches_rem = porches - hfp_min - hbp_min;
+
+		hfp = hfp_min + DIV_ROUND_UP(porches_rem, 2);
+	}
+
+	drm_dbg_kms(dev, "Horizontal Front Porch: %u\n", hfp);
+
+	hfp_duration_ns = hfp * pixel_duration_ns;
+	if (!bt601 &&
+	    (hfp_duration_ns < params->hfp_ns.min ||
+	     hfp_duration_ns > params->hfp_ns.max)) {
+		DRM_ERROR("Invalid horizontal front porch duration: %uns (min: %u, max %u)\n",
+			  hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max);
+		return -EINVAL;
+	}
+
+	hbp = porches - hfp;
+	drm_dbg_kms(dev, "Horizontal Back Porch: %u\n", hbp);
+
+	hbp_duration_ns = hbp * pixel_duration_ns;
+	if (!bt601 &&
+	    (hbp_duration_ns < params->hbp_ns.min ||
+	     hbp_duration_ns > params->hbp_ns.max)) {
+		DRM_ERROR("Invalid horizontal back porch duration: %uns (min: %u, max %u)\n",
+			  hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max);
+		return -EINVAL;
+	}
+
+	if (htotal != (hactive + hfp + hslen + hbp))
+		return -EINVAL;
+
+	mode->clock = pixel_clock_hz / 1000;
+	mode->hdisplay = hactive;
+	mode->hsync_start = hactive + hfp;
+	mode->hsync_end = hactive + hfp + hslen;
+	mode->htotal = hactive + hfp + hslen + hbp;
+
+	if (interlace) {
+		vfp_min = params->vfp_lines.even + params->vfp_lines.odd;
+		vbp_min = params->vbp_lines.even + params->vbp_lines.odd;
+		vslen = params->vslen_lines.even + params->vslen_lines.odd;
+	} else {
+		/*
+		 * By convention, NSTC (aka 525/60) systems start with
+		 * the even field, but PAL (aka 625/50) systems start
+		 * with the odd one.
+		 *
+		 * PAL systems also have asymetric timings between the
+		 * even and odd field, while NTSC is symetric.
+		 *
+		 * Moreover, if we want to create a progressive mode for
+		 * PAL, we need to use the odd field timings.
+		 *
+		 * Since odd == even for NTSC, we can just use the odd
+		 * one all the time to simplify the code a bit.
+		 */
+		vfp_min = params->vfp_lines.odd;
+		vbp_min = params->vbp_lines.odd;
+		vslen = params->vslen_lines.odd;
+	}
+
+	drm_dbg_kms(dev, "Vertical Sync Period: %u\n", vslen);
+
+	porches = params->num_lines - vactive - vslen;
+	drm_dbg_kms(dev, "Remaining vertical pixels for both porches: %u\n", porches);
+
+	porches_rem = porches - vfp_min - vbp_min;
+	vfp = vfp_min + (porches_rem / 2);
+	drm_dbg_kms(dev, "Vertical Front Porch: %u\n", vfp);
+
+	vbp = porches - vfp;
+	drm_dbg_kms(dev, "Vertical Back Porch: %u\n", vbp);
+
+	vtotal = vactive + vfp + vslen + vbp;
+	if (params->num_lines != vtotal) {
+		DRM_ERROR("Invalid vertical total: %upx (expected %upx)\n",
+			  vtotal, params->num_lines);
+		return -EINVAL;
+	}
+
+	mode->vdisplay = vactive;
+	mode->vsync_start = vactive + vfp;
+	mode->vsync_end = vactive + vfp + vslen;
+	mode->vtotal = vactive + vfp + vslen + vbp;
+
+	mode->type = DRM_MODE_TYPE_DRIVER;
+	mode->flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC;
+	if (interlace)
+		mode->flags |= DRM_MODE_FLAG_INTERLACE;
+
+	drm_mode_set_name(mode);
+
+	if (mode->vtotal != params->num_lines)
+		return -EINVAL;
+
+	drm_dbg_kms(dev, "Generated mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
+
+	return 0;
+}
+
+/**
+ * drm_analog_tv_mode - create a display mode for an analog TV
+ * @dev: drm device
+ * @tv_mode: TV Mode standard to create a mode for. See DRM_MODE_TV_MODE_*.
+ * @pixel_clock_hz: Pixel Clock Frequency, in Hertz
+ * @hdisplay: hdisplay size
+ * @vdisplay: vdisplay size
+ * @interlace: whether to compute an interlaced mode
+ *
+ * This function creates a struct drm_display_mode instance suited for
+ * an analog TV output, for one of the usual analog TV mode.
+ *
+ * Note that @hdisplay is larger than the usual constraints for the PAL
+ * and NTSC timings, and we'll choose to ignore most timings constraints
+ * to reach those resolutions.
+ *
+ * Returns:
+ *
+ * A pointer to the mode, allocated with drm_mode_create(). Returns NULL
+ * on error.
+ */
+struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
+					    enum drm_connector_tv_mode tv_mode,
+					    unsigned long pixel_clock_hz,
+					    unsigned int hdisplay,
+					    unsigned int vdisplay,
+					    bool interlace)
+{
+	struct drm_display_mode *mode;
+	enum drm_mode_analog analog;
+	int ret;
+
+	switch (tv_mode) {
+	case DRM_MODE_TV_MODE_NTSC:
+		fallthrough;
+	case DRM_MODE_TV_MODE_NTSC_443:
+		fallthrough;
+	case DRM_MODE_TV_MODE_NTSC_J:
+		fallthrough;
+	case DRM_MODE_TV_MODE_PAL_M:
+		analog = DRM_MODE_ANALOG_NTSC;
+		break;
+
+	case DRM_MODE_TV_MODE_PAL:
+		fallthrough;
+	case DRM_MODE_TV_MODE_PAL_N:
+		fallthrough;
+	case DRM_MODE_TV_MODE_SECAM:
+		analog = DRM_MODE_ANALOG_PAL;
+		break;
+
+	default:
+		return NULL;
+	}
+
+	mode = drm_mode_create(dev);
+	if (!mode)
+		return NULL;
+
+	ret = fill_analog_mode(dev, mode,
+			       &tv_modes_parameters[analog],
+			       pixel_clock_hz, hdisplay, vdisplay, interlace);
+	if (ret)
+		goto err_free_mode;
+
+	return mode;
+
+err_free_mode:
+	drm_mode_destroy(dev, mode);
+	return NULL;
+}
+EXPORT_SYMBOL(drm_analog_tv_mode);
+
 /**
  * drm_cvt_mode -create a modeline based on the CVT algorithm
  * @dev: drm device
diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index b29ef1085cad..b22ac96fdd65 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -10,5 +10,6 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
 	drm_framebuffer_test.o \
 	drm_kunit_helpers.o \
 	drm_mm_test.o \
+	drm_modes_test.o \
 	drm_plane_helper_test.o \
 	drm_rect_test.o
diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c
new file mode 100644
index 000000000000..be1ff0e21022
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_modes_test.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kunit test for drm_modes functions
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_modes.h>
+
+#include "drm_kunit_helpers.h"
+
+struct drm_modes_test_priv {
+	struct drm_device *drm;
+};
+
+static int drm_modes_test_init(struct kunit *test)
+{
+	struct drm_modes_test_priv *priv;
+
+	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, priv);
+
+	priv->drm = drm_kunit_device_init("drm-modes-test");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
+
+	test->priv = priv;
+
+	return 0;
+}
+
+static void drm_modes_test_exit(struct kunit *test)
+{
+	struct drm_modes_test_priv *priv = test->priv;
+
+	drm_kunit_device_exit(priv->drm);
+}
+
+static void drm_modes_analog_tv_ntsc_480i(struct kunit *test)
+{
+	struct drm_modes_test_priv *priv = test->priv;
+	struct drm_display_mode *mode;
+
+	mode = drm_analog_tv_mode(priv->drm,
+				  DRM_MODE_TV_MODE_NTSC,
+				  13500 * 1000, 720, 480,
+				  true);
+	KUNIT_ASSERT_NOT_NULL(test, mode);
+
+	KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 60);
+	KUNIT_EXPECT_EQ(test, mode->hdisplay, 720);
+
+	/* BT.601 defines hsync_start at 736 for 480i */
+	KUNIT_EXPECT_EQ(test, mode->hsync_start, 736);
+
+	/* 63.556us * 13.5MHz = 858 pixels */
+	KUNIT_EXPECT_EQ(test, mode->htotal, 858);
+	KUNIT_EXPECT_EQ(test, mode->vdisplay, 480);
+	KUNIT_EXPECT_EQ(test, mode->vtotal, 525);
+}
+
+static void drm_modes_analog_tv_ntsc_480i_inlined(struct kunit *test)
+{
+	struct drm_modes_test_priv *priv = test->priv;
+	struct drm_display_mode *expected, *mode;
+
+	expected = drm_analog_tv_mode(priv->drm,
+				      DRM_MODE_TV_MODE_NTSC,
+				      13500 * 1000, 720, 480,
+				      true);
+	KUNIT_ASSERT_NOT_NULL(test, expected);
+
+	mode = drm_mode_analog_ntsc_480i(priv->drm);
+	KUNIT_ASSERT_NOT_NULL(test, mode);
+
+	KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode));
+}
+
+static void drm_modes_analog_tv_pal_576i(struct kunit *test)
+{
+	struct drm_modes_test_priv *priv = test->priv;
+	struct drm_display_mode *mode;
+
+	mode = drm_analog_tv_mode(priv->drm,
+				  DRM_MODE_TV_MODE_PAL,
+				  13500 * 1000, 720, 576,
+				  true);
+	KUNIT_ASSERT_NOT_NULL(test, mode);
+
+	KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 50);
+	KUNIT_EXPECT_EQ(test, mode->hdisplay, 720);
+
+	/* BT.601 defines hsync_start at 732 for 576i */
+	KUNIT_EXPECT_EQ(test, mode->hsync_start, 732);
+
+	/* 64us * 13.5MHz = 864 pixels */
+	KUNIT_EXPECT_EQ(test, mode->htotal, 864);
+	KUNIT_EXPECT_EQ(test, mode->vdisplay, 576);
+	KUNIT_EXPECT_EQ(test, mode->vtotal, 625);
+}
+
+static void drm_modes_analog_tv_pal_576i_inlined(struct kunit *test)
+{
+	struct drm_modes_test_priv *priv = test->priv;
+	struct drm_display_mode *expected, *mode;
+
+	expected = drm_analog_tv_mode(priv->drm,
+				      DRM_MODE_TV_MODE_PAL,
+				      13500 * 1000, 720, 576,
+				      true);
+	KUNIT_ASSERT_NOT_NULL(test, expected);
+
+	mode = drm_mode_analog_pal_576i(priv->drm);
+	KUNIT_ASSERT_NOT_NULL(test, mode);
+
+	KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode));
+}
+
+static struct kunit_case drm_modes_analog_tv_tests[] = {
+	KUNIT_CASE(drm_modes_analog_tv_ntsc_480i),
+	KUNIT_CASE(drm_modes_analog_tv_ntsc_480i_inlined),
+	KUNIT_CASE(drm_modes_analog_tv_pal_576i),
+	KUNIT_CASE(drm_modes_analog_tv_pal_576i_inlined),
+	{ }
+};
+
+static struct kunit_suite drm_modes_analog_tv_test_suite = {
+	.name = "drm_modes_analog_tv",
+	.init = drm_modes_test_init,
+	.exit = drm_modes_test_exit,
+	.test_cases = drm_modes_analog_tv_tests,
+};
+
+kunit_test_suites(
+	&drm_modes_analog_tv_test_suite
+);
+MODULE_LICENSE("GPL v2");
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index a80ae9639e96..dc03ce03e229 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -443,6 +443,23 @@ bool drm_mode_is_420_also(const struct drm_display_info *display,
 bool drm_mode_is_420(const struct drm_display_info *display,
 		     const struct drm_display_mode *mode);
 
+struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
+					    enum drm_connector_tv_mode mode,
+					    unsigned long pixel_clock_hz,
+					    unsigned int hdisplay,
+					    unsigned int vdisplay,
+					    bool interlace);
+
+static inline struct drm_display_mode *drm_mode_analog_ntsc_480i(struct drm_device *dev)
+{
+	return drm_analog_tv_mode(dev, DRM_MODE_TV_MODE_NTSC, 13500000, 720, 480, true);
+}
+
+static inline struct drm_display_mode *drm_mode_analog_pal_576i(struct drm_device *dev)
+{
+	return drm_analog_tv_mode(dev, DRM_MODE_TV_MODE_PAL, 13500000, 720, 576, true);
+}
+
 struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
 				      int hdisplay, int vdisplay, int vrefresh,
 				      bool reduced, bool interlaced,

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 11/33] drm/modes: Only consider bpp and refresh before options
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (9 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 12/33] drm/modes: parse_cmdline: Add support for named modes containing dashes Maxime Ripard
                   ` (23 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

Some video= options might have a value that contains a dash. However, the
command line parsing mode considers all dashes as the separator between the
mode and the bpp count.

Let's rework the parsing code a bit to only consider a dash as the bpp
separator if it before a comma, the options separator.

A follow-up patch will add a unit-test for this once such an option is
introduced.

Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 76ab700f56ff..8742ee078fe6 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2275,20 +2275,22 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 
 	name = mode_option;
 
+	/* Locate the start of named options */
+	options_ptr = strchr(name, ',');
+	if (options_ptr)
+		options_off = options_ptr - name;
+	else
+		options_off = strlen(name);
+
 	/* Try to locate the bpp and refresh specifiers, if any */
-	bpp_ptr = strchr(name, '-');
+	bpp_ptr = strnchr(name, options_off, '-');
 	if (bpp_ptr)
 		bpp_off = bpp_ptr - name;
 
-	refresh_ptr = strchr(name, '@');
+	refresh_ptr = strnchr(name, options_off, '@');
 	if (refresh_ptr)
 		refresh_off = refresh_ptr - name;
 
-	/* 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) {
 		mode_end = bpp_off;

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 12/33] drm/modes: parse_cmdline: Add support for named modes containing dashes
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (10 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 11/33] drm/modes: Only consider bpp and refresh before options Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode() Maxime Ripard
                   ` (22 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

From: Geert Uytterhoeven <geert@linux-m68k.org>

It is fairly common for named video modes to contain dashes (e.g.
"tt-mid" on Atari, "dblntsc-ff" on Amiga).  Currently such mode names
are not recognized, as the dash is considered to be a separator between
mode name and bpp.

Fix this by skipping any dashes that are not followed immediately by a
digit when looking for the separator.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 8742ee078fe6..a1964e08c38f 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2284,6 +2284,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 
 	/* Try to locate the bpp and refresh specifiers, if any */
 	bpp_ptr = strnchr(name, options_off, '-');
+	while (bpp_ptr && !isdigit(bpp_ptr[1]))
+		bpp_ptr = strnchr(bpp_ptr + 1, options_off, '-');
 	if (bpp_ptr)
 		bpp_off = bpp_ptr - name;
 

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode()
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (11 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 12/33] drm/modes: parse_cmdline: Add support for named modes containing dashes Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-23  9:15   ` Thomas Zimmermann
  2022-09-23 11:59   ` Jani Nikula
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 14/33] drm/modes: Move named modes parsing to a separate function Maxime Ripard
                   ` (21 subsequent siblings)
  34 siblings, 2 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

drm_connector_pick_cmdline_mode() is in charge of finding a proper
drm_display_mode from the definition we got in the video= command line
argument.

Let's add some unit tests to make sure we're not getting any regressions
there.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index bbc535cc50dd..d553e793e673 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -1237,3 +1237,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
 	return ret;
 }
 EXPORT_SYMBOL(drm_client_modeset_dpms);
+
+#ifdef CONFIG_DRM_KUNIT_TEST
+#include "tests/drm_client_modeset_test.c"
+#endif
diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c
new file mode 100644
index 000000000000..46335de7bc6b
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Maxime Ripard <mripard@kernel.org>
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_probe_helper.h>
+
+#include "drm_kunit_helpers.h"
+
+struct drm_client_modeset_test_priv {
+	struct drm_device *drm;
+	struct drm_connector connector;
+};
+
+static int drm_client_modeset_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_display_mode *mode;
+	int count;
+
+	count = drm_add_modes_noedid(connector, 1920, 1200);
+
+	return count;
+}
+
+static const struct drm_connector_helper_funcs drm_client_modeset_connector_helper_funcs = {
+	.get_modes = drm_client_modeset_connector_get_modes,
+};
+
+static const struct drm_connector_funcs drm_client_modeset_connector_funcs = {
+};
+
+static int drm_client_modeset_test_init(struct kunit *test)
+{
+	struct drm_client_modeset_test_priv *priv;
+	int ret;
+
+	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	test->priv = priv;
+
+	priv->drm = drm_kunit_device_init("drm-client-modeset-test");
+	if (IS_ERR(priv->drm))
+		return PTR_ERR(priv->drm);
+
+	ret = drmm_connector_init(priv->drm, &priv->connector,
+				  &drm_client_modeset_connector_funcs,
+				  DRM_MODE_CONNECTOR_Unknown,
+				  NULL);
+	if (ret)
+		return ret;
+	drm_connector_helper_add(&priv->connector, &drm_client_modeset_connector_helper_funcs);
+
+	return 0;
+}
+
+static void drm_client_modeset_test_exit(struct kunit *test)
+{
+	struct drm_client_modeset_test_priv *priv = test->priv;
+
+	drm_kunit_device_exit(priv->drm);
+}
+
+static void drm_pick_cmdline_res_1920_1080_60(struct kunit *test)
+{
+	struct drm_client_modeset_test_priv *priv = test->priv;
+	struct drm_device *drm = priv->drm;
+	struct drm_connector *connector = &priv->connector;
+	struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+	struct drm_display_mode *expected_mode, *mode;
+	const char *cmdline = "1920x1080@60";
+	int ret;
+
+	expected_mode = drm_mode_find_dmt(priv->drm, 1920, 1080, 60, false);
+	KUNIT_ASSERT_PTR_NE(test, expected_mode, NULL);
+
+	KUNIT_ASSERT_TRUE(test,
+			  drm_mode_parse_command_line_for_connector(cmdline,
+								    connector,
+								    cmdline_mode));
+
+	mutex_lock(&drm->mode_config.mutex);
+	ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+	mutex_unlock(&drm->mode_config.mutex);
+	KUNIT_ASSERT_GT(test, ret, 0);
+
+	mode = drm_connector_pick_cmdline_mode(connector);
+	KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+	KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
+}
+
+static struct kunit_case drm_pick_cmdline_tests[] = {
+	KUNIT_CASE(drm_pick_cmdline_res_1920_1080_60),
+	{}
+};
+
+static struct kunit_suite drm_pick_cmdline_test_suite = {
+	.name = "drm_pick_cmdline",
+	.init = drm_client_modeset_test_init,
+	.exit = drm_client_modeset_test_exit,
+	.test_cases = drm_pick_cmdline_tests
+};
+
+kunit_test_suite(drm_pick_cmdline_test_suite);
+MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
+MODULE_LICENSE("GPL");

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 14/33] drm/modes: Move named modes parsing to a separate function
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (12 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode() Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 15/33] drm/modes: Bail out of named mode parsing if empty Maxime Ripard
                   ` (20 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The current construction of the named mode parsing doesn't allow to extend
it easily. Let's move it to a separate function so we can add more
parameters and modes.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index a1964e08c38f..b1e800e4ed60 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2229,6 +2229,32 @@ static const char * const drm_named_modes_whitelist[] = {
 	"PAL",
 };
 
+static int drm_mode_parse_cmdline_named_mode(const char *name,
+					     unsigned int name_end,
+					     struct drm_cmdline_mode *cmdline_mode)
+{
+	unsigned int i;
+
+	/*
+	 * We're sure we're a named mode at that point, iterate over the
+	 * list of modes we're aware of.
+	 */
+	for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
+		int ret;
+
+		ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
+		if (ret != name_end)
+			continue;
+
+		strcpy(cmdline_mode->name, drm_named_modes_whitelist[i]);
+		cmdline_mode->specified = true;
+
+		return 1;
+	}
+
+	return -EINVAL;
+}
+
 /**
  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
  * @mode_option: optional per connector mode option
@@ -2265,7 +2291,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 	const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
 	const char *options_ptr = NULL;
 	char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
-	int i, len, ret;
+	int len, ret;
 
 	memset(mode, 0, sizeof(*mode));
 	mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
@@ -2306,17 +2332,19 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 		parse_extras = true;
 	}
 
-	/* First check for a named mode */
-	for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
-		ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
-		if (ret == mode_end) {
-			if (refresh_ptr)
-				return false; /* named + refresh is invalid */
 
-			strcpy(mode->name, drm_named_modes_whitelist[i]);
-			mode->specified = true;
-			break;
-		}
+	if (mode_end) {
+		ret = drm_mode_parse_cmdline_named_mode(name, mode_end, mode);
+		if (ret < 0)
+			return false;
+
+		/*
+		 * Having a mode that starts by a letter (and thus is named)
+		 * and an at-sign (used to specify a refresh rate) is
+		 * disallowed.
+		 */
+		if (ret && refresh_ptr)
+			return false;
 	}
 
 	/* No named mode? Check for a normal mode argument, e.g. 1024x768 */

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 15/33] drm/modes: Bail out of named mode parsing if empty
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (13 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 14/33] drm/modes: Move named modes parsing to a separate function Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 16/33] drm/modes: Bail out of named mode parsing early if it's a number Maxime Ripard
                   ` (19 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

If the name we want to parse has a length of zero, there's no need to
compare it to the list of all the named modes we support, we can return
straight away.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index b1e800e4ed60..8d629fbb1047 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2235,6 +2235,9 @@ static int drm_mode_parse_cmdline_named_mode(const char *name,
 {
 	unsigned int i;
 
+	if (!name_end)
+		return 0;
+
 	/*
 	 * We're sure we're a named mode at that point, iterate over the
 	 * list of modes we're aware of.

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 16/33] drm/modes: Bail out of named mode parsing early if it's a number
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (14 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 15/33] drm/modes: Bail out of named mode parsing if empty Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 17/33] drm/modes: Bail out of named mode parsing early if it's an option Maxime Ripard
                   ` (18 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

If the name we want to parse starts with a digit, it's not a named mode.
Thus, there's no need to compare it to the list of all the named modes
we support, we can return straight away.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 8d629fbb1047..ede5b094da4c 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2238,6 +2238,10 @@ static int drm_mode_parse_cmdline_named_mode(const char *name,
 	if (!name_end)
 		return 0;
 
+	/* If the name starts with a digit, it's not a named mode */
+	if (isdigit(name[0]))
+		return 0;
+
 	/*
 	 * We're sure we're a named mode at that point, iterate over the
 	 * list of modes we're aware of.

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 17/33] drm/modes: Bail out of named mode parsing early if it's an option
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (15 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 16/33] drm/modes: Bail out of named mode parsing early if it's a number Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 18/33] drm/modes: Bail out of named mode parsing early if it's a status Maxime Ripard
                   ` (17 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The name we are given is the first part of the command line split at a
comma.

We can thus be called in two cases, either we are parsing a (named?)
mode, before the optional part separated by a comma, or we never had a
mode specified but only options.

Options use the equal sign as separator between the name and its value,
so if we ever find an equal sign in our string, we can bail early since
we never had a mode to parse.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index ede5b094da4c..dc5d5bdbea7a 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2242,6 +2242,13 @@ static int drm_mode_parse_cmdline_named_mode(const char *name,
 	if (isdigit(name[0]))
 		return 0;
 
+	/*
+	 * If there's an equal sign in the name, the command-line
+	 * contains only an option and no mode.
+	 */
+	if (strnchr(name, name_end, '='))
+		return 0;
+
 	/*
 	 * We're sure we're a named mode at that point, iterate over the
 	 * list of modes we're aware of.

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 18/33] drm/modes: Bail out of named mode parsing early if it's a status
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (16 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 17/33] drm/modes: Bail out of named mode parsing early if it's an option Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 19/33] drm/modes: Switch to named mode descriptors Maxime Ripard
                   ` (16 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The name we are given is the first part of the command line, the part
before any option.

The most trivial case is thus that we're parsing a mode. However, the
connection status uses a single character to encode what status we want
to force on a connector.

It's thus fairly easy to confuse that character with a named mode, and
our current code works because the list of the named modes we consider
doesn't start with any of those characters.

However, it's not very obvious and quite fragile, so let's add an
explicit test for this, with some comment to explain what's going on.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index dc5d5bdbea7a..9cee0ad806b8 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2249,6 +2249,15 @@ static int drm_mode_parse_cmdline_named_mode(const char *name,
 	if (strnchr(name, name_end, '='))
 		return 0;
 
+#define STR_STRICT_EQ(str, len, cmp) \
+	(str_has_prefix(str, cmp) == len)
+
+	/* The connection status extras can be set without a mode. */
+	if (STR_STRICT_EQ(name, name_end, "d") ||
+	    STR_STRICT_EQ(name, name_end, "D") ||
+	    STR_STRICT_EQ(name, name_end, "e"))
+		return 0;
+
 	/*
 	 * We're sure we're a named mode at that point, iterate over the
 	 * list of modes we're aware of.

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 19/33] drm/modes: Switch to named mode descriptors
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (17 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 18/33] drm/modes: Bail out of named mode parsing early if it's a status Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 20/33] drm/modes: Fill drm_cmdline mode from named modes Maxime Ripard
                   ` (15 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The current named mode parsing relies only the mode name, and doesn't allow
to specify any other parameter.

Let's convert that string list to an array of a custom structure that will
hold the name and some additional parameters in the future.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 9cee0ad806b8..8c8b37ba37dc 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2224,9 +2224,13 @@ static int drm_mode_parse_cmdline_options(const char *str,
 	return 0;
 }
 
-static const char * const drm_named_modes_whitelist[] = {
-	"NTSC",
-	"PAL",
+struct drm_named_mode {
+	const char *name;
+};
+
+static const struct drm_named_mode drm_named_modes[] = {
+	{ "NTSC", },
+	{ "PAL", },
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2262,14 +2266,15 @@ static int drm_mode_parse_cmdline_named_mode(const char *name,
 	 * We're sure we're a named mode at that point, iterate over the
 	 * list of modes we're aware of.
 	 */
-	for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
+	for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
+		const struct drm_named_mode *mode = &drm_named_modes[i];
 		int ret;
 
-		ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
+		ret = str_has_prefix(name, mode->name);
 		if (ret != name_end)
 			continue;
 
-		strcpy(cmdline_mode->name, drm_named_modes_whitelist[i]);
+		strcpy(cmdline_mode->name, mode->name);
 		cmdline_mode->specified = true;
 
 		return 1;

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 20/33] drm/modes: Fill drm_cmdline mode from named modes
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (18 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 19/33] drm/modes: Switch to named mode descriptors Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 21/33] drm/connector: Add pixel clock to cmdline mode Maxime Ripard
                   ` (14 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The current code to deal with named modes will only set the mode name, and
then it's up to drivers to try to match that name to whatever mode or
configuration they see fit.

The plan is to remove that need and move the named mode handling out of
drivers and into the core, and only rely on modes and properties. Let's
start by properly filling drm_cmdline_mode from a named mode.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 8c8b37ba37dc..5d8b6a0d96f3 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2226,11 +2226,22 @@ static int drm_mode_parse_cmdline_options(const char *str,
 
 struct drm_named_mode {
 	const char *name;
+	unsigned int xres;
+	unsigned int yres;
+	unsigned int flags;
 };
 
+#define NAMED_MODE(_name, _x, _y, _flags)		\
+	{						\
+		.name = _name,				\
+		.xres = _x,				\
+		.yres = _y,				\
+		.flags = _flags,			\
+	}
+
 static const struct drm_named_mode drm_named_modes[] = {
-	{ "NTSC", },
-	{ "PAL", },
+	NAMED_MODE("NTSC", 720, 480, DRM_MODE_FLAG_INTERLACE),
+	NAMED_MODE("PAL", 720, 576, DRM_MODE_FLAG_INTERLACE),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2275,6 +2286,9 @@ static int drm_mode_parse_cmdline_named_mode(const char *name,
 			continue;
 
 		strcpy(cmdline_mode->name, mode->name);
+		cmdline_mode->xres = mode->xres;
+		cmdline_mode->yres = mode->yres;
+		cmdline_mode->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
 		cmdline_mode->specified = true;
 
 		return 1;

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 21/33] drm/connector: Add pixel clock to cmdline mode
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (19 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 20/33] drm/modes: Fill drm_cmdline mode from named modes Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 22/33] drm/connector: Add a function to lookup a TV mode by its name Maxime Ripard
                   ` (13 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

We'll need to get the pixel clock to generate proper display modes for
all the current named modes. Let's add it to struct drm_cmdline_mode and
fill it when parsing the named mode.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 5d8b6a0d96f3..eb3c4e596c67 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2226,22 +2226,24 @@ static int drm_mode_parse_cmdline_options(const char *str,
 
 struct drm_named_mode {
 	const char *name;
+	unsigned int pixel_clock_khz;
 	unsigned int xres;
 	unsigned int yres;
 	unsigned int flags;
 };
 
-#define NAMED_MODE(_name, _x, _y, _flags)		\
+#define NAMED_MODE(_name, _pclk, _x, _y, _flags)	\
 	{						\
 		.name = _name,				\
+		.pixel_clock_khz = _pclk,		\
 		.xres = _x,				\
 		.yres = _y,				\
 		.flags = _flags,			\
 	}
 
 static const struct drm_named_mode drm_named_modes[] = {
-	NAMED_MODE("NTSC", 720, 480, DRM_MODE_FLAG_INTERLACE),
-	NAMED_MODE("PAL", 720, 576, DRM_MODE_FLAG_INTERLACE),
+	NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE),
+	NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2286,6 +2288,7 @@ static int drm_mode_parse_cmdline_named_mode(const char *name,
 			continue;
 
 		strcpy(cmdline_mode->name, mode->name);
+		cmdline_mode->pixel_clock = mode->pixel_clock_khz;
 		cmdline_mode->xres = mode->xres;
 		cmdline_mode->yres = mode->yres;
 		cmdline_mode->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index fffacbfd0a45..80e19efb3f42 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1279,6 +1279,13 @@ struct drm_cmdline_mode {
 	 */
 	bool bpp_specified;
 
+	/**
+	 * @pixel_clock:
+	 *
+	 * Pixel Clock in kHz. Optional.
+	 */
+	unsigned int pixel_clock;
+
 	/**
 	 * @xres:
 	 *

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 22/33] drm/connector: Add a function to lookup a TV mode by its name
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (20 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 21/33] drm/connector: Add pixel clock to cmdline mode Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 23/33] drm/modes: Introduce the tv_mode property as a command-line option Maxime Ripard
                   ` (12 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

As part of the command line parsing rework coming in the next patches,
we'll need to lookup drm_connector_tv_mode values by their name, already
defined in drm_tv_mode_enum_list.

In order to avoid any code duplication, let's do a function that will
perform a lookup of a TV mode name and return its value.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index e7aa8de08f5b..7acf294aba5f 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -992,6 +992,30 @@ static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = {
 };
 DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list)
 
+/**
+ * drm_get_tv_mode_from_name - Translates a TV mode name into its enum value
+ * @name: TV Mode name we want to convert
+ * @len: Length of @name
+ *
+ * Translates @name into an enum drm_connector_tv_mode.
+ *
+ * Returns: the enum value on success, a negative errno otherwise.
+ */
+int drm_get_tv_mode_from_name(const char *name, size_t len)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(drm_tv_mode_enum_list); i++) {
+		const struct drm_prop_enum_list *item = &drm_tv_mode_enum_list[i];
+
+		if (strlen(item->name) == len && !strncmp(item->name, name, len))
+			return item->type;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(drm_get_tv_mode_from_name);
+
 static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
 	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
 	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 80e19efb3f42..0dcd08e036b6 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1870,6 +1870,8 @@ const char *drm_get_dp_subconnector_name(int val);
 const char *drm_get_content_protection_name(int val);
 const char *drm_get_hdcp_content_type_name(int val);
 
+int drm_get_tv_mode_from_name(const char *name, size_t len);
+
 int drm_mode_create_dvi_i_properties(struct drm_device *dev);
 void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector);
 

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 23/33] drm/modes: Introduce the tv_mode property as a command-line option
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (21 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 22/33] drm/connector: Add a function to lookup a TV mode by its name Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 24/33] drm/modes: Properly generate a drm_display_mode from a named mode Maxime Ripard
                   ` (11 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

Our new tv mode option allows to specify the TV mode from a property.
However, it can still be useful, for example to avoid any boot time
artifact, to set that property directly from the kernel command line.

Let's add some code to allow it, and some unit tests to exercise that code.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index eb3c4e596c67..23e665fd808e 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2133,6 +2133,29 @@ static int drm_mode_parse_panel_orientation(const char *delim,
 	return 0;
 }
 
+static int drm_mode_parse_tv_mode(const char *delim,
+				  struct drm_cmdline_mode *mode)
+{
+	const char *value;
+	int ret;
+
+	if (*delim != '=')
+		return -EINVAL;
+
+	value = delim + 1;
+	delim = strchr(value, ',');
+	if (!delim)
+		delim = value + strlen(value);
+
+	ret = drm_get_tv_mode_from_name(value, delim - value);
+	if (ret < 0)
+		return ret;
+
+	mode->tv_mode = ret;
+
+	return 0;
+}
+
 static int drm_mode_parse_cmdline_options(const char *str,
 					  bool freestanding,
 					  const struct drm_connector *connector,
@@ -2202,6 +2225,9 @@ static int drm_mode_parse_cmdline_options(const char *str,
 		} else if (!strncmp(option, "panel_orientation", delim - option)) {
 			if (drm_mode_parse_panel_orientation(delim, mode))
 				return -EINVAL;
+		} else if (!strncmp(option, "tv_mode", delim - option)) {
+			if (drm_mode_parse_tv_mode(delim, mode))
+				return -EINVAL;
 		} else {
 			return -EINVAL;
 		}
@@ -2230,20 +2256,22 @@ struct drm_named_mode {
 	unsigned int xres;
 	unsigned int yres;
 	unsigned int flags;
+	unsigned int tv_mode;
 };
 
-#define NAMED_MODE(_name, _pclk, _x, _y, _flags)	\
+#define NAMED_MODE(_name, _pclk, _x, _y, _flags, _mode)	\
 	{						\
 		.name = _name,				\
 		.pixel_clock_khz = _pclk,		\
 		.xres = _x,				\
 		.yres = _y,				\
 		.flags = _flags,			\
+		.tv_mode = _mode,			\
 	}
 
 static const struct drm_named_mode drm_named_modes[] = {
-	NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE),
-	NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE),
+	NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC),
+	NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
@@ -2292,6 +2320,7 @@ static int drm_mode_parse_cmdline_named_mode(const char *name,
 		cmdline_mode->xres = mode->xres;
 		cmdline_mode->yres = mode->yres;
 		cmdline_mode->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+		cmdline_mode->tv_mode = mode->tv_mode;
 		cmdline_mode->specified = true;
 
 		return 1;
diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
index 09b806e27506..019ff5aa4f8d 100644
--- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
+++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
@@ -927,6 +927,14 @@ static const struct drm_cmdline_invalid_test drm_cmdline_invalid_tests[] = {
 		.name = "invalid_option",
 		.cmdline = "720x480,test=42",
 	},
+	{
+		.name = "invalid_tv_option",
+		.cmdline = "720x480i,tv_mode=invalid",
+	},
+	{
+		.name = "truncated_tv_option",
+		.cmdline = "720x480i,tv_mode=NTS",
+	},
 };
 
 static void drm_cmdline_invalid_desc(const struct drm_cmdline_invalid_test *t,
@@ -937,6 +945,64 @@ static void drm_cmdline_invalid_desc(const struct drm_cmdline_invalid_test *t,
 
 KUNIT_ARRAY_PARAM(drm_cmdline_invalid, drm_cmdline_invalid_tests, drm_cmdline_invalid_desc);
 
+struct drm_cmdline_tv_option_test {
+	const char *name;
+	const char *cmdline;
+	struct drm_display_mode *(*mode_fn)(struct drm_device *dev);
+	enum drm_connector_tv_mode tv_mode;
+};
+
+static void drm_cmdline_test_tv_options(struct kunit *test)
+{
+	const struct drm_cmdline_tv_option_test *params = test->param_value;
+	const struct drm_display_mode *expected_mode = params->mode_fn(NULL);
+	struct drm_cmdline_mode mode = { };
+
+	KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(params->cmdline,
+									  &no_connector, &mode));
+	KUNIT_EXPECT_TRUE(test, mode.specified);
+	KUNIT_EXPECT_EQ(test, mode.xres, expected_mode->hdisplay);
+	KUNIT_EXPECT_EQ(test, mode.yres, expected_mode->vdisplay);
+	KUNIT_EXPECT_EQ(test, mode.tv_mode, params->tv_mode);
+
+	KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+	KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+	KUNIT_EXPECT_FALSE(test, mode.rb);
+	KUNIT_EXPECT_FALSE(test, mode.cvt);
+	KUNIT_EXPECT_EQ(test, mode.interlace, !!(expected_mode->flags & DRM_MODE_FLAG_INTERLACE));
+	KUNIT_EXPECT_FALSE(test, mode.margins);
+	KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+#define TV_OPT_TEST(_opt, _cmdline, _mode_fn)		\
+	{						\
+		.name = #_opt,				\
+		.cmdline = _cmdline,			\
+		.mode_fn = _mode_fn,			\
+		.tv_mode = DRM_MODE_TV_MODE_ ## _opt,	\
+	}
+
+static const struct drm_cmdline_tv_option_test drm_cmdline_tv_option_tests[] = {
+	TV_OPT_TEST(NTSC, "720x480i,tv_mode=NTSC", drm_mode_analog_ntsc_480i),
+	TV_OPT_TEST(NTSC_443, "720x480i,tv_mode=NTSC-443", drm_mode_analog_ntsc_480i),
+	TV_OPT_TEST(NTSC_J, "720x480i,tv_mode=NTSC-J", drm_mode_analog_ntsc_480i),
+	TV_OPT_TEST(PAL, "720x576i,tv_mode=PAL", drm_mode_analog_pal_576i),
+	TV_OPT_TEST(PAL_M, "720x480i,tv_mode=PAL-M", drm_mode_analog_ntsc_480i),
+	TV_OPT_TEST(PAL_N, "720x576i,tv_mode=PAL-N", drm_mode_analog_pal_576i),
+	TV_OPT_TEST(SECAM, "720x576i,tv_mode=SECAM", drm_mode_analog_pal_576i),
+};
+
+static void drm_cmdline_tv_option_desc(const struct drm_cmdline_tv_option_test *t,
+				       char *desc)
+{
+	sprintf(desc, "%s", t->name);
+}
+KUNIT_ARRAY_PARAM(drm_cmdline_tv_option,
+		  drm_cmdline_tv_option_tests,
+		  drm_cmdline_tv_option_desc);
+
 static struct kunit_case drm_cmdline_parser_tests[] = {
 	KUNIT_CASE(drm_cmdline_test_force_d_only),
 	KUNIT_CASE(drm_cmdline_test_force_D_only_dvi),
@@ -977,6 +1043,7 @@ static struct kunit_case drm_cmdline_parser_tests[] = {
 	KUNIT_CASE(drm_cmdline_test_freestanding_force_e_and_options),
 	KUNIT_CASE(drm_cmdline_test_panel_orientation),
 	KUNIT_CASE_PARAM(drm_cmdline_test_invalid, drm_cmdline_invalid_gen_params),
+	KUNIT_CASE_PARAM(drm_cmdline_test_tv_options, drm_cmdline_tv_option_gen_params),
 	{}
 };
 
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 0dcd08e036b6..a8f7b2fdde87 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1374,6 +1374,11 @@ struct drm_cmdline_mode {
 	 * @tv_margins: TV margins to apply to the mode.
 	 */
 	struct drm_connector_tv_margins tv_margins;
+
+	/**
+	 * @tv_mode: TV mode standard. See DRM_MODE_TV_MODE_*.
+	 */
+	enum drm_connector_tv_mode tv_mode;
 };
 
 /**

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 24/33] drm/modes: Properly generate a drm_display_mode from a named mode
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (22 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 23/33] drm/modes: Introduce the tv_mode property as a command-line option Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 25/33] drm/modes: Introduce more named modes Maxime Ripard
                   ` (10 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The framework will get the drm_display_mode from the drm_cmdline_mode it
got by parsing the video command line argument by calling
drm_connector_pick_cmdline_mode().

The heavy lifting will then be done by the drm_mode_create_from_cmdline_mode()
function.

In the case of the named modes though, there's no real code to make that
translation and we rely on the drivers to guess which actual display mode
we meant.

Let's modify drm_mode_create_from_cmdline_mode() to properly generate the
drm_display_mode we mean when passing a named mode.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 23e665fd808e..1ca1f82dfd12 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2500,6 +2500,36 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
 }
 EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
 
+static struct drm_display_mode *drm_named_mode(struct drm_device *dev,
+					       struct drm_cmdline_mode *cmd)
+{
+	struct drm_display_mode *mode;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
+		const struct drm_named_mode *named_mode = &drm_named_modes[i];
+
+		if (strcmp(cmd->name, named_mode->name))
+			continue;
+
+		if (!named_mode->tv_mode)
+			continue;
+
+		mode = drm_analog_tv_mode(dev,
+					  named_mode->tv_mode,
+					  named_mode->pixel_clock_khz * 1000,
+					  named_mode->xres,
+					  named_mode->yres,
+					  named_mode->flags & DRM_MODE_FLAG_INTERLACE);
+		if (!mode)
+			return NULL;
+
+		return mode;
+	}
+
+	return NULL;
+}
+
 /**
  * drm_mode_create_from_cmdline_mode - convert a command line modeline into a DRM display mode
  * @dev: DRM device to create the new mode for
@@ -2517,7 +2547,9 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
 	if (cmd->xres == 0 || cmd->yres == 0)
 		return NULL;
 
-	if (cmd->cvt)
+	if (strlen(cmd->name))
+		mode = drm_named_mode(dev, cmd);
+	else if (cmd->cvt)
 		mode = drm_cvt_mode(dev,
 				    cmd->xres, cmd->yres,
 				    cmd->refresh_specified ? cmd->refresh : 60,
diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c
index 46335de7bc6b..4380cf670fb4 100644
--- a/drivers/gpu/drm/tests/drm_client_modeset_test.c
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -26,6 +26,20 @@ static int drm_client_modeset_connector_get_modes(struct drm_connector *connecto
 
 	count = drm_add_modes_noedid(connector, 1920, 1200);
 
+	mode = drm_mode_analog_ntsc_480i(connector->dev);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_probed_add(connector, mode);
+	count += 1;
+
+	mode = drm_mode_analog_pal_576i(connector->dev);
+	if (!mode)
+		return -ENOMEM;
+
+	drm_mode_probed_add(connector, mode);
+	count += 1;
+
 	return count;
 }
 
@@ -58,6 +72,9 @@ static int drm_client_modeset_test_init(struct kunit *test)
 		return ret;
 	drm_connector_helper_add(&priv->connector, &drm_client_modeset_connector_helper_funcs);
 
+	priv->connector.interlace_allowed = true;
+	priv->connector.doublescan_allowed = true;
+
 	return 0;
 }
 
@@ -97,8 +114,62 @@ static void drm_pick_cmdline_res_1920_1080_60(struct kunit *test)
 	KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
 }
 
+static void drm_pick_cmdline_named_ntsc(struct kunit *test)
+{
+	struct drm_client_modeset_test_priv *priv = test->priv;
+	struct drm_device *drm = priv->drm;
+	struct drm_connector *connector = &priv->connector;
+	struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+	struct drm_display_mode *mode;
+	const char *cmdline = "NTSC";
+	int ret;
+
+	KUNIT_ASSERT_TRUE(test,
+			  drm_mode_parse_command_line_for_connector(cmdline,
+								    connector,
+								    cmdline_mode));
+
+	mutex_lock(&drm->mode_config.mutex);
+	ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+	mutex_unlock(&drm->mode_config.mutex);
+	KUNIT_ASSERT_GT(test, ret, 0);
+
+	mode = drm_connector_pick_cmdline_mode(connector);
+	KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+	KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), mode));
+}
+
+static void drm_pick_cmdline_named_pal(struct kunit *test)
+{
+	struct drm_client_modeset_test_priv *priv = test->priv;
+	struct drm_device *drm = priv->drm;
+	struct drm_connector *connector = &priv->connector;
+	struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+	struct drm_display_mode *mode;
+	const char *cmdline = "PAL";
+	int ret;
+
+	KUNIT_ASSERT_TRUE(test,
+			  drm_mode_parse_command_line_for_connector(cmdline,
+								    connector,
+								    cmdline_mode));
+
+	mutex_lock(&drm->mode_config.mutex);
+	ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+	mutex_unlock(&drm->mode_config.mutex);
+	KUNIT_ASSERT_GT(test, ret, 0);
+
+	mode = drm_connector_pick_cmdline_mode(connector);
+	KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+	KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_pal_576i(drm), mode));
+}
+
 static struct kunit_case drm_pick_cmdline_tests[] = {
 	KUNIT_CASE(drm_pick_cmdline_res_1920_1080_60),
+	KUNIT_CASE(drm_pick_cmdline_named_ntsc),
+	KUNIT_CASE(drm_pick_cmdline_named_pal),
 	{}
 };
 

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 25/33] drm/modes: Introduce more named modes
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (23 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 24/33] drm/modes: Properly generate a drm_display_mode from a named mode Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 26/33] drm/atomic-helper: Add a TV properties reset helper Maxime Ripard
                   ` (9 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

Now that we can easily extend the named modes list, let's add a few more
analog TV modes that were used in the wild, and some unit tests to make
sure it works as intended.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 1ca1f82dfd12..6f315385bd02 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2271,7 +2271,9 @@ struct drm_named_mode {
 
 static const struct drm_named_mode drm_named_modes[] = {
 	NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC),
+	NAMED_MODE("NTSC-J", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC_J),
 	NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL),
+	NAMED_MODE("PAL-M", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL_M),
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c
index 4380cf670fb4..521505753af9 100644
--- a/drivers/gpu/drm/tests/drm_client_modeset_test.c
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -140,6 +140,32 @@ static void drm_pick_cmdline_named_ntsc(struct kunit *test)
 	KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), mode));
 }
 
+static void drm_pick_cmdline_named_ntsc_j(struct kunit *test)
+{
+	struct drm_client_modeset_test_priv *priv = test->priv;
+	struct drm_device *drm = priv->drm;
+	struct drm_connector *connector = &priv->connector;
+	struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+	struct drm_display_mode *mode;
+	const char *cmdline = "NTSC-J";
+	int ret;
+
+	KUNIT_ASSERT_TRUE(test,
+			  drm_mode_parse_command_line_for_connector(cmdline,
+								    connector,
+								    cmdline_mode));
+
+	mutex_lock(&drm->mode_config.mutex);
+	ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+	mutex_unlock(&drm->mode_config.mutex);
+	KUNIT_ASSERT_GT(test, ret, 0);
+
+	mode = drm_connector_pick_cmdline_mode(connector);
+	KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+	KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), mode));
+}
+
 static void drm_pick_cmdline_named_pal(struct kunit *test)
 {
 	struct drm_client_modeset_test_priv *priv = test->priv;
@@ -166,10 +192,38 @@ static void drm_pick_cmdline_named_pal(struct kunit *test)
 	KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_pal_576i(drm), mode));
 }
 
+static void drm_pick_cmdline_named_pal_m(struct kunit *test)
+{
+	struct drm_client_modeset_test_priv *priv = test->priv;
+	struct drm_device *drm = priv->drm;
+	struct drm_connector *connector = &priv->connector;
+	struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+	struct drm_display_mode *mode;
+	const char *cmdline = "PAL-M";
+	int ret;
+
+	KUNIT_ASSERT_TRUE(test,
+			  drm_mode_parse_command_line_for_connector(cmdline,
+								    connector,
+								    cmdline_mode));
+
+	mutex_lock(&drm->mode_config.mutex);
+	ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+	mutex_unlock(&drm->mode_config.mutex);
+	KUNIT_ASSERT_GT(test, ret, 0);
+
+	mode = drm_connector_pick_cmdline_mode(connector);
+	KUNIT_ASSERT_PTR_NE(test, mode, NULL);
+
+	KUNIT_EXPECT_TRUE(test, drm_mode_equal(drm_mode_analog_ntsc_480i(drm), mode));
+}
+
 static struct kunit_case drm_pick_cmdline_tests[] = {
 	KUNIT_CASE(drm_pick_cmdline_res_1920_1080_60),
 	KUNIT_CASE(drm_pick_cmdline_named_ntsc),
+	KUNIT_CASE(drm_pick_cmdline_named_ntsc_j),
 	KUNIT_CASE(drm_pick_cmdline_named_pal),
+	KUNIT_CASE(drm_pick_cmdline_named_pal_m),
 	{}
 };
 

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 26/33] drm/atomic-helper: Add a TV properties reset helper
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (24 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 25/33] drm/modes: Introduce more named modes Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 27/33] drm/atomic-helper: Add an analog TV atomic_check implementation Maxime Ripard
                   ` (8 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The drm_tv_create_properties() function will create a bunch of properties,
but it's up to each and every driver using that function to properly reset
the state of these properties leading to inconsistent behaviours.

Let's create a helper that will take care of it.

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index dfb57217253b..0373c3dc824b 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -481,6 +481,81 @@ void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connecto
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
 
+/**
+ * drm_atomic_helper_connector_tv_reset - Resets Analog TV connector properties
+ * @connector: DRM connector
+ *
+ * Resets the analog TV properties attached to a connector
+ */
+void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
+	struct drm_connector_state *state = connector->state;
+	struct drm_property *prop;
+	uint64_t val;
+
+	prop = dev->mode_config.tv_mode_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.mode = val;
+
+	if (cmdline->tv_mode)
+		state->tv.mode = cmdline->tv_mode;
+
+	prop = dev->mode_config.tv_select_subconnector_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.select_subconnector = val;
+
+	prop = dev->mode_config.tv_subconnector_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.subconnector = val;
+
+	prop = dev->mode_config.tv_brightness_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.brightness = val;
+
+	prop = dev->mode_config.tv_contrast_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.contrast = val;
+
+	prop = dev->mode_config.tv_flicker_reduction_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.flicker_reduction = val;
+
+	prop = dev->mode_config.tv_overscan_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.overscan = val;
+
+	prop = dev->mode_config.tv_saturation_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.saturation = val;
+
+	prop = dev->mode_config.tv_hue_property;
+	if (prop)
+		if (!drm_object_property_get_default_value(&connector->base,
+							   prop, &val))
+			state->tv.hue = val;
+
+	drm_atomic_helper_connector_tv_margins_reset(connector);
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
+
 /**
  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
  * @connector: connector object
diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h
index 192766656b88..c8fbce795ee7 100644
--- a/include/drm/drm_atomic_state_helper.h
+++ b/include/drm/drm_atomic_state_helper.h
@@ -70,6 +70,7 @@ void __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_
 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_tv_margins_reset(struct drm_connector *connector);
 void
 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 27/33] drm/atomic-helper: Add an analog TV atomic_check implementation
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (25 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 26/33] drm/atomic-helper: Add a TV properties reset helper Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-24 15:58   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 28/33] drm/vc4: vec: Fix definition of PAL-M mode Maxime Ripard
                   ` (7 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The analog TV connector drivers share some atomic_check logic, and the new
TV standard property have created a bunch of new constraints that needs to
be shared across drivers too.

Let's create an atomic_check helper for those use cases.

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 0373c3dc824b..e88c57a4f7be 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -556,6 +556,55 @@ void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
 
+/**
+ * @drm_atomic_helper_connector_tv_check: Validate an analog TV connector state
+ * @connector: DRM Connector
+ * @state: the DRM State object
+ *
+ * Checks the state object to see if the requested state is valid for an
+ * analog TV connector.
+ *
+ * Returns:
+ * Zero for success, a negative error code on error.
+ */
+int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
+					 struct drm_atomic_state *state)
+{
+	struct drm_connector_state *old_conn_state =
+		drm_atomic_get_old_connector_state(state, connector);
+	struct drm_connector_state *new_conn_state =
+		drm_atomic_get_new_connector_state(state, connector);
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+
+	crtc = new_conn_state->crtc;
+	if (!crtc)
+		return 0;
+
+	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+	if (!crtc_state)
+		return -EINVAL;
+
+	if (old_conn_state->tv.mode != new_conn_state->tv.mode)
+		crtc_state->mode_changed = true;
+
+	if ((old_conn_state->tv.margins.left != new_conn_state->tv.margins.left) ||
+	    (old_conn_state->tv.margins.right != new_conn_state->tv.margins.right) ||
+	    (old_conn_state->tv.margins.top != new_conn_state->tv.margins.top) ||
+	    (old_conn_state->tv.margins.bottom != new_conn_state->tv.margins.bottom) ||
+	    (old_conn_state->tv.mode != new_conn_state->tv.mode) ||
+	    (old_conn_state->tv.brightness != new_conn_state->tv.brightness) ||
+	    (old_conn_state->tv.contrast != new_conn_state->tv.contrast) ||
+	    (old_conn_state->tv.flicker_reduction != new_conn_state->tv.flicker_reduction) ||
+	    (old_conn_state->tv.overscan != new_conn_state->tv.overscan) ||
+	    (old_conn_state->tv.saturation != new_conn_state->tv.saturation) ||
+	    (old_conn_state->tv.hue != new_conn_state->tv.hue))
+		crtc_state->connectors_changed = true;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check);
+
 /**
  * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
  * @connector: connector object
diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h
index c8fbce795ee7..b9740edb2658 100644
--- a/include/drm/drm_atomic_state_helper.h
+++ b/include/drm/drm_atomic_state_helper.h
@@ -26,6 +26,7 @@
 
 #include <linux/types.h>
 
+struct drm_atomic_state;
 struct drm_bridge;
 struct drm_bridge_state;
 struct drm_crtc;
@@ -71,6 +72,8 @@ 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);
+int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
+					 struct drm_atomic_state *state);
 void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector);
 void
 __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 28/33] drm/vc4: vec: Fix definition of PAL-M mode
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (26 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 27/33] drm/atomic-helper: Add an analog TV atomic_check implementation Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-24 15:59   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 29/33] drm/vc4: vec: Use TV Reset implementation Maxime Ripard
                   ` (6 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>

PAL-M is a Brazilian analog TV standard that uses a PAL-style chroma
subcarrier at 3.575611[888111] MHz on top of 525-line (480i60) timings.
This commit makes the driver actually use the proper VEC preset for this
mode instead of just changing PAL subcarrier frequency.

Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index f31fef938f11..5ec3a12359b1 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -69,6 +69,7 @@
 #define VEC_CONFIG0_STD_MASK		GENMASK(1, 0)
 #define VEC_CONFIG0_NTSC_STD		0
 #define VEC_CONFIG0_PAL_BDGHI_STD	1
+#define VEC_CONFIG0_PAL_M_STD		2
 #define VEC_CONFIG0_PAL_N_STD		3
 
 #define VEC_SCHPH			0x108
@@ -255,10 +256,9 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
 		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
 	},
 	[VC4_VEC_TV_MODE_PAL_M] = {
-		.mode = &pal_mode,
-		.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
-		.config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
-		.custom_freq = 0x223b61d1,
+		.mode = &ntsc_mode,
+		.config0 = VEC_CONFIG0_PAL_M_STD,
+		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
 	},
 };
 

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 29/33] drm/vc4: vec: Use TV Reset implementation
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (27 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 28/33] drm/vc4: vec: Fix definition of PAL-M mode Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 30/33] drm/vc4: vec: Check for VEC output constraints Maxime Ripard
                   ` (5 subsequent siblings)
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

The analog TV properties created by the drm_mode_create_tv_properties() are
not properly initialised at reset. Let's switch our implementation to call
drm_atomic_helper_connector_tv_reset().

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 5ec3a12359b1..baa29067a1ff 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -268,6 +268,12 @@ vc4_vec_connector_detect(struct drm_connector *connector, bool force)
 	return connector_status_unknown;
 }
 
+static void vc4_vec_connector_reset(struct drm_connector *connector)
+{
+	drm_atomic_helper_connector_reset(connector);
+	drm_atomic_helper_connector_tv_reset(connector);
+}
+
 static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 {
 	struct drm_connector_state *state = connector->state;
@@ -288,7 +294,7 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 static const struct drm_connector_funcs vc4_vec_connector_funcs = {
 	.detect = vc4_vec_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.reset = drm_atomic_helper_connector_reset,
+	.reset = vc4_vec_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 30/33] drm/vc4: vec: Check for VEC output constraints
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (28 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 29/33] drm/vc4: vec: Use TV Reset implementation Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-24 16:00   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 31/33] drm/vc4: vec: Convert to the new TV mode property Maxime Ripard
                   ` (4 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>

The VEC can accept pretty much any relatively reasonable mode, but still
has a bunch of constraints to meet.

Let's create an atomic_check() implementation that will make sure we
don't end up accepting a non-functional mode.

Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index baa29067a1ff..6828b79a1001 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -453,6 +453,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
 					struct drm_crtc_state *crtc_state,
 					struct drm_connector_state *conn_state)
 {
+	const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
 	const struct vc4_vec_tv_mode *vec_mode;
 
 	vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode];
@@ -461,6 +462,53 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
 	    !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
 		return -EINVAL;
 
+	if (mode->crtc_hdisplay % 4)
+		return -EINVAL;
+
+	if (!(mode->crtc_hsync_end - mode->crtc_hsync_start))
+		return -EINVAL;
+
+	switch (mode->vtotal) {
+	case 525:
+		if (mode->crtc_vtotal > 262)
+			return -EINVAL;
+
+		if (mode->crtc_vdisplay < 1 || mode->crtc_vdisplay > 253)
+			return -EINVAL;
+
+		if (!(mode->crtc_vsync_start - mode->crtc_vdisplay))
+			return -EINVAL;
+
+		if ((mode->crtc_vsync_end - mode->crtc_vsync_start) != 3)
+			return -EINVAL;
+
+		if ((mode->crtc_vtotal - mode->crtc_vsync_end) < 4)
+			return -EINVAL;
+
+		break;
+
+	case 625:
+		if (mode->crtc_vtotal > 312)
+			return -EINVAL;
+
+		if (mode->crtc_vdisplay < 1 || mode->crtc_vdisplay > 305)
+			return -EINVAL;
+
+		if (!(mode->crtc_vsync_start - mode->crtc_vdisplay))
+			return -EINVAL;
+
+		if ((mode->crtc_vsync_end - mode->crtc_vsync_start) != 3)
+			return -EINVAL;
+
+		if ((mode->crtc_vtotal - mode->crtc_vsync_end) < 2)
+			return -EINVAL;
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
 	return 0;
 }
 

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 31/33] drm/vc4: vec: Convert to the new TV mode property
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (29 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 30/33] drm/vc4: vec: Check for VEC output constraints Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-24 17:09   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 32/33] drm/vc4: vec: Add support for more analog TV standards Maxime Ripard
                   ` (3 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

Now that the core can deal fine with analog TV modes, let's convert the vc4
VEC driver to leverage those new features.

We've added some backward compatibility to support the old TV mode property
and translate it into the new TV norm property.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 6828b79a1001..a9463364015b 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -172,6 +172,8 @@ struct vc4_vec {
 
 	struct clk *clock;
 
+	struct drm_property *legacy_tv_mode_property;
+
 	struct debugfs_regset32 regset;
 };
 
@@ -184,6 +186,12 @@ encoder_to_vc4_vec(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_vec, encoder.base);
 }
 
+static inline struct vc4_vec *
+connector_to_vc4_vec(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_vec, connector);
+}
+
 enum vc4_vec_tv_mode_id {
 	VC4_VEC_TV_MODE_NTSC,
 	VC4_VEC_TV_MODE_NTSC_J,
@@ -192,7 +200,7 @@ enum vc4_vec_tv_mode_id {
 };
 
 struct vc4_vec_tv_mode {
-	const struct drm_display_mode *mode;
+	unsigned int mode;
 	u32 config0;
 	u32 config1;
 	u32 custom_freq;
@@ -225,43 +233,51 @@ static const struct debugfs_reg32 vec_regs[] = {
 	VC4_REG32(VEC_DAC_MISC),
 };
 
-static const struct drm_display_mode ntsc_mode = {
-	DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
-		 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
-		 480, 480 + 7, 480 + 7 + 6, 525, 0,
-		 DRM_MODE_FLAG_INTERLACE)
-};
-
-static const struct drm_display_mode pal_mode = {
-	DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
-		 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
-		 576, 576 + 4, 576 + 4 + 6, 625, 0,
-		 DRM_MODE_FLAG_INTERLACE)
-};
-
 static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
-	[VC4_VEC_TV_MODE_NTSC] = {
-		.mode = &ntsc_mode,
+	{
+		.mode = DRM_MODE_TV_MODE_NTSC,
 		.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
 		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
 	},
-	[VC4_VEC_TV_MODE_NTSC_J] = {
-		.mode = &ntsc_mode,
+	{
+		.mode = DRM_MODE_TV_MODE_NTSC_J,
 		.config0 = VEC_CONFIG0_NTSC_STD,
 		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
 	},
-	[VC4_VEC_TV_MODE_PAL] = {
-		.mode = &pal_mode,
+	{
+		.mode = DRM_MODE_TV_MODE_PAL,
 		.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
 		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
 	},
-	[VC4_VEC_TV_MODE_PAL_M] = {
-		.mode = &ntsc_mode,
+	{
+		.mode = DRM_MODE_TV_MODE_PAL_M,
 		.config0 = VEC_CONFIG0_PAL_M_STD,
 		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
 	},
 };
 
+static inline const struct vc4_vec_tv_mode *
+vc4_vec_tv_mode_lookup(unsigned int mode)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(vc4_vec_tv_modes); i++) {
+		const struct vc4_vec_tv_mode *tv_mode = &vc4_vec_tv_modes[i];
+
+		if (tv_mode->mode == mode)
+			return tv_mode;
+	}
+
+	return NULL;
+}
+
+static const struct drm_prop_enum_list tv_mode_names[] = {
+	{ VC4_VEC_TV_MODE_NTSC, "NTSC", },
+	{ VC4_VEC_TV_MODE_NTSC_J, "NTSC-J", },
+	{ VC4_VEC_TV_MODE_PAL, "PAL", },
+	{ VC4_VEC_TV_MODE_PAL_M, "PAL-M", },
+};
+
 static enum drm_connector_status
 vc4_vec_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -276,19 +292,99 @@ static void vc4_vec_connector_reset(struct drm_connector *connector)
 
 static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 {
-	struct drm_connector_state *state = connector->state;
 	struct drm_display_mode *mode;
+	int count = 0;
 
-	mode = drm_mode_duplicate(connector->dev,
-				  vc4_vec_tv_modes[state->tv.legacy_mode].mode);
+	mode = drm_mode_analog_ntsc_480i(connector->dev);
 	if (!mode) {
 		DRM_ERROR("Failed to create a new display mode\n");
 		return -ENOMEM;
 	}
 
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
 	drm_mode_probed_add(connector, mode);
+	count += 1;
 
-	return 1;
+	mode = drm_mode_analog_pal_576i(connector->dev);
+	if (!mode) {
+		DRM_ERROR("Failed to create a new display mode\n");
+		return -ENOMEM;
+	}
+
+	drm_mode_probed_add(connector, mode);
+	count += 1;
+
+	return count;
+}
+
+static int
+vc4_vec_connector_set_property(struct drm_connector *connector,
+			       struct drm_connector_state *state,
+			       struct drm_property *property,
+			       uint64_t val)
+{
+	struct vc4_vec *vec = connector_to_vc4_vec(connector);
+
+	if (property != vec->legacy_tv_mode_property)
+		return -EINVAL;
+
+	switch (val) {
+	case VC4_VEC_TV_MODE_NTSC:
+		state->tv.mode = DRM_MODE_TV_MODE_NTSC;
+		break;
+
+	case VC4_VEC_TV_MODE_NTSC_J:
+		state->tv.mode = DRM_MODE_TV_MODE_NTSC_J;
+		break;
+
+	case VC4_VEC_TV_MODE_PAL:
+		state->tv.mode = DRM_MODE_TV_MODE_PAL;
+		break;
+
+	case VC4_VEC_TV_MODE_PAL_M:
+		state->tv.mode = DRM_MODE_TV_MODE_PAL_M;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+vc4_vec_connector_get_property(struct drm_connector *connector,
+			       const struct drm_connector_state *state,
+			       struct drm_property *property,
+			       uint64_t *val)
+{
+	struct vc4_vec *vec = connector_to_vc4_vec(connector);
+
+	if (property != vec->legacy_tv_mode_property)
+		return -EINVAL;
+
+	switch (state->tv.mode) {
+	case DRM_MODE_TV_MODE_NTSC:
+		*val = VC4_VEC_TV_MODE_NTSC;
+		break;
+
+	case DRM_MODE_TV_MODE_NTSC_J:
+		*val = VC4_VEC_TV_MODE_NTSC_J;
+		break;
+
+	case DRM_MODE_TV_MODE_PAL:
+		*val = VC4_VEC_TV_MODE_PAL;
+		break;
+
+	case DRM_MODE_TV_MODE_PAL_M:
+		*val = VC4_VEC_TV_MODE_PAL_M;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static const struct drm_connector_funcs vc4_vec_connector_funcs = {
@@ -297,15 +393,19 @@ static const struct drm_connector_funcs vc4_vec_connector_funcs = {
 	.reset = vc4_vec_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+	.atomic_get_property = vc4_vec_connector_get_property,
+	.atomic_set_property = vc4_vec_connector_set_property,
 };
 
 static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = {
+	.atomic_check = drm_atomic_helper_connector_tv_check,
 	.get_modes = vc4_vec_connector_get_modes,
 };
 
 static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
 {
 	struct drm_connector *connector = &vec->connector;
+	struct drm_property *prop;
 	int ret;
 
 	connector->interlace_allowed = true;
@@ -318,8 +418,16 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
 	drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
 
 	drm_object_attach_property(&connector->base,
-				   dev->mode_config.legacy_tv_mode_property,
-				   VC4_VEC_TV_MODE_NTSC);
+				   dev->mode_config.tv_mode_property,
+				   DRM_MODE_TV_MODE_NTSC);
+
+	prop = drm_property_create_enum(dev, 0, "mode",
+					tv_mode_names, ARRAY_SIZE(tv_mode_names));
+	if (!prop)
+		return -ENOMEM;
+	vec->legacy_tv_mode_property = prop;
+
+	drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC);
 
 	drm_connector_attach_encoder(connector, &vec->encoder.base);
 
@@ -366,13 +474,16 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
 	struct drm_connector *connector = &vec->connector;
 	struct drm_connector_state *conn_state =
 		drm_atomic_get_new_connector_state(state, connector);
-	const struct vc4_vec_tv_mode *tv_mode =
-		&vc4_vec_tv_modes[conn_state->tv.mode];
+	const struct vc4_vec_tv_mode *tv_mode;
 	int idx, ret;
 
 	if (!drm_dev_enter(drm, &idx))
 		return;
 
+	tv_mode = vc4_vec_tv_mode_lookup(conn_state->tv.mode);
+	if (!tv_mode)
+		goto err_dev_exit;
+
 	ret = pm_runtime_get_sync(&vec->pdev->dev);
 	if (ret < 0) {
 		DRM_ERROR("Failed to retain power domain: %d\n", ret);
@@ -454,13 +565,6 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
 					struct drm_connector_state *conn_state)
 {
 	const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
-	const struct vc4_vec_tv_mode *vec_mode;
-
-	vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode];
-
-	if (conn_state->crtc &&
-	    !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
-		return -EINVAL;
 
 	if (mode->crtc_hdisplay % 4)
 		return -EINVAL;
@@ -554,13 +658,6 @@ static const struct of_device_id vc4_vec_dt_match[] = {
 	{ /* sentinel */ },
 };
 
-static const char * const tv_mode_names[] = {
-	[VC4_VEC_TV_MODE_NTSC] = "NTSC",
-	[VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
-	[VC4_VEC_TV_MODE_PAL] = "PAL",
-	[VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
-};
-
 static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -568,9 +665,11 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
 	struct vc4_vec *vec;
 	int ret;
 
-	ret = drm_mode_create_tv_properties_legacy(drm,
-						   ARRAY_SIZE(tv_mode_names),
-						   tv_mode_names);
+	ret = drm_mode_create_tv_properties(drm,
+					    BIT(DRM_MODE_TV_MODE_NTSC) |
+					    BIT(DRM_MODE_TV_MODE_NTSC_J) |
+					    BIT(DRM_MODE_TV_MODE_PAL) |
+					    BIT(DRM_MODE_TV_MODE_PAL_M));
 	if (ret)
 		return ret;
 

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 32/33] drm/vc4: vec: Add support for more analog TV standards
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (30 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 31/33] drm/vc4: vec: Convert to the new TV mode property Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-24 17:12   ` Noralf Trønnes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 33/33] drm/sun4i: tv: Convert to the new TV mode property Maxime Ripard
                   ` (2 subsequent siblings)
  34 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>

Add support for the following composite output modes (all of them are
somewhat more obscure than the previously defined ones):

- NTSC_443 - NTSC-style signal with the chroma subcarrier shifted to
  4.43361875 MHz (the PAL subcarrier frequency). Never used for
  broadcasting, but sometimes used as a hack to play NTSC content in PAL
  regions (e.g. on VCRs).
- PAL_N - PAL with alternative chroma subcarrier frequency,
  3.58205625 MHz. Used as a broadcast standard in Argentina, Paraguay
  and Uruguay to fit 576i50 with colour in 6 MHz channel raster.
- PAL60 - 480i60 signal with PAL-style color at normal European PAL
  frequency. Another non-standard, non-broadcast mode, used in similar
  contexts as NTSC_443. Some displays support one but not the other.
- SECAM - French frequency-modulated analog color standard; also have
  been broadcast in Eastern Europe and various parts of Africa and Asia.
  Uses the same 576i50 timings as PAL.

Also added some comments explaining color subcarrier frequency
registers.

Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index a9463364015b..0862462aa9e3 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -46,6 +46,7 @@
 #define VEC_CONFIG0_YDEL(x)		((x) << 26)
 #define VEC_CONFIG0_CDEL_MASK		GENMASK(25, 24)
 #define VEC_CONFIG0_CDEL(x)		((x) << 24)
+#define VEC_CONFIG0_SECAM_STD		BIT(21)
 #define VEC_CONFIG0_PBPR_FIL		BIT(18)
 #define VEC_CONFIG0_CHROMA_GAIN_MASK	GENMASK(17, 16)
 #define VEC_CONFIG0_CHROMA_GAIN_UNITY	(0 << 16)
@@ -76,6 +77,27 @@
 #define VEC_SOFT_RESET			0x10c
 #define VEC_CLMP0_START			0x144
 #define VEC_CLMP0_END			0x148
+
+/*
+ * These set the color subcarrier frequency
+ * if VEC_CONFIG1_CUSTOM_FREQ is enabled.
+ *
+ * VEC_FREQ1_0 contains the most significant 16-bit half-word,
+ * VEC_FREQ3_2 contains the least significant 16-bit half-word.
+ * 0x80000000 seems to be equivalent to the pixel clock
+ * (which itself is the VEC clock divided by 8).
+ *
+ * Reference values (with the default pixel clock of 13.5 MHz):
+ *
+ * NTSC  (3579545.[45] Hz)     - 0x21F07C1F
+ * PAL   (4433618.75 Hz)       - 0x2A098ACB
+ * PAL-M (3575611.[888111] Hz) - 0x21E6EFE3
+ * PAL-N (3582056.25 Hz)       - 0x21F69446
+ *
+ * NOTE: For SECAM, it is used as the Dr center frequency,
+ * regardless of whether VEC_CONFIG1_CUSTOM_FREQ is enabled or not;
+ * that is specified as 4406250 Hz, which corresponds to 0x29C71C72.
+ */
 #define VEC_FREQ3_2			0x180
 #define VEC_FREQ1_0			0x184
 
@@ -118,6 +140,14 @@
 
 #define VEC_INTERRUPT_CONTROL		0x190
 #define VEC_INTERRUPT_STATUS		0x194
+
+/*
+ * Db center frequency for SECAM; the clock for this is the same as for
+ * VEC_FREQ3_2/VEC_FREQ1_0, which is used for Dr center frequency.
+ *
+ * This is specified as 4250000 Hz, which corresponds to 0x284BDA13.
+ * That is also the default value, so no need to set it explicitly.
+ */
 #define VEC_FCW_SECAM_B			0x198
 #define VEC_SECAM_GAIN_VAL		0x19c
 
@@ -197,6 +227,10 @@ enum vc4_vec_tv_mode_id {
 	VC4_VEC_TV_MODE_NTSC_J,
 	VC4_VEC_TV_MODE_PAL,
 	VC4_VEC_TV_MODE_PAL_M,
+	VC4_VEC_TV_MODE_NTSC_443,
+	VC4_VEC_TV_MODE_PAL_60,
+	VC4_VEC_TV_MODE_PAL_N,
+	VC4_VEC_TV_MODE_SECAM,
 };
 
 struct vc4_vec_tv_mode {
@@ -239,6 +273,12 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
 		.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
 		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
 	},
+	{
+		.mode = DRM_MODE_TV_MODE_NTSC_443,
+		.config0 = VEC_CONFIG0_NTSC_STD,
+		.config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
+		.custom_freq = 0x2a098acb,
+	},
 	{
 		.mode = DRM_MODE_TV_MODE_NTSC_J,
 		.config0 = VEC_CONFIG0_NTSC_STD,
@@ -254,6 +294,17 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
 		.config0 = VEC_CONFIG0_PAL_M_STD,
 		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
 	},
+	{
+		.mode = DRM_MODE_TV_MODE_PAL_N,
+		.config0 = VEC_CONFIG0_PAL_N_STD,
+		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
+	},
+	{
+		.mode = DRM_MODE_TV_MODE_SECAM,
+		.config0 = VEC_CONFIG0_SECAM_STD,
+		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
+		.custom_freq = 0x29c71c72,
+	},
 };
 
 static inline const struct vc4_vec_tv_mode *
@@ -273,9 +324,13 @@ vc4_vec_tv_mode_lookup(unsigned int mode)
 
 static const struct drm_prop_enum_list tv_mode_names[] = {
 	{ VC4_VEC_TV_MODE_NTSC, "NTSC", },
+	{ VC4_VEC_TV_MODE_NTSC_443, "NTSC-443", },
 	{ VC4_VEC_TV_MODE_NTSC_J, "NTSC-J", },
 	{ VC4_VEC_TV_MODE_PAL, "PAL", },
+	{ VC4_VEC_TV_MODE_PAL_60, "PAL-60", },
 	{ VC4_VEC_TV_MODE_PAL_M, "PAL-M", },
+	{ VC4_VEC_TV_MODE_PAL_N, "PAL-N", },
+	{ VC4_VEC_TV_MODE_SECAM, "SECAM", },
 };
 
 static enum drm_connector_status
@@ -333,6 +388,10 @@ vc4_vec_connector_set_property(struct drm_connector *connector,
 		state->tv.mode = DRM_MODE_TV_MODE_NTSC;
 		break;
 
+	case VC4_VEC_TV_MODE_NTSC_443:
+		state->tv.mode = DRM_MODE_TV_MODE_NTSC_443;
+		break;
+
 	case VC4_VEC_TV_MODE_NTSC_J:
 		state->tv.mode = DRM_MODE_TV_MODE_NTSC_J;
 		break;
@@ -345,6 +404,14 @@ vc4_vec_connector_set_property(struct drm_connector *connector,
 		state->tv.mode = DRM_MODE_TV_MODE_PAL_M;
 		break;
 
+	case VC4_VEC_TV_MODE_PAL_N:
+		state->tv.mode = DRM_MODE_TV_MODE_PAL_N;
+		break;
+
+	case VC4_VEC_TV_MODE_SECAM:
+		state->tv.mode = DRM_MODE_TV_MODE_SECAM;
+		break;
+
 	default:
 		return -EINVAL;
 	}
@@ -368,6 +435,10 @@ vc4_vec_connector_get_property(struct drm_connector *connector,
 		*val = VC4_VEC_TV_MODE_NTSC;
 		break;
 
+	case DRM_MODE_TV_MODE_NTSC_443:
+		*val = VC4_VEC_TV_MODE_NTSC_443;
+		break;
+
 	case DRM_MODE_TV_MODE_NTSC_J:
 		*val = VC4_VEC_TV_MODE_NTSC_J;
 		break;
@@ -380,6 +451,14 @@ vc4_vec_connector_get_property(struct drm_connector *connector,
 		*val = VC4_VEC_TV_MODE_PAL_M;
 		break;
 
+	case DRM_MODE_TV_MODE_PAL_N:
+		*val = VC4_VEC_TV_MODE_PAL_N;
+		break;
+
+	case DRM_MODE_TV_MODE_SECAM:
+		*val = VC4_VEC_TV_MODE_SECAM;
+		break;
+
 	default:
 		return -EINVAL;
 	}
@@ -667,9 +746,12 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
 
 	ret = drm_mode_create_tv_properties(drm,
 					    BIT(DRM_MODE_TV_MODE_NTSC) |
+					    BIT(DRM_MODE_TV_MODE_NTSC_443) |
 					    BIT(DRM_MODE_TV_MODE_NTSC_J) |
 					    BIT(DRM_MODE_TV_MODE_PAL) |
-					    BIT(DRM_MODE_TV_MODE_PAL_M));
+					    BIT(DRM_MODE_TV_MODE_PAL_M) |
+					    BIT(DRM_MODE_TV_MODE_PAL_N) |
+					    BIT(DRM_MODE_TV_MODE_SECAM));
 	if (ret)
 		return ret;
 

-- 
b4 0.10.0

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

* [Nouveau] [PATCH v2 33/33] drm/sun4i: tv: Convert to the new TV mode property
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (31 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 32/33] drm/vc4: vec: Add support for more analog TV standards Maxime Ripard
@ 2022-09-22 14:25 ` Maxime Ripard
  2022-09-22 14:31 ` [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
  2022-09-25 15:58 ` Noralf Trønnes
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:25 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Maxime Ripard, Joonas Lahtinen, Emma Anholt, Karol Herbst,
	Samuel Holland, Jani Nikula, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

Now that the core can deal fine with analog TV modes, let's convert the
sun4i TV driver to leverage those new features.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>

diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 74ff5ad6a8b9..833742cee745 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -140,23 +140,14 @@ struct resync_parameters {
 struct tv_mode {
 	char		*name;
 
+	unsigned int	tv_mode;
+
 	u32		mode;
 	u32		chroma_freq;
 	u16		back_porch;
 	u16		front_porch;
-	u16		line_number;
 	u16		vblank_level;
 
-	u32		hdisplay;
-	u16		hfront_porch;
-	u16		hsync_len;
-	u16		hback_porch;
-
-	u32		vdisplay;
-	u16		vfront_porch;
-	u16		vsync_len;
-	u16		vback_porch;
-
 	bool		yc_en;
 	bool		dac3_en;
 	bool		dac_bit25_en;
@@ -212,7 +203,7 @@ static const struct resync_parameters pal_resync_parameters = {
 
 static const struct tv_mode tv_modes[] = {
 	{
-		.name		= "NTSC",
+		.tv_mode	= DRM_MODE_TV_MODE_NTSC,
 		.mode		= SUN4I_TVE_CFG0_RES_480i,
 		.chroma_freq	= 0x21f07c1f,
 		.yc_en		= true,
@@ -221,17 +212,6 @@ static const struct tv_mode tv_modes[] = {
 
 		.back_porch	= 118,
 		.front_porch	= 32,
-		.line_number	= 525,
-
-		.hdisplay	= 720,
-		.hfront_porch	= 18,
-		.hsync_len	= 2,
-		.hback_porch	= 118,
-
-		.vdisplay	= 480,
-		.vfront_porch	= 26,
-		.vsync_len	= 2,
-		.vback_porch	= 17,
 
 		.vblank_level	= 240,
 
@@ -241,23 +221,12 @@ static const struct tv_mode tv_modes[] = {
 		.resync_params	= &ntsc_resync_parameters,
 	},
 	{
-		.name		= "PAL",
+		.tv_mode	= DRM_MODE_TV_MODE_PAL,
 		.mode		= SUN4I_TVE_CFG0_RES_576i,
 		.chroma_freq	= 0x2a098acb,
 
 		.back_porch	= 138,
 		.front_porch	= 24,
-		.line_number	= 625,
-
-		.hdisplay	= 720,
-		.hfront_porch	= 3,
-		.hsync_len	= 2,
-		.hback_porch	= 139,
-
-		.vdisplay	= 576,
-		.vfront_porch	= 28,
-		.vsync_len	= 2,
-		.vback_porch	= 19,
 
 		.vblank_level	= 252,
 
@@ -275,63 +244,21 @@ drm_encoder_to_sun4i_tv(struct drm_encoder *encoder)
 			    encoder);
 }
 
-/*
- * FIXME: If only the drm_display_mode private field was usable, this
- * could go away...
- *
- * So far, it doesn't seem to be preserved when the mode is passed by
- * to mode_set for some reason.
- */
-static const struct tv_mode *sun4i_tv_find_tv_by_mode(const struct drm_display_mode *mode)
+static const struct tv_mode *
+sun4i_tv_find_tv_by_mode(unsigned int mode)
 {
 	int i;
 
-	/* First try to identify the mode by name */
 	for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
 		const struct tv_mode *tv_mode = &tv_modes[i];
 
-		DRM_DEBUG_DRIVER("Comparing mode %s vs %s",
-				 mode->name, tv_mode->name);
-
-		if (!strcmp(mode->name, tv_mode->name))
-			return tv_mode;
-	}
-
-	/* Then by number of lines */
-	for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
-		const struct tv_mode *tv_mode = &tv_modes[i];
-
-		DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)",
-				 mode->name, tv_mode->name,
-				 mode->vdisplay, tv_mode->vdisplay);
-
-		if (mode->vdisplay == tv_mode->vdisplay)
+		if (tv_mode->tv_mode == mode)
 			return tv_mode;
 	}
 
 	return NULL;
 }
 
-static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode,
-				      struct drm_display_mode *mode)
-{
-	DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name);
-
-	mode->type = DRM_MODE_TYPE_DRIVER;
-	mode->clock = 13500;
-	mode->flags = DRM_MODE_FLAG_INTERLACE;
-
-	mode->hdisplay = tv_mode->hdisplay;
-	mode->hsync_start = mode->hdisplay + tv_mode->hfront_porch;
-	mode->hsync_end = mode->hsync_start + tv_mode->hsync_len;
-	mode->htotal = mode->hsync_end  + tv_mode->hback_porch;
-
-	mode->vdisplay = tv_mode->vdisplay;
-	mode->vsync_start = mode->vdisplay + tv_mode->vfront_porch;
-	mode->vsync_end = mode->vsync_start + tv_mode->vsync_len;
-	mode->vtotal = mode->vsync_end  + tv_mode->vback_porch;
-}
-
 static void sun4i_tv_disable(struct drm_encoder *encoder,
 			    struct drm_atomic_state *state)
 {
@@ -355,7 +282,11 @@ static void sun4i_tv_enable(struct drm_encoder *encoder,
 	struct drm_crtc_state *crtc_state =
 		drm_atomic_get_new_crtc_state(state, encoder->crtc);
 	struct drm_display_mode *mode = &crtc_state->mode;
-	const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
+	struct drm_connector *connector = &tv->connector;
+	struct drm_connector_state *conn_state =
+		drm_atomic_get_new_connector_state(state, connector);
+	const struct tv_mode *tv_mode =
+		sun4i_tv_find_tv_by_mode(conn_state->tv.mode);
 
 	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
 
@@ -403,7 +334,7 @@ static void sun4i_tv_enable(struct drm_encoder *encoder,
 	/* Set the lines setup */
 	regmap_write(tv->regs, SUN4I_TVE_LINE_REG,
 		     SUN4I_TVE_LINE_FIRST(22) |
-		     SUN4I_TVE_LINE_NUMBER(tv_mode->line_number));
+		     SUN4I_TVE_LINE_NUMBER(mode->vtotal));
 
 	regmap_write(tv->regs, SUN4I_TVE_LEVEL_REG,
 		     SUN4I_TVE_LEVEL_BLANK(tv_mode->video_levels->blank) |
@@ -466,35 +397,46 @@ static const struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = {
 
 static int sun4i_tv_comp_get_modes(struct drm_connector *connector)
 {
-	int i;
+	struct drm_display_mode *mode;
+	int count = 0;
 
-	for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
-		struct drm_display_mode *mode;
-		const struct tv_mode *tv_mode = &tv_modes[i];
-
-		mode = drm_mode_create(connector->dev);
-		if (!mode) {
-			DRM_ERROR("Failed to create a new display mode\n");
-			return 0;
-		}
+	mode = drm_mode_analog_ntsc_480i(connector->dev);
+	if (!mode) {
+		DRM_ERROR("Failed to create a new display mode\n");
+		return -ENOMEM;
+	}
 
-		strcpy(mode->name, tv_mode->name);
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+	drm_mode_probed_add(connector, mode);
+	count += 1;
 
-		sun4i_tv_mode_to_drm_mode(tv_mode, mode);
-		drm_mode_probed_add(connector, mode);
+	mode = drm_mode_analog_pal_576i(connector->dev);
+	if (!mode) {
+		DRM_ERROR("Failed to create a new display mode\n");
+		return -ENOMEM;
 	}
 
-	return i;
+	drm_mode_probed_add(connector, mode);
+	count += 1;
+
+	return count;
 }
 
 static const struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_funcs = {
+	.atomic_check	= drm_atomic_helper_connector_tv_check,
 	.get_modes	= sun4i_tv_comp_get_modes,
 };
 
+static void sun4i_tv_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 sun4i_tv_comp_connector_funcs = {
 	.fill_modes		= drm_helper_probe_single_connector_modes,
 	.destroy		= drm_connector_cleanup,
-	.reset			= drm_atomic_helper_connector_reset,
+	.reset			= sun4i_tv_connector_reset,
 	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
 };
@@ -586,8 +528,20 @@ static int sun4i_tv_bind(struct device *dev, struct device *master,
 
 	drm_connector_attach_encoder(&tv->connector, &tv->encoder);
 
+	ret = drm_mode_create_tv_properties(drm,
+					    BIT(DRM_MODE_TV_MODE_NTSC) |
+					    BIT(DRM_MODE_TV_MODE_PAL));
+	if (ret)
+		goto err_cleanup_connector;
+
+	drm_object_attach_property(&tv->connector.base,
+				   drm->mode_config.tv_mode_property,
+				   DRM_MODE_TV_MODE_NTSC);
+
 	return 0;
 
+err_cleanup_connector:
+	drm_connector_cleanup(&tv->connector);
 err_cleanup_encoder:
 	drm_encoder_cleanup(&tv->encoder);
 err_disable_clk:
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 0862462aa9e3..b9f7bd7b8b7a 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -322,7 +322,7 @@ vc4_vec_tv_mode_lookup(unsigned int mode)
 	return NULL;
 }
 
-static const struct drm_prop_enum_list tv_mode_names[] = {
+static const struct drm_prop_enum_list legacy_tv_mode_names[] = {
 	{ VC4_VEC_TV_MODE_NTSC, "NTSC", },
 	{ VC4_VEC_TV_MODE_NTSC_443, "NTSC-443", },
 	{ VC4_VEC_TV_MODE_NTSC_J, "NTSC-J", },
@@ -501,7 +501,8 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
 				   DRM_MODE_TV_MODE_NTSC);
 
 	prop = drm_property_create_enum(dev, 0, "mode",
-					tv_mode_names, ARRAY_SIZE(tv_mode_names));
+					legacy_tv_mode_names,
+					ARRAY_SIZE(legacy_tv_mode_names));
 	if (!prop)
 		return -ENOMEM;
 	vec->legacy_tv_mode_property = prop;

-- 
b4 0.10.0

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

* Re: [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (32 preceding siblings ...)
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 33/33] drm/sun4i: tv: Convert to the new TV mode property Maxime Ripard
@ 2022-09-22 14:31 ` Maxime Ripard
  2022-09-25 15:58 ` Noralf Trønnes
  34 siblings, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-22 14:31 UTC (permalink / raw)
  To: Jernej Skrabec, Rodrigo Vivi, Ben Skeggs, David Airlie,
	Joonas Lahtinen, Emma Anholt, Karol Herbst, Samuel Holland,
	Jani Nikula, Thomas Zimmermann, Daniel Vetter, Lyude Paul,
	Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 4479 bytes --]

Hi,

On Thu, Sep 22, 2022 at 04:25:17PM +0200, Maxime Ripard wrote:
> Here's a series aiming at improving the command line named modes support,
> and more importantly how we deal with all the analog TV variants.
> 
> The named modes support were initially introduced to allow to specify the
> analog TV mode to be used.
> 
> However, this was causing multiple issues:
> 
>   * The mode name parsed on the command line was passed directly to the
>     driver, which had to figure out which mode it was suppose to match;
> 
>   * Figuring that out wasn't really easy, since the video= argument or what
>     the userspace might not even have a name in the first place, but
>     instead could have passed a mode with the same timings;
> 
>   * The fallback to matching on the timings was mostly working as long as
>     we were supporting one 525 lines (most likely NSTC) and one 625 lines
>     (PAL), but couldn't differentiate between two modes with the same
>     timings (NTSC vs PAL-M vs NSTC-J for example);
> 
>   * There was also some overlap with the tv mode property registered by
>     drm_mode_create_tv_properties(), but named modes weren't interacting
>     with that property at all.
> 
>   * Even though that property was generic, its possible values were
>     specific to each drivers, which made some generic support difficult.
> 
> Thus, I chose to tackle in multiple steps:
> 
>   * A new TV mode property was introduced, with generic values, each driver
>     reporting through a bitmask what standard it supports to the userspace;
> 
>   * This option was added to the command line parsing code to be able to
>     specify it on the kernel command line, and new atomic_check and reset
>     helpers were created to integrate properly into atomic KMS;
> 
>   * The named mode parsing code is now creating a proper display mode for
>     the given named mode, and the TV standard will thus be part of the
>     connector state;
> 
>   * Two drivers were converted and tested for now (vc4 and sun4i), with
>     some backward compatibility code to translate the old TV mode to the
>     new TV mode;
> 
> Unit tests were created along the way.
> 
> One can switch from NTSC to PAL now using (on vc4)
> 
> modetest -M vc4  -s 53:720x480i -w 53:'TV mode':1 # NTSC
> modetest -M vc4  -s 53:720x576i -w 53:'TV mode':4 # PAL
> 
> Let me know what you think,
> Maxime
> 
> To: David Airlie <airlied@linux.ie>
> To: Daniel Vetter <daniel@ffwll.ch>
> To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> To: Maxime Ripard <mripard@kernel.org>
> To: Thomas Zimmermann <tzimmermann@suse.de>
> To: Emma Anholt <emma@anholt.net>
> To: Jani Nikula <jani.nikula@linux.intel.com>
> To: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> To: Rodrigo Vivi <rodrigo.vivi@intel.com>
> To: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> To: Ben Skeggs <bskeggs@redhat.com>
> To: Karol Herbst <kherbst@redhat.com>
> To: Lyude Paul <lyude@redhat.com>
> To: Chen-Yu Tsai <wens@csie.org>
> To: Jernej Skrabec <jernej.skrabec@gmail.com>
> To: Samuel Holland <samuel@sholland.org>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
> Cc: "Noralf Trønnes" <noralf@tronnes.org>
> Cc: Dave Stevenson <dave.stevenson@raspberrypi.com>
> Cc: Dom Cobley <dom@raspberrypi.com>
> Cc: Phil Elwell <phil@raspberrypi.com>
> Cc: <dri-devel@lists.freedesktop.org>
> Cc: linux-kernel@vger.kernel.org
> Cc: intel-gfx@lists.freedesktop.org
> Cc: nouveau@lists.freedesktop.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-sunxi@lists.linux.dev
> Cc: Hans de Goede <hdegoede@redhat.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> ---
> Changes in v3:
> - Applied some of the fixes to vc4 and sun4i
> - Renamed the old TV mode property to legacy_mode
> - Fixed a bunch of bisection errors
> - Removed most of the redundant TV modes
> - Added a new None TV mode to not fall back on NTSC by mistake
> - Fixed the mode generation function to match better what is expected
> - Added some logging to the mode generation function
> - Split the improvements to the named mode parsing logic into separate patches
> - Added more checks to the TV atomic_check helper
> - Link to v2: https://lore.kernel.org/dri-devel/20220728-rpi-analog-tv-properties-v2-0-459522d653a7@cerno.tech/

Sorry, this is obviously the v3...

Maxime

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

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

* Re: [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property Maxime Ripard
@ 2022-09-22 20:44   ` Lyude Paul
  2022-09-23  8:19   ` Thomas Zimmermann
  2022-09-24 15:38   ` Noralf Trønnes
  2 siblings, 0 replies; 75+ messages in thread
From: Lyude Paul @ 2022-09-22 20:44 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel

nouveau changes:

Reviewed-by: Lyude Paul <lyude@redhat.com>

On Thu, 2022-09-22 at 16:25 +0200, Maxime Ripard wrote:
> The current tv_mode has driver-specific values that don't allow to
> easily share code using it, either at the userspace or kernel level.
> 
> Since we're going to introduce a new, generic, property that fit the
> same purpose, let's rename this one to legacy_tv_mode to make it
> obvious we should move away from it.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index c06d0639d552..7f2b9a07fbdf 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -698,8 +698,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
>  		state->tv.margins.top = val;
>  	} else if (property == config->tv_bottom_margin_property) {
>  		state->tv.margins.bottom = val;
> -	} else if (property == config->tv_mode_property) {
> -		state->tv.mode = val;
> +	} else if (property == config->legacy_tv_mode_property) {
> +		state->tv.legacy_mode = val;
>  	} else if (property == config->tv_brightness_property) {
>  		state->tv.brightness = val;
>  	} else if (property == config->tv_contrast_property) {
> @@ -808,8 +808,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>  		*val = state->tv.margins.top;
>  	} else if (property == config->tv_bottom_margin_property) {
>  		*val = state->tv.margins.bottom;
> -	} else if (property == config->tv_mode_property) {
> -		*val = state->tv.mode;
> +	} else if (property == config->legacy_tv_mode_property) {
> +		*val = state->tv.legacy_mode;
>  	} else if (property == config->tv_brightness_property) {
>  		*val = state->tv.brightness;
>  	} else if (property == config->tv_contrast_property) {
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index e3142c8142b3..ede6025638d7 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -1686,14 +1686,14 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
>  	if (drm_mode_create_tv_margin_properties(dev))
>  		goto nomem;
>  
> -	dev->mode_config.tv_mode_property =
> +	dev->mode_config.legacy_tv_mode_property =
>  		drm_property_create(dev, DRM_MODE_PROP_ENUM,
>  				    "mode", num_modes);
> -	if (!dev->mode_config.tv_mode_property)
> +	if (!dev->mode_config.legacy_tv_mode_property)
>  		goto nomem;
>  
>  	for (i = 0; i < num_modes; i++)
> -		drm_property_add_enum(dev->mode_config.tv_mode_property,
> +		drm_property_add_enum(dev->mode_config.legacy_tv_mode_property,
>  				      i, modes[i]);
>  
>  	dev->mode_config.tv_brightness_property =
> diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
> index fa636206f232..86e992b2108b 100644
> --- a/drivers/gpu/drm/gud/gud_connector.c
> +++ b/drivers/gpu/drm/gud/gud_connector.c
> @@ -303,7 +303,7 @@ static int gud_connector_atomic_check(struct drm_connector *connector,
>  	    old_state->tv.margins.right != new_state->tv.margins.right ||
>  	    old_state->tv.margins.top != new_state->tv.margins.top ||
>  	    old_state->tv.margins.bottom != new_state->tv.margins.bottom ||
> -	    old_state->tv.mode != new_state->tv.mode ||
> +	    old_state->tv.legacy_mode != new_state->tv.legacy_mode ||
>  	    old_state->tv.brightness != new_state->tv.brightness ||
>  	    old_state->tv.contrast != new_state->tv.contrast ||
>  	    old_state->tv.flicker_reduction != new_state->tv.flicker_reduction ||
> @@ -424,7 +424,7 @@ gud_connector_property_lookup(struct drm_connector *connector, u16 prop)
>  	case GUD_PROPERTY_TV_BOTTOM_MARGIN:
>  		return config->tv_bottom_margin_property;
>  	case GUD_PROPERTY_TV_MODE:
> -		return config->tv_mode_property;
> +		return config->legacy_tv_mode_property;
>  	case GUD_PROPERTY_TV_BRIGHTNESS:
>  		return config->tv_brightness_property;
>  	case GUD_PROPERTY_TV_CONTRAST:
> @@ -454,7 +454,7 @@ static unsigned int *gud_connector_tv_state_val(u16 prop, struct drm_tv_connecto
>  	case GUD_PROPERTY_TV_BOTTOM_MARGIN:
>  		return &state->margins.bottom;
>  	case GUD_PROPERTY_TV_MODE:
> -		return &state->mode;
> +		return &state->legacy_mode;
>  	case GUD_PROPERTY_TV_BRIGHTNESS:
>  		return &state->brightness;
>  	case GUD_PROPERTY_TV_CONTRAST:
> diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
> index b91e48d2190d..d29b63fd6178 100644
> --- a/drivers/gpu/drm/i2c/ch7006_drv.c
> +++ b/drivers/gpu/drm/i2c/ch7006_drv.c
> @@ -264,7 +264,7 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder,
>  				      priv->hmargin);
>  	drm_object_attach_property(&connector->base, conf->tv_bottom_margin_property,
>  				      priv->vmargin);
> -	drm_object_attach_property(&connector->base, conf->tv_mode_property,
> +	drm_object_attach_property(&connector->base, conf->legacy_tv_mode_property,
>  				      priv->norm);
>  	drm_object_attach_property(&connector->base, conf->tv_brightness_property,
>  				      priv->brightness);
> @@ -315,7 +315,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder,
>  		ch7006_load_reg(client, state, CH7006_POV);
>  		ch7006_load_reg(client, state, CH7006_VPOS);
>  
> -	} else if (property == conf->tv_mode_property) {
> +	} else if (property == conf->legacy_tv_mode_property) {
>  		if (connector->dpms != DRM_MODE_DPMS_OFF)
>  			return -EINVAL;
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
> index 9379f3463344..abaf9ded942d 100644
> --- a/drivers/gpu/drm/i915/display/intel_tv.c
> +++ b/drivers/gpu/drm/i915/display/intel_tv.c
> @@ -1986,7 +1986,8 @@ intel_tv_init(struct drm_i915_private *dev_priv)
>  	}
>  	drm_mode_create_tv_properties(dev, i, tv_format_names);
>  
> -	drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
> +	drm_object_attach_property(&connector->base,
> +				   dev->mode_config.legacy_tv_mode_property,
>  				   state->tv.mode);
>  	drm_object_attach_property(&connector->base,
>  				   dev->mode_config.tv_left_margin_property,
> diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> index be28e7bd7490..1a15534adc60 100644
> --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> @@ -662,7 +662,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder,
>  					conf->tv_subconnector_property,
>  					tv_enc->subconnector);
>  	drm_object_attach_property(&connector->base,
> -					conf->tv_mode_property,
> +					conf->legacy_tv_mode_property,
>  					tv_enc->tv_norm);
>  	drm_object_attach_property(&connector->base,
>  					conf->tv_flicker_reduction_property,
> @@ -722,7 +722,7 @@ static int nv17_tv_set_property(struct drm_encoder *encoder,
>  		if (encoder->crtc)
>  			nv17_tv_update_rescaler(encoder);
>  
> -	} else if (property == conf->tv_mode_property) {
> +	} else if (property == conf->legacy_tv_mode_property) {
>  		if (connector->dpms != DRM_MODE_DPMS_OFF)
>  			return -EINVAL;
>  
> diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
> index 0b3333865702..77c50ecb0309 100644
> --- a/drivers/gpu/drm/vc4/vc4_vec.c
> +++ b/drivers/gpu/drm/vc4/vc4_vec.c
> @@ -274,7 +274,7 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector)
>  	struct drm_display_mode *mode;
>  
>  	mode = drm_mode_duplicate(connector->dev,
> -				  vc4_vec_tv_modes[state->tv.mode].mode);
> +				  vc4_vec_tv_modes[state->tv.legacy_mode].mode);
>  	if (!mode) {
>  		DRM_ERROR("Failed to create a new display mode\n");
>  		return -ENOMEM;
> @@ -312,7 +312,7 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
>  	drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
>  
>  	drm_object_attach_property(&connector->base,
> -				   dev->mode_config.tv_mode_property,
> +				   dev->mode_config.legacy_tv_mode_property,
>  				   VC4_VEC_TV_MODE_NTSC);
>  
>  	drm_connector_attach_encoder(connector, &vec->encoder.base);
> @@ -449,7 +449,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
>  {
>  	const struct vc4_vec_tv_mode *vec_mode;
>  
> -	vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
> +	vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode];
>  
>  	if (conn_state->crtc &&
>  	    !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 1d5e3cccb9e3..5cfad8b6ad83 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -695,7 +695,7 @@ struct drm_connector_tv_margins {
>   * @select_subconnector: selected subconnector
>   * @subconnector: detected subconnector
>   * @margins: TV margins
> - * @mode: TV mode
> + * @legacy_mode: Legacy TV mode, driver specific value
>   * @brightness: brightness in percent
>   * @contrast: contrast in percent
>   * @flicker_reduction: flicker reduction in percent
> @@ -707,7 +707,7 @@ struct drm_tv_connector_state {
>  	enum drm_mode_subconnector select_subconnector;
>  	enum drm_mode_subconnector subconnector;
>  	struct drm_connector_tv_margins margins;
> -	unsigned int mode;
> +	unsigned int legacy_mode;
>  	unsigned int brightness;
>  	unsigned int contrast;
>  	unsigned int flicker_reduction;
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 6b5e01295348..35a827175c24 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -714,11 +714,13 @@ struct drm_mode_config {
>  	 * between different TV connector types.
>  	 */
>  	struct drm_property *tv_select_subconnector_property;
> +
>  	/**
> -	 * @tv_mode_property: Optional TV property to select
> +	 * @legacy_tv_mode_property: Optional TV property to select
>  	 * the output TV mode.
>  	 */
> -	struct drm_property *tv_mode_property;
> +	struct drm_property *legacy_tv_mode_property;
> +
>  	/**
>  	 * @tv_left_margin_property: Optional TV property to set the left
>  	 * margin (expressed in pixels).
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [Nouveau] [PATCH v2 08/33] drm/connector: Rename drm_mode_create_tv_properties
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 08/33] drm/connector: Rename drm_mode_create_tv_properties Maxime Ripard
@ 2022-09-22 20:45   ` Lyude Paul
  2022-09-24 15:43   ` Noralf Trønnes
  1 sibling, 0 replies; 75+ messages in thread
From: Lyude Paul @ 2022-09-22 20:45 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel

For nouveau:

Reviewed-by: Lyude Paul <lyude@redhat.com>

On Thu, 2022-09-22 at 16:25 +0200, Maxime Ripard wrote:
> drm_mode_create_tv_properties(), among other things, will create the
> "mode" property that stores the analog TV mode that connector is
> supposed to output.
> 
> However, that property is getting deprecated, so let's rename that
> function to mention it's deprecated. We'll introduce a new variant of
> that function creating the property superseeding it in a later patch.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 17a5913cefe3..4e4fbc9e0049 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -1600,7 +1600,7 @@ EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties);
>   * Called by a driver's HDMI connector initialization routine, this function
>   * creates the TV margin properties for a given device. No need to call this
>   * function for an SDTV connector, it's already called from
> - * drm_mode_create_tv_properties().
> + * drm_mode_create_tv_properties_legacy().
>   *
>   * Returns:
>   * 0 on success or a negative error code on failure.
> @@ -1635,7 +1635,7 @@ int drm_mode_create_tv_margin_properties(struct drm_device *dev)
>  EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
>  
>  /**
> - * drm_mode_create_tv_properties - create TV specific connector properties
> + * drm_mode_create_tv_properties_legacy - create TV specific connector properties
>   * @dev: DRM device
>   * @num_modes: number of different TV formats (modes) supported
>   * @modes: array of pointers to strings containing name of each format
> @@ -1648,9 +1648,9 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
>   * Returns:
>   * 0 on success or a negative error code on failure.
>   */
> -int drm_mode_create_tv_properties(struct drm_device *dev,
> -				  unsigned int num_modes,
> -				  const char * const modes[])
> +int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
> +					 unsigned int num_modes,
> +					 const char * const modes[])
>  {
>  	struct drm_property *tv_selector;
>  	struct drm_property *tv_subconnector;
> @@ -1733,7 +1733,7 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
>  nomem:
>  	return -ENOMEM;
>  }
> -EXPORT_SYMBOL(drm_mode_create_tv_properties);
> +EXPORT_SYMBOL(drm_mode_create_tv_properties_legacy);
>  
>  /**
>   * drm_mode_create_scaling_mode_property - create scaling mode property
> diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
> index 86e992b2108b..034e78360d4f 100644
> --- a/drivers/gpu/drm/gud/gud_connector.c
> +++ b/drivers/gpu/drm/gud/gud_connector.c
> @@ -400,7 +400,7 @@ static int gud_connector_add_tv_mode(struct gud_device *gdrm, struct drm_connect
>  	for (i = 0; i < num_modes; i++)
>  		modes[i] = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN];
>  
> -	ret = drm_mode_create_tv_properties(connector->dev, num_modes, modes);
> +	ret = drm_mode_create_tv_properties_legacy(connector->dev, num_modes, modes);
>  free:
>  	kfree(buf);
>  	if (ret < 0)
> @@ -539,7 +539,7 @@ static int gud_connector_add_properties(struct gud_device *gdrm, struct gud_conn
>  			fallthrough;
>  		case GUD_PROPERTY_TV_HUE:
>  			/* This is a no-op if already added. */
> -			ret = drm_mode_create_tv_properties(drm, 0, NULL);
> +			ret = drm_mode_create_tv_properties_legacy(drm, 0, NULL);
>  			if (ret)
>  				goto out;
>  			break;
> diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
> index d29b63fd6178..506f6f932518 100644
> --- a/drivers/gpu/drm/i2c/ch7006_drv.c
> +++ b/drivers/gpu/drm/i2c/ch7006_drv.c
> @@ -250,7 +250,7 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder,
>  	struct drm_device *dev = encoder->dev;
>  	struct drm_mode_config *conf = &dev->mode_config;
>  
> -	drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names);
> +	drm_mode_create_tv_properties_legacy(dev, NUM_TV_NORMS, ch7006_tv_norm_names);
>  
>  	priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2);
>  	if (!priv->scale_property)
> diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
> index abaf9ded942d..5e88da8185ee 100644
> --- a/drivers/gpu/drm/i915/display/intel_tv.c
> +++ b/drivers/gpu/drm/i915/display/intel_tv.c
> @@ -1984,7 +1984,7 @@ intel_tv_init(struct drm_i915_private *dev_priv)
>  
>  		tv_format_names[i] = tv_modes[i].name;
>  	}
> -	drm_mode_create_tv_properties(dev, i, tv_format_names);
> +	drm_mode_create_tv_properties_legacy(dev, i, tv_format_names);
>  
>  	drm_object_attach_property(&connector->base,
>  				   dev->mode_config.legacy_tv_mode_property,
> diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> index 1a15534adc60..e5480dab55e3 100644
> --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> @@ -653,7 +653,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder,
>  			tv_enc->tv_norm = i;
>  	}
>  
> -	drm_mode_create_tv_properties(dev, num_tv_norms, nv17_tv_norm_names);
> +	drm_mode_create_tv_properties_legacy(dev, num_tv_norms, nv17_tv_norm_names);
>  
>  	drm_object_attach_property(&connector->base,
>  					conf->tv_select_subconnector_property,
> diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
> index 77c50ecb0309..f31fef938f11 100644
> --- a/drivers/gpu/drm/vc4/vc4_vec.c
> +++ b/drivers/gpu/drm/vc4/vc4_vec.c
> @@ -514,8 +514,9 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
>  	struct vc4_vec *vec;
>  	int ret;
>  
> -	ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names),
> -					    tv_mode_names);
> +	ret = drm_mode_create_tv_properties_legacy(drm,
> +						   ARRAY_SIZE(tv_mode_names),
> +						   tv_mode_names);
>  	if (ret)
>  		return ret;
>  
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 5cfad8b6ad83..d566b4a4709c 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -1799,9 +1799,9 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev);
>  void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector);
>  
>  int drm_mode_create_tv_margin_properties(struct drm_device *dev);
> -int drm_mode_create_tv_properties(struct drm_device *dev,
> -				  unsigned int num_modes,
> -				  const char * const modes[]);
> +int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
> +					 unsigned int num_modes,
> +					 const char * const modes[]);
>  void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
>  int drm_mode_create_scaling_mode_property(struct drm_device *dev);
>  int drm_connector_attach_content_type_property(struct drm_connector *dev);
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile Maxime Ripard
@ 2022-09-23  8:06   ` Thomas Zimmermann
  2022-09-24 17:33   ` Noralf Trønnes
  1 sibling, 0 replies; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-23  8:06 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, Phil Elwell, nouveau, intel-gfx, linux-kernel,
	dri-devel, Mateusz Kwiatkowski, Hans de Goede,
	Noralf Trønnes, Geert Uytterhoeven, linux-sunxi,
	linux-arm-kernel


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



Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> Since we've recently added a ton of tests, the list starts to be a bit
> of a mess and creates unneeded conflicts.
> 
> Let's order it alphabetically.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> 
> diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
> index 91b70f7d2769..2d9f49b62ecb 100644
> --- a/drivers/gpu/drm/tests/Makefile
> +++ b/drivers/gpu/drm/tests/Makefile
> @@ -1,5 +1,13 @@
>   # SPDX-License-Identifier: GPL-2.0
>   
> -obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \
> -	drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \
> -	drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o drm_mm_test.o
> +obj-$(CONFIG_DRM_KUNIT_TEST) += \
> +	drm_buddy_test.o \
> +	drm_cmdline_parser_test.o \
> +	drm_damage_helper_test.o \
> +	drm_dp_mst_helper_test.o \
> +	drm_format_helper_test.o \
> +	drm_format_test.o \
> +	drm_framebuffer_test.o \
> +	drm_mm_test.o \
> +	drm_plane_helper_test.o \
> +	drm_rect_test.o
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 03/33] drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid ambiguity
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 03/33] drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid ambiguity Maxime Ripard
@ 2022-09-23  8:09   ` Thomas Zimmermann
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-23  8:09 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, Phil Elwell, nouveau, intel-gfx, linux-kernel,
	dri-devel, Mateusz Kwiatkowski, Hans de Goede,
	Noralf Trønnes, Geert Uytterhoeven, linux-sunxi,
	linux-arm-kernel


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

Hi

Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> We currently have two sets of TV properties.
> 
> The first one is there to deal with analog TV properties, creating
> properties such as the TV mode, subconnectors, saturation, hue and so on.
> It's created by calling the drm_mode_create_tv_properties() function.
> 
> The second one is there to deal with properties that might be useful on a
> TV, creating the overscan margins for example. It's created by calling the
> drm_mode_create_tv_margin_properties().
> 
> However, we also have a drm_atomic_helper_connector_tv_reset() function
> that will reset the TV margin properties to their default values, and thus
> is supposed to be called for the latter set. This creates an ambiguity due
> to the inconsistent naming.
> 
> We can thus rename the drm_atomic_helper_connector_tv_reset() function to
> drm_atomic_helper_connector_tv_margins_reset() to remove that ambiguity
> and hopefully make it more obvious.
> 
> Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
> index bf31b9d92094..dfb57217253b 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -464,12 +464,12 @@ 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
> + * drm_atomic_helper_connector_tv_margins_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)
> +void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector)
>   {
>   	struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
>   	struct drm_connector_state *state = connector->state;
> @@ -479,7 +479,7 @@ void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
>   	state->tv.margins.top = cmdline->tv_margins.top;
>   	state->tv.margins.bottom = cmdline->tv_margins.bottom;
>   }
> -EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
> +EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
>   
>   /**
>    * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
> diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
> index d0addd478815..fa636206f232 100644
> --- a/drivers/gpu/drm/gud/gud_connector.c
> +++ b/drivers/gpu/drm/gud/gud_connector.c
> @@ -355,7 +355,7 @@ static void gud_connector_reset(struct drm_connector *connector)
>   	drm_atomic_helper_connector_reset(connector);
>   	connector->state->tv = gconn->initial_tv_state;
>   	/* Set margins from command line */
> -	drm_atomic_helper_connector_tv_reset(connector);
> +	drm_atomic_helper_connector_tv_margins_reset(connector);
>   	if (gconn->initial_brightness >= 0)
>   		connector->state->tv.brightness = gconn->initial_brightness;
>   }
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 4d3ff51ad2a8..fe01ca5a07d3 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -396,7 +396,7 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector)
>   	new_state->base.max_bpc = 8;
>   	new_state->base.max_requested_bpc = 8;
>   	new_state->output_format = VC4_HDMI_OUTPUT_RGB;
> -	drm_atomic_helper_connector_tv_reset(connector);
> +	drm_atomic_helper_connector_tv_margins_reset(connector);
>   }
>   
>   static struct drm_connector_state *
> diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h
> index 3f8f1d627f7c..192766656b88 100644
> --- a/include/drm/drm_atomic_state_helper.h
> +++ b/include/drm/drm_atomic_state_helper.h
> @@ -70,7 +70,7 @@ void __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_
>   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_tv_margins_reset(struct drm_connector *connector);
>   void
>   __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
>   					   struct drm_connector_state *state);
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 248206bbd975..23112f0c11cf 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -692,7 +692,7 @@ struct drm_connector_tv_margins {
>   
>   /**
>    * struct drm_tv_connector_state - TV connector related states
> - * @subconnector: selected subconnector
> + * @select_subconnector: selected subconnector
>    * @margins: TV margins
>    * @mode: TV mode
>    * @brightness: brightness in percent
> 

That final chunk looks like a separate patch.

In any case

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>


-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 04/33] drm/connector: Rename subconnector state variable
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 04/33] drm/connector: Rename subconnector state variable Maxime Ripard
@ 2022-09-23  8:14   ` Thomas Zimmermann
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-23  8:14 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, Phil Elwell, nouveau, intel-gfx, linux-kernel,
	dri-devel, Mateusz Kwiatkowski, Hans de Goede,
	Noralf Trønnes, Geert Uytterhoeven, linux-sunxi,
	linux-arm-kernel


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

Hi

Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> There is two TV subconnector related properties registered by
> drm_mode_create_tv_properties(): subconnector and select subconnector.
> 
> While the select subconnector property is stored in the kernel by the
> drm_tv_connector_state structure, the subconnector property isn't stored
> anywhere.
> 
> Worse, the select subconnector property is stored in a field called
> subconnector, creating some ambiguity about which property content we're
> accessing.
> 
> Let's rename that field to one called select_subconnector to make it move
> obvious what it's about.

Is this the place where that extra chuck in patch 3 belong to?

> 
> Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> 
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index 79730fa1dd8e..c74c78a28171 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -687,7 +687,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
>   		 */
>   		return -EINVAL;
>   	} else if (property == config->tv_select_subconnector_property) {
> -		state->tv.subconnector = val;
> +		state->tv.select_subconnector = val;
>   	} else if (property == config->tv_left_margin_property) {
>   		state->tv.margins.left = val;
>   	} else if (property == config->tv_right_margin_property) {
> @@ -795,7 +795,7 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>   		else
>   			*val = connector->dpms;
>   	} else if (property == config->tv_select_subconnector_property) {
> -		*val = state->tv.subconnector;
> +		*val = state->tv.select_subconnector;
>   	} else if (property == config->tv_left_margin_property) {
>   		*val = state->tv.margins.left;
>   	} else if (property == config->tv_right_margin_property) {
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 23112f0c11cf..60b5662dec7c 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -703,7 +703,7 @@ struct drm_connector_tv_margins {
>    * @hue: hue in percent
>    */
>   struct drm_tv_connector_state {
> -	enum drm_mode_subconnector subconnector;
> +	enum drm_mode_subconnector select_subconnector;
>   	struct drm_connector_tv_margins margins;
>   	unsigned int mode;
>   	unsigned int brightness;
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property Maxime Ripard
  2022-09-22 20:44   ` Lyude Paul
@ 2022-09-23  8:19   ` Thomas Zimmermann
  2022-09-26  9:50     ` Maxime Ripard
  2022-09-24 15:38   ` Noralf Trønnes
  2 siblings, 1 reply; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-23  8:19 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, Phil Elwell, nouveau, intel-gfx, linux-kernel,
	dri-devel, Mateusz Kwiatkowski, Hans de Goede,
	Noralf Trønnes, Geert Uytterhoeven, linux-sunxi,
	linux-arm-kernel


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

Hi

Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> The current tv_mode has driver-specific values that don't allow to
> easily share code using it, either at the userspace or kernel level.
> 
> Since we're going to introduce a new, generic, property that fit the
> same purpose, let's rename this one to legacy_tv_mode to make it
> obvious we should move away from it.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

It's not wrong, but 'legacy' is already overloaded with meaning. If you 
can, maybe name it 'driver_tv_mode_property' or 
'custom_tv_mode_property' instead.

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

> 
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index c06d0639d552..7f2b9a07fbdf 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -698,8 +698,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
>   		state->tv.margins.top = val;
>   	} else if (property == config->tv_bottom_margin_property) {
>   		state->tv.margins.bottom = val;
> -	} else if (property == config->tv_mode_property) {
> -		state->tv.mode = val;
> +	} else if (property == config->legacy_tv_mode_property) {
> +		state->tv.legacy_mode = val;
>   	} else if (property == config->tv_brightness_property) {
>   		state->tv.brightness = val;
>   	} else if (property == config->tv_contrast_property) {
> @@ -808,8 +808,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>   		*val = state->tv.margins.top;
>   	} else if (property == config->tv_bottom_margin_property) {
>   		*val = state->tv.margins.bottom;
> -	} else if (property == config->tv_mode_property) {
> -		*val = state->tv.mode;
> +	} else if (property == config->legacy_tv_mode_property) {
> +		*val = state->tv.legacy_mode;
>   	} else if (property == config->tv_brightness_property) {
>   		*val = state->tv.brightness;
>   	} else if (property == config->tv_contrast_property) {
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index e3142c8142b3..ede6025638d7 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -1686,14 +1686,14 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
>   	if (drm_mode_create_tv_margin_properties(dev))
>   		goto nomem;
>   
> -	dev->mode_config.tv_mode_property =
> +	dev->mode_config.legacy_tv_mode_property =
>   		drm_property_create(dev, DRM_MODE_PROP_ENUM,
>   				    "mode", num_modes);
> -	if (!dev->mode_config.tv_mode_property)
> +	if (!dev->mode_config.legacy_tv_mode_property)
>   		goto nomem;
>   
>   	for (i = 0; i < num_modes; i++)
> -		drm_property_add_enum(dev->mode_config.tv_mode_property,
> +		drm_property_add_enum(dev->mode_config.legacy_tv_mode_property,
>   				      i, modes[i]);
>   
>   	dev->mode_config.tv_brightness_property =
> diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
> index fa636206f232..86e992b2108b 100644
> --- a/drivers/gpu/drm/gud/gud_connector.c
> +++ b/drivers/gpu/drm/gud/gud_connector.c
> @@ -303,7 +303,7 @@ static int gud_connector_atomic_check(struct drm_connector *connector,
>   	    old_state->tv.margins.right != new_state->tv.margins.right ||
>   	    old_state->tv.margins.top != new_state->tv.margins.top ||
>   	    old_state->tv.margins.bottom != new_state->tv.margins.bottom ||
> -	    old_state->tv.mode != new_state->tv.mode ||
> +	    old_state->tv.legacy_mode != new_state->tv.legacy_mode ||
>   	    old_state->tv.brightness != new_state->tv.brightness ||
>   	    old_state->tv.contrast != new_state->tv.contrast ||
>   	    old_state->tv.flicker_reduction != new_state->tv.flicker_reduction ||
> @@ -424,7 +424,7 @@ gud_connector_property_lookup(struct drm_connector *connector, u16 prop)
>   	case GUD_PROPERTY_TV_BOTTOM_MARGIN:
>   		return config->tv_bottom_margin_property;
>   	case GUD_PROPERTY_TV_MODE:
> -		return config->tv_mode_property;
> +		return config->legacy_tv_mode_property;
>   	case GUD_PROPERTY_TV_BRIGHTNESS:
>   		return config->tv_brightness_property;
>   	case GUD_PROPERTY_TV_CONTRAST:
> @@ -454,7 +454,7 @@ static unsigned int *gud_connector_tv_state_val(u16 prop, struct drm_tv_connecto
>   	case GUD_PROPERTY_TV_BOTTOM_MARGIN:
>   		return &state->margins.bottom;
>   	case GUD_PROPERTY_TV_MODE:
> -		return &state->mode;
> +		return &state->legacy_mode;
>   	case GUD_PROPERTY_TV_BRIGHTNESS:
>   		return &state->brightness;
>   	case GUD_PROPERTY_TV_CONTRAST:
> diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
> index b91e48d2190d..d29b63fd6178 100644
> --- a/drivers/gpu/drm/i2c/ch7006_drv.c
> +++ b/drivers/gpu/drm/i2c/ch7006_drv.c
> @@ -264,7 +264,7 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder,
>   				      priv->hmargin);
>   	drm_object_attach_property(&connector->base, conf->tv_bottom_margin_property,
>   				      priv->vmargin);
> -	drm_object_attach_property(&connector->base, conf->tv_mode_property,
> +	drm_object_attach_property(&connector->base, conf->legacy_tv_mode_property,
>   				      priv->norm);
>   	drm_object_attach_property(&connector->base, conf->tv_brightness_property,
>   				      priv->brightness);
> @@ -315,7 +315,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder,
>   		ch7006_load_reg(client, state, CH7006_POV);
>   		ch7006_load_reg(client, state, CH7006_VPOS);
>   
> -	} else if (property == conf->tv_mode_property) {
> +	} else if (property == conf->legacy_tv_mode_property) {
>   		if (connector->dpms != DRM_MODE_DPMS_OFF)
>   			return -EINVAL;
>   
> diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
> index 9379f3463344..abaf9ded942d 100644
> --- a/drivers/gpu/drm/i915/display/intel_tv.c
> +++ b/drivers/gpu/drm/i915/display/intel_tv.c
> @@ -1986,7 +1986,8 @@ intel_tv_init(struct drm_i915_private *dev_priv)
>   	}
>   	drm_mode_create_tv_properties(dev, i, tv_format_names);
>   
> -	drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
> +	drm_object_attach_property(&connector->base,
> +				   dev->mode_config.legacy_tv_mode_property,
>   				   state->tv.mode);
>   	drm_object_attach_property(&connector->base,
>   				   dev->mode_config.tv_left_margin_property,
> diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> index be28e7bd7490..1a15534adc60 100644
> --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
> @@ -662,7 +662,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder,
>   					conf->tv_subconnector_property,
>   					tv_enc->subconnector);
>   	drm_object_attach_property(&connector->base,
> -					conf->tv_mode_property,
> +					conf->legacy_tv_mode_property,
>   					tv_enc->tv_norm);
>   	drm_object_attach_property(&connector->base,
>   					conf->tv_flicker_reduction_property,
> @@ -722,7 +722,7 @@ static int nv17_tv_set_property(struct drm_encoder *encoder,
>   		if (encoder->crtc)
>   			nv17_tv_update_rescaler(encoder);
>   
> -	} else if (property == conf->tv_mode_property) {
> +	} else if (property == conf->legacy_tv_mode_property) {
>   		if (connector->dpms != DRM_MODE_DPMS_OFF)
>   			return -EINVAL;
>   
> diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
> index 0b3333865702..77c50ecb0309 100644
> --- a/drivers/gpu/drm/vc4/vc4_vec.c
> +++ b/drivers/gpu/drm/vc4/vc4_vec.c
> @@ -274,7 +274,7 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector)
>   	struct drm_display_mode *mode;
>   
>   	mode = drm_mode_duplicate(connector->dev,
> -				  vc4_vec_tv_modes[state->tv.mode].mode);
> +				  vc4_vec_tv_modes[state->tv.legacy_mode].mode);
>   	if (!mode) {
>   		DRM_ERROR("Failed to create a new display mode\n");
>   		return -ENOMEM;
> @@ -312,7 +312,7 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
>   	drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
>   
>   	drm_object_attach_property(&connector->base,
> -				   dev->mode_config.tv_mode_property,
> +				   dev->mode_config.legacy_tv_mode_property,
>   				   VC4_VEC_TV_MODE_NTSC);
>   
>   	drm_connector_attach_encoder(connector, &vec->encoder.base);
> @@ -449,7 +449,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
>   {
>   	const struct vc4_vec_tv_mode *vec_mode;
>   
> -	vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
> +	vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode];
>   
>   	if (conn_state->crtc &&
>   	    !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 1d5e3cccb9e3..5cfad8b6ad83 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -695,7 +695,7 @@ struct drm_connector_tv_margins {
>    * @select_subconnector: selected subconnector
>    * @subconnector: detected subconnector
>    * @margins: TV margins
> - * @mode: TV mode
> + * @legacy_mode: Legacy TV mode, driver specific value
>    * @brightness: brightness in percent
>    * @contrast: contrast in percent
>    * @flicker_reduction: flicker reduction in percent
> @@ -707,7 +707,7 @@ struct drm_tv_connector_state {
>   	enum drm_mode_subconnector select_subconnector;
>   	enum drm_mode_subconnector subconnector;
>   	struct drm_connector_tv_margins margins;
> -	unsigned int mode;
> +	unsigned int legacy_mode;
>   	unsigned int brightness;
>   	unsigned int contrast;
>   	unsigned int flicker_reduction;
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 6b5e01295348..35a827175c24 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -714,11 +714,13 @@ struct drm_mode_config {
>   	 * between different TV connector types.
>   	 */
>   	struct drm_property *tv_select_subconnector_property;
> +
>   	/**
> -	 * @tv_mode_property: Optional TV property to select
> +	 * @legacy_tv_mode_property: Optional TV property to select
>   	 * the output TV mode.
>   	 */
> -	struct drm_property *tv_mode_property;
> +	struct drm_property *legacy_tv_mode_property;
> +
>   	/**
>   	 * @tv_left_margin_property: Optional TV property to set the left
>   	 * margin (expressed in pixels).
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes Maxime Ripard
@ 2022-09-23  9:05   ` Thomas Zimmermann
  2022-09-23  9:18     ` Jani Nikula
  2022-09-26 10:17     ` Maxime Ripard
  0 siblings, 2 replies; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-23  9:05 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel


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

Hi

Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> Multiple drivers (meson, vc4, sun4i) define analog TV 525-lines and
> 625-lines modes in their drivers.
> 
> Since those modes are fairly standard, and that we'll need to use them
> in more places in the future, it makes sense to move their definition
> into the core framework.
> 
> However, analog display usually have fairly loose timings requirements,
> the only discrete parameters being the total number of lines and pixel
> clock frequency. Thus, we created a function that will create a display
> mode from the standard, the pixel frequency and the active area.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index 304004fb80aa..76ab700f56ff 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -116,6 +116,480 @@ void drm_mode_probed_add(struct drm_connector *connector,
>   }
>   EXPORT_SYMBOL(drm_mode_probed_add);
>   
> +enum drm_mode_analog {
> +	DRM_MODE_ANALOG_NTSC, /* 525 lines, 60Hz */
> +	DRM_MODE_ANALOG_PAL, /* 625 lines, 50Hz */
> +};
> +
> +/*
> + * The timings come from:
> + * - https://web.archive.org/web/20220406232708/http://www.kolumbus.fi/pami1/video/pal_ntsc.html
> + * - https://web.archive.org/web/20220406124914/http://martin.hinner.info/vga/pal.html
> + * - https://web.archive.org/web/20220609202433/http://www.batsocks.co.uk/readme/video_timing.htm
> + */
> +#define NTSC_LINE_DURATION_NS		63556U
> +#define NTSC_LINES_NUMBER		525
> +
> +#define NTSC_HBLK_DURATION_TYP_NS	10900U
> +#define NTSC_HBLK_DURATION_MIN_NS	(NTSC_HBLK_DURATION_TYP_NS - 200)
> +#define NTSC_HBLK_DURATION_MAX_NS	(NTSC_HBLK_DURATION_TYP_NS + 200)
> +
> +#define NTSC_HACT_DURATION_TYP_NS	(NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_TYP_NS)
> +#define NTSC_HACT_DURATION_MIN_NS	(NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MAX_NS)
> +#define NTSC_HACT_DURATION_MAX_NS	(NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MIN_NS)
> +
> +#define NTSC_HFP_DURATION_TYP_NS	1500
> +#define NTSC_HFP_DURATION_MIN_NS	1270
> +#define NTSC_HFP_DURATION_MAX_NS	2220
> +
> +#define NTSC_HSLEN_DURATION_TYP_NS	4700
> +#define NTSC_HSLEN_DURATION_MIN_NS	(NTSC_HSLEN_DURATION_TYP_NS - 100)
> +#define NTSC_HSLEN_DURATION_MAX_NS	(NTSC_HSLEN_DURATION_TYP_NS + 100)
> +
> +#define NTSC_HBP_DURATION_TYP_NS	4700
> +
> +/*
> + * I couldn't find the actual tolerance for the back porch, so let's
> + * just reuse the sync length ones.
> + */
> +#define NTSC_HBP_DURATION_MIN_NS	(NTSC_HBP_DURATION_TYP_NS - 100)
> +#define NTSC_HBP_DURATION_MAX_NS	(NTSC_HBP_DURATION_TYP_NS + 100)
> +
> +#define PAL_LINE_DURATION_NS		64000U
> +#define PAL_LINES_NUMBER		625
> +
> +#define PAL_HACT_DURATION_TYP_NS	51950U
> +#define PAL_HACT_DURATION_MIN_NS	(PAL_HACT_DURATION_TYP_NS - 100)
> +#define PAL_HACT_DURATION_MAX_NS	(PAL_HACT_DURATION_TYP_NS + 400)
> +
> +#define PAL_HBLK_DURATION_TYP_NS	(PAL_LINE_DURATION_NS - PAL_HACT_DURATION_TYP_NS)
> +#define PAL_HBLK_DURATION_MIN_NS	(PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MAX_NS)
> +#define PAL_HBLK_DURATION_MAX_NS	(PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MIN_NS)
> +
> +#define PAL_HFP_DURATION_TYP_NS		1650
> +#define PAL_HFP_DURATION_MIN_NS		(PAL_HFP_DURATION_TYP_NS - 100)
> +#define PAL_HFP_DURATION_MAX_NS		(PAL_HFP_DURATION_TYP_NS + 400)
> +
> +#define PAL_HSLEN_DURATION_TYP_NS	4700
> +#define PAL_HSLEN_DURATION_MIN_NS	(PAL_HSLEN_DURATION_TYP_NS - 200)
> +#define PAL_HSLEN_DURATION_MAX_NS	(PAL_HSLEN_DURATION_TYP_NS + 200)
> +
> +#define PAL_HBP_DURATION_TYP_NS		5700
> +#define PAL_HBP_DURATION_MIN_NS		(PAL_HBP_DURATION_TYP_NS - 200)
> +#define PAL_HBP_DURATION_MAX_NS		(PAL_HBP_DURATION_TYP_NS + 200)
> +
> +struct analog_param_field {
> +	unsigned int even, odd;
> +};
> +
> +#define PARAM_FIELD(_odd, _even)		\
> +	{ .even = _even, .odd = _odd }
> +
> +struct analog_param_range {
> +	unsigned int	min, typ, max;
> +};
> +
> +#define PARAM_RANGE(_min, _typ, _max)		\
> +	{ .min = _min, .typ = _typ, .max = _max }
> +
> +struct analog_parameters {
> +	unsigned int			num_lines;
> +	unsigned int			line_duration_ns;
> +
> +	struct analog_param_range	hact_ns;
> +	struct analog_param_range	hfp_ns;
> +	struct analog_param_range	hslen_ns;
> +	struct analog_param_range	hbp_ns;
> +	struct analog_param_range	hblk_ns;
> +
> +	unsigned int			bt601_hfp;
> +
> +	struct analog_param_field	vfp_lines;
> +	struct analog_param_field	vslen_lines;
> +	struct analog_param_field	vbp_lines;
> +};
> +
> +#define TV_MODE_PARAMETER(_mode, _lines, _line_dur, _hact, _hfp, _hslen, _hbp, _hblk, _bt601_hfp, _vfp, _vslen, _vbp) \
> +	[_mode] = {							\
> +		.num_lines = _lines,					\
> +		.line_duration_ns = _line_dur,				\
> +		.hact_ns = _hact,					\
> +		.hfp_ns = _hfp,						\
> +		.hslen_ns = _hslen,					\
> +		.hbp_ns = _hbp,						\
> +		.hblk_ns = _hblk,					\
> +		.bt601_hfp = _bt601_hfp,				\
> +		.vfp_lines = _vfp,					\
> +		.vslen_lines = _vslen,					\
> +		.vbp_lines = _vbp,					\
> +	}
> +
> +const static struct analog_parameters tv_modes_parameters[] = {
> +	TV_MODE_PARAMETER(DRM_MODE_ANALOG_NTSC,
> +			  NTSC_LINES_NUMBER,
> +			  NTSC_LINE_DURATION_NS,
> +			  PARAM_RANGE(NTSC_HACT_DURATION_MIN_NS,
> +				      NTSC_HACT_DURATION_TYP_NS,
> +				      NTSC_HACT_DURATION_MAX_NS),
> +			  PARAM_RANGE(NTSC_HFP_DURATION_MIN_NS,
> +				      NTSC_HFP_DURATION_TYP_NS,
> +				      NTSC_HFP_DURATION_MAX_NS),
> +			  PARAM_RANGE(NTSC_HSLEN_DURATION_MIN_NS,
> +				      NTSC_HSLEN_DURATION_TYP_NS,
> +				      NTSC_HSLEN_DURATION_MAX_NS),
> +			  PARAM_RANGE(NTSC_HBP_DURATION_MIN_NS,
> +				      NTSC_HBP_DURATION_TYP_NS,
> +				      NTSC_HBP_DURATION_MAX_NS),
> +			  PARAM_RANGE(NTSC_HBLK_DURATION_MIN_NS,
> +				      NTSC_HBLK_DURATION_TYP_NS,
> +				      NTSC_HBLK_DURATION_MAX_NS),
> +			  16,
> +			  PARAM_FIELD(3, 3),
> +			  PARAM_FIELD(3, 3),
> +			  PARAM_FIELD(16, 17)),
> +	TV_MODE_PARAMETER(DRM_MODE_ANALOG_PAL,
> +			  PAL_LINES_NUMBER,
> +			  PAL_LINE_DURATION_NS,
> +			  PARAM_RANGE(PAL_HACT_DURATION_MIN_NS,
> +				      PAL_HACT_DURATION_TYP_NS,
> +				      PAL_HACT_DURATION_MAX_NS),
> +			  PARAM_RANGE(PAL_HFP_DURATION_MIN_NS,
> +				      PAL_HFP_DURATION_TYP_NS,
> +				      PAL_HFP_DURATION_MAX_NS),
> +			  PARAM_RANGE(PAL_HSLEN_DURATION_MIN_NS,
> +				      PAL_HSLEN_DURATION_TYP_NS,
> +				      PAL_HSLEN_DURATION_MAX_NS),
> +			  PARAM_RANGE(PAL_HBP_DURATION_MIN_NS,
> +				      PAL_HBP_DURATION_TYP_NS,
> +				      PAL_HBP_DURATION_MAX_NS),
> +			  PARAM_RANGE(PAL_HBLK_DURATION_MIN_NS,
> +				      PAL_HBLK_DURATION_TYP_NS,
> +				      PAL_HBLK_DURATION_MAX_NS),
> +			  12,
> +
> +			  /*
> +			   * The front porch is actually 6 short sync
> +			   * pulses for the even field, and 5 for the
> +			   * odd field. Each sync takes half a life so
> +			   * the odd field front porch is shorter by
> +			   * half a line.
> +			   *
> +			   * In progressive, we're supposed to use 6
> +			   * pulses, so we're fine there
> +			   */
> +			  PARAM_FIELD(3, 2),
> +
> +			  /*
> +			   * The vsync length is 5 long sync pulses,
> +			   * each field taking half a line. We're
> +			   * shorter for both fields by half a line.
> +			   *
> +			   * In progressive, we're supposed to use 5
> +			   * pulses, so we're off by half
> +			   * a line.
> +			   *
> +			   * In interlace, we're now off by half a line
> +			   * for the even field and one line for the odd
> +			   * field.
> +			   */
> +			  PARAM_FIELD(3, 3),
> +
> +			  /*
> +			   * The back porch starts with post-equalizing
> +			   * pulses, consisting in 5 short sync pulses
> +			   * for the even field, 4 for the odd field. In
> +			   * progressive, it's 5 short syncs.
> +			   *
> +			   * In progressive, we thus have 2.5 lines,
> +			   * plus the 0.5 line we were missing
> +			   * previously, so we should use 3 lines.
> +			   *
> +			   * In interlace, the even field is in the
> +			   * exact same case than progressive. For the
> +			   * odd field, we should be using 2 lines but
> +			   * we're one line short, so we'll make up for
> +			   * it here by using 3.
> +			   *
> +			   * The entire blanking area is supposed to
> +			   * take 25 lines, so we also need to account
> +			   * for the rest of the blanking area that
> +			   * can't be in either the front porch or sync
> +			   * period.
> +			   */
> +			  PARAM_FIELD(19, 20)),
> +};
> +
> +static int fill_analog_mode(struct drm_device *dev,
> +			    struct drm_display_mode *mode,
> +			    const struct analog_parameters *params,
> +			    unsigned long pixel_clock_hz,
> +			    unsigned int hactive,
> +			    unsigned int vactive,
> +			    bool interlace)
> +{
> +	unsigned long pixel_duration_ns = NSEC_PER_SEC / pixel_clock_hz;
> +	unsigned int htotal, vtotal;
> +	unsigned int max_hact, hact_duration_ns;
> +	unsigned int hblk, hblk_duration_ns;
> +	unsigned int hfp, hfp_duration_ns;
> +	unsigned int hslen, hslen_duration_ns;
> +	unsigned int hbp, hbp_duration_ns;
> +	unsigned int porches, porches_duration_ns;
> +	unsigned int vfp, vfp_min;
> +	unsigned int vbp, vbp_min;
> +	unsigned int vslen;
> +	bool bt601 = false;
> +	int porches_rem;
> +	u64 result;
> +
> +	drm_dbg_kms(dev,
> +		    "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
> +		    hactive, vactive,
> +		    interlace ? 'i' : 'p',
> +		    params->num_lines,
> +		    pixel_clock_hz / 1000);

Divide by HZ_PER_KHZ here and in other places.

   https://elixir.bootlin.com/linux/latest/source/include/linux/units.h#L23

> +
> +	max_hact = params->hact_ns.max / pixel_duration_ns;
> +	if (pixel_clock_hz == 13500000 && hactive > max_hact && hactive <= 720) {
> +		drm_dbg_kms(dev, "Trying to generate a BT.601 mode. Disabling checks.\n");
> +		bt601 = true;
> +	}
> +
> +	/*
> +	 * Our pixel duration is going to be round down by the division,
> +	 * so rounding up is probably going to introduce even more
> +	 * deviation.
> +	 */
> +	result = (u64)params->line_duration_ns * pixel_clock_hz;
> +	do_div(result, NSEC_PER_SEC);
> +	htotal = result;
> +
> +	drm_dbg_kms(dev, "Total Horizontal Number of Pixels: %u\n", htotal);
> +
> +	hact_duration_ns = hactive * pixel_duration_ns;
> +	if (!bt601 &&
> +	    (hact_duration_ns < params->hact_ns.min ||
> +	     hact_duration_ns > params->hact_ns.max)) {
> +		DRM_ERROR("Invalid horizontal active area duration: %uns (min: %u, max %u)\n",
> +			  hact_duration_ns, params->hact_ns.min, params->hact_ns.max);
> +		return -EINVAL;
> +	}
> +
> +	hblk = htotal - hactive;
> +	drm_dbg_kms(dev, "Horizontal Blanking Period: %u\n", hblk);
> +
> +	hblk_duration_ns = hblk * pixel_duration_ns;
> +	if (!bt601 &&
> +	    (hblk_duration_ns < params->hblk_ns.min ||
> +	     hblk_duration_ns > params->hblk_ns.max)) {
> +		DRM_ERROR("Invalid horizontal blanking duration: %uns (min: %u, max %u)\n",
> +			  hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max);
> +		return -EINVAL;
> +	}
> +
> +	hslen = DIV_ROUND_UP(params->hslen_ns.typ, pixel_duration_ns);
> +	drm_dbg_kms(dev, "Horizontal Sync Period: %u\n", hslen);
> +
> +	hslen_duration_ns = hslen * pixel_duration_ns;
> +	if (!bt601 &&
> +	    (hslen_duration_ns < params->hslen_ns.min ||
> +	     hslen_duration_ns > params->hslen_ns.max)) {
> +		DRM_ERROR("Invalid horizontal sync duration: %uns (min: %u, max %u)\n",
> +			  hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max);
> +		return -EINVAL;
> +	}
> +
> +	porches = hblk - hslen;
> +	drm_dbg_kms(dev, "Remaining horizontal pixels for both porches: %u\n", porches);
> +
> +	porches_duration_ns = porches * pixel_duration_ns;
> +	if (!bt601 &&
> +	    (porches_duration_ns > (params->hfp_ns.max + params->hbp_ns.max) ||
> +	     porches_duration_ns < (params->hfp_ns.min + params->hbp_ns.min))) {
> +		DRM_ERROR("Invalid horizontal porches duration: %uns\n", porches_duration_ns);
> +		return -EINVAL;
> +	}
> +
> +	if (bt601) {
> +		hfp = params->bt601_hfp;
> +	} else {
> +		unsigned int hfp_min = DIV_ROUND_UP(params->hfp_ns.min,
> +						    pixel_duration_ns);
> +		unsigned int hbp_min = DIV_ROUND_UP(params->hbp_ns.min,
> +						    pixel_duration_ns);
> +		 int porches_rem = porches - hfp_min - hbp_min;
> +
> +		hfp = hfp_min + DIV_ROUND_UP(porches_rem, 2);
> +	}
> +
> +	drm_dbg_kms(dev, "Horizontal Front Porch: %u\n", hfp);
> +
> +	hfp_duration_ns = hfp * pixel_duration_ns;
> +	if (!bt601 &&
> +	    (hfp_duration_ns < params->hfp_ns.min ||
> +	     hfp_duration_ns > params->hfp_ns.max)) {
> +		DRM_ERROR("Invalid horizontal front porch duration: %uns (min: %u, max %u)\n",
> +			  hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max);
> +		return -EINVAL;
> +	}
> +
> +	hbp = porches - hfp;
> +	drm_dbg_kms(dev, "Horizontal Back Porch: %u\n", hbp);
> +
> +	hbp_duration_ns = hbp * pixel_duration_ns;
> +	if (!bt601 &&
> +	    (hbp_duration_ns < params->hbp_ns.min ||
> +	     hbp_duration_ns > params->hbp_ns.max)) {
> +		DRM_ERROR("Invalid horizontal back porch duration: %uns (min: %u, max %u)\n",
> +			  hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max);
> +		return -EINVAL;
> +	}
> +
> +	if (htotal != (hactive + hfp + hslen + hbp))
> +		return -EINVAL;
> +
> +	mode->clock = pixel_clock_hz / 1000;

HZ_PER_KHZ

> +	mode->hdisplay = hactive;
> +	mode->hsync_start = hactive + hfp;
> +	mode->hsync_end = hactive + hfp + hslen;
> +	mode->htotal = hactive + hfp + hslen + hbp;

I'd compute them from each other:

   hdisplay = hactive
   hsync_start = hactive + hfp
   hsynv_end  = hsync_start + hslen
   htotal = hsync_end + hbp

It's certainly a personal preference, but seems easier to see how they 
relate to each other.

> +
> +	if (interlace) {
> +		vfp_min = params->vfp_lines.even + params->vfp_lines.odd;
> +		vbp_min = params->vbp_lines.even + params->vbp_lines.odd;
> +		vslen = params->vslen_lines.even + params->vslen_lines.odd;
> +	} else {
> +		/*
> +		 * By convention, NSTC (aka 525/60) systems start with
> +		 * the even field, but PAL (aka 625/50) systems start
> +		 * with the odd one.
> +		 *
> +		 * PAL systems also have asymetric timings between the
> +		 * even and odd field, while NTSC is symetric.
> +		 *
> +		 * Moreover, if we want to create a progressive mode for
> +		 * PAL, we need to use the odd field timings.
> +		 *
> +		 * Since odd == even for NTSC, we can just use the odd
> +		 * one all the time to simplify the code a bit.
> +		 */
> +		vfp_min = params->vfp_lines.odd;
> +		vbp_min = params->vbp_lines.odd;
> +		vslen = params->vslen_lines.odd;
> +	}
> +
> +	drm_dbg_kms(dev, "Vertical Sync Period: %u\n", vslen);
> +
> +	porches = params->num_lines - vactive - vslen;
> +	drm_dbg_kms(dev, "Remaining vertical pixels for both porches: %u\n", porches);
> +
> +	porches_rem = porches - vfp_min - vbp_min;
> +	vfp = vfp_min + (porches_rem / 2);
> +	drm_dbg_kms(dev, "Vertical Front Porch: %u\n", vfp);
> +
> +	vbp = porches - vfp;
> +	drm_dbg_kms(dev, "Vertical Back Porch: %u\n", vbp);
> +
> +	vtotal = vactive + vfp + vslen + vbp;
> +	if (params->num_lines != vtotal) {
> +		DRM_ERROR("Invalid vertical total: %upx (expected %upx)\n",
> +			  vtotal, params->num_lines);
> +		return -EINVAL;
> +	}
> +
> +	mode->vdisplay = vactive;
> +	mode->vsync_start = vactive + vfp;
> +	mode->vsync_end = vactive + vfp + vslen;
> +	mode->vtotal = vactive + vfp + vslen + vbp;

Same comment as for the horizontal values.

> +
> +	mode->type = DRM_MODE_TYPE_DRIVER;
> +	mode->flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC;
> +	if (interlace)
> +		mode->flags |= DRM_MODE_FLAG_INTERLACE;
> +
> +	drm_mode_set_name(mode);
> +
> +	if (mode->vtotal != params->num_lines)
> +		return -EINVAL;

Should this test happen earlier?

> +
> +	drm_dbg_kms(dev, "Generated mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
> +
> +	return 0;
> +}
> +
> +/**
> + * drm_analog_tv_mode - create a display mode for an analog TV
> + * @dev: drm device
> + * @tv_mode: TV Mode standard to create a mode for. See DRM_MODE_TV_MODE_*.
> + * @pixel_clock_hz: Pixel Clock Frequency, in Hertz
> + * @hdisplay: hdisplay size
> + * @vdisplay: vdisplay size
> + * @interlace: whether to compute an interlaced mode
> + *
> + * This function creates a struct drm_display_mode instance suited for
> + * an analog TV output, for one of the usual analog TV mode.
> + *
> + * Note that @hdisplay is larger than the usual constraints for the PAL
> + * and NTSC timings, and we'll choose to ignore most timings constraints
> + * to reach those resolutions.
> + *
> + * Returns:
> + *
> + * A pointer to the mode, allocated with drm_mode_create(). Returns NULL
> + * on error.
> + */
> +struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
> +					    enum drm_connector_tv_mode tv_mode,
> +					    unsigned long pixel_clock_hz,
> +					    unsigned int hdisplay,
> +					    unsigned int vdisplay,
> +					    bool interlace)
> +{
> +	struct drm_display_mode *mode;
> +	enum drm_mode_analog analog;
> +	int ret;
> +
> +	switch (tv_mode) {
> +	case DRM_MODE_TV_MODE_NTSC:
> +		fallthrough;
> +	case DRM_MODE_TV_MODE_NTSC_443:
> +		fallthrough;
> +	case DRM_MODE_TV_MODE_NTSC_J:
> +		fallthrough;
> +	case DRM_MODE_TV_MODE_PAL_M:
> +		analog = DRM_MODE_ANALOG_NTSC;
> +		break;
> +
> +	case DRM_MODE_TV_MODE_PAL:
> +		fallthrough;
> +	case DRM_MODE_TV_MODE_PAL_N:
> +		fallthrough;
> +	case DRM_MODE_TV_MODE_SECAM:
> +		analog = DRM_MODE_ANALOG_PAL;
> +		break;
> +
> +	default:
> +		return NULL;
> +	}
> +
> +	mode = drm_mode_create(dev);
> +	if (!mode)
> +		return NULL;
> +
> +	ret = fill_analog_mode(dev, mode,
> +			       &tv_modes_parameters[analog],
> +			       pixel_clock_hz, hdisplay, vdisplay, interlace);
> +	if (ret)
> +		goto err_free_mode;
> +
> +	return mode;
> +
> +err_free_mode:
> +	drm_mode_destroy(dev, mode);
> +	return NULL;
> +}
> +EXPORT_SYMBOL(drm_analog_tv_mode);
> +
>   /**
>    * drm_cvt_mode -create a modeline based on the CVT algorithm
>    * @dev: drm device
> diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
> index b29ef1085cad..b22ac96fdd65 100644
> --- a/drivers/gpu/drm/tests/Makefile
> +++ b/drivers/gpu/drm/tests/Makefile
> @@ -10,5 +10,6 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
>   	drm_framebuffer_test.o \
>   	drm_kunit_helpers.o \
>   	drm_mm_test.o \
> +	drm_modes_test.o \
>   	drm_plane_helper_test.o \
>   	drm_rect_test.o
> diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c
> new file mode 100644
> index 000000000000..be1ff0e21022
> --- /dev/null
> +++ b/drivers/gpu/drm/tests/drm_modes_test.c
> @@ -0,0 +1,136 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Kunit test for drm_modes functions
> + */
> +
> +#include <kunit/test.h>
> +
> +#include <drm/drm_modes.h>
> +
> +#include "drm_kunit_helpers.h"
> +
> +struct drm_modes_test_priv {
> +	struct drm_device *drm;
> +};
> +
> +static int drm_modes_test_init(struct kunit *test)
> +{
> +	struct drm_modes_test_priv *priv;
> +
> +	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
> +	KUNIT_ASSERT_NOT_NULL(test, priv);
> +
> +	priv->drm = drm_kunit_device_init("drm-modes-test");
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
> +
> +	test->priv = priv;
> +
> +	return 0;
> +}
> +
> +static void drm_modes_test_exit(struct kunit *test)
> +{
> +	struct drm_modes_test_priv *priv = test->priv;
> +
> +	drm_kunit_device_exit(priv->drm);
> +}
> +
> +static void drm_modes_analog_tv_ntsc_480i(struct kunit *test)
> +{
> +	struct drm_modes_test_priv *priv = test->priv;
> +	struct drm_display_mode *mode;
> +
> +	mode = drm_analog_tv_mode(priv->drm,
> +				  DRM_MODE_TV_MODE_NTSC,
> +				  13500 * 1000, 720, 480,

HZ_PER_KHZ

> +				  true);
> +	KUNIT_ASSERT_NOT_NULL(test, mode);
> +
> +	KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 60);
> +	KUNIT_EXPECT_EQ(test, mode->hdisplay, 720);
> +
> +	/* BT.601 defines hsync_start at 736 for 480i */
> +	KUNIT_EXPECT_EQ(test, mode->hsync_start, 736);
> +
> +	/* 63.556us * 13.5MHz = 858 pixels */

I kind of get what the comment wants to tell me, but the units don't add 
up. I think you want to end up with 858 pixels/line =

   13,5 pixels/second / (60/2I frame/second * 525 lines/frame)

I: interlaced

Maybe just remove the short comments and document that in a more 
meaningful place.


> +	KUNIT_EXPECT_EQ(test, mode->htotal, 858);
> +	KUNIT_EXPECT_EQ(test, mode->vdisplay, 480);
> +	KUNIT_EXPECT_EQ(test, mode->vtotal, 525);
> +}
> +
> +static void drm_modes_analog_tv_ntsc_480i_inlined(struct kunit *test)
> +{
> +	struct drm_modes_test_priv *priv = test->priv;
> +	struct drm_display_mode *expected, *mode;
> +
> +	expected = drm_analog_tv_mode(priv->drm,
> +				      DRM_MODE_TV_MODE_NTSC,
> +				      13500 * 1000, 720, 480,

HZ_PER_KHZ

> +				      true);
> +	KUNIT_ASSERT_NOT_NULL(test, expected);
> +
> +	mode = drm_mode_analog_ntsc_480i(priv->drm);
> +	KUNIT_ASSERT_NOT_NULL(test, mode);
> +
> +	KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode));
> +}
> +
> +static void drm_modes_analog_tv_pal_576i(struct kunit *test)
> +{
> +	struct drm_modes_test_priv *priv = test->priv;
> +	struct drm_display_mode *mode;
> +
> +	mode = drm_analog_tv_mode(priv->drm,
> +				  DRM_MODE_TV_MODE_PAL,
> +				  13500 * 1000, 720, 576,
> +				  true);
> +	KUNIT_ASSERT_NOT_NULL(test, mode);
> +
> +	KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 50);
> +	KUNIT_EXPECT_EQ(test, mode->hdisplay, 720);
> +
> +	/* BT.601 defines hsync_start at 732 for 576i */
> +	KUNIT_EXPECT_EQ(test, mode->hsync_start, 732);
> +
> +	/* 64us * 13.5MHz = 864 pixels */
> +	KUNIT_EXPECT_EQ(test, mode->htotal, 864);
> +	KUNIT_EXPECT_EQ(test, mode->vdisplay, 576);
> +	KUNIT_EXPECT_EQ(test, mode->vtotal, 625);
> +}
> +
> +static void drm_modes_analog_tv_pal_576i_inlined(struct kunit *test)
> +{
> +	struct drm_modes_test_priv *priv = test->priv;
> +	struct drm_display_mode *expected, *mode;
> +
> +	expected = drm_analog_tv_mode(priv->drm,
> +				      DRM_MODE_TV_MODE_PAL,
> +				      13500 * 1000, 720, 576,
> +				      true);
> +	KUNIT_ASSERT_NOT_NULL(test, expected);
> +
> +	mode = drm_mode_analog_pal_576i(priv->drm);
> +	KUNIT_ASSERT_NOT_NULL(test, mode);
> +
> +	KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode));
> +}
> +
> +static struct kunit_case drm_modes_analog_tv_tests[] = {
> +	KUNIT_CASE(drm_modes_analog_tv_ntsc_480i),
> +	KUNIT_CASE(drm_modes_analog_tv_ntsc_480i_inlined),
> +	KUNIT_CASE(drm_modes_analog_tv_pal_576i),
> +	KUNIT_CASE(drm_modes_analog_tv_pal_576i_inlined),
> +	{ }
> +};
> +
> +static struct kunit_suite drm_modes_analog_tv_test_suite = {
> +	.name = "drm_modes_analog_tv",
> +	.init = drm_modes_test_init,
> +	.exit = drm_modes_test_exit,
> +	.test_cases = drm_modes_analog_tv_tests,
> +};
> +
> +kunit_test_suites(
> +	&drm_modes_analog_tv_test_suite
> +);
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
> index a80ae9639e96..dc03ce03e229 100644
> --- a/include/drm/drm_modes.h
> +++ b/include/drm/drm_modes.h
> @@ -443,6 +443,23 @@ bool drm_mode_is_420_also(const struct drm_display_info *display,
>   bool drm_mode_is_420(const struct drm_display_info *display,
>   		     const struct drm_display_mode *mode);
>   
> +struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
> +					    enum drm_connector_tv_mode mode,
> +					    unsigned long pixel_clock_hz,
> +					    unsigned int hdisplay,
> +					    unsigned int vdisplay,
> +					    bool interlace);
> +
> +static inline struct drm_display_mode *drm_mode_analog_ntsc_480i(struct drm_device *dev)
> +{
> +	return drm_analog_tv_mode(dev, DRM_MODE_TV_MODE_NTSC, 13500000, 720, 480, true);
> +}
> +
> +static inline struct drm_display_mode *drm_mode_analog_pal_576i(struct drm_device *dev)
> +{
> +	return drm_analog_tv_mode(dev, DRM_MODE_TV_MODE_PAL, 13500000, 720, 576, true);
> +}
> +
>   struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
>   				      int hdisplay, int vdisplay, int vrefresh,
>   				      bool reduced, bool interlaced,
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode()
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode() Maxime Ripard
@ 2022-09-23  9:15   ` Thomas Zimmermann
  2022-09-23  9:26     ` Javier Martinez Canillas
  2022-09-23 11:59   ` Jani Nikula
  1 sibling, 1 reply; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-23  9:15 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, Phil Elwell, nouveau, intel-gfx, linux-kernel,
	dri-devel, Mateusz Kwiatkowski, Hans de Goede,
	Noralf Trønnes, Geert Uytterhoeven, linux-sunxi,
	linux-arm-kernel


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

Hi

Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> drm_connector_pick_cmdline_mode() is in charge of finding a proper
> drm_display_mode from the definition we got in the video= command line
> argument.
> 
> Let's add some unit tests to make sure we're not getting any regressions
> there.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
> index bbc535cc50dd..d553e793e673 100644
> --- a/drivers/gpu/drm/drm_client_modeset.c
> +++ b/drivers/gpu/drm/drm_client_modeset.c
> @@ -1237,3 +1237,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
>   	return ret;
>   }
>   EXPORT_SYMBOL(drm_client_modeset_dpms);
> +
> +#ifdef CONFIG_DRM_KUNIT_TEST
> +#include "tests/drm_client_modeset_test.c"
> +#endif

I strongly dislike this style of including source files in each other. 
It's a recipe for all kind of build errors. Can you do something else?

As the tested function is an internal interface, maybe export a wrapper 
if tests are enabled, like this:

#ifdef CONFIG_DRM_KUNIT_TEST
struct drm_display_mode *
drm_connector_pick_cmdline_mode_kunit(drm_conenctor)
{
   return drm_connector_pick_cmdline_mode(connector)
}
EXPORT_SYMBOL(drm_connector_pick_cmdline_mode_kunit)
#endif

The wrapper's declaration can be located in the kunit test file.

Best regards
Thomas

> diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c
> new file mode 100644
> index 000000000000..46335de7bc6b
> --- /dev/null
> +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
> @@ -0,0 +1,114 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2022 Maxime Ripard <mripard@kernel.org>
> + */
> +
> +#include <kunit/test.h>
> +
> +#include <drm/drm_connector.h>
> +#include <drm/drm_edid.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_modes.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +#include <drm/drm_probe_helper.h>
> +
> +#include "drm_kunit_helpers.h"
> +
> +struct drm_client_modeset_test_priv {
> +	struct drm_device *drm;
> +	struct drm_connector connector;
> +};
> +
> +static int drm_client_modeset_connector_get_modes(struct drm_connector *connector)
> +{
> +	struct drm_display_mode *mode;
> +	int count;
> +
> +	count = drm_add_modes_noedid(connector, 1920, 1200);
> +
> +	return count;
> +}
> +
> +static const struct drm_connector_helper_funcs drm_client_modeset_connector_helper_funcs = {
> +	.get_modes = drm_client_modeset_connector_get_modes,
> +};
> +
> +static const struct drm_connector_funcs drm_client_modeset_connector_funcs = {
> +};
> +
> +static int drm_client_modeset_test_init(struct kunit *test)
> +{
> +	struct drm_client_modeset_test_priv *priv;
> +	int ret;
> +
> +	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +	test->priv = priv;
> +
> +	priv->drm = drm_kunit_device_init("drm-client-modeset-test");
> +	if (IS_ERR(priv->drm))
> +		return PTR_ERR(priv->drm);
> +
> +	ret = drmm_connector_init(priv->drm, &priv->connector,
> +				  &drm_client_modeset_connector_funcs,
> +				  DRM_MODE_CONNECTOR_Unknown,
> +				  NULL);
> +	if (ret)
> +		return ret;
> +	drm_connector_helper_add(&priv->connector, &drm_client_modeset_connector_helper_funcs);
> +
> +	return 0;
> +}
> +
> +static void drm_client_modeset_test_exit(struct kunit *test)
> +{
> +	struct drm_client_modeset_test_priv *priv = test->priv;
> +
> +	drm_kunit_device_exit(priv->drm);
> +}
> +
> +static void drm_pick_cmdline_res_1920_1080_60(struct kunit *test)
> +{
> +	struct drm_client_modeset_test_priv *priv = test->priv;
> +	struct drm_device *drm = priv->drm;
> +	struct drm_connector *connector = &priv->connector;
> +	struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
> +	struct drm_display_mode *expected_mode, *mode;
> +	const char *cmdline = "1920x1080@60";
> +	int ret;
> +
> +	expected_mode = drm_mode_find_dmt(priv->drm, 1920, 1080, 60, false);
> +	KUNIT_ASSERT_PTR_NE(test, expected_mode, NULL);
> +
> +	KUNIT_ASSERT_TRUE(test,
> +			  drm_mode_parse_command_line_for_connector(cmdline,
> +								    connector,
> +								    cmdline_mode));
> +
> +	mutex_lock(&drm->mode_config.mutex);
> +	ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
> +	mutex_unlock(&drm->mode_config.mutex);
> +	KUNIT_ASSERT_GT(test, ret, 0);
> +
> +	mode = drm_connector_pick_cmdline_mode(connector);
> +	KUNIT_ASSERT_PTR_NE(test, mode, NULL);
> +
> +	KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
> +}
> +
> +static struct kunit_case drm_pick_cmdline_tests[] = {
> +	KUNIT_CASE(drm_pick_cmdline_res_1920_1080_60),
> +	{}
> +};
> +
> +static struct kunit_suite drm_pick_cmdline_test_suite = {
> +	.name = "drm_pick_cmdline",
> +	.init = drm_client_modeset_test_init,
> +	.exit = drm_client_modeset_test_exit,
> +	.test_cases = drm_pick_cmdline_tests
> +};
> +
> +kunit_test_suite(drm_pick_cmdline_test_suite);
> +MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
> +MODULE_LICENSE("GPL");
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-23  9:05   ` Thomas Zimmermann
@ 2022-09-23  9:18     ` Jani Nikula
  2022-09-23 10:16       ` Thomas Zimmermann
  2022-09-26 10:17     ` Maxime Ripard
  1 sibling, 1 reply; 75+ messages in thread
From: Jani Nikula @ 2022-09-23  9:18 UTC (permalink / raw)
  To: Thomas Zimmermann, Maxime Ripard, Jernej Skrabec, Rodrigo Vivi,
	Ben Skeggs, David Airlie, Maxime Ripard, Joonas Lahtinen,
	Emma Anholt, Karol Herbst, Samuel Holland, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel

On Fri, 23 Sep 2022, Thomas Zimmermann <tzimmermann@suse.de> wrote:
> Am 22.09.22 um 16:25 schrieb Maxime Ripard:
>> +	drm_dbg_kms(dev,
>> +		    "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
>> +		    hactive, vactive,
>> +		    interlace ? 'i' : 'p',
>> +		    params->num_lines,
>> +		    pixel_clock_hz / 1000);
>
> Divide by HZ_PER_KHZ here and in other places.
>
>    https://elixir.bootlin.com/linux/latest/source/include/linux/units.h#L23

From the Department of Bikeshedding:

I find "pixel_clock_hz / 1000" has much more clarity than
"pixel_clock_hz / HZ_PER_KHZ".

I don't consider the SI prefixes magic numbers.


BR,
Jani.

-- 
Jani Nikula, Intel Open Source Graphics Center

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

* Re: [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode()
  2022-09-23  9:15   ` Thomas Zimmermann
@ 2022-09-23  9:26     ` Javier Martinez Canillas
  2022-09-23 10:30       ` Thomas Zimmermann
  0 siblings, 1 reply; 75+ messages in thread
From: Javier Martinez Canillas @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Thomas Zimmermann, Maxime Ripard, Jernej Skrabec, Rodrigo Vivi,
	Ben Skeggs, David Airlie, Maxime Ripard, Joonas Lahtinen,
	Emma Anholt, Karol Herbst, Samuel Holland, Jani Nikula,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	Mateusz Kwiatkowski, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, linux-sunxi, Phil Elwell, linux-arm-kernel

On 9/23/22 11:15, Thomas Zimmermann wrote:
> Hi
> 
> Am 22.09.22 um 16:25 schrieb Maxime Ripard:
>> drm_connector_pick_cmdline_mode() is in charge of finding a proper
>> drm_display_mode from the definition we got in the video= command line
>> argument.
>>
>> Let's add some unit tests to make sure we're not getting any regressions
>> there.
>>
>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>
>> diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
>> index bbc535cc50dd..d553e793e673 100644
>> --- a/drivers/gpu/drm/drm_client_modeset.c
>> +++ b/drivers/gpu/drm/drm_client_modeset.c
>> @@ -1237,3 +1237,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
>>   	return ret;
>>   }
>>   EXPORT_SYMBOL(drm_client_modeset_dpms);
>> +
>> +#ifdef CONFIG_DRM_KUNIT_TEST
>> +#include "tests/drm_client_modeset_test.c"
>> +#endif
> 
> I strongly dislike this style of including source files in each other. 
> It's a recipe for all kind of build errors. Can you do something else?
>

This seems to be the convention used to test static functions and what's
documented in the Kunit docs: https://kunit.dev/third_party/kernel/docs/tips.html#testing-static-functions

I agree with you that's not ideal but I think that consistency with how
it is done by other subsystems is also important.
 
> As the tested function is an internal interface, maybe export a wrapper 
> if tests are enabled, like this:
> 
> #ifdef CONFIG_DRM_KUNIT_TEST
> struct drm_display_mode *
> drm_connector_pick_cmdline_mode_kunit(drm_conenctor)
> {
>    return drm_connector_pick_cmdline_mode(connector)
> }
> EXPORT_SYMBOL(drm_connector_pick_cmdline_mode_kunit)
> #endif
> 
> The wrapper's declaration can be located in the kunit test file.
> 

But that's also not nice since we are artificially exposing these only
to allow the static functions to be called from unit tests. And would
be a different approach than the one used by all other subsystems...

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-23  9:18     ` Jani Nikula
@ 2022-09-23 10:16       ` Thomas Zimmermann
  2022-09-26 10:18         ` Maxime Ripard
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-23 10:16 UTC (permalink / raw)
  To: Jani Nikula, Maxime Ripard, Jernej Skrabec, Rodrigo Vivi,
	Ben Skeggs, David Airlie, Maxime Ripard, Joonas Lahtinen,
	Emma Anholt, Karol Herbst, Samuel Holland, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel


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

Hi

Am 23.09.22 um 11:18 schrieb Jani Nikula:
> On Fri, 23 Sep 2022, Thomas Zimmermann <tzimmermann@suse.de> wrote:
>> Am 22.09.22 um 16:25 schrieb Maxime Ripard:
>>> +	drm_dbg_kms(dev,
>>> +		    "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
>>> +		    hactive, vactive,
>>> +		    interlace ? 'i' : 'p',
>>> +		    params->num_lines,
>>> +		    pixel_clock_hz / 1000);
>>
>> Divide by HZ_PER_KHZ here and in other places.
>>
>>     https://elixir.bootlin.com/linux/latest/source/include/linux/units.h#L23
> 
>  From the Department of Bikeshedding:
> 
> I find "pixel_clock_hz / 1000" has much more clarity than
> "pixel_clock_hz / HZ_PER_KHZ".

This one's easy to see because it tells you with the _hz postfix. Many 
places don't and then it quickly gets confusing what units the code's 
converting.

Best regards
Thomas

> 
> I don't consider the SI prefixes magic numbers.
> 
> 
> BR,
> Jani.
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode()
  2022-09-23  9:26     ` Javier Martinez Canillas
@ 2022-09-23 10:30       ` Thomas Zimmermann
  2022-09-23 11:01         ` Javier Martinez Canillas
  2022-09-23 11:14         ` Maxime Ripard
  0 siblings, 2 replies; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-23 10:30 UTC (permalink / raw)
  To: Javier Martinez Canillas, Maxime Ripard, Jernej Skrabec,
	Rodrigo Vivi, Ben Skeggs, David Airlie, Maxime Ripard,
	Joonas Lahtinen, Emma Anholt, Karol Herbst, Samuel Holland,
	Jani Nikula, Daniel Vetter, Lyude Paul, Maarten Lankhorst,
	Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	Mateusz Kwiatkowski, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, linux-sunxi, Phil Elwell, linux-arm-kernel


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

Hi

Am 23.09.22 um 11:26 schrieb Javier Martinez Canillas:
> On 9/23/22 11:15, Thomas Zimmermann wrote:
>> Hi
>>
>> Am 22.09.22 um 16:25 schrieb Maxime Ripard:
>>> drm_connector_pick_cmdline_mode() is in charge of finding a proper
>>> drm_display_mode from the definition we got in the video= command line
>>> argument.
>>>
>>> Let's add some unit tests to make sure we're not getting any regressions
>>> there.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>>
>>> diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
>>> index bbc535cc50dd..d553e793e673 100644
>>> --- a/drivers/gpu/drm/drm_client_modeset.c
>>> +++ b/drivers/gpu/drm/drm_client_modeset.c
>>> @@ -1237,3 +1237,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
>>>    	return ret;
>>>    }
>>>    EXPORT_SYMBOL(drm_client_modeset_dpms);
>>> +
>>> +#ifdef CONFIG_DRM_KUNIT_TEST
>>> +#include "tests/drm_client_modeset_test.c"
>>> +#endif
>>
>> I strongly dislike this style of including source files in each other.
>> It's a recipe for all kind of build errors. Can you do something else?
>>
> 
> This seems to be the convention used to test static functions and what's
> documented in the Kunit docs: https://kunit.dev/third_party/kernel/docs/tips.html#testing-static-functions

That document says "...one option is to conditionally #include the test 
file...". This doesn't sound like a strong requirement.

> 
> I agree with you that's not ideal but I think that consistency with how
> it is done by other subsystems is also important.
>   
>> As the tested function is an internal interface, maybe export a wrapper
>> if tests are enabled, like this:
>>
>> #ifdef CONFIG_DRM_KUNIT_TEST
>> struct drm_display_mode *
>> drm_connector_pick_cmdline_mode_kunit(drm_conenctor)
>> {
>>     return drm_connector_pick_cmdline_mode(connector)
>> }
>> EXPORT_SYMBOL(drm_connector_pick_cmdline_mode_kunit)
>> #endif
>>
>> The wrapper's declaration can be located in the kunit test file.
>>
> 
> But that's also not nice since we are artificially exposing these only
> to allow the static functions to be called from unit tests. And would
> be a different approach than the one used by all other subsystems...
> 

There's the problem of interference between the source files when 
building the code. It's also not the same source code after including 
the test file. At a minimum, including the tests' source file further 
includes more files. <kunit/tests.h> also includes quite a few of Linux 
header files.

IMHO the current convention (if any) is far from optimal and we should 
consider breaking it.

Best regards
Thomas

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode()
  2022-09-23 10:30       ` Thomas Zimmermann
@ 2022-09-23 11:01         ` Javier Martinez Canillas
  2022-09-23 11:14         ` Maxime Ripard
  1 sibling, 0 replies; 75+ messages in thread
From: Javier Martinez Canillas @ 2022-09-23 11:01 UTC (permalink / raw)
  To: Thomas Zimmermann, Maxime Ripard, Jernej Skrabec, Rodrigo Vivi,
	Ben Skeggs, David Airlie, Maxime Ripard, Joonas Lahtinen,
	Emma Anholt, Karol Herbst, Samuel Holland, Jani Nikula,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	Mateusz Kwiatkowski, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, linux-sunxi, Phil Elwell, linux-arm-kernel

On 9/23/22 12:30, Thomas Zimmermann wrote:

[...]

>>>> +
>>>> +#ifdef CONFIG_DRM_KUNIT_TEST
>>>> +#include "tests/drm_client_modeset_test.c"
>>>> +#endif
>>>
>>> I strongly dislike this style of including source files in each other.
>>> It's a recipe for all kind of build errors. Can you do something else?
>>>
>>
>> This seems to be the convention used to test static functions and what's
>> documented in the Kunit docs: https://kunit.dev/third_party/kernel/docs/tips.html#testing-static-functions
> 
> That document says "...one option is to conditionally #include the test 
> file...". This doesn't sound like a strong requirement.
>

That's true.

>>
>> I agree with you that's not ideal but I think that consistency with how
>> it is done by other subsystems is also important.
>>   
>>> As the tested function is an internal interface, maybe export a wrapper
>>> if tests are enabled, like this:
>>>
>>> #ifdef CONFIG_DRM_KUNIT_TEST
>>> struct drm_display_mode *
>>> drm_connector_pick_cmdline_mode_kunit(drm_conenctor)
>>> {
>>>     return drm_connector_pick_cmdline_mode(connector)
>>> }
>>> EXPORT_SYMBOL(drm_connector_pick_cmdline_mode_kunit)
>>> #endif
>>>
>>> The wrapper's declaration can be located in the kunit test file.
>>>
>>
>> But that's also not nice since we are artificially exposing these only
>> to allow the static functions to be called from unit tests. And would
>> be a different approach than the one used by all other subsystems...
>>
> 
> There's the problem of interference between the source files when 
> building the code. It's also not the same source code after including 
> the test file. At a minimum, including the tests' source file further 
> includes more files. <kunit/tests.h> also includes quite a few of Linux 
> header files.
> 
> IMHO the current convention (if any) is far from optimal and we should 
> consider breaking it.
>

Yes, I agree with that. But probably we should be explicit about the
wrapper export symbols to access static functions pattern in the KUnit
docs so other subsystems could do the same and it becomes a convention ?
 
> Best regards
> Thomas
> 

-- 
Best regards,

Javier Martinez Canillas
Core Platforms
Red Hat


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

* Re: [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode()
  2022-09-23 10:30       ` Thomas Zimmermann
  2022-09-23 11:01         ` Javier Martinez Canillas
@ 2022-09-23 11:14         ` Maxime Ripard
  1 sibling, 0 replies; 75+ messages in thread
From: Maxime Ripard @ 2022-09-23 11:14 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Javier Martinez Canillas,
	Jernej Skrabec, Chen-Yu Tsai, Geert Uytterhoeven, Ben Skeggs,
	linux-sunxi, intel-gfx, Maarten Lankhorst, Jani Nikula,
	Hans de Goede, Rodrigo Vivi, linux-arm-kernel, Tvrtko Ursulin,
	Dom Cobley, linux-kernel, Mateusz Kwiatkowski,
	Noralf Trønnes, Daniel Vetter

[-- Attachment #1: Type: text/plain, Size: 3714 bytes --]

On Fri, Sep 23, 2022 at 12:30:09PM +0200, Thomas Zimmermann wrote:
> Am 23.09.22 um 11:26 schrieb Javier Martinez Canillas:
> > On 9/23/22 11:15, Thomas Zimmermann wrote:
> > > Hi
> > > 
> > > Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> > > > drm_connector_pick_cmdline_mode() is in charge of finding a proper
> > > > drm_display_mode from the definition we got in the video= command line
> > > > argument.
> > > > 
> > > > Let's add some unit tests to make sure we're not getting any regressions
> > > > there.
> > > > 
> > > > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > > > 
> > > > diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
> > > > index bbc535cc50dd..d553e793e673 100644
> > > > --- a/drivers/gpu/drm/drm_client_modeset.c
> > > > +++ b/drivers/gpu/drm/drm_client_modeset.c
> > > > @@ -1237,3 +1237,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
> > > >    	return ret;
> > > >    }
> > > >    EXPORT_SYMBOL(drm_client_modeset_dpms);
> > > > +
> > > > +#ifdef CONFIG_DRM_KUNIT_TEST
> > > > +#include "tests/drm_client_modeset_test.c"
> > > > +#endif
> > > 
> > > I strongly dislike this style of including source files in each other.
> > > It's a recipe for all kind of build errors. Can you do something else?
> > > 
> > 
> > This seems to be the convention used to test static functions and what's
> > documented in the Kunit docs: https://kunit.dev/third_party/kernel/docs/tips.html#testing-static-functions
> 
> That document says "...one option is to conditionally #include the test
> file...". This doesn't sound like a strong requirement.

No, but this is the only option documented, which still indicates a very
strong preference.

> > I agree with you that's not ideal but I think that consistency with how
> > it is done by other subsystems is also important.
> > > As the tested function is an internal interface, maybe export a wrapper
> > > if tests are enabled, like this:
> > > 
> > > #ifdef CONFIG_DRM_KUNIT_TEST
> > > struct drm_display_mode *
> > > drm_connector_pick_cmdline_mode_kunit(drm_conenctor)
> > > {
> > >     return drm_connector_pick_cmdline_mode(connector)
> > > }
> > > EXPORT_SYMBOL(drm_connector_pick_cmdline_mode_kunit)
> > > #endif
> > > 
> > > The wrapper's declaration can be located in the kunit test file.

And I'm afraid this just doesn't scale. If we start testing more and
more static functions, do we really want to have that wrapper for each
of them?

> > But that's also not nice since we are artificially exposing these only
> > to allow the static functions to be called from unit tests. And would
> > be a different approach than the one used by all other subsystems...
> > 
> 
> There's the problem of interference between the source files when building
> the code. It's also not the same source code after including the test file.
> At a minimum, including the tests' source file further includes more files.
> <kunit/tests.h> also includes quite a few of Linux header files.
> 
> IMHO the current convention (if any) is far from optimal and we should
> consider breaking it.

I mean... this is a discussion about theoretical issues. If there is
indeed some regular build errors on this, then sure, we can change it.

I'm confident that will affect pretty much every one using kunit equally
though, so I'm fairly sure the documentation itself will have changed.

But right now we're discussing an alternative because of a problem we
never experienced. I don't see the point of breaking the consistency
provided by the documentation for something not backed by any actual
problem.

Maxime

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

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

* Re: [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode()
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode() Maxime Ripard
  2022-09-23  9:15   ` Thomas Zimmermann
@ 2022-09-23 11:59   ` Jani Nikula
  1 sibling, 0 replies; 75+ messages in thread
From: Jani Nikula @ 2022-09-23 11:59 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Thomas Zimmermann, Daniel Vetter,
	Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin, Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Maxime Ripard, Mateusz Kwiatkowski,
	Phil Elwell, linux-arm-kernel

On Thu, 22 Sep 2022, Maxime Ripard <maxime@cerno.tech> wrote:
> drm_connector_pick_cmdline_mode() is in charge of finding a proper
> drm_display_mode from the definition we got in the video= command line
> argument.
>
> Let's add some unit tests to make sure we're not getting any regressions
> there.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>
> diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
> index bbc535cc50dd..d553e793e673 100644
> --- a/drivers/gpu/drm/drm_client_modeset.c
> +++ b/drivers/gpu/drm/drm_client_modeset.c
> @@ -1237,3 +1237,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
>  	return ret;
>  }
>  EXPORT_SYMBOL(drm_client_modeset_dpms);
> +
> +#ifdef CONFIG_DRM_KUNIT_TEST
> +#include "tests/drm_client_modeset_test.c"
> +#endif
> diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c
> new file mode 100644
> index 000000000000..46335de7bc6b
> --- /dev/null
> +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c

[snip]

> +MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
> +MODULE_LICENSE("GPL");

I think these annotations are incompatible with including the unit test,
and, in this case, affect drm.ko.

And we'll have two kinds of tests, those that get built via
tests/Makefile, and those that get included, like this one, which should
not be mentioned in tests/Makefile.

BR,
Jani.

-- 
Jani Nikula, Intel Open Source Graphics Center

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

* Re: [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property Maxime Ripard
  2022-09-22 20:44   ` Lyude Paul
  2022-09-23  8:19   ` Thomas Zimmermann
@ 2022-09-24 15:38   ` Noralf Trønnes
  2 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 15:38 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> The current tv_mode has driver-specific values that don't allow to
> easily share code using it, either at the userspace or kernel level.
> 
> Since we're going to introduce a new, generic, property that fit the
> same purpose, let's rename this one to legacy_tv_mode to make it
> obvious we should move away from it.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 

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

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

* Re: [Nouveau] [PATCH v2 08/33] drm/connector: Rename drm_mode_create_tv_properties
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 08/33] drm/connector: Rename drm_mode_create_tv_properties Maxime Ripard
  2022-09-22 20:45   ` Lyude Paul
@ 2022-09-24 15:43   ` Noralf Trønnes
  1 sibling, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 15:43 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> drm_mode_create_tv_properties(), among other things, will create the
> "mode" property that stores the analog TV mode that connector is
> supposed to output.
> 
> However, that property is getting deprecated, so let's rename that
> function to mention it's deprecated. We'll introduce a new variant of
> that function creating the property superseeding it in a later patch.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 

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

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

* Re: [Nouveau] [PATCH v2 09/33] drm/connector: Add TV standard property
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 09/33] drm/connector: Add TV standard property Maxime Ripard
@ 2022-09-24 15:52   ` Noralf Trønnes
  2022-09-26 10:01     ` Maxime Ripard
  0 siblings, 1 reply; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 15:52 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> The TV mode property has been around for a while now to select and get the
> current TV mode output on an analog TV connector.
> 
> Despite that property name being generic, its content isn't and has been
> driver-specific which makes it hard to build any generic behaviour on top
> of it, both in kernel and user-space.
> 
> Let's create a new enum tv norm property, that can contain any of the
> analog TV standards currently supported by kernel drivers. Each driver can
> then pass in a bitmask of the modes it supports, and the property
> creation function will filter out the modes not supported.
> 
> We'll then be able to phase out the older tv mode property.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 

Please can you add per patch changelogs, it's hard to review when I have
to recall what might have happened with each patch. If you do it drm
style and put in the commit message it should be easy enough to do.

> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 4e4fbc9e0049..e7aa8de08f5b 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -980,6 +980,18 @@ static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = {
>  DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
>  		 drm_dvi_i_subconnector_enum_list)
>  
> +static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = {
> +	{ DRM_MODE_TV_MODE_NONE, "None" },
> +	{ DRM_MODE_TV_MODE_NTSC, "NTSC" },

I think going back to plain NTSC and PAL is a good choice for the common
variants.

> +	{ DRM_MODE_TV_MODE_NTSC_443, "NTSC-443" },
> +	{ DRM_MODE_TV_MODE_NTSC_J, "NTSC-J" },
> +	{ DRM_MODE_TV_MODE_PAL, "PAL" },
> +	{ DRM_MODE_TV_MODE_PAL_M, "PAL-M" },
> +	{ DRM_MODE_TV_MODE_PAL_N, "PAL-N" },
> +	{ DRM_MODE_TV_MODE_SECAM, "SECAM" },
> +};
> +DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list)
> +
>  static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
>  	{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
>  	{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
> @@ -1645,6 +1657,10 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties);
>   * responsible for allocating a list of format names and passing them to
>   * this routine.
>   *
> + * NOTE: This functions registers the deprecated "mode" connector
> + * property to select the analog TV mode (ie, NTSC, PAL, etc.). New
> + * drivers must use drm_mode_create_tv_properties() instead.
> + *
>   * Returns:
>   * 0 on success or a negative error code on failure.
>   */
> @@ -1686,7 +1702,6 @@ int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
>  	if (drm_mode_create_tv_margin_properties(dev))
>  		goto nomem;
>  
> -
>  	if (num_modes) {
>  		dev->mode_config.legacy_tv_mode_property =
>  			drm_property_create(dev, DRM_MODE_PROP_ENUM,
> @@ -1735,6 +1750,49 @@ int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
>  }
>  EXPORT_SYMBOL(drm_mode_create_tv_properties_legacy);
>  
> +/**
> + * drm_mode_create_tv_properties - create TV specific connector properties
> + * @dev: DRM device
> + * @supported_tv_modes: Bitmask of TV modes supported (See DRM_MODE_TV_MODE_*)
> +
> + * Called by a driver's TV initialization routine, this function creates
> + * the TV specific connector properties for a given device.  Caller is
> + * responsible for allocating a list of format names and passing them to
> + * this routine.

Copy-paste error, there are no format names in this version.

> + *
> + * Returns:
> + * 0 on success or a negative error code on failure.
> + */
> +int drm_mode_create_tv_properties(struct drm_device *dev,
> +				  unsigned int supported_tv_modes)
> +{
> +	struct drm_prop_enum_list tv_mode_list[DRM_MODE_TV_MODE_MAX];
> +	struct drm_property *tv_mode;
> +	unsigned int i, len = 0;
> +
> +	if (dev->mode_config.tv_mode_property)
> +		return 0;
> +
> +	for (i = 0; i < DRM_MODE_TV_MODE_MAX; i++) {
> +		if (!(supported_tv_modes & BIT(i)))
> +			continue;
> +
> +		tv_mode_list[len].type = i;
> +		tv_mode_list[len].name = drm_get_tv_mode_name(i);
> +		len++;
> +	}
> +
> +	tv_mode = drm_property_create_enum(dev, 0, "TV mode",
> +					   tv_mode_list, len);
> +	if (!tv_mode)
> +		return -ENOMEM;
> +
> +	dev->mode_config.tv_mode_property = tv_mode;
> +
> +	return drm_mode_create_tv_properties_legacy(dev, 0, NULL);
> +}
> +EXPORT_SYMBOL(drm_mode_create_tv_properties);
> +
>  /**
>   * drm_mode_create_scaling_mode_property - create scaling mode property
>   * @dev: DRM device
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index d566b4a4709c..fffacbfd0a45 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -143,6 +143,71 @@ enum subpixel_order {
>  
>  };
>  
> +/**
> + * enum drm_connector_tv_mode - Analog TV output mode
> + *
> + * This enum is used to indicate the TV output mode used on an analog TV
> + * connector.
> + *
> + * WARNING: The values of this enum is uABI since they're exposed in the
> + * "TV mode" connector property.
> + */
> +enum drm_connector_tv_mode {
> +	/**
> +	 * @DRM_MODE_TV_MODE_NONE: Placeholder to not default on one
> +	 * variant or the other when nothing is set.
> +	 */
> +	DRM_MODE_TV_MODE_NONE = 0,

How is this supposed to be used?

Noralf.

> +
> +	/**
> +	 * @DRM_MODE_TV_MODE_NTSC: CCIR System M (aka 525-lines)
> +	 * together with the NTSC Color Encoding.
> +	 */
> +	DRM_MODE_TV_MODE_NTSC,
> +
> +	/**
> +	 * @DRM_MODE_TV_MODE_NTSC_443: Variant of
> +	 * @DRM_MODE_TV_MODE_NTSC. Uses a color subcarrier frequency
> +	 * of 4.43 MHz.
> +	 */
> +	DRM_MODE_TV_MODE_NTSC_443,
> +
> +	/**
> +	 * @DRM_MODE_TV_MODE_NTSC_J: Variant of @DRM_MODE_TV_MODE_NTSC
> +	 * used in Japan. Uses a black level equals to the blanking
> +	 * level.
> +	 */
> +	DRM_MODE_TV_MODE_NTSC_J,
> +
> +	/**
> +	 * @DRM_MODE_TV_MODE_PAL: CCIR System B together with the PAL
> +	 * color system.
> +	 */
> +	DRM_MODE_TV_MODE_PAL,
> +
> +	/**
> +	 * @DRM_MODE_TV_MODE_PAL_M: CCIR System M (aka 525-lines)
> +	 * together with the PAL color encoding
> +	 */
> +	DRM_MODE_TV_MODE_PAL_M,
> +
> +	/**
> +	 * @DRM_MODE_TV_MODE_PAL_N: CCIR System N together with the PAL
> +	 * color encoding. It uses 625 lines, but has a color subcarrier
> +	 * frequency of 3.58MHz, the SECAM color space, and narrower
> +	 * channels compared to most of the other PAL variants.
> +	 */
> +	DRM_MODE_TV_MODE_PAL_N,
> +
> +	/**
> +	 * @DRM_MODE_TV_MODE_SECAM: CCIR System B together with the
> +	 * SECAM color system.
> +	 */
> +	DRM_MODE_TV_MODE_SECAM,
> +
> +	DRM_MODE_TV_MODE_MAX,
> +};
> +
>  /**
>   * struct drm_scrambling: sink's scrambling support.
>   */
> @@ -696,6 +761,7 @@ struct drm_connector_tv_margins {
>   * @subconnector: detected subconnector
>   * @margins: TV margins
>   * @legacy_mode: Legacy TV mode, driver specific value
> + * @mode: TV mode
>   * @brightness: brightness in percent
>   * @contrast: contrast in percent
>   * @flicker_reduction: flicker reduction in percent
> @@ -708,6 +774,7 @@ struct drm_tv_connector_state {
>  	enum drm_mode_subconnector subconnector;
>  	struct drm_connector_tv_margins margins;
>  	unsigned int legacy_mode;
> +	unsigned int mode;
>  	unsigned int brightness;
>  	unsigned int contrast;
>  	unsigned int flicker_reduction;
> @@ -1789,6 +1856,7 @@ const char *drm_get_subpixel_order_name(enum subpixel_order order);
>  const char *drm_get_dpms_name(int val);
>  const char *drm_get_dvi_i_subconnector_name(int val);
>  const char *drm_get_dvi_i_select_name(int val);
> +const char *drm_get_tv_mode_name(int val);
>  const char *drm_get_tv_subconnector_name(int val);
>  const char *drm_get_tv_select_name(int val);
>  const char *drm_get_dp_subconnector_name(int val);
> @@ -1802,6 +1870,8 @@ int drm_mode_create_tv_margin_properties(struct drm_device *dev);
>  int drm_mode_create_tv_properties_legacy(struct drm_device *dev,
>  					 unsigned int num_modes,
>  					 const char * const modes[]);
> +int drm_mode_create_tv_properties(struct drm_device *dev,
> +				  unsigned int supported_tv_modes);
>  void drm_connector_attach_tv_margin_properties(struct drm_connector *conn);
>  int drm_mode_create_scaling_mode_property(struct drm_device *dev);
>  int drm_connector_attach_content_type_property(struct drm_connector *dev);
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 35a827175c24..10a6f7d1df0d 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -718,9 +718,17 @@ struct drm_mode_config {
>  	/**
>  	 * @legacy_tv_mode_property: Optional TV property to select
>  	 * the output TV mode.
> +	 *
> +	 * Superseeded by @tv_mode_property
>  	 */
>  	struct drm_property *legacy_tv_mode_property;
>  
> +	/**
> +	 * @tv_mode_property: Optional TV property to select the TV
> +	 * standard output on the connector.
> +	 */
> +	struct drm_property *tv_mode_property;
> +
>  	/**
>  	 * @tv_left_margin_property: Optional TV property to set the left
>  	 * margin (expressed in pixels).
> 

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

* Re: [Nouveau] [PATCH v2 27/33] drm/atomic-helper: Add an analog TV atomic_check implementation
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 27/33] drm/atomic-helper: Add an analog TV atomic_check implementation Maxime Ripard
@ 2022-09-24 15:58   ` Noralf Trønnes
  0 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 15:58 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> The analog TV connector drivers share some atomic_check logic, and the new
> TV standard property have created a bunch of new constraints that needs to
> be shared across drivers too.

The constraints part doesn't apply anymore after removing the display
mode check. It's only about detecting changes now.

Noralf.

> 
> Let's create an atomic_check helper for those use cases.
> 
> Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
> index 0373c3dc824b..e88c57a4f7be 100644
> --- a/drivers/gpu/drm/drm_atomic_state_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_state_helper.c
> @@ -556,6 +556,55 @@ void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
>  
> +/**
> + * @drm_atomic_helper_connector_tv_check: Validate an analog TV connector state
> + * @connector: DRM Connector
> + * @state: the DRM State object
> + *
> + * Checks the state object to see if the requested state is valid for an
> + * analog TV connector.
> + *
> + * Returns:
> + * Zero for success, a negative error code on error.
> + */
> +int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
> +					 struct drm_atomic_state *state)
> +{
> +	struct drm_connector_state *old_conn_state =
> +		drm_atomic_get_old_connector_state(state, connector);
> +	struct drm_connector_state *new_conn_state =
> +		drm_atomic_get_new_connector_state(state, connector);
> +	struct drm_crtc_state *crtc_state;
> +	struct drm_crtc *crtc;
> +
> +	crtc = new_conn_state->crtc;
> +	if (!crtc)
> +		return 0;
> +
> +	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> +	if (!crtc_state)
> +		return -EINVAL;
> +
> +	if (old_conn_state->tv.mode != new_conn_state->tv.mode)
> +		crtc_state->mode_changed = true;
> +
> +	if ((old_conn_state->tv.margins.left != new_conn_state->tv.margins.left) ||
> +	    (old_conn_state->tv.margins.right != new_conn_state->tv.margins.right) ||
> +	    (old_conn_state->tv.margins.top != new_conn_state->tv.margins.top) ||
> +	    (old_conn_state->tv.margins.bottom != new_conn_state->tv.margins.bottom) ||
> +	    (old_conn_state->tv.mode != new_conn_state->tv.mode) ||
> +	    (old_conn_state->tv.brightness != new_conn_state->tv.brightness) ||
> +	    (old_conn_state->tv.contrast != new_conn_state->tv.contrast) ||
> +	    (old_conn_state->tv.flicker_reduction != new_conn_state->tv.flicker_reduction) ||
> +	    (old_conn_state->tv.overscan != new_conn_state->tv.overscan) ||
> +	    (old_conn_state->tv.saturation != new_conn_state->tv.saturation) ||
> +	    (old_conn_state->tv.hue != new_conn_state->tv.hue))
> +		crtc_state->connectors_changed = true;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check);
> +
>  /**
>   * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
>   * @connector: connector object
> diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h
> index c8fbce795ee7..b9740edb2658 100644
> --- a/include/drm/drm_atomic_state_helper.h
> +++ b/include/drm/drm_atomic_state_helper.h
> @@ -26,6 +26,7 @@
>  
>  #include <linux/types.h>
>  
> +struct drm_atomic_state;
>  struct drm_bridge;
>  struct drm_bridge_state;
>  struct drm_crtc;
> @@ -71,6 +72,8 @@ 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);
> +int drm_atomic_helper_connector_tv_check(struct drm_connector *connector,
> +					 struct drm_atomic_state *state);
>  void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector);
>  void
>  __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
> 

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

* Re: [Nouveau] [PATCH v2 28/33] drm/vc4: vec: Fix definition of PAL-M mode
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 28/33] drm/vc4: vec: Fix definition of PAL-M mode Maxime Ripard
@ 2022-09-24 15:59   ` Noralf Trønnes
  0 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 15:59 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
> 
> PAL-M is a Brazilian analog TV standard that uses a PAL-style chroma
> subcarrier at 3.575611[888111] MHz on top of 525-line (480i60) timings.
> This commit makes the driver actually use the proper VEC preset for this
> mode instead of just changing PAL subcarrier frequency.
> 
> Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 

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

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

* Re: [Nouveau] [PATCH v2 30/33] drm/vc4: vec: Check for VEC output constraints
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 30/33] drm/vc4: vec: Check for VEC output constraints Maxime Ripard
@ 2022-09-24 16:00   ` Noralf Trønnes
  0 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 16:00 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
> 
> The VEC can accept pretty much any relatively reasonable mode, but still
> has a bunch of constraints to meet.
> 
> Let's create an atomic_check() implementation that will make sure we
> don't end up accepting a non-functional mode.
> 
> Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 

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

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

* Re: [Nouveau] [PATCH v2 31/33] drm/vc4: vec: Convert to the new TV mode property
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 31/33] drm/vc4: vec: Convert to the new TV mode property Maxime Ripard
@ 2022-09-24 17:09   ` Noralf Trønnes
  0 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 17:09 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> Now that the core can deal fine with analog TV modes, let's convert the vc4
> VEC driver to leverage those new features.
> 
> We've added some backward compatibility to support the old TV mode property
> and translate it into the new TV norm property.
> 

You can mention here that atomic_check is added in order to trigger a
modeset should tv.mode change.

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
> index 6828b79a1001..a9463364015b 100644
> --- a/drivers/gpu/drm/vc4/vc4_vec.c
> +++ b/drivers/gpu/drm/vc4/vc4_vec.c
> @@ -172,6 +172,8 @@ struct vc4_vec {
>  
>  	struct clk *clock;
>  
> +	struct drm_property *legacy_tv_mode_property;
> +
>  	struct debugfs_regset32 regset;
>  };
>  
> @@ -184,6 +186,12 @@ encoder_to_vc4_vec(struct drm_encoder *encoder)
>  	return container_of(encoder, struct vc4_vec, encoder.base);
>  }
>  
> +static inline struct vc4_vec *
> +connector_to_vc4_vec(struct drm_connector *connector)
> +{
> +	return container_of(connector, struct vc4_vec, connector);
> +}
> +
>  enum vc4_vec_tv_mode_id {
>  	VC4_VEC_TV_MODE_NTSC,
>  	VC4_VEC_TV_MODE_NTSC_J,
> @@ -192,7 +200,7 @@ enum vc4_vec_tv_mode_id {
>  };
>  
>  struct vc4_vec_tv_mode {
> -	const struct drm_display_mode *mode;
> +	unsigned int mode;
>  	u32 config0;
>  	u32 config1;
>  	u32 custom_freq;
> @@ -225,43 +233,51 @@ static const struct debugfs_reg32 vec_regs[] = {
>  	VC4_REG32(VEC_DAC_MISC),
>  };
>  
> -static const struct drm_display_mode ntsc_mode = {
> -	DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
> -		 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
> -		 480, 480 + 7, 480 + 7 + 6, 525, 0,
> -		 DRM_MODE_FLAG_INTERLACE)
> -};
> -
> -static const struct drm_display_mode pal_mode = {
> -	DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
> -		 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
> -		 576, 576 + 4, 576 + 4 + 6, 625, 0,
> -		 DRM_MODE_FLAG_INTERLACE)
> -};
> -
>  static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
> -	[VC4_VEC_TV_MODE_NTSC] = {
> -		.mode = &ntsc_mode,
> +	{
> +		.mode = DRM_MODE_TV_MODE_NTSC,
>  		.config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN,
>  		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
>  	},
> -	[VC4_VEC_TV_MODE_NTSC_J] = {
> -		.mode = &ntsc_mode,
> +	{
> +		.mode = DRM_MODE_TV_MODE_NTSC_J,
>  		.config0 = VEC_CONFIG0_NTSC_STD,
>  		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
>  	},
> -	[VC4_VEC_TV_MODE_PAL] = {
> -		.mode = &pal_mode,
> +	{
> +		.mode = DRM_MODE_TV_MODE_PAL,
>  		.config0 = VEC_CONFIG0_PAL_BDGHI_STD,
>  		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
>  	},
> -	[VC4_VEC_TV_MODE_PAL_M] = {
> -		.mode = &ntsc_mode,
> +	{
> +		.mode = DRM_MODE_TV_MODE_PAL_M,
>  		.config0 = VEC_CONFIG0_PAL_M_STD,
>  		.config1 = VEC_CONFIG1_C_CVBS_CVBS,
>  	},
>  };
>  
> +static inline const struct vc4_vec_tv_mode *
> +vc4_vec_tv_mode_lookup(unsigned int mode)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(vc4_vec_tv_modes); i++) {
> +		const struct vc4_vec_tv_mode *tv_mode = &vc4_vec_tv_modes[i];
> +
> +		if (tv_mode->mode == mode)
> +			return tv_mode;
> +	}
> +
> +	return NULL;
> +}
> +
> +static const struct drm_prop_enum_list tv_mode_names[] = {
> +	{ VC4_VEC_TV_MODE_NTSC, "NTSC", },
> +	{ VC4_VEC_TV_MODE_NTSC_J, "NTSC-J", },
> +	{ VC4_VEC_TV_MODE_PAL, "PAL", },
> +	{ VC4_VEC_TV_MODE_PAL_M, "PAL-M", },
> +};
> +
>  static enum drm_connector_status
>  vc4_vec_connector_detect(struct drm_connector *connector, bool force)
>  {
> @@ -276,19 +292,99 @@ static void vc4_vec_connector_reset(struct drm_connector *connector)
>  
>  static int vc4_vec_connector_get_modes(struct drm_connector *connector)
>  {
> -	struct drm_connector_state *state = connector->state;
>  	struct drm_display_mode *mode;
> +	int count = 0;
>  
> -	mode = drm_mode_duplicate(connector->dev,
> -				  vc4_vec_tv_modes[state->tv.legacy_mode].mode);
> +	mode = drm_mode_analog_ntsc_480i(connector->dev);
>  	if (!mode) {
>  		DRM_ERROR("Failed to create a new display mode\n");
>  		return -ENOMEM;
>  	}
>  
> +	mode->type |= DRM_MODE_TYPE_PREFERRED;
>  	drm_mode_probed_add(connector, mode);
> +	count += 1;
>  
> -	return 1;
> +	mode = drm_mode_analog_pal_576i(connector->dev);
> +	if (!mode) {
> +		DRM_ERROR("Failed to create a new display mode\n");
> +		return -ENOMEM;
> +	}
> +
> +	drm_mode_probed_add(connector, mode);
> +	count += 1;
> +
> +	return count;

Why not just return 2 here since that's the only value count can be.

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

> +}
> +
> +static int
> +vc4_vec_connector_set_property(struct drm_connector *connector,
> +			       struct drm_connector_state *state,
> +			       struct drm_property *property,
> +			       uint64_t val)
> +{
> +	struct vc4_vec *vec = connector_to_vc4_vec(connector);
> +
> +	if (property != vec->legacy_tv_mode_property)
> +		return -EINVAL;
> +
> +	switch (val) {
> +	case VC4_VEC_TV_MODE_NTSC:
> +		state->tv.mode = DRM_MODE_TV_MODE_NTSC;
> +		break;
> +
> +	case VC4_VEC_TV_MODE_NTSC_J:
> +		state->tv.mode = DRM_MODE_TV_MODE_NTSC_J;
> +		break;
> +
> +	case VC4_VEC_TV_MODE_PAL:
> +		state->tv.mode = DRM_MODE_TV_MODE_PAL;
> +		break;
> +
> +	case VC4_VEC_TV_MODE_PAL_M:
> +		state->tv.mode = DRM_MODE_TV_MODE_PAL_M;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +vc4_vec_connector_get_property(struct drm_connector *connector,
> +			       const struct drm_connector_state *state,
> +			       struct drm_property *property,
> +			       uint64_t *val)
> +{
> +	struct vc4_vec *vec = connector_to_vc4_vec(connector);
> +
> +	if (property != vec->legacy_tv_mode_property)
> +		return -EINVAL;
> +
> +	switch (state->tv.mode) {
> +	case DRM_MODE_TV_MODE_NTSC:
> +		*val = VC4_VEC_TV_MODE_NTSC;
> +		break;
> +
> +	case DRM_MODE_TV_MODE_NTSC_J:
> +		*val = VC4_VEC_TV_MODE_NTSC_J;
> +		break;
> +
> +	case DRM_MODE_TV_MODE_PAL:
> +		*val = VC4_VEC_TV_MODE_PAL;
> +		break;
> +
> +	case DRM_MODE_TV_MODE_PAL_M:
> +		*val = VC4_VEC_TV_MODE_PAL_M;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
>  }
>  
>  static const struct drm_connector_funcs vc4_vec_connector_funcs = {
> @@ -297,15 +393,19 @@ static const struct drm_connector_funcs vc4_vec_connector_funcs = {
>  	.reset = vc4_vec_connector_reset,
>  	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
>  	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +	.atomic_get_property = vc4_vec_connector_get_property,
> +	.atomic_set_property = vc4_vec_connector_set_property,
>  };
>  
>  static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = {
> +	.atomic_check = drm_atomic_helper_connector_tv_check,
>  	.get_modes = vc4_vec_connector_get_modes,
>  };
>  
>  static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
>  {
>  	struct drm_connector *connector = &vec->connector;
> +	struct drm_property *prop;
>  	int ret;
>  
>  	connector->interlace_allowed = true;
> @@ -318,8 +418,16 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
>  	drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
>  
>  	drm_object_attach_property(&connector->base,
> -				   dev->mode_config.legacy_tv_mode_property,
> -				   VC4_VEC_TV_MODE_NTSC);
> +				   dev->mode_config.tv_mode_property,
> +				   DRM_MODE_TV_MODE_NTSC);
> +
> +	prop = drm_property_create_enum(dev, 0, "mode",
> +					tv_mode_names, ARRAY_SIZE(tv_mode_names));
> +	if (!prop)
> +		return -ENOMEM;
> +	vec->legacy_tv_mode_property = prop;
> +
> +	drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC);
>  
>  	drm_connector_attach_encoder(connector, &vec->encoder.base);
>  
> @@ -366,13 +474,16 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder,
>  	struct drm_connector *connector = &vec->connector;
>  	struct drm_connector_state *conn_state =
>  		drm_atomic_get_new_connector_state(state, connector);
> -	const struct vc4_vec_tv_mode *tv_mode =
> -		&vc4_vec_tv_modes[conn_state->tv.mode];
> +	const struct vc4_vec_tv_mode *tv_mode;
>  	int idx, ret;
>  
>  	if (!drm_dev_enter(drm, &idx))
>  		return;
>  
> +	tv_mode = vc4_vec_tv_mode_lookup(conn_state->tv.mode);
> +	if (!tv_mode)
> +		goto err_dev_exit;
> +
>  	ret = pm_runtime_get_sync(&vec->pdev->dev);
>  	if (ret < 0) {
>  		DRM_ERROR("Failed to retain power domain: %d\n", ret);
> @@ -454,13 +565,6 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
>  					struct drm_connector_state *conn_state)
>  {
>  	const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
> -	const struct vc4_vec_tv_mode *vec_mode;
> -
> -	vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode];
> -
> -	if (conn_state->crtc &&
> -	    !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
> -		return -EINVAL;
>  
>  	if (mode->crtc_hdisplay % 4)
>  		return -EINVAL;
> @@ -554,13 +658,6 @@ static const struct of_device_id vc4_vec_dt_match[] = {
>  	{ /* sentinel */ },
>  };
>  
> -static const char * const tv_mode_names[] = {
> -	[VC4_VEC_TV_MODE_NTSC] = "NTSC",
> -	[VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
> -	[VC4_VEC_TV_MODE_PAL] = "PAL",
> -	[VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
> -};
> -
>  static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
>  {
>  	struct platform_device *pdev = to_platform_device(dev);
> @@ -568,9 +665,11 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
>  	struct vc4_vec *vec;
>  	int ret;
>  
> -	ret = drm_mode_create_tv_properties_legacy(drm,
> -						   ARRAY_SIZE(tv_mode_names),
> -						   tv_mode_names);
> +	ret = drm_mode_create_tv_properties(drm,
> +					    BIT(DRM_MODE_TV_MODE_NTSC) |
> +					    BIT(DRM_MODE_TV_MODE_NTSC_J) |
> +					    BIT(DRM_MODE_TV_MODE_PAL) |
> +					    BIT(DRM_MODE_TV_MODE_PAL_M));
>  	if (ret)
>  		return ret;
>  
> 

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

* Re: [Nouveau] [PATCH v2 32/33] drm/vc4: vec: Add support for more analog TV standards
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 32/33] drm/vc4: vec: Add support for more analog TV standards Maxime Ripard
@ 2022-09-24 17:12   ` Noralf Trønnes
  0 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 17:12 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
> 
> Add support for the following composite output modes (all of them are
> somewhat more obscure than the previously defined ones):
> 
> - NTSC_443 - NTSC-style signal with the chroma subcarrier shifted to
>   4.43361875 MHz (the PAL subcarrier frequency). Never used for
>   broadcasting, but sometimes used as a hack to play NTSC content in PAL
>   regions (e.g. on VCRs).
> - PAL_N - PAL with alternative chroma subcarrier frequency,
>   3.58205625 MHz. Used as a broadcast standard in Argentina, Paraguay
>   and Uruguay to fit 576i50 with colour in 6 MHz channel raster.
> - PAL60 - 480i60 signal with PAL-style color at normal European PAL
>   frequency. Another non-standard, non-broadcast mode, used in similar
>   contexts as NTSC_443. Some displays support one but not the other.
> - SECAM - French frequency-modulated analog color standard; also have
>   been broadcast in Eastern Europe and various parts of Africa and Asia.
>   Uses the same 576i50 timings as PAL.
> 
> Also added some comments explaining color subcarrier frequency
> registers.
> 
> Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 

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

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

* Re: [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile Maxime Ripard
  2022-09-23  8:06   ` Thomas Zimmermann
@ 2022-09-24 17:33   ` Noralf Trønnes
  1 sibling, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 17:33 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> Since we've recently added a ton of tests, the list starts to be a bit
> of a mess and creates unneeded conflicts.
> 
> Let's order it alphabetically.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 

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

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

* Re: [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers
  2022-09-22 14:25 ` [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers Maxime Ripard
@ 2022-09-24 17:56   ` Noralf Trønnes
  2022-09-24 18:06     ` Noralf Trønnes
  0 siblings, 1 reply; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 17:56 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> As the number of kunit tests in KMS grows further, we start to have
> multiple test suites that, for example, need to register a mock DRM
> driver to interact with the KMS function they are supposed to test.
> 
> Let's add a file meant to provide those kind of helpers to avoid
> duplication.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
> index 2d9f49b62ecb..b29ef1085cad 100644
> --- a/drivers/gpu/drm/tests/Makefile
> +++ b/drivers/gpu/drm/tests/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
>  	drm_format_helper_test.o \
>  	drm_format_test.o \
>  	drm_framebuffer_test.o \
> +	drm_kunit_helpers.o \
>  	drm_mm_test.o \
>  	drm_plane_helper_test.o \
>  	drm_rect_test.o
> diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
> new file mode 100644
> index 000000000000..7ebd620481c1
> --- /dev/null
> +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
> @@ -0,0 +1,54 @@
> +#include <drm/drm_drv.h>
> +#include <drm/drm_managed.h>
> +
> +#include <linux/device.h>
> +
> +static const struct drm_mode_config_funcs drm_mode_config_funcs = {
> +};
> +
> +static const struct drm_driver drm_mode_driver = {
> +};
> +
> +static void drm_kunit_free_device(struct drm_device *drm, void *ptr)
> +{
> +	struct device *dev = ptr;
> +
> +	root_device_unregister(dev);
> +}
> +
> +struct drm_device *drm_kunit_device_init(const char *name)
> +{
> +	struct drm_device *drm;
> +	struct device *dev;
> +	int ret;
> +
> +	dev = root_device_register(name);
> +	if (IS_ERR(dev))
> +		return ERR_CAST(dev);
> +
> +	drm = drm_dev_alloc(&drm_mode_driver, dev);

I can't find drm being freed anywhere?
Maybe you could assign it to drm->managed.final_kfree.

Noralf.

> +	if (IS_ERR(drm)) {
> +		root_device_unregister(dev);
> +		return ERR_CAST(drm);
> +	}
> +	drm->mode_config.funcs = &drm_mode_config_funcs;
> +
> +	ret = drmm_add_action_or_reset(drm, drm_kunit_free_device, dev);
> +	if (ret)
> +		goto err_put_device;
> +
> +	ret = drmm_mode_config_init(drm);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return drm;
> +
> +err_put_device:
> +	drm_dev_put(drm);
> +	return ERR_PTR(ret);
> +}
> +
> +void drm_kunit_device_exit(struct drm_device *drm)
> +{
> +	drm_dev_put(drm);
> +}
> diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.h b/drivers/gpu/drm/tests/drm_kunit_helpers.h
> new file mode 100644
> index 000000000000..5015a327a8c1
> --- /dev/null
> +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.h
> @@ -0,0 +1,9 @@
> +#ifndef DRM_KUNIT_HELPERS_H_
> +#define DRM_KUNIT_HELPERS_H_
> +
> +struct drm_device;
> +
> +struct drm_device *drm_kunit_device_init(const char *name);
> +void drm_kunit_device_exit(struct drm_device *drm);
> +
> +#endif // DRM_KUNIT_HELPERS_H_
> 

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

* Re: [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers
  2022-09-24 17:56   ` Noralf Trønnes
@ 2022-09-24 18:06     ` Noralf Trønnes
  2022-09-26  9:36       ` Maxime Ripard
  0 siblings, 1 reply; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-24 18:06 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 24.09.2022 19.56, skrev Noralf Trønnes:
> 
> 
> Den 22.09.2022 16.25, skrev Maxime Ripard:
>> As the number of kunit tests in KMS grows further, we start to have
>> multiple test suites that, for example, need to register a mock DRM
>> driver to interact with the KMS function they are supposed to test.
>>
>> Let's add a file meant to provide those kind of helpers to avoid
>> duplication.
>>
>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>
>> diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
>> index 2d9f49b62ecb..b29ef1085cad 100644
>> --- a/drivers/gpu/drm/tests/Makefile
>> +++ b/drivers/gpu/drm/tests/Makefile
>> @@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
>>  	drm_format_helper_test.o \
>>  	drm_format_test.o \
>>  	drm_framebuffer_test.o \
>> +	drm_kunit_helpers.o \
>>  	drm_mm_test.o \
>>  	drm_plane_helper_test.o \
>>  	drm_rect_test.o
>> diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
>> new file mode 100644
>> index 000000000000..7ebd620481c1
>> --- /dev/null
>> +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
>> @@ -0,0 +1,54 @@
>> +#include <drm/drm_drv.h>
>> +#include <drm/drm_managed.h>
>> +
>> +#include <linux/device.h>
>> +
>> +static const struct drm_mode_config_funcs drm_mode_config_funcs = {
>> +};
>> +
>> +static const struct drm_driver drm_mode_driver = {
>> +};
>> +
>> +static void drm_kunit_free_device(struct drm_device *drm, void *ptr)
>> +{
>> +	struct device *dev = ptr;
>> +
>> +	root_device_unregister(dev);
>> +}
>> +
>> +struct drm_device *drm_kunit_device_init(const char *name)
>> +{
>> +	struct drm_device *drm;
>> +	struct device *dev;
>> +	int ret;
>> +
>> +	dev = root_device_register(name);
>> +	if (IS_ERR(dev))
>> +		return ERR_CAST(dev);
>> +
>> +	drm = drm_dev_alloc(&drm_mode_driver, dev);
> 
> I can't find drm being freed anywhere?
> Maybe you could assign it to drm->managed.final_kfree.
> 

Perhaps a better solution would be to use devm_drm_dev_alloc() and
unregister the root device on exit. That avoids reaching into the drm
managed internals and it looks more like a regular driver.

> Noralf.
> 
>> +	if (IS_ERR(drm)) {
>> +		root_device_unregister(dev);
>> +		return ERR_CAST(drm);
>> +	}
>> +	drm->mode_config.funcs = &drm_mode_config_funcs;
>> +
>> +	ret = drmm_add_action_or_reset(drm, drm_kunit_free_device, dev);
>> +	if (ret)
>> +		goto err_put_device;
>> +
>> +	ret = drmm_mode_config_init(drm);
>> +	if (ret)
>> +		return ERR_PTR(ret);
>> +
>> +	return drm;
>> +
>> +err_put_device:
>> +	drm_dev_put(drm);
>> +	return ERR_PTR(ret);
>> +}
>> +
>> +void drm_kunit_device_exit(struct drm_device *drm)
>> +{
>> +	drm_dev_put(drm);
>> +}
>> diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.h b/drivers/gpu/drm/tests/drm_kunit_helpers.h
>> new file mode 100644
>> index 000000000000..5015a327a8c1
>> --- /dev/null
>> +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.h
>> @@ -0,0 +1,9 @@
>> +#ifndef DRM_KUNIT_HELPERS_H_
>> +#define DRM_KUNIT_HELPERS_H_
>> +
>> +struct drm_device;
>> +
>> +struct drm_device *drm_kunit_device_init(const char *name);
>> +void drm_kunit_device_exit(struct drm_device *drm);
>> +
>> +#endif // DRM_KUNIT_HELPERS_H_
>>

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

* Re: [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements
  2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
                   ` (33 preceding siblings ...)
  2022-09-22 14:31 ` [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
@ 2022-09-25 15:58 ` Noralf Trønnes
  34 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-25 15:58 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Skrabec, Rodrigo Vivi, Ben Skeggs,
	David Airlie, Maxime Ripard, Joonas Lahtinen, Emma Anholt,
	Karol Herbst, Samuel Holland, Jani Nikula, Thomas Zimmermann,
	Daniel Vetter, Lyude Paul, Maarten Lankhorst, Tvrtko Ursulin,
	Chen-Yu Tsai
  Cc: Dom Cobley, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Noralf Trønnes,
	Geert Uytterhoeven, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel



Den 22.09.2022 16.25, skrev Maxime Ripard:
> Hi,
> 
> Here's a series aiming at improving the command line named modes support,
> and more importantly how we deal with all the analog TV variants.
> 
> The named modes support were initially introduced to allow to specify the
> analog TV mode to be used.
> 
> However, this was causing multiple issues:
> 
>   * The mode name parsed on the command line was passed directly to the
>     driver, which had to figure out which mode it was suppose to match;
> 
>   * Figuring that out wasn't really easy, since the video= argument or what
>     the userspace might not even have a name in the first place, but
>     instead could have passed a mode with the same timings;
> 
>   * The fallback to matching on the timings was mostly working as long as
>     we were supporting one 525 lines (most likely NSTC) and one 625 lines
>     (PAL), but couldn't differentiate between two modes with the same
>     timings (NTSC vs PAL-M vs NSTC-J for example);
> 
>   * There was also some overlap with the tv mode property registered by
>     drm_mode_create_tv_properties(), but named modes weren't interacting
>     with that property at all.
> 
>   * Even though that property was generic, its possible values were
>     specific to each drivers, which made some generic support difficult.
> 
> Thus, I chose to tackle in multiple steps:
> 
>   * A new TV mode property was introduced, with generic values, each driver
>     reporting through a bitmask what standard it supports to the userspace;
> 
>   * This option was added to the command line parsing code to be able to
>     specify it on the kernel command line, and new atomic_check and reset
>     helpers were created to integrate properly into atomic KMS;
> 
>   * The named mode parsing code is now creating a proper display mode for
>     the given named mode, and the TV standard will thus be part of the
>     connector state;
> 
>   * Two drivers were converted and tested for now (vc4 and sun4i), with
>     some backward compatibility code to translate the old TV mode to the
>     new TV mode;
> 
> Unit tests were created along the way.
> 
> One can switch from NTSC to PAL now using (on vc4)
> 
> modetest -M vc4  -s 53:720x480i -w 53:'TV mode':1 # NTSC
> modetest -M vc4  -s 53:720x576i -w 53:'TV mode':4 # PAL
> 
> Let me know what you think,
> Maxime

<snip>

>  drivers/gpu/drm/drm_atomic_state_helper.c       | 128 ++++-
>  drivers/gpu/drm/drm_atomic_uapi.c               |   8 +
>  drivers/gpu/drm/drm_client_modeset.c            |   4 +
>  drivers/gpu/drm/drm_connector.c                 | 111 +++-
>  drivers/gpu/drm/drm_modes.c                     | 658 +++++++++++++++++++++++-
>  drivers/gpu/drm/gud/gud_connector.c             |  12 +-
>  drivers/gpu/drm/i2c/ch7006_drv.c                |   6 +-
>  drivers/gpu/drm/i915/display/intel_tv.c         |   5 +-
>  drivers/gpu/drm/nouveau/dispnv04/tvnv17.c       |   6 +-
>  drivers/gpu/drm/sun4i/sun4i_tv.c                | 148 ++----
>  drivers/gpu/drm/tests/Makefile                  |  16 +-
>  drivers/gpu/drm/tests/drm_client_modeset_test.c | 239 +++++++++
>  drivers/gpu/drm/tests/drm_cmdline_parser_test.c |  67 +++
>  drivers/gpu/drm/tests/drm_kunit_helpers.c       |  54 ++
>  drivers/gpu/drm/tests/drm_kunit_helpers.h       |   9 +
>  drivers/gpu/drm/tests/drm_modes_test.c          | 136 +++++
>  drivers/gpu/drm/vc4/vc4_hdmi.c                  |   2 +-
>  drivers/gpu/drm/vc4/vc4_vec.c                   | 339 ++++++++++--
>  include/drm/drm_atomic_state_helper.h           |   4 +
>  include/drm/drm_connector.h                     |  92 +++-
>  include/drm/drm_mode_config.h                   |  12 +-
>  include/drm/drm_modes.h                         |  17 +

These also needs updating:

Documentation/gpu/kms-properties.csv
Documentation/fb/modedb.rst

Noralf.

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

* Re: [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers
  2022-09-24 18:06     ` Noralf Trønnes
@ 2022-09-26  9:36       ` Maxime Ripard
  2022-09-26 12:15         ` Noralf Trønnes
  0 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-26  9:36 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Jernej Skrabec, Chen-Yu Tsai,
	Geert Uytterhoeven, Ben Skeggs, linux-sunxi, Daniel Vetter,
	intel-gfx, Maarten Lankhorst, Jani Nikula, Hans de Goede,
	Rodrigo Vivi, linux-arm-kernel, Tvrtko Ursulin, Dom Cobley,
	linux-kernel, Mateusz Kwiatkowski

[-- Attachment #1: Type: text/plain, Size: 2545 bytes --]

Hi Noralf,

On Sat, Sep 24, 2022 at 08:06:17PM +0200, Noralf Trønnes wrote:
> Den 24.09.2022 19.56, skrev Noralf Trønnes:
> > 
> > 
> > Den 22.09.2022 16.25, skrev Maxime Ripard:
> >> As the number of kunit tests in KMS grows further, we start to have
> >> multiple test suites that, for example, need to register a mock DRM
> >> driver to interact with the KMS function they are supposed to test.
> >>
> >> Let's add a file meant to provide those kind of helpers to avoid
> >> duplication.
> >>
> >> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>
> >> diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
> >> index 2d9f49b62ecb..b29ef1085cad 100644
> >> --- a/drivers/gpu/drm/tests/Makefile
> >> +++ b/drivers/gpu/drm/tests/Makefile
> >> @@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
> >>  	drm_format_helper_test.o \
> >>  	drm_format_test.o \
> >>  	drm_framebuffer_test.o \
> >> +	drm_kunit_helpers.o \
> >>  	drm_mm_test.o \
> >>  	drm_plane_helper_test.o \
> >>  	drm_rect_test.o
> >> diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
> >> new file mode 100644
> >> index 000000000000..7ebd620481c1
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
> >> @@ -0,0 +1,54 @@
> >> +#include <drm/drm_drv.h>
> >> +#include <drm/drm_managed.h>
> >> +
> >> +#include <linux/device.h>
> >> +
> >> +static const struct drm_mode_config_funcs drm_mode_config_funcs = {
> >> +};
> >> +
> >> +static const struct drm_driver drm_mode_driver = {
> >> +};
> >> +
> >> +static void drm_kunit_free_device(struct drm_device *drm, void *ptr)
> >> +{
> >> +	struct device *dev = ptr;
> >> +
> >> +	root_device_unregister(dev);
> >> +}
> >> +
> >> +struct drm_device *drm_kunit_device_init(const char *name)
> >> +{
> >> +	struct drm_device *drm;
> >> +	struct device *dev;
> >> +	int ret;
> >> +
> >> +	dev = root_device_register(name);
> >> +	if (IS_ERR(dev))
> >> +		return ERR_CAST(dev);
> >> +
> >> +	drm = drm_dev_alloc(&drm_mode_driver, dev);
> > 
> > I can't find drm being freed anywhere?
> > Maybe you could assign it to drm->managed.final_kfree.

There's a drm_dev_put in the test_exit hook which should free it.

> Perhaps a better solution would be to use devm_drm_dev_alloc() and
> unregister the root device on exit. That avoids reaching into the drm
> managed internals and it looks more like a regular driver.

But yeah, this is a good idea, I'll do it.

Maxime

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

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

* Re: [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property
  2022-09-23  8:19   ` Thomas Zimmermann
@ 2022-09-26  9:50     ` Maxime Ripard
  2022-09-26 12:34       ` Thomas Zimmermann
  0 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-26  9:50 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Jernej Skrabec, Chen-Yu Tsai,
	Geert Uytterhoeven, Ben Skeggs, linux-sunxi, intel-gfx,
	Maarten Lankhorst, Jani Nikula, Hans de Goede, Rodrigo Vivi,
	linux-arm-kernel, Tvrtko Ursulin, Dom Cobley, linux-kernel,
	Mateusz Kwiatkowski, Noralf Trønnes, Daniel Vetter

[-- Attachment #1: Type: text/plain, Size: 991 bytes --]

Hi Thomas,

On Fri, Sep 23, 2022 at 10:19:08AM +0200, Thomas Zimmermann wrote:
> Hi
> 
> Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> > The current tv_mode has driver-specific values that don't allow to
> > easily share code using it, either at the userspace or kernel level.
> > 
> > Since we're going to introduce a new, generic, property that fit the
> > same purpose, let's rename this one to legacy_tv_mode to make it
> > obvious we should move away from it.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> It's not wrong, but 'legacy' is already overloaded with meaning. If you can,
> maybe name it 'driver_tv_mode_property' or 'custom_tv_mode_property'
> instead.
> 
> Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

I'd really like to point out that new drivers shouldn't be using this.
If we're using either of your proposals then writers might get the
impression that this is ok to us.

Would you prefer deprecated to legacy?

Maxime

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

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

* Re: [Nouveau] [PATCH v2 09/33] drm/connector: Add TV standard property
  2022-09-24 15:52   ` Noralf Trønnes
@ 2022-09-26 10:01     ` Maxime Ripard
  2022-09-26 12:59       ` Noralf Trønnes
  0 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-26 10:01 UTC (permalink / raw)
  To: Noralf Trønnes
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Jernej Skrabec, Chen-Yu Tsai,
	Geert Uytterhoeven, Ben Skeggs, linux-sunxi, Daniel Vetter,
	intel-gfx, Maarten Lankhorst, Jani Nikula, Hans de Goede,
	Rodrigo Vivi, linux-arm-kernel, Tvrtko Ursulin, Dom Cobley,
	linux-kernel, Mateusz Kwiatkowski

[-- Attachment #1: Type: text/plain, Size: 2036 bytes --]

On Sat, Sep 24, 2022 at 05:52:29PM +0200, Noralf Trønnes wrote:
> Den 22.09.2022 16.25, skrev Maxime Ripard:
> > The TV mode property has been around for a while now to select and get the
> > current TV mode output on an analog TV connector.
> > 
> > Despite that property name being generic, its content isn't and has been
> > driver-specific which makes it hard to build any generic behaviour on top
> > of it, both in kernel and user-space.
> > 
> > Let's create a new enum tv norm property, that can contain any of the
> > analog TV standards currently supported by kernel drivers. Each driver can
> > then pass in a bitmask of the modes it supports, and the property
> > creation function will filter out the modes not supported.
> > 
> > We'll then be able to phase out the older tv mode property.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>
> Please can you add per patch changelogs, it's hard to review when I have
> to recall what might have happened with each patch. If you do it drm
> style and put in the commit message it should be easy enough to do.

I certainly don't want to start that discussion, but I'm really not a
fan of that format either. I'll do it for that series if you prefer.

> > +/**
> > + * enum drm_connector_tv_mode - Analog TV output mode
> > + *
> > + * This enum is used to indicate the TV output mode used on an analog TV
> > + * connector.
> > + *
> > + * WARNING: The values of this enum is uABI since they're exposed in the
> > + * "TV mode" connector property.
> > + */
> > +enum drm_connector_tv_mode {
> > +	/**
> > +	 * @DRM_MODE_TV_MODE_NONE: Placeholder to not default on one
> > +	 * variant or the other when nothing is set.
> > +	 */
> > +	DRM_MODE_TV_MODE_NONE = 0,
> 
> How is this supposed to be used?

It's not supposed to be used. It was a suggestion from Mateusz to avoid
to default to any standard when we don't initialize something. I don't
have any strong feeling about it, so I can drop it if you prefer.

Maxime

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

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-23  9:05   ` Thomas Zimmermann
  2022-09-23  9:18     ` Jani Nikula
@ 2022-09-26 10:17     ` Maxime Ripard
  2022-09-26 10:34       ` Geert Uytterhoeven
  1 sibling, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-26 10:17 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Jernej Skrabec, Chen-Yu Tsai,
	Geert Uytterhoeven, Ben Skeggs, linux-sunxi, intel-gfx,
	Maarten Lankhorst, Jani Nikula, Hans de Goede, Rodrigo Vivi,
	linux-arm-kernel, Tvrtko Ursulin, Dom Cobley, linux-kernel,
	Mateusz Kwiatkowski, Noralf Trønnes, Daniel Vetter

[-- Attachment #1: Type: text/plain, Size: 985 bytes --]

Hi,

On Fri, Sep 23, 2022 at 11:05:48AM +0200, Thomas Zimmermann wrote:
> > +	/* 63.556us * 13.5MHz = 858 pixels */
> 
> I kind of get what the comment wants to tell me, but the units don't add up.

I'm not sure how it doesn't add up?

We have a frequency in Hz (equivalent to s^-1) and a duration in s, so
the result ends up with no dimension, which is to be expected for a
number of periods?

If you're talking about the comment itself, then NTSC mandates that a
line is 63.556us long. If we're using a pixel clock at 13.5 MHz, it
means that the period (== pixel) is ~74ns, so we get 63556 / 74 = 858
pixels / line.

> I think you want to end up with 858 pixels/line =
> 
>   13,5 pixels/second / (60/2I frame/second * 525 lines/frame)
> 
> I: interlaced
> 
> Maybe just remove the short comments and document that in a more meaningful
> place.

I guess this is where it's meaningful, we really want to hit that
target. BT601 also mandates it.

Maxime

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

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-23 10:16       ` Thomas Zimmermann
@ 2022-09-26 10:18         ` Maxime Ripard
  2022-09-26 10:55           ` Thomas Zimmermann
  0 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-26 10:18 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Jernej Skrabec, Chen-Yu Tsai,
	Geert Uytterhoeven, Ben Skeggs, linux-sunxi, intel-gfx,
	Maarten Lankhorst, Jani Nikula, Hans de Goede, Rodrigo Vivi,
	linux-arm-kernel, Tvrtko Ursulin, Dom Cobley, linux-kernel,
	Mateusz Kwiatkowski, Noralf Trønnes, Daniel Vetter

[-- Attachment #1: Type: text/plain, Size: 1096 bytes --]

On Fri, Sep 23, 2022 at 12:16:13PM +0200, Thomas Zimmermann wrote:
> Hi
> 
> Am 23.09.22 um 11:18 schrieb Jani Nikula:
> > On Fri, 23 Sep 2022, Thomas Zimmermann <tzimmermann@suse.de> wrote:
> > > Am 22.09.22 um 16:25 schrieb Maxime Ripard:
> > > > +	drm_dbg_kms(dev,
> > > > +		    "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
> > > > +		    hactive, vactive,
> > > > +		    interlace ? 'i' : 'p',
> > > > +		    params->num_lines,
> > > > +		    pixel_clock_hz / 1000);
> > > 
> > > Divide by HZ_PER_KHZ here and in other places.
> > > 
> > >     https://elixir.bootlin.com/linux/latest/source/include/linux/units.h#L23
> > 
> >  From the Department of Bikeshedding:
> > 
> > I find "pixel_clock_hz / 1000" has much more clarity than
> > "pixel_clock_hz / HZ_PER_KHZ".
> 
> This one's easy to see because it tells you with the _hz postfix. Many
> places don't and then it quickly gets confusing what units the code's
> converting.

So if I add it to places that don't have it explicitly (ie, tests) would
that be acceptable to both of you?

Maxime

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

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-26 10:17     ` Maxime Ripard
@ 2022-09-26 10:34       ` Geert Uytterhoeven
  2022-09-26 11:17         ` Thomas Zimmermann
  0 siblings, 1 reply; 75+ messages in thread
From: Geert Uytterhoeven @ 2022-09-26 10:34 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Jernej Skrabec, Chen-Yu Tsai,
	Ben Skeggs, linux-sunxi, Daniel Vetter, intel-gfx,
	Maarten Lankhorst, Jani Nikula, Hans de Goede, Rodrigo Vivi,
	linux-arm-kernel, Tvrtko Ursulin, Dom Cobley, linux-kernel,
	Mateusz Kwiatkowski, Noralf Trønnes

Hi Maxime,

On Mon, Sep 26, 2022 at 12:17 PM Maxime Ripard <maxime@cerno.tech> wrote:
> On Fri, Sep 23, 2022 at 11:05:48AM +0200, Thomas Zimmermann wrote:
> > > +   /* 63.556us * 13.5MHz = 858 pixels */
> >
> > I kind of get what the comment wants to tell me, but the units don't add up.
>
> I'm not sure how it doesn't add up?
>
> We have a frequency in Hz (equivalent to s^-1) and a duration in s, so
> the result ends up with no dimension, which is to be expected for a
> number of periods?

To make the units add up, it should be 13.5 Mpixel/s
(which is what a pixel clock of 13.5 MHz really means ;-)

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-26 10:18         ` Maxime Ripard
@ 2022-09-26 10:55           ` Thomas Zimmermann
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-26 10:55 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Airlie, nouveau, dri-devel, Phil Elwell, Emma Anholt,
	Samuel Holland, Jernej Skrabec, Chen-Yu Tsai, Geert Uytterhoeven,
	Ben Skeggs, linux-sunxi, intel-gfx, Hans de Goede, Rodrigo Vivi,
	linux-arm-kernel, Tvrtko Ursulin, Dom Cobley, linux-kernel,
	Mateusz Kwiatkowski, Noralf Trønnes


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

Hi

Am 26.09.22 um 12:18 schrieb Maxime Ripard:
> On Fri, Sep 23, 2022 at 12:16:13PM +0200, Thomas Zimmermann wrote:
>> Hi
>>
>> Am 23.09.22 um 11:18 schrieb Jani Nikula:
>>> On Fri, 23 Sep 2022, Thomas Zimmermann <tzimmermann@suse.de> wrote:
>>>> Am 22.09.22 um 16:25 schrieb Maxime Ripard:
>>>>> +	drm_dbg_kms(dev,
>>>>> +		    "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
>>>>> +		    hactive, vactive,
>>>>> +		    interlace ? 'i' : 'p',
>>>>> +		    params->num_lines,
>>>>> +		    pixel_clock_hz / 1000);
>>>>
>>>> Divide by HZ_PER_KHZ here and in other places.
>>>>
>>>>      https://elixir.bootlin.com/linux/latest/source/include/linux/units.h#L23
>>>
>>>   From the Department of Bikeshedding:
>>>
>>> I find "pixel_clock_hz / 1000" has much more clarity than
>>> "pixel_clock_hz / HZ_PER_KHZ".
>>
>> This one's easy to see because it tells you with the _hz postfix. Many
>> places don't and then it quickly gets confusing what units the code's
>> converting.
> 
> So if I add it to places that don't have it explicitly (ie, tests) would
> that be acceptable to both of you?

I'm OK with either. Or just leave it as-is.

A HZ_TO_KHZ macro would be nice, but that's beyond this patchset.

Best regards
Thomas

> 
> Maxime

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-26 10:34       ` Geert Uytterhoeven
@ 2022-09-26 11:17         ` Thomas Zimmermann
  2022-09-26 12:42           ` Maxime Ripard
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-26 11:17 UTC (permalink / raw)
  To: Geert Uytterhoeven, Maxime Ripard
  Cc: Tvrtko Ursulin, Noralf Trønnes, Emma Anholt, Samuel Holland,
	David Airlie, nouveau, intel-gfx, linux-kernel, dri-devel,
	linux-sunxi, Hans de Goede, Chen-Yu Tsai, Dom Cobley,
	Jernej Skrabec, Rodrigo Vivi, Mateusz Kwiatkowski, Phil Elwell,
	linux-arm-kernel, Ben Skeggs


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

Hi

Am 26.09.22 um 12:34 schrieb Geert Uytterhoeven:
> Hi Maxime,
> 
> On Mon, Sep 26, 2022 at 12:17 PM Maxime Ripard <maxime@cerno.tech> wrote:
>> On Fri, Sep 23, 2022 at 11:05:48AM +0200, Thomas Zimmermann wrote:
>>>> +   /* 63.556us * 13.5MHz = 858 pixels */
>>>
>>> I kind of get what the comment wants to tell me, but the units don't add up.
>>
>> I'm not sure how it doesn't add up?
>>
>> We have a frequency in Hz (equivalent to s^-1) and a duration in s, so
>> the result ends up with no dimension, which is to be expected for a
>> number of periods?
> 
> To make the units add up, it should be 13.5 Mpixel/s
> (which is what a pixel clock of 13.5 MHz really means ;-)

Sort of. It leaves the time value as a magic number, which obfuscates 
what's happening.

The unit for htotal is pixels/scanline because if you multiply it with 
the number of scanlines per frame (which is in vtotal), you get 
pixels/frame. Multiplying with the frames per second results in the 
pixel clock in pixels/second.

That's a bit much for this comment. Hence, I suggested to remove these 
comments entirely and document the relation among the numbers in a more 
prominent location. The documentation for drm_display_mode would be a 
good place, I guess.

Best regards
Thomas

> 
> Gr{oetje,eeting}s,
> 
>                          Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                  -- Linus Torvalds

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers
  2022-09-26  9:36       ` Maxime Ripard
@ 2022-09-26 12:15         ` Noralf Trønnes
  0 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-26 12:15 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Jernej Skrabec, Chen-Yu Tsai,
	Geert Uytterhoeven, Ben Skeggs, linux-sunxi, Daniel Vetter,
	intel-gfx, Maarten Lankhorst, Jani Nikula, Hans de Goede,
	Rodrigo Vivi, linux-arm-kernel, Tvrtko Ursulin, Dom Cobley,
	linux-kernel, Mateusz Kwiatkowski, Noralf Trønnes



Den 26.09.2022 11.36, skrev Maxime Ripard:
> Hi Noralf,
> 
> On Sat, Sep 24, 2022 at 08:06:17PM +0200, Noralf Trønnes wrote:
>> Den 24.09.2022 19.56, skrev Noralf Trønnes:
>>>
>>>
>>> Den 22.09.2022 16.25, skrev Maxime Ripard:
>>>> As the number of kunit tests in KMS grows further, we start to have
>>>> multiple test suites that, for example, need to register a mock DRM
>>>> driver to interact with the KMS function they are supposed to test.
>>>>
>>>> Let's add a file meant to provide those kind of helpers to avoid
>>>> duplication.
>>>>
>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>>>
>>>> diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
>>>> index 2d9f49b62ecb..b29ef1085cad 100644
>>>> --- a/drivers/gpu/drm/tests/Makefile
>>>> +++ b/drivers/gpu/drm/tests/Makefile
>>>> @@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
>>>>  	drm_format_helper_test.o \
>>>>  	drm_format_test.o \
>>>>  	drm_framebuffer_test.o \
>>>> +	drm_kunit_helpers.o \
>>>>  	drm_mm_test.o \
>>>>  	drm_plane_helper_test.o \
>>>>  	drm_rect_test.o
>>>> diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
>>>> new file mode 100644
>>>> index 000000000000..7ebd620481c1
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
>>>> @@ -0,0 +1,54 @@
>>>> +#include <drm/drm_drv.h>
>>>> +#include <drm/drm_managed.h>
>>>> +
>>>> +#include <linux/device.h>
>>>> +
>>>> +static const struct drm_mode_config_funcs drm_mode_config_funcs = {
>>>> +};
>>>> +
>>>> +static const struct drm_driver drm_mode_driver = {
>>>> +};
>>>> +
>>>> +static void drm_kunit_free_device(struct drm_device *drm, void *ptr)
>>>> +{
>>>> +	struct device *dev = ptr;
>>>> +
>>>> +	root_device_unregister(dev);
>>>> +}
>>>> +
>>>> +struct drm_device *drm_kunit_device_init(const char *name)
>>>> +{
>>>> +	struct drm_device *drm;
>>>> +	struct device *dev;
>>>> +	int ret;
>>>> +
>>>> +	dev = root_device_register(name);
>>>> +	if (IS_ERR(dev))
>>>> +		return ERR_CAST(dev);
>>>> +
>>>> +	drm = drm_dev_alloc(&drm_mode_driver, dev);
>>>
>>> I can't find drm being freed anywhere?
>>> Maybe you could assign it to drm->managed.final_kfree.
> 
> There's a drm_dev_put in the test_exit hook which should free it.
> 

I see now, there's a drmm_add_final_kfree() in drm_dev_alloc().

Noralf.

>> Perhaps a better solution would be to use devm_drm_dev_alloc() and
>> unregister the root device on exit. That avoids reaching into the drm
>> managed internals and it looks more like a regular driver.
> 
> But yeah, this is a good idea, I'll do it.
> 
> Maxime

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

* Re: [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property
  2022-09-26  9:50     ` Maxime Ripard
@ 2022-09-26 12:34       ` Thomas Zimmermann
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-26 12:34 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Airlie, nouveau, dri-devel, Phil Elwell, Emma Anholt,
	Samuel Holland, Jernej Skrabec, Chen-Yu Tsai, Geert Uytterhoeven,
	Ben Skeggs, linux-sunxi, intel-gfx, Hans de Goede, Rodrigo Vivi,
	linux-arm-kernel, Tvrtko Ursulin, Dom Cobley, linux-kernel,
	Mateusz Kwiatkowski, Noralf Trønnes


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

Hi

Am 26.09.22 um 11:50 schrieb Maxime Ripard:
> Hi Thomas,
> 
> On Fri, Sep 23, 2022 at 10:19:08AM +0200, Thomas Zimmermann wrote:
>> Hi
>>
>> Am 22.09.22 um 16:25 schrieb Maxime Ripard:
>>> The current tv_mode has driver-specific values that don't allow to
>>> easily share code using it, either at the userspace or kernel level.
>>>
>>> Since we're going to introduce a new, generic, property that fit the
>>> same purpose, let's rename this one to legacy_tv_mode to make it
>>> obvious we should move away from it.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>
>> It's not wrong, but 'legacy' is already overloaded with meaning. If you can,
>> maybe name it 'driver_tv_mode_property' or 'custom_tv_mode_property'
>> instead.
>>
>> Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
> 
> I'd really like to point out that new drivers shouldn't be using this.
> If we're using either of your proposals then writers might get the
> impression that this is ok to us.
> 
> Would you prefer deprecated to legacy?

I'm merely suggesting. Call it legacy then, so you don't have to rework 
all of the patches.

Best regards
Thomas

> 
> Maxime

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-26 11:17         ` Thomas Zimmermann
@ 2022-09-26 12:42           ` Maxime Ripard
  2022-09-26 13:02             ` Thomas Zimmermann
  0 siblings, 1 reply; 75+ messages in thread
From: Maxime Ripard @ 2022-09-26 12:42 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: Emma Anholt, David Airlie, nouveau, dri-devel, Phil Elwell,
	Samuel Holland, Jernej Skrabec, Chen-Yu Tsai, Geert Uytterhoeven,
	Ben Skeggs, linux-sunxi, intel-gfx, Hans de Goede, Rodrigo Vivi,
	linux-arm-kernel, Tvrtko Ursulin, Dom Cobley, linux-kernel,
	Mateusz Kwiatkowski, Noralf Trønnes

[-- Attachment #1: Type: text/plain, Size: 1635 bytes --]

On Mon, Sep 26, 2022 at 01:17:52PM +0200, Thomas Zimmermann wrote:
> Hi
> 
> Am 26.09.22 um 12:34 schrieb Geert Uytterhoeven:
> > Hi Maxime,
> > 
> > On Mon, Sep 26, 2022 at 12:17 PM Maxime Ripard <maxime@cerno.tech> wrote:
> > > On Fri, Sep 23, 2022 at 11:05:48AM +0200, Thomas Zimmermann wrote:
> > > > > +   /* 63.556us * 13.5MHz = 858 pixels */
> > > > 
> > > > I kind of get what the comment wants to tell me, but the units don't add up.
> > > 
> > > I'm not sure how it doesn't add up?
> > > 
> > > We have a frequency in Hz (equivalent to s^-1) and a duration in s, so
> > > the result ends up with no dimension, which is to be expected for a
> > > number of periods?
> > 
> > To make the units add up, it should be 13.5 Mpixel/s
> > (which is what a pixel clock of 13.5 MHz really means ;-)
> 
> Sort of. It leaves the time value as a magic number, which obfuscates what's
> happening.
> 
> The unit for htotal is pixels/scanline because if you multiply it with the
> number of scanlines per frame (which is in vtotal), you get pixels/frame.
> Multiplying with the frames per second results in the pixel clock in
> pixels/second.

That's true, but both are true?

> That's a bit much for this comment. Hence, I suggested to remove these
> comments entirely and document the relation among the numbers in a more
> prominent location. The documentation for drm_display_mode would be a good
> place, I guess.

I'm not sure I understand what it's about. It's an explicit requirement
of PAL and NTSC, why would something so specific be in the generic
definition of drm_display_mode?

Maxime

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

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

* Re: [Nouveau] [PATCH v2 09/33] drm/connector: Add TV standard property
  2022-09-26 10:01     ` Maxime Ripard
@ 2022-09-26 12:59       ` Noralf Trønnes
  0 siblings, 0 replies; 75+ messages in thread
From: Noralf Trønnes @ 2022-09-26 12:59 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Airlie, nouveau, Joonas Lahtinen, dri-devel, Phil Elwell,
	Emma Anholt, Samuel Holland, Jernej Skrabec, Chen-Yu Tsai,
	Geert Uytterhoeven, Ben Skeggs, linux-sunxi, Daniel Vetter,
	intel-gfx, Maarten Lankhorst, Jani Nikula, Hans de Goede,
	Rodrigo Vivi, linux-arm-kernel, Tvrtko Ursulin, Dom Cobley,
	linux-kernel, Mateusz Kwiatkowski, Noralf Trønnes



Den 26.09.2022 12.01, skrev Maxime Ripard:
> On Sat, Sep 24, 2022 at 05:52:29PM +0200, Noralf Trønnes wrote:
>> Den 22.09.2022 16.25, skrev Maxime Ripard:
>>> The TV mode property has been around for a while now to select and get the
>>> current TV mode output on an analog TV connector.
>>>
>>> Despite that property name being generic, its content isn't and has been
>>> driver-specific which makes it hard to build any generic behaviour on top
>>> of it, both in kernel and user-space.
>>>
>>> Let's create a new enum tv norm property, that can contain any of the
>>> analog TV standards currently supported by kernel drivers. Each driver can
>>> then pass in a bitmask of the modes it supports, and the property
>>> creation function will filter out the modes not supported.
>>>
>>> We'll then be able to phase out the older tv mode property.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>
>> Please can you add per patch changelogs, it's hard to review when I have
>> to recall what might have happened with each patch. If you do it drm
>> style and put in the commit message it should be easy enough to do.
> 
> I certainly don't want to start that discussion, but I'm really not a
> fan of that format either. I'll do it for that series if you prefer.
> 

The format isn't important, but especially a big series like this and
being weeks between each iteration it's difficult to follow and see
which review comments that you have chosen to implement and how. It's
almost a full review each time. Even if I see that I have acked/rewieved
a patch, if I don't remember, I have to go back to the previous version
and see if I had any comments and if you followed up on that.

>>> +/**
>>> + * enum drm_connector_tv_mode - Analog TV output mode
>>> + *
>>> + * This enum is used to indicate the TV output mode used on an analog TV
>>> + * connector.
>>> + *
>>> + * WARNING: The values of this enum is uABI since they're exposed in the
>>> + * "TV mode" connector property.
>>> + */
>>> +enum drm_connector_tv_mode {
>>> +	/**
>>> +	 * @DRM_MODE_TV_MODE_NONE: Placeholder to not default on one
>>> +	 * variant or the other when nothing is set.
>>> +	 */
>>> +	DRM_MODE_TV_MODE_NONE = 0,
>>
>> How is this supposed to be used?
> 
> It's not supposed to be used. It was a suggestion from Mateusz to avoid
> to default to any standard when we don't initialize something. I don't
> have any strong feeling about it, so I can drop it if you prefer.
> 

The confusing thing to me is that "None" is part of the property enum
list, so the idea is that it can end up in userspace if there's a driver
error? Hmm, that won't work since TV_MODE_NONE won't be part of the
bitmask that the driver sets. So userspace reading the property ends up
with a value for which there's no enum name to match.

So usespace should be trained to know that zero for this property is a
driver error? No, not a good idea.

I think to catch a bug like this drm_atomic_connector_get_property()
should check the tv.mode value and see if it's a legal enum value and if
not it has to just pick a legal one and print an error. But I'm not sure
it's worth it to catch a bug like this. And I don't see any other enum
properties being checked for validity either before being returned to
userspace.

Based on this reasoning I think you should drop the NONE value.

Noralf.

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

* Re: [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes
  2022-09-26 12:42           ` Maxime Ripard
@ 2022-09-26 13:02             ` Thomas Zimmermann
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Zimmermann @ 2022-09-26 13:02 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Emma Anholt, David Airlie, nouveau, dri-devel, Phil Elwell,
	Samuel Holland, Jernej Skrabec, Chen-Yu Tsai, Geert Uytterhoeven,
	Ben Skeggs, linux-sunxi, intel-gfx, Hans de Goede, Rodrigo Vivi,
	linux-arm-kernel, Tvrtko Ursulin, Dom Cobley, linux-kernel,
	Mateusz Kwiatkowski, Noralf Trønnes


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

Hi

Am 26.09.22 um 14:42 schrieb Maxime Ripard:
> On Mon, Sep 26, 2022 at 01:17:52PM +0200, Thomas Zimmermann wrote:
>> Hi
>>
>> Am 26.09.22 um 12:34 schrieb Geert Uytterhoeven:
>>> Hi Maxime,
>>>
>>> On Mon, Sep 26, 2022 at 12:17 PM Maxime Ripard <maxime@cerno.tech> wrote:
>>>> On Fri, Sep 23, 2022 at 11:05:48AM +0200, Thomas Zimmermann wrote:
>>>>>> +   /* 63.556us * 13.5MHz = 858 pixels */
>>>>>
>>>>> I kind of get what the comment wants to tell me, but the units don't add up.
>>>>
>>>> I'm not sure how it doesn't add up?
>>>>
>>>> We have a frequency in Hz (equivalent to s^-1) and a duration in s, so
>>>> the result ends up with no dimension, which is to be expected for a
>>>> number of periods?
>>>
>>> To make the units add up, it should be 13.5 Mpixel/s
>>> (which is what a pixel clock of 13.5 MHz really means ;-)
>>
>> Sort of. It leaves the time value as a magic number, which obfuscates what's
>> happening.
>>
>> The unit for htotal is pixels/scanline because if you multiply it with the
>> number of scanlines per frame (which is in vtotal), you get pixels/frame.
>> Multiplying with the frames per second results in the pixel clock in
>> pixels/second.
> 
> That's true, but both are true?

I'm not quite sure what you mean. I tried to say that this magic time 
value makes all this hard to see.

> 
>> That's a bit much for this comment. Hence, I suggested to remove these
>> comments entirely and document the relation among the numbers in a more
>> prominent location. The documentation for drm_display_mode would be a good
>> place, I guess.
> 
> I'm not sure I understand what it's about. It's an explicit requirement
> of PAL and NTSC, why would something so specific be in the generic
> definition of drm_display_mode?

Not just TV signals, it's the case for all displays were we control the 
electron beam in some way (VGA). Such documentation could therefore be 
added to DRM in an appropriate place. That makes it easier for newcomers 
to see why certain modes are defined the way they are. (At first, 
display modes can look like they are made up randomly.)

For your test cases, maybe simply refer to the relevant standard documents.

Best regards
Thomas

> 
> Maxime

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

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

end of thread, other threads:[~2022-09-26 13:03 UTC | newest]

Thread overview: 75+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-22 14:25 [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 01/33] drm/tests: Order Kunit tests in Makefile Maxime Ripard
2022-09-23  8:06   ` Thomas Zimmermann
2022-09-24 17:33   ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 02/33] drm/tests: Add Kunit Helpers Maxime Ripard
2022-09-24 17:56   ` Noralf Trønnes
2022-09-24 18:06     ` Noralf Trønnes
2022-09-26  9:36       ` Maxime Ripard
2022-09-26 12:15         ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 03/33] drm/atomic-helper: Rename drm_atomic_helper_connector_tv_reset to avoid ambiguity Maxime Ripard
2022-09-23  8:09   ` Thomas Zimmermann
2022-09-22 14:25 ` [Nouveau] [PATCH v2 04/33] drm/connector: Rename subconnector state variable Maxime Ripard
2022-09-23  8:14   ` Thomas Zimmermann
2022-09-22 14:25 ` [Nouveau] [PATCH v2 05/33] drm/atomic: Add TV subconnector property to get/set_property Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 06/33] drm/connector: Rename legacy TV property Maxime Ripard
2022-09-22 20:44   ` Lyude Paul
2022-09-23  8:19   ` Thomas Zimmermann
2022-09-26  9:50     ` Maxime Ripard
2022-09-26 12:34       ` Thomas Zimmermann
2022-09-24 15:38   ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 07/33] drm/connector: Only register TV mode property if present Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 08/33] drm/connector: Rename drm_mode_create_tv_properties Maxime Ripard
2022-09-22 20:45   ` Lyude Paul
2022-09-24 15:43   ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 09/33] drm/connector: Add TV standard property Maxime Ripard
2022-09-24 15:52   ` Noralf Trønnes
2022-09-26 10:01     ` Maxime Ripard
2022-09-26 12:59       ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 10/33] drm/modes: Add a function to generate analog display modes Maxime Ripard
2022-09-23  9:05   ` Thomas Zimmermann
2022-09-23  9:18     ` Jani Nikula
2022-09-23 10:16       ` Thomas Zimmermann
2022-09-26 10:18         ` Maxime Ripard
2022-09-26 10:55           ` Thomas Zimmermann
2022-09-26 10:17     ` Maxime Ripard
2022-09-26 10:34       ` Geert Uytterhoeven
2022-09-26 11:17         ` Thomas Zimmermann
2022-09-26 12:42           ` Maxime Ripard
2022-09-26 13:02             ` Thomas Zimmermann
2022-09-22 14:25 ` [Nouveau] [PATCH v2 11/33] drm/modes: Only consider bpp and refresh before options Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 12/33] drm/modes: parse_cmdline: Add support for named modes containing dashes Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 13/33] drm/client: Add some tests for drm_connector_pick_cmdline_mode() Maxime Ripard
2022-09-23  9:15   ` Thomas Zimmermann
2022-09-23  9:26     ` Javier Martinez Canillas
2022-09-23 10:30       ` Thomas Zimmermann
2022-09-23 11:01         ` Javier Martinez Canillas
2022-09-23 11:14         ` Maxime Ripard
2022-09-23 11:59   ` Jani Nikula
2022-09-22 14:25 ` [Nouveau] [PATCH v2 14/33] drm/modes: Move named modes parsing to a separate function Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 15/33] drm/modes: Bail out of named mode parsing if empty Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 16/33] drm/modes: Bail out of named mode parsing early if it's a number Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 17/33] drm/modes: Bail out of named mode parsing early if it's an option Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 18/33] drm/modes: Bail out of named mode parsing early if it's a status Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 19/33] drm/modes: Switch to named mode descriptors Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 20/33] drm/modes: Fill drm_cmdline mode from named modes Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 21/33] drm/connector: Add pixel clock to cmdline mode Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 22/33] drm/connector: Add a function to lookup a TV mode by its name Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 23/33] drm/modes: Introduce the tv_mode property as a command-line option Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 24/33] drm/modes: Properly generate a drm_display_mode from a named mode Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 25/33] drm/modes: Introduce more named modes Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 26/33] drm/atomic-helper: Add a TV properties reset helper Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 27/33] drm/atomic-helper: Add an analog TV atomic_check implementation Maxime Ripard
2022-09-24 15:58   ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 28/33] drm/vc4: vec: Fix definition of PAL-M mode Maxime Ripard
2022-09-24 15:59   ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 29/33] drm/vc4: vec: Use TV Reset implementation Maxime Ripard
2022-09-22 14:25 ` [Nouveau] [PATCH v2 30/33] drm/vc4: vec: Check for VEC output constraints Maxime Ripard
2022-09-24 16:00   ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 31/33] drm/vc4: vec: Convert to the new TV mode property Maxime Ripard
2022-09-24 17:09   ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 32/33] drm/vc4: vec: Add support for more analog TV standards Maxime Ripard
2022-09-24 17:12   ` Noralf Trønnes
2022-09-22 14:25 ` [Nouveau] [PATCH v2 33/33] drm/sun4i: tv: Convert to the new TV mode property Maxime Ripard
2022-09-22 14:31 ` [Nouveau] [PATCH v2 00/33] drm: Analog TV Improvements Maxime Ripard
2022-09-25 15:58 ` 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).