drm/connector: Add a function to lookup a TV mode by its name
authorMaxime Ripard <maxime@cerno.tech>
Thu, 17 Nov 2022 09:28:50 +0000 (10:28 +0100)
committerMaxime Ripard <maxime@cerno.tech>
Thu, 24 Nov 2022 11:42:39 +0000 (12:42 +0100)
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>
Acked-in-principle-or-something-like-that-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-7-256dad125326@cerno.tech
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/tests/Makefile
drivers/gpu/drm/tests/drm_connector_test.c [new file with mode: 0644]
include/drm/drm_connector.h

index 07d449736956cf0a82a29dc3c903a54872905db8..8d92777e57ddfbddc5d8a4bd08e47199c22da978 100644 (file)
@@ -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 */
index b22ac96fdd652947172fd2e0b0b590629dc5498d..c7903c112c65cf9138142b64a79e9bfb44426570 100644 (file)
@@ -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 (file)
index 0000000..c66aa2d
--- /dev/null
@@ -0,0 +1,76 @@
+// 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_truncated(struct kunit *test)
+{
+       const char *name = "NTS";
+       int ret;
+
+       ret = drm_get_tv_mode_from_name(name, strlen(name));
+       KUNIT_EXPECT_LT(test, ret, 0);
+};
+
+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(drm_test_get_tv_mode_from_name_truncated),
+       { }
+};
+
+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_suite(drm_get_tv_mode_from_name_test_suite);
+
+MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
+MODULE_LICENSE("GPL");
index efa32e88a5b72bde02d89297e20a56b7832b23b0..3390b93b07e98a4bd5b202b9536adef6268223c7 100644 (file)
@@ -1878,6 +1878,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);