1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <drm/drm_drv.h>
4 #include <drm/drm_kunit_helpers.h>
5 #include <drm/drm_managed.h>
6
7 #include <kunit/resource.h>
8
9 #include <linux/device.h>
10 #include <linux/platform_device.h>
11
12 #define KUNIT_DEVICE_NAME "drm-kunit-mock-device"
13
14 static const struct drm_mode_config_funcs drm_mode_config_funcs = {
15 };
16
fake_probe(struct platform_device * pdev)17 static int fake_probe(struct platform_device *pdev)
18 {
19 return 0;
20 }
21
fake_remove(struct platform_device * pdev)22 static int fake_remove(struct platform_device *pdev)
23 {
24 return 0;
25 }
26
27 static struct platform_driver fake_platform_driver = {
28 .probe = fake_probe,
29 .remove = fake_remove,
30 .driver = {
31 .name = KUNIT_DEVICE_NAME,
32 },
33 };
34
35 /**
36 * drm_kunit_helper_alloc_device - Allocate a mock device for a KUnit test
37 * @test: The test context object
38 *
39 * This allocates a fake struct &device to create a mock for a KUnit
40 * test. The device will also be bound to a fake driver. It will thus be
41 * able to leverage the usual infrastructure and most notably the
42 * device-managed resources just like a "real" device.
43 *
44 * Callers need to make sure drm_kunit_helper_free_device() on the
45 * device when done.
46 *
47 * Returns:
48 * A pointer to the new device, or an ERR_PTR() otherwise.
49 */
drm_kunit_helper_alloc_device(struct kunit * test)50 struct device *drm_kunit_helper_alloc_device(struct kunit *test)
51 {
52 struct platform_device *pdev;
53 int ret;
54
55 ret = platform_driver_register(&fake_platform_driver);
56 KUNIT_ASSERT_EQ(test, ret, 0);
57
58 pdev = platform_device_alloc(KUNIT_DEVICE_NAME, PLATFORM_DEVID_NONE);
59 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
60
61 ret = platform_device_add(pdev);
62 KUNIT_ASSERT_EQ(test, ret, 0);
63
64 return &pdev->dev;
65 }
66 EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_device);
67
68 /**
69 * drm_kunit_helper_free_device - Frees a mock device
70 * @test: The test context object
71 * @dev: The device to free
72 *
73 * Frees a device allocated with drm_kunit_helper_alloc_device().
74 */
drm_kunit_helper_free_device(struct kunit * test,struct device * dev)75 void drm_kunit_helper_free_device(struct kunit *test, struct device *dev)
76 {
77 struct platform_device *pdev = to_platform_device(dev);
78
79 platform_device_unregister(pdev);
80 platform_driver_unregister(&fake_platform_driver);
81 }
82 EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device);
83
84 struct drm_device *
__drm_kunit_helper_alloc_drm_device_with_driver(struct kunit * test,struct device * dev,size_t size,size_t offset,const struct drm_driver * driver)85 __drm_kunit_helper_alloc_drm_device_with_driver(struct kunit *test,
86 struct device *dev,
87 size_t size, size_t offset,
88 const struct drm_driver *driver)
89 {
90 struct drm_device *drm;
91 void *container;
92 int ret;
93
94 container = __devm_drm_dev_alloc(dev, driver, size, offset);
95 if (IS_ERR(container))
96 return ERR_CAST(container);
97
98 drm = container + offset;
99 drm->mode_config.funcs = &drm_mode_config_funcs;
100
101 ret = drmm_mode_config_init(drm);
102 if (ret)
103 return ERR_PTR(ret);
104
105 return drm;
106 }
107 EXPORT_SYMBOL_GPL(__drm_kunit_helper_alloc_drm_device_with_driver);
108
109 MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
110 MODULE_LICENSE("GPL");
111