summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_modes.c37
-rw-r--r--drivers/gpu/drm/tests/drm_cmdline_parser_test.c68
2 files changed, 102 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 9426c87df623..f9fe065f189b 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -2135,6 +2135,30 @@ 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_specified = true;
+ mode->tv_mode = ret;
+
+ return 0;
+}
+
static int drm_mode_parse_cmdline_options(const char *str,
bool freestanding,
const struct drm_connector *connector,
@@ -2204,6 +2228,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;
}
@@ -2232,20 +2259,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,
@@ -2290,6 +2319,8 @@ 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->tv_mode_specified = true;
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 34790e7a3760..88f7f518ffb3 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,65 @@ 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_test_cmdline_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_test_cmdline_force_d_only),
KUNIT_CASE(drm_test_cmdline_force_D_only_dvi),
@@ -977,6 +1044,7 @@ static struct kunit_case drm_cmdline_parser_tests[] = {
KUNIT_CASE(drm_test_cmdline_freestanding_force_e_and_options),
KUNIT_CASE(drm_test_cmdline_panel_orientation),
KUNIT_CASE_PARAM(drm_test_cmdline_invalid, drm_cmdline_invalid_gen_params),
+ KUNIT_CASE_PARAM(drm_test_cmdline_tv_options, drm_cmdline_tv_option_gen_params),
{}
};