diff mbox series

[v8,12/24] drm/connector: Add a function to lookup a TV mode by its name

Message ID 20220728-rpi-analog-tv-properties-v8-12-09ce1466967c@cerno.tech (mailing list archive)
State New, archived
Headers show
Series drm: Analog TV Improvements | expand

Commit Message

Maxime Ripard Nov. 10, 2022, 11:07 a.m. UTC
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.

Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
Tested-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

---
Changes in v7:
- Add kunit tests
---
 drivers/gpu/drm/drm_connector.c            | 24 ++++++++
 drivers/gpu/drm/tests/Makefile             |  1 +
 drivers/gpu/drm/tests/drm_connector_test.c | 90 ++++++++++++++++++++++++++++++
 include/drm/drm_connector.h                |  2 +
 4 files changed, 117 insertions(+)

Comments

Maíra Canal Nov. 10, 2022, 11:11 p.m. UTC | #1
Hi Maxime,

On 11/10/22 08:07, Maxime Ripard wrote:
> 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.
> 
> Reviewed-by: Noralf Trønnes <noralf@tronnes.org>
> Tested-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> 
> ---
> Changes in v7:
> - Add kunit tests
> ---
>  drivers/gpu/drm/drm_connector.c            | 24 ++++++++
>  drivers/gpu/drm/tests/Makefile             |  1 +
>  drivers/gpu/drm/tests/drm_connector_test.c | 90 ++++++++++++++++++++++++++++++
>  include/drm/drm_connector.h                |  2 +
>  4 files changed, 117 insertions(+)
> 
> diff --git a/drivers/gpu/drm/tests/drm_connector_test.c b/drivers/gpu/drm/tests/drm_connector_test.c
> new file mode 100644
> index 000000000000..f2272b9df211
> --- /dev/null
> +++ b/drivers/gpu/drm/tests/drm_connector_test.c
> @@ -0,0 +1,90 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Kunit test for drm_modes functions
> + */
> +
> +#include <drm/drm_connector.h>
> +
> +#include <kunit/test.h>
> +
> +struct drm_get_tv_mode_from_name_test {
> +	const char *name;
> +	enum drm_connector_tv_mode expected_mode;
> +};
> +
> +#define TV_MODE_NAME(_name, _mode)		\
> +	{					\
> +		.name = _name,			\
> +		.expected_mode = _mode,		\
> +	}
> +
> +static void drm_test_get_tv_mode_from_name_valid(struct kunit *test)
> +{
> +	const struct drm_get_tv_mode_from_name_test *params = test->param_value;
> +
> +	KUNIT_EXPECT_EQ(test,
> +			drm_get_tv_mode_from_name(params->name, strlen(params->name)),
> +			params->expected_mode);
> +}
> +
> +static const
> +struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] = {
> +	TV_MODE_NAME("NTSC", DRM_MODE_TV_MODE_NTSC),
> +	TV_MODE_NAME("NTSC-443", DRM_MODE_TV_MODE_NTSC_443),
> +	TV_MODE_NAME("NTSC-J", DRM_MODE_TV_MODE_NTSC_J),
> +	TV_MODE_NAME("PAL", DRM_MODE_TV_MODE_PAL),
> +	TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M),
> +	TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N),
> +	TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM),
> +};
> +
> +static void
> +drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t,
> +				     char *desc)
> +{
> +	sprintf(desc, "%s", t->name);
> +}

I believe that it should be a blank line here for code style.

> +KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid,
> +		  drm_get_tv_mode_from_name_valid_tests,
> +		  drm_get_tv_mode_from_name_valid_desc);
> +
> +static void drm_test_get_tv_mode_from_name_invalid(struct kunit *test)
> +{
> +	const char *name = *(const char **)test->param_value;
> +
> +	KUNIT_EXPECT_LT(test,
> +			drm_get_tv_mode_from_name(name, strlen(name)),
> +			0);
> +}
> +
> +static const
> +char *drm_get_tv_mode_from_name_invalid_tests[] = {
> +	/* Truncated */
> +	"NTS",
> +};

Considering that there is only one invalid test, is there a particular
reason to parametrize this test?

