193 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2022 Maxime Ripard <mripard@kernel.org>4 */5 6#include <kunit/test.h>7 8#include <drm/drm_connector.h>9#include <drm/drm_edid.h>10#include <drm/drm_drv.h>11#include <drm/drm_kunit_helpers.h>12#include <drm/drm_modes.h>13#include <drm/drm_modeset_helper_vtables.h>14#include <drm/drm_probe_helper.h>15 16struct drm_client_modeset_test_priv {17 struct drm_device *drm;18 struct device *dev;19 struct drm_connector connector;20};21 22static int drm_client_modeset_connector_get_modes(struct drm_connector *connector)23{24 struct drm_display_mode *mode;25 int count;26 27 count = drm_add_modes_noedid(connector, 1920, 1200);28 29 mode = drm_mode_analog_ntsc_480i(connector->dev);30 if (!mode)31 return count;32 33 drm_mode_probed_add(connector, mode);34 count += 1;35 36 mode = drm_mode_analog_pal_576i(connector->dev);37 if (!mode)38 return count;39 40 drm_mode_probed_add(connector, mode);41 count += 1;42 43 return count;44}45 46static const struct drm_connector_helper_funcs drm_client_modeset_connector_helper_funcs = {47 .get_modes = drm_client_modeset_connector_get_modes,48};49 50static const struct drm_connector_funcs drm_client_modeset_connector_funcs = {51};52 53static int drm_client_modeset_test_init(struct kunit *test)54{55 struct drm_client_modeset_test_priv *priv;56 int ret;57 58 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);59 KUNIT_ASSERT_NOT_NULL(test, priv);60 61 test->priv = priv;62 63 priv->dev = drm_kunit_helper_alloc_device(test);64 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);65 66 priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev,67 sizeof(*priv->drm), 0,68 DRIVER_MODESET);69 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);70 71 ret = drmm_connector_init(priv->drm, &priv->connector,72 &drm_client_modeset_connector_funcs,73 DRM_MODE_CONNECTOR_Unknown,74 NULL);75 KUNIT_ASSERT_EQ(test, ret, 0);76 77 drm_connector_helper_add(&priv->connector, &drm_client_modeset_connector_helper_funcs);78 79 priv->connector.interlace_allowed = true;80 priv->connector.doublescan_allowed = true;81 82 return 0;83}84 85static void drm_test_pick_cmdline_res_1920_1080_60(struct kunit *test)86{87 struct drm_client_modeset_test_priv *priv = test->priv;88 struct drm_device *drm = priv->drm;89 struct drm_connector *connector = &priv->connector;90 struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;91 struct drm_display_mode *expected_mode, *mode;92 const char *cmdline = "1920x1080@60";93 int ret;94 95 expected_mode = drm_mode_find_dmt(priv->drm, 1920, 1080, 60, false);96 KUNIT_ASSERT_NOT_NULL(test, expected_mode);97 98 KUNIT_ASSERT_TRUE(test,99 drm_mode_parse_command_line_for_connector(cmdline,100 connector,101 cmdline_mode));102 103 mutex_lock(&drm->mode_config.mutex);104 ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);105 mutex_unlock(&drm->mode_config.mutex);106 KUNIT_ASSERT_GT(test, ret, 0);107 108 mode = drm_connector_pick_cmdline_mode(connector);109 KUNIT_ASSERT_NOT_NULL(test, mode);110 111 KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));112}113 114struct drm_connector_pick_cmdline_mode_test {115 const char *cmdline;116 struct drm_display_mode *(*func)(struct drm_device *drm);117};118 119#define TEST_CMDLINE(_cmdline, _fn) \120 { \121 .cmdline = _cmdline, \122 .func = _fn, \123 }124 125static void drm_test_pick_cmdline_named(struct kunit *test)126{127 const struct drm_connector_pick_cmdline_mode_test *params = test->param_value;128 struct drm_client_modeset_test_priv *priv = test->priv;129 struct drm_device *drm = priv->drm;130 struct drm_connector *connector = &priv->connector;131 struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;132 const struct drm_display_mode *expected_mode, *mode;133 const char *cmdline = params->cmdline;134 int ret;135 136 KUNIT_ASSERT_TRUE(test,137 drm_mode_parse_command_line_for_connector(cmdline,138 connector,139 cmdline_mode));140 141 mutex_lock(&drm->mode_config.mutex);142 ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);143 mutex_unlock(&drm->mode_config.mutex);144 KUNIT_ASSERT_GT(test, ret, 0);145 146 mode = drm_connector_pick_cmdline_mode(connector);147 KUNIT_ASSERT_NOT_NULL(test, mode);148 149 expected_mode = params->func(drm);150 KUNIT_ASSERT_NOT_NULL(test, expected_mode);151 152 KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));153}154 155static const156struct drm_connector_pick_cmdline_mode_test drm_connector_pick_cmdline_mode_tests[] = {157 TEST_CMDLINE("NTSC", drm_mode_analog_ntsc_480i),158 TEST_CMDLINE("NTSC-J", drm_mode_analog_ntsc_480i),159 TEST_CMDLINE("PAL", drm_mode_analog_pal_576i),160 TEST_CMDLINE("PAL-M", drm_mode_analog_ntsc_480i),161};162 163static void164drm_connector_pick_cmdline_mode_desc(const struct drm_connector_pick_cmdline_mode_test *t,165 char *desc)166{167 sprintf(desc, "%s", t->cmdline);168}169 170KUNIT_ARRAY_PARAM(drm_connector_pick_cmdline_mode,171 drm_connector_pick_cmdline_mode_tests,172 drm_connector_pick_cmdline_mode_desc);173 174static struct kunit_case drm_test_pick_cmdline_tests[] = {175 KUNIT_CASE(drm_test_pick_cmdline_res_1920_1080_60),176 KUNIT_CASE_PARAM(drm_test_pick_cmdline_named,177 drm_connector_pick_cmdline_mode_gen_params),178 {}179};180 181static struct kunit_suite drm_test_pick_cmdline_test_suite = {182 .name = "drm_test_pick_cmdline",183 .init = drm_client_modeset_test_init,184 .test_cases = drm_test_pick_cmdline_tests185};186 187kunit_test_suite(drm_test_pick_cmdline_test_suite);188 189/*190 * This file is included directly by drm_client_modeset.c so we can't191 * use any MODULE_* macro here.192 */193