212 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Kunit test for drm_probe_helper functions4 */5 6#include <drm/drm_atomic_state_helper.h>7#include <drm/drm_connector.h>8#include <drm/drm_device.h>9#include <drm/drm_drv.h>10#include <drm/drm_kunit_helpers.h>11#include <drm/drm_mode.h>12#include <drm/drm_modes.h>13#include <drm/drm_modeset_helper_vtables.h>14#include <drm/drm_probe_helper.h>15 16#include <kunit/test.h>17 18struct drm_probe_helper_test_priv {19 struct drm_device *drm;20 struct device *dev;21 struct drm_connector connector;22};23 24static const struct drm_connector_helper_funcs drm_probe_helper_connector_helper_funcs = {25};26 27static const struct drm_connector_funcs drm_probe_helper_connector_funcs = {28 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,29 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,30 .reset = drm_atomic_helper_connector_reset,31};32 33static int drm_probe_helper_test_init(struct kunit *test)34{35 struct drm_probe_helper_test_priv *priv;36 struct drm_connector *connector;37 int ret;38 39 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);40 KUNIT_ASSERT_NOT_NULL(test, priv);41 test->priv = priv;42 43 priv->dev = drm_kunit_helper_alloc_device(test);44 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);45 46 priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev,47 sizeof(*priv->drm), 0,48 DRIVER_MODESET | DRIVER_ATOMIC);49 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);50 51 connector = &priv->connector;52 ret = drmm_connector_init(priv->drm, connector,53 &drm_probe_helper_connector_funcs,54 DRM_MODE_CONNECTOR_Unknown,55 NULL);56 KUNIT_ASSERT_EQ(test, ret, 0);57 58 drm_connector_helper_add(connector, &drm_probe_helper_connector_helper_funcs);59 60 return 0;61}62 63typedef struct drm_display_mode *(*expected_mode_func_t)(struct drm_device *);64 65struct drm_connector_helper_tv_get_modes_test {66 const char *name;67 unsigned int supported_tv_modes;68 enum drm_connector_tv_mode default_mode;69 bool cmdline;70 enum drm_connector_tv_mode cmdline_mode;71 expected_mode_func_t *expected_modes;72 unsigned int num_expected_modes;73};74 75#define _TV_MODE_TEST(_name, _supported, _default, _cmdline, _cmdline_mode, ...) \76 { \77 .name = _name, \78 .supported_tv_modes = _supported, \79 .default_mode = _default, \80 .cmdline = _cmdline, \81 .cmdline_mode = _cmdline_mode, \82 .expected_modes = (expected_mode_func_t[]) { __VA_ARGS__ }, \83 .num_expected_modes = sizeof((expected_mode_func_t[]) { __VA_ARGS__ }) / \84 (sizeof(expected_mode_func_t)), \85 }86 87#define TV_MODE_TEST(_name, _supported, _default, ...) \88 _TV_MODE_TEST(_name, _supported, _default, false, 0, __VA_ARGS__)89 90#define TV_MODE_TEST_CMDLINE(_name, _supported, _default, _cmdline, ...) \91 _TV_MODE_TEST(_name, _supported, _default, true, _cmdline, __VA_ARGS__)92 93static void94drm_test_connector_helper_tv_get_modes_check(struct kunit *test)95{96 const struct drm_connector_helper_tv_get_modes_test *params = test->param_value;97 struct drm_probe_helper_test_priv *priv = test->priv;98 struct drm_connector *connector = &priv->connector;99 struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;100 struct drm_display_mode *mode;101 const struct drm_display_mode *expected;102 size_t len;103 int ret;104 105 if (params->cmdline) {106 cmdline->tv_mode_specified = true;107 cmdline->tv_mode = params->cmdline_mode;108 }109 110 ret = drm_mode_create_tv_properties(priv->drm, params->supported_tv_modes);111 KUNIT_ASSERT_EQ(test, ret, 0);112 113 drm_object_attach_property(&connector->base,114 priv->drm->mode_config.tv_mode_property,115 params->default_mode);116 117 mutex_lock(&priv->drm->mode_config.mutex);118 119 ret = drm_connector_helper_tv_get_modes(connector);120 KUNIT_EXPECT_EQ(test, ret, params->num_expected_modes);121 122 len = 0;123 list_for_each_entry(mode, &connector->probed_modes, head)124 len++;125 KUNIT_EXPECT_EQ(test, len, params->num_expected_modes);126 127 if (params->num_expected_modes >= 1) {128 mode = list_first_entry_or_null(&connector->probed_modes,129 struct drm_display_mode, head);130 KUNIT_ASSERT_NOT_NULL(test, mode);131 132 expected = params->expected_modes[0](priv->drm);133 KUNIT_ASSERT_NOT_NULL(test, expected);134 135 KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected));136 KUNIT_EXPECT_TRUE(test, mode->type & DRM_MODE_TYPE_PREFERRED);137 }138 139 if (params->num_expected_modes >= 2) {140 mode = list_next_entry(mode, head);141 KUNIT_ASSERT_NOT_NULL(test, mode);142 143 expected = params->expected_modes[1](priv->drm);144 KUNIT_ASSERT_NOT_NULL(test, expected);145 146 KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected));147 KUNIT_EXPECT_FALSE(test, mode->type & DRM_MODE_TYPE_PREFERRED);148 }149 150 mutex_unlock(&priv->drm->mode_config.mutex);151}152 153static const154struct drm_connector_helper_tv_get_modes_test drm_connector_helper_tv_get_modes_tests[] = {155 { .name = "None" },156 TV_MODE_TEST("PAL",157 BIT(DRM_MODE_TV_MODE_PAL),158 DRM_MODE_TV_MODE_PAL,159 drm_mode_analog_pal_576i),160 TV_MODE_TEST("NTSC",161 BIT(DRM_MODE_TV_MODE_NTSC),162 DRM_MODE_TV_MODE_NTSC,163 drm_mode_analog_ntsc_480i),164 TV_MODE_TEST("Both, NTSC Default",165 BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL),166 DRM_MODE_TV_MODE_NTSC,167 drm_mode_analog_ntsc_480i, drm_mode_analog_pal_576i),168 TV_MODE_TEST("Both, PAL Default",169 BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL),170 DRM_MODE_TV_MODE_PAL,171 drm_mode_analog_pal_576i, drm_mode_analog_ntsc_480i),172 TV_MODE_TEST_CMDLINE("Both, NTSC Default, with PAL on command-line",173 BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL),174 DRM_MODE_TV_MODE_NTSC,175 DRM_MODE_TV_MODE_PAL,176 drm_mode_analog_pal_576i, drm_mode_analog_ntsc_480i),177 TV_MODE_TEST_CMDLINE("Both, PAL Default, with NTSC on command-line",178 BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL),179 DRM_MODE_TV_MODE_PAL,180 DRM_MODE_TV_MODE_NTSC,181 drm_mode_analog_ntsc_480i, drm_mode_analog_pal_576i),182};183 184static void185drm_connector_helper_tv_get_modes_desc(const struct drm_connector_helper_tv_get_modes_test *t,186 char *desc)187{188 sprintf(desc, "%s", t->name);189}190 191KUNIT_ARRAY_PARAM(drm_connector_helper_tv_get_modes,192 drm_connector_helper_tv_get_modes_tests,193 drm_connector_helper_tv_get_modes_desc);194 195static struct kunit_case drm_test_connector_helper_tv_get_modes_tests[] = {196 KUNIT_CASE_PARAM(drm_test_connector_helper_tv_get_modes_check,197 drm_connector_helper_tv_get_modes_gen_params),198 { }199};200 201static struct kunit_suite drm_test_connector_helper_tv_get_modes_suite = {202 .name = "drm_connector_helper_tv_get_modes",203 .init = drm_probe_helper_test_init,204 .test_cases = drm_test_connector_helper_tv_get_modes_tests,205};206 207kunit_test_suite(drm_test_connector_helper_tv_get_modes_suite);208 209MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");210MODULE_DESCRIPTION("Kunit test for drm_probe_helper functions");211MODULE_LICENSE("GPL");212