> +
> +static void
> +drm_get_tv_mode_from_name_invalid_desc(const char **name, char *desc)
> +{
> +	sprintf(desc, "%s", *name);
> +}
> +KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_invalid,
> +		  drm_get_tv_mode_from_name_invalid_tests,
> +		  drm_get_tv_mode_from_name_invalid_desc);
> +
> +static struct kunit_case drm_get_tv_mode_from_name_tests[] = {
> +	KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid,
> +			 drm_get_tv_mode_from_name_valid_gen_params),
> +	KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_invalid,
> +			 drm_get_tv_mode_from_name_invalid_gen_params),
> +	{ }
> +};
> +
> +static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
> +	.name = "drm_get_tv_mode_from_name",
> +	.test_cases = drm_get_tv_mode_from_name_tests,
> +};
> +
> +kunit_test_suites(
> +	&drm_get_tv_mode_from_name_test_suite
> +);

Considering that there is only one suite, you could use the
kunit_test_suite macro instead.

Best Regards,
- Maíra Canal

>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 07d449736956..8d92777e57dd 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -995,6 +995,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/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index b22ac96fdd65..c7903c112c65 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -3,6 +3,7 @@ 
 obj-$(CONFIG_DRM_KUNIT_TEST) += \
 	drm_buddy_test.o \
 	drm_cmdline_parser_test.o \
+	drm_connector_test.o \
 	drm_damage_helper_test.o \
 	drm_dp_mst_helper_test.o \
 	drm_format_helper_test.o \
diff --git a/drivers/gpu/drm/tests/drm_connector_test.c b/drivers/gpu/drm/tests/drm_connector_test.c
new file mode 100644
index 000000000000..f2272b9df211
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_connector_test.c
@@ -0,0 +1,90 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kunit test for drm_modes functions
+ */
+
+#include <drm/drm_connector.h>
+
+#include <kunit/test.h>
+
+struct drm_get_tv_mode_from_name_test {
+	const char *name;
+	enum drm_connector_tv_mode expected_mode;
+};
+
+#define TV_MODE_NAME(_name, _mode)		\
+	{					\
+		.name = _name,			\
+		.expected_mode = _mode,		\
+	}
+
+static void drm_test_get_tv_mode_from_name_valid(struct kunit *test)
+{
+	const struct drm_get_tv_mode_from_name_test *params = test->param_value;
+
+	KUNIT_EXPECT_EQ(test,
+			drm_get_tv_mode_from_name(params->name, strlen(params->name)),
+			params->expected_mode);
+}
+
+static const
+struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] = {
+	TV_MODE_NAME("NTSC", DRM_MODE_TV_MODE_NTSC),
+	TV_MODE_NAME("NTSC-443", DRM_MODE_TV_MODE_NTSC_443),
+	TV_MODE_NAME("NTSC-J", DRM_MODE_TV_MODE_NTSC_J),
+	TV_MODE_NAME("PAL", DRM_MODE_TV_MODE_PAL),
+	TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M),
+	TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N),
+	TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM),
+};
+
+static void
+drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t,
+				     char *desc)
+{
+	sprintf(desc, "%s", t->name);
+}
+KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid,
+		  drm_get_tv_mode_from_name_valid_tests,
+		  drm_get_tv_mode_from_name_valid_desc);
+
+static void drm_test_get_tv_mode_from_name_invalid(struct kunit *test)
+{
+	const char *name = *(const char **)test->param_value;
+
+	KUNIT_EXPECT_LT(test,
+			drm_get_tv_mode_from_name(name, strlen(name)),
+			0);
+}
+
+static const
+char *drm_get_tv_mode_from_name_invalid_tests[] = {
+	/* Truncated */
+	"NTS",
+};
+
+static void
+drm_get_tv_mode_from_name_invalid_desc(const char **name, char *desc)
+{
+	sprintf(desc, "%s", *name);
+}
+KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_invalid,
+		  drm_get_tv_mode_from_name_invalid_tests,
+		  drm_get_tv_mode_from_name_invalid_desc);
+
+static struct kunit_case drm_get_tv_mode_from_name_tests[] = {
+	KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid,
+			 drm_get_tv_mode_from_name_valid_gen_params),
+	KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_invalid,
+			 drm_get_tv_mode_from_name_invalid_gen_params),
+	{ }
+};
+
+static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
+	.name = "drm_get_tv_mode_from_name",
+	.test_cases = drm_get_tv_mode_from_name_tests,
+};
+
+kunit_test_suites(
+	&drm_get_tv_mode_from_name_test_suite
+);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 4927dcb2573f..c856f4871697 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1872,6 +1872,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);