]> Git Repo - linux.git/blob - drivers/gpu/drm/tests/drm_kunit_helpers.c
Merge tag 'ti-k3-dt-for-v6.11-part2' into ti-k3-dts-next
[linux.git] / drivers / gpu / drm / tests / drm_kunit_helpers.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <drm/drm_atomic.h>
4 #include <drm/drm_atomic_helper.h>
5 #include <drm/drm_drv.h>
6 #include <drm/drm_fourcc.h>
7 #include <drm/drm_kunit_helpers.h>
8 #include <drm/drm_managed.h>
9
10 #include <kunit/device.h>
11 #include <kunit/resource.h>
12
13 #include <linux/device.h>
14 #include <linux/platform_device.h>
15
16 #define KUNIT_DEVICE_NAME       "drm-kunit-mock-device"
17
18 static const struct drm_mode_config_funcs drm_mode_config_funcs = {
19         .atomic_check   = drm_atomic_helper_check,
20         .atomic_commit  = drm_atomic_helper_commit,
21 };
22
23 /**
24  * drm_kunit_helper_alloc_device - Allocate a mock device for a KUnit test
25  * @test: The test context object
26  *
27  * This allocates a fake struct &device to create a mock for a KUnit
28  * test. The device will also be bound to a fake driver. It will thus be
29  * able to leverage the usual infrastructure and most notably the
30  * device-managed resources just like a "real" device.
31  *
32  * Resources will be cleaned up automatically, but the removal can be
33  * forced using @drm_kunit_helper_free_device.
34  *
35  * Returns:
36  * A pointer to the new device, or an ERR_PTR() otherwise.
37  */
38 struct device *drm_kunit_helper_alloc_device(struct kunit *test)
39 {
40         return kunit_device_register(test, KUNIT_DEVICE_NAME);
41 }
42 EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_device);
43
44 /**
45  * drm_kunit_helper_free_device - Frees a mock device
46  * @test: The test context object
47  * @dev: The device to free
48  *
49  * Frees a device allocated with drm_kunit_helper_alloc_device().
50  */
51 void drm_kunit_helper_free_device(struct kunit *test, struct device *dev)
52 {
53         kunit_device_unregister(test, dev);
54 }
55 EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device);
56
57 struct drm_device *
58 __drm_kunit_helper_alloc_drm_device_with_driver(struct kunit *test,
59                                                 struct device *dev,
60                                                 size_t size, size_t offset,
61                                                 const struct drm_driver *driver)
62 {
63         struct drm_device *drm;
64         void *container;
65         int ret;
66
67         container = __devm_drm_dev_alloc(dev, driver, size, offset);
68         if (IS_ERR(container))
69                 return ERR_CAST(container);
70
71         drm = container + offset;
72         drm->mode_config.funcs = &drm_mode_config_funcs;
73
74         ret = drmm_mode_config_init(drm);
75         if (ret)
76                 return ERR_PTR(ret);
77
78         return drm;
79 }
80 EXPORT_SYMBOL_GPL(__drm_kunit_helper_alloc_drm_device_with_driver);
81
82 static void action_drm_release_context(void *ptr)
83 {
84         struct drm_modeset_acquire_ctx *ctx = ptr;
85
86         drm_modeset_drop_locks(ctx);
87         drm_modeset_acquire_fini(ctx);
88 }
89
90 /**
91  * drm_kunit_helper_acquire_ctx_alloc - Allocates an acquire context
92  * @test: The test context object
93  *
94  * Allocates and initializes a modeset acquire context.
95  *
96  * The context is tied to the kunit test context, so we must not call
97  * drm_modeset_acquire_fini() on it, it will be done so automatically.
98  *
99  * Returns:
100  * An ERR_PTR on error, a pointer to the newly allocated context otherwise
101  */
102 struct drm_modeset_acquire_ctx *
103 drm_kunit_helper_acquire_ctx_alloc(struct kunit *test)
104 {
105         struct drm_modeset_acquire_ctx *ctx;
106         int ret;
107
108         ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
109         KUNIT_ASSERT_NOT_NULL(test, ctx);
110
111         drm_modeset_acquire_init(ctx, 0);
112
113         ret = kunit_add_action_or_reset(test,
114                                         action_drm_release_context,
115                                         ctx);
116         if (ret)
117                 return ERR_PTR(ret);
118
119         return ctx;
120 }
121 EXPORT_SYMBOL_GPL(drm_kunit_helper_acquire_ctx_alloc);
122
123 static void kunit_action_drm_atomic_state_put(void *ptr)
124 {
125         struct drm_atomic_state *state = ptr;
126
127         drm_atomic_state_put(state);
128 }
129
130 /**
131  * drm_kunit_helper_atomic_state_alloc - Allocates an atomic state
132  * @test: The test context object
133  * @drm: The device to alloc the state for
134  * @ctx: Locking context for that atomic update
135  *
136  * Allocates a empty atomic state.
137  *
138  * The state is tied to the kunit test context, so we must not call
139  * drm_atomic_state_put() on it, it will be done so automatically.
140  *
141  * Returns:
142  * An ERR_PTR on error, a pointer to the newly allocated state otherwise
143  */
144 struct drm_atomic_state *
145 drm_kunit_helper_atomic_state_alloc(struct kunit *test,
146                                     struct drm_device *drm,
147                                     struct drm_modeset_acquire_ctx *ctx)
148 {
149         struct drm_atomic_state *state;
150         int ret;
151
152         state = drm_atomic_state_alloc(drm);
153         if (!state)
154                 return ERR_PTR(-ENOMEM);
155
156         ret = kunit_add_action_or_reset(test,
157                                         kunit_action_drm_atomic_state_put,
158                                         state);
159         if (ret)
160                 return ERR_PTR(ret);
161
162         state->acquire_ctx = ctx;
163
164         return state;
165 }
166 EXPORT_SYMBOL_GPL(drm_kunit_helper_atomic_state_alloc);
167
168 static const uint32_t default_plane_formats[] = {
169         DRM_FORMAT_XRGB8888,
170 };
171
172 static const uint64_t default_plane_modifiers[] = {
173         DRM_FORMAT_MOD_LINEAR,
174         DRM_FORMAT_MOD_INVALID
175 };
176
177 static const struct drm_plane_helper_funcs default_plane_helper_funcs = {
178 };
179
180 static const struct drm_plane_funcs default_plane_funcs = {
181         .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
182         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
183         .reset                  = drm_atomic_helper_plane_reset,
184 };
185
186 /**
187  * drm_kunit_helper_create_primary_plane - Creates a mock primary plane for a KUnit test
188  * @test: The test context object
189  * @drm: The device to alloc the plane for
190  * @funcs: Callbacks for the new plane. Optional.
191  * @helper_funcs: Helpers callbacks for the new plane. Optional.
192  * @formats: array of supported formats (DRM_FORMAT\_\*). Optional.
193  * @num_formats: number of elements in @formats
194  * @modifiers: array of struct drm_format modifiers terminated by
195  *             DRM_FORMAT_MOD_INVALID. Optional.
196  *
197  * This allocates and initializes a mock struct &drm_plane meant to be
198  * part of a mock device for a KUnit test.
199  *
200  * Resources will be cleaned up automatically.
201  *
202  * @funcs will default to the default helpers implementations.
203  * @helper_funcs will default to an empty implementation. @formats will
204  * default to XRGB8888 only. @modifiers will default to a linear
205  * modifier only.
206  *
207  * Returns:
208  * A pointer to the new plane, or an ERR_PTR() otherwise.
209  */
210 struct drm_plane *
211 drm_kunit_helper_create_primary_plane(struct kunit *test,
212                                       struct drm_device *drm,
213                                       const struct drm_plane_funcs *funcs,
214                                       const struct drm_plane_helper_funcs *helper_funcs,
215                                       const uint32_t *formats,
216                                       unsigned int num_formats,
217                                       const uint64_t *modifiers)
218 {
219         struct drm_plane *plane;
220
221         if (!funcs)
222                 funcs = &default_plane_funcs;
223
224         if (!helper_funcs)
225                 helper_funcs = &default_plane_helper_funcs;
226
227         if (!formats || !num_formats) {
228                 formats = default_plane_formats;
229                 num_formats = ARRAY_SIZE(default_plane_formats);
230         }
231
232         if (!modifiers)
233                 modifiers = default_plane_modifiers;
234
235         plane = __drmm_universal_plane_alloc(drm,
236                                              sizeof(struct drm_plane), 0,
237                                              0,
238                                              funcs,
239                                              formats,
240                                              num_formats,
241                                              default_plane_modifiers,
242                                              DRM_PLANE_TYPE_PRIMARY,
243                                              NULL);
244         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
245
246         drm_plane_helper_add(plane, helper_funcs);
247
248         return plane;
249 }
250 EXPORT_SYMBOL_GPL(drm_kunit_helper_create_primary_plane);
251
252 static const struct drm_crtc_helper_funcs default_crtc_helper_funcs = {
253 };
254
255 static const struct drm_crtc_funcs default_crtc_funcs = {
256         .atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,
257         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
258         .reset                  = drm_atomic_helper_crtc_reset,
259 };
260
261 /**
262  * drm_kunit_helper_create_crtc - Creates a mock CRTC for a KUnit test
263  * @test: The test context object
264  * @drm: The device to alloc the plane for
265  * @primary: Primary plane for CRTC
266  * @cursor: Cursor plane for CRTC. Optional.
267  * @funcs: Callbacks for the new plane. Optional.
268  * @helper_funcs: Helpers callbacks for the new plane. Optional.
269  *
270  * This allocates and initializes a mock struct &drm_crtc meant to be
271  * part of a mock device for a KUnit test.
272  *
273  * Resources will be cleaned up automatically.
274  *
275  * @funcs will default to the default helpers implementations.
276  * @helper_funcs will default to an empty implementation.
277  *
278  * Returns:
279  * A pointer to the new CRTC, or an ERR_PTR() otherwise.
280  */
281 struct drm_crtc *
282 drm_kunit_helper_create_crtc(struct kunit *test,
283                              struct drm_device *drm,
284                              struct drm_plane *primary,
285                              struct drm_plane *cursor,
286                              const struct drm_crtc_funcs *funcs,
287                              const struct drm_crtc_helper_funcs *helper_funcs)
288 {
289         struct drm_crtc *crtc;
290         int ret;
291
292         if (!funcs)
293                 funcs = &default_crtc_funcs;
294
295         if (!helper_funcs)
296                 helper_funcs = &default_crtc_helper_funcs;
297
298         crtc = drmm_kzalloc(drm, sizeof(*crtc), GFP_KERNEL);
299         KUNIT_ASSERT_NOT_NULL(test, crtc);
300
301         ret = drmm_crtc_init_with_planes(drm, crtc,
302                                          primary,
303                                          cursor,
304                                          funcs,
305                                          NULL);
306         KUNIT_ASSERT_EQ(test, ret, 0);
307
308         drm_crtc_helper_add(crtc, helper_funcs);
309
310         return crtc;
311 }
312 EXPORT_SYMBOL_GPL(drm_kunit_helper_create_crtc);
313
314 MODULE_AUTHOR("Maxime Ripard <[email protected]>");
315 MODULE_DESCRIPTION("KUnit test suite helper functions");
316 MODULE_LICENSE("GPL");
This page took 0.049447 seconds and 4 git commands to generate.