xref: /linux/drivers/gpu/drm/tests/drm_bridge_test.c (revision 6bfca938471b1804c4a63774ca2fd30cb3596215)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Kunit test for drm_bridge functions
4  */
5 #include <linux/cleanup.h>
6 #include <linux/media-bus-format.h>
7 
8 #include <drm/drm_atomic_helper.h>
9 #include <drm/drm_atomic_state_helper.h>
10 #include <drm/drm_atomic_uapi.h>
11 #include <drm/drm_bridge.h>
12 #include <drm/drm_bridge_connector.h>
13 #include <drm/drm_bridge_helper.h>
14 #include <drm/drm_edid.h>
15 #include <drm/drm_kunit_helpers.h>
16 #include <drm/drm_managed.h>
17 
18 #include <kunit/device.h>
19 #include <kunit/test.h>
20 
21 #include "drm_kunit_edid.h"
22 
23 /*
24  * Mimick the typical "private" struct defined by a bridge driver, which
25  * embeds a bridge plus other fields.
26  *
27  * Having at least one member before @bridge ensures we test non-zero
28  * @bridge offset.
29  */
30 struct drm_bridge_priv {
31 	unsigned int enable_count;
32 	unsigned int disable_count;
33 	struct drm_bridge bridge;
34 	void *data;
35 };
36 
37 struct drm_bridge_init_priv {
38 	struct drm_device drm;
39 	/** @dev: device, only for tests not needing a whole drm_device */
40 	struct device *dev;
41 	struct drm_plane *plane;
42 	struct drm_crtc *crtc;
43 	struct drm_encoder encoder;
44 	struct drm_bridge_priv *test_bridge;
45 	struct drm_connector *connector;
46 	bool destroyed;
47 };
48 
49 struct drm_bridge_chain_priv {
50 	struct drm_device drm;
51 	struct drm_encoder encoder;
52 	struct drm_plane *plane;
53 	struct drm_crtc *crtc;
54 	struct drm_connector *connector;
55 	unsigned int num_bridges;
56 
57 	/**
58 	 * @test_bridges: array of pointers to &struct drm_bridge_priv entries
59 	 *                of which the first @num_bridges entries are valid.
60 	 */
61 	struct drm_bridge_priv **test_bridges;
62 };
63 
64 static struct drm_bridge_priv *bridge_to_priv(struct drm_bridge *bridge)
65 {
66 	return container_of(bridge, struct drm_bridge_priv, bridge);
67 }
68 
69 static void drm_test_bridge_priv_destroy(struct drm_bridge *bridge)
70 {
71 	struct drm_bridge_priv *bridge_priv = bridge_to_priv(bridge);
72 	struct drm_bridge_init_priv *priv = (struct drm_bridge_init_priv *)bridge_priv->data;
73 
74 	priv->destroyed = true;
75 }
76 
77 static void drm_test_bridge_enable(struct drm_bridge *bridge)
78 {
79 	struct drm_bridge_priv *priv = bridge_to_priv(bridge);
80 
81 	priv->enable_count++;
82 }
83 
84 static void drm_test_bridge_disable(struct drm_bridge *bridge)
85 {
86 	struct drm_bridge_priv *priv = bridge_to_priv(bridge);
87 
88 	priv->disable_count++;
89 }
90 
91 static const struct drm_bridge_funcs drm_test_bridge_legacy_funcs = {
92 	.destroy		= drm_test_bridge_priv_destroy,
93 	.enable			= drm_test_bridge_enable,
94 	.disable		= drm_test_bridge_disable,
95 };
96 
97 static void drm_test_bridge_atomic_enable(struct drm_bridge *bridge,
98 					  struct drm_atomic_commit *state)
99 {
100 	struct drm_bridge_priv *priv = bridge_to_priv(bridge);
101 
102 	priv->enable_count++;
103 }
104 
105 static void drm_test_bridge_atomic_disable(struct drm_bridge *bridge,
106 					   struct drm_atomic_commit *state)
107 {
108 	struct drm_bridge_priv *priv = bridge_to_priv(bridge);
109 
110 	priv->disable_count++;
111 }
112 
113 static const struct drm_bridge_funcs drm_test_bridge_atomic_funcs = {
114 	.destroy		= drm_test_bridge_priv_destroy,
115 	.atomic_enable		= drm_test_bridge_atomic_enable,
116 	.atomic_disable		= drm_test_bridge_atomic_disable,
117 	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
118 	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,
119 	.atomic_create_state	= drm_atomic_helper_bridge_create_state,
120 };
121 
122 static int dummy_clear_infoframe(struct drm_bridge *bridge)
123 {
124 	return 0;
125 }
126 
127 static int dummy_write_infoframe(struct drm_bridge *bridge, const u8 *buffer,
128 				 size_t len)
129 {
130 	return 0;
131 }
132 
133 static const struct drm_bridge_funcs drm_test_bridge_bus_fmts_funcs = {
134 	.atomic_get_output_bus_fmts	= drm_atomic_helper_bridge_get_hdmi_output_bus_fmts,
135 	.atomic_destroy_state		= drm_atomic_helper_bridge_destroy_state,
136 	.atomic_duplicate_state		= drm_atomic_helper_bridge_duplicate_state,
137 	.atomic_create_state		= drm_atomic_helper_bridge_create_state,
138 	.hdmi_write_avi_infoframe	= dummy_write_infoframe,
139 	.hdmi_write_hdmi_infoframe	= dummy_write_infoframe,
140 	.hdmi_clear_avi_infoframe	= dummy_clear_infoframe,
141 	.hdmi_clear_hdmi_infoframe	= dummy_clear_infoframe,
142 };
143 
144 /**
145  * struct fmt_tuple - a tuple of input/output MEDIA_BUS_FMT_*
146  */
147 struct fmt_tuple {
148 	u32 in_fmt;
149 	u32 out_fmt;
150 };
151 
152 /*
153  * Format mapping that only accepts RGB888, and outputs only RGB888
154  */
155 static const struct fmt_tuple rgb8_passthrough[] = {
156 	{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
157 };
158 
159 /*
160  * Format mapping that only accepts YUV444, and outputs only YUV444
161  */
162 static const struct fmt_tuple yuv8_passthrough[] = {
163 	{ MEDIA_BUS_FMT_YUV8_1X24,   MEDIA_BUS_FMT_YUV8_1X24 },
164 };
165 
166 /*
167  * Format mapping where 8bpc RGB -> 8bpc YUV444, or ID(RGB) or ID(YUV444)
168  */
169 static const struct fmt_tuple rgb8_to_yuv8_or_id[] = {
170 	{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
171 	{ MEDIA_BUS_FMT_YUV8_1X24,   MEDIA_BUS_FMT_YUV8_1X24 },
172 	{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_YUV8_1X24 },
173 };
174 
175 static const struct fmt_tuple rgb8_to_id_yuv8_or_yuv8_to_yuv422_yuv420[] = {
176 	{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
177 	{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_YUV8_1X24 },
178 	{ MEDIA_BUS_FMT_YUV8_1X24,   MEDIA_BUS_FMT_UYVY8_1X16 },
179 	{ MEDIA_BUS_FMT_YUV8_1X24,   MEDIA_BUS_FMT_UYYVYY8_0_5X24 },
180 };
181 
182 /*
183  * Format mapping where 8bpc YUV444 -> 8bpc RGB, or ID(YUV444)
184  */
185 static const struct fmt_tuple yuv8_to_rgb8_or_id[] = {
186 	{ MEDIA_BUS_FMT_YUV8_1X24, MEDIA_BUS_FMT_YUV8_1X24 },
187 	{ MEDIA_BUS_FMT_YUV8_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
188 };
189 
190 /*
191  * A format mapping that acts like a video processor that generates an RGB signal
192  */
193 static const struct fmt_tuple rgb_producer[] = {
194 	{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB888_1X24 },
195 	{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB101010_1X30 },
196 	{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB121212_1X36 },
197 };
198 
199 /*
200  * A format mapping that acts like a video processor that generates an 8-bit RGB,
201  * YUV444 or YUV420 signal
202  */
203 static const struct fmt_tuple rgb_yuv444_yuv420_producer[] = {
204 	{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB888_1X24 },
205 	{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_YUV8_1X24 },
206 	{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_UYYVYY8_0_5X24 },
207 };
208 
209 static const struct fmt_tuple rgb8_yuv444_yuv422_passthrough[] = {
210 	{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
211 	{ MEDIA_BUS_FMT_YUV8_1X24,   MEDIA_BUS_FMT_YUV8_1X24 },
212 	{ MEDIA_BUS_FMT_UYVY8_1X16,  MEDIA_BUS_FMT_UYVY8_1X16 },
213 };
214 
215 static const struct fmt_tuple yuv444_yuv422_rgb8_passthrough[] = {
216 	{ MEDIA_BUS_FMT_YUV8_1X24,   MEDIA_BUS_FMT_YUV8_1X24 },
217 	{ MEDIA_BUS_FMT_UYVY8_1X16,  MEDIA_BUS_FMT_UYVY8_1X16 },
218 	{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
219 };
220 
221 static bool fmt_in_list(const u32 fmt, const u32 *out_fmts, const size_t num_fmts)
222 {
223 	size_t i;
224 
225 	for (i = 0; i < num_fmts; i++)
226 		if (out_fmts[i] == fmt)
227 			return true;
228 
229 	return false;
230 }
231 
232 /**
233  * get_tuples_out_fmts - Get unique output formats of a &struct fmt_tuple list
234  * @fmt_tuples: array of &struct fmt_tuple
235  * @num_fmt_tuples: number of entries in @fmt_tuples
236  * @out_fmts: target array to store the unique output bus formats
237  *
238  * Returns the number of unique output formats, i.e. the number of entries in
239  * @out_fmts that were populated with sensible values.
240  */
241 static size_t get_tuples_out_fmts(const struct fmt_tuple *fmt_tuples,
242 				  const size_t num_fmt_tuples, u32 *out_fmts)
243 {
244 	size_t num_unique = 0;
245 	size_t i;
246 
247 	for (i = 0; i < num_fmt_tuples; i++)
248 		if (!fmt_in_list(fmt_tuples[i].out_fmt, out_fmts, num_unique))
249 			out_fmts[num_unique++] = fmt_tuples[i].out_fmt;
250 
251 	return num_unique;
252 }
253 
254 #define DEFINE_FMT_FUNCS_FROM_TUPLES(name) \
255 static u32 *drm_test_bridge_ ## name ## _out_fmts(struct drm_bridge *bridge,			\
256 						  struct drm_bridge_state *bridge_state,	\
257 						  struct drm_crtc_state *crtc_state,		\
258 						  struct drm_connector_state *conn_state,	\
259 						  unsigned int *num_output_fmts)		\
260 {												\
261 	u32 *out_fmts = kcalloc(ARRAY_SIZE((name)), sizeof(u32), GFP_KERNEL);			\
262 												\
263 	if (out_fmts)										\
264 		*num_output_fmts = get_tuples_out_fmts((name), ARRAY_SIZE((name)), out_fmts);	\
265 	else											\
266 		*num_output_fmts = 0;								\
267 												\
268 	return out_fmts;									\
269 }												\
270 												\
271 static u32 *drm_test_bridge_ ## name ## _in_fmts(struct drm_bridge *bridge,			\
272 						 struct drm_bridge_state *bridge_state,		\
273 						 struct drm_crtc_state *crtc_state,		\
274 						 struct drm_connector_state *conn_state,	\
275 						 u32 output_fmt,				\
276 						 unsigned int *num_input_fmts)			\
277 {												\
278 	u32 *in_fmts = kcalloc(ARRAY_SIZE((name)), sizeof(u32), GFP_KERNEL);			\
279 	unsigned int num_fmts = 0;								\
280 	size_t i;										\
281 												\
282 	if (!in_fmts) {										\
283 		*num_input_fmts = 0;								\
284 		return NULL;									\
285 	}											\
286 												\
287 	for (i = 0; i < ARRAY_SIZE((name)); i++)						\
288 		if ((name)[i].out_fmt == output_fmt)						\
289 			in_fmts[num_fmts++] = (name)[i].in_fmt;					\
290 												\
291 	*num_input_fmts = num_fmts;								\
292 												\
293 	return in_fmts;										\
294 }
295 
296 #define DRM_BRIDGE_ATOMIC_WITH_BUS_FMT_HDMI_FUNC(ident, input_fmts_func, output_fmts_func,	\
297 						 hdmi_write_infoframe_func,			\
298 						 hdmi_clear_infoframe_func)			\
299 static const struct drm_bridge_funcs (ident) = {						\
300 	.atomic_enable			= drm_test_bridge_atomic_enable,			\
301 	.atomic_disable			= drm_test_bridge_atomic_disable,			\
302 	.atomic_destroy_state		= drm_atomic_helper_bridge_destroy_state,		\
303 	.atomic_duplicate_state		= drm_atomic_helper_bridge_duplicate_state,		\
304 	.atomic_create_state		= drm_atomic_helper_bridge_create_state,		\
305 	.atomic_get_input_bus_fmts	= (input_fmts_func),					\
306 	.atomic_get_output_bus_fmts	= (output_fmts_func),					\
307 	.hdmi_write_avi_infoframe	= (hdmi_write_infoframe_func),				\
308 	.hdmi_clear_avi_infoframe	= (hdmi_clear_infoframe_func),				\
309 	.hdmi_write_hdmi_infoframe	= (hdmi_write_infoframe_func),				\
310 	.hdmi_clear_hdmi_infoframe	= (hdmi_clear_infoframe_func),				\
311 }
312 
313 #define DRM_BRIDGE_ATOMIC_WITH_BUS_FMT_FUNC(ident, input_fmts_func, output_fmts_func)		\
314 	DRM_BRIDGE_ATOMIC_WITH_BUS_FMT_HDMI_FUNC(ident, input_fmts_func, output_fmts_func,	\
315 						 NULL, NULL)
316 
317 #define DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(_name)						\
318 	DRM_BRIDGE_ATOMIC_WITH_BUS_FMT_FUNC(_name ## _funcs,				\
319 					    drm_test_bridge_ ## _name ## _in_fmts,	\
320 					    drm_test_bridge_ ## _name ## _out_fmts)
321 
322 static int drm_test_bridge_write_infoframe_stub(struct drm_bridge *bridge,
323 						const u8 *buffer, size_t len)
324 {
325 	return 0;
326 }
327 
328 static int drm_test_bridge_clear_infoframe_stub(struct drm_bridge *bridge)
329 {
330 	return 0;
331 }
332 
333 #define DRM_BRIDGE_ATOMIC_WITH_BUS_FMT_HDMI(_name)						\
334 	DRM_BRIDGE_ATOMIC_WITH_BUS_FMT_HDMI_FUNC(_name ## _hdmi ## _funcs,			\
335 						 drm_test_bridge_ ## _name ## _in_fmts,		\
336 						 drm_test_bridge_ ## _name ## _out_fmts,	\
337 						 drm_test_bridge_write_infoframe_stub,		\
338 						 drm_test_bridge_clear_infoframe_stub)
339 DEFINE_FMT_FUNCS_FROM_TUPLES(rgb8_passthrough)
340 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(rgb8_passthrough);
341 
342 DEFINE_FMT_FUNCS_FROM_TUPLES(yuv8_passthrough)
343 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(yuv8_passthrough);
344 
345 DEFINE_FMT_FUNCS_FROM_TUPLES(rgb8_to_yuv8_or_id)
346 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(rgb8_to_yuv8_or_id);
347 
348 DEFINE_FMT_FUNCS_FROM_TUPLES(yuv8_to_rgb8_or_id)
349 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(yuv8_to_rgb8_or_id);
350 
351 DEFINE_FMT_FUNCS_FROM_TUPLES(rgb_producer)
352 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(rgb_producer);
353 
354 DEFINE_FMT_FUNCS_FROM_TUPLES(rgb_yuv444_yuv420_producer)
355 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(rgb_yuv444_yuv420_producer);
356 
357 DEFINE_FMT_FUNCS_FROM_TUPLES(rgb8_to_id_yuv8_or_yuv8_to_yuv422_yuv420)
358 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(rgb8_to_id_yuv8_or_yuv8_to_yuv422_yuv420);
359 
360 DEFINE_FMT_FUNCS_FROM_TUPLES(rgb8_yuv444_yuv422_passthrough)
361 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(rgb8_yuv444_yuv422_passthrough);
362 
363 DEFINE_FMT_FUNCS_FROM_TUPLES(yuv444_yuv422_rgb8_passthrough)
364 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT(yuv444_yuv422_rgb8_passthrough);
365 DRM_BRIDGE_ATOMIC_WITH_BUS_FMT_HDMI(yuv444_yuv422_rgb8_passthrough);
366 
367 KUNIT_DEFINE_ACTION_WRAPPER(drm_bridge_remove_wrapper,
368 			    drm_bridge_remove,
369 			    struct drm_bridge *);
370 
371 static int drm_kunit_bridge_add(struct kunit *test,
372 				struct drm_bridge *bridge)
373 {
374 	drm_bridge_add(bridge);
375 
376 	return kunit_add_action_or_reset(test,
377 					 drm_bridge_remove_wrapper,
378 					 bridge);
379 }
380 
381 static struct drm_bridge_init_priv *
382 drm_test_bridge_init(struct kunit *test, const struct drm_bridge_funcs *funcs)
383 {
384 	struct drm_bridge_init_priv *priv;
385 	struct drm_encoder *enc;
386 	struct drm_bridge *bridge;
387 	struct drm_device *drm;
388 	struct device *dev;
389 	int ret;
390 
391 	dev = drm_kunit_helper_alloc_device(test);
392 	if (IS_ERR(dev))
393 		return ERR_CAST(dev);
394 
395 	priv = drm_kunit_helper_alloc_drm_device(test, dev,
396 						 struct drm_bridge_init_priv, drm,
397 						 DRIVER_MODESET | DRIVER_ATOMIC);
398 	if (IS_ERR(priv))
399 		return ERR_CAST(priv);
400 
401 	priv->test_bridge = devm_drm_bridge_alloc(dev, struct drm_bridge_priv, bridge, funcs);
402 	if (IS_ERR(priv->test_bridge))
403 		return ERR_CAST(priv->test_bridge);
404 
405 	priv->test_bridge->data = priv;
406 
407 	drm = &priv->drm;
408 	priv->plane = drm_kunit_helper_create_primary_plane(test, drm,
409 							    NULL,
410 							    NULL,
411 							    NULL, 0,
412 							    NULL);
413 	if (IS_ERR(priv->plane))
414 		return ERR_CAST(priv->plane);
415 
416 	priv->crtc = drm_kunit_helper_create_crtc(test, drm,
417 						  priv->plane, NULL,
418 						  NULL,
419 						  NULL);
420 	if (IS_ERR(priv->crtc))
421 		return ERR_CAST(priv->crtc);
422 
423 	enc = &priv->encoder;
424 	ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL);
425 	if (ret)
426 		return ERR_PTR(ret);
427 
428 	enc->possible_crtcs = drm_crtc_mask(priv->crtc);
429 
430 	bridge = &priv->test_bridge->bridge;
431 	bridge->type = DRM_MODE_CONNECTOR_VIRTUAL;
432 
433 	ret = drm_kunit_bridge_add(test, bridge);
434 	if (ret)
435 		return ERR_PTR(ret);
436 
437 	ret = drm_bridge_attach(enc, bridge, NULL, 0);
438 	if (ret)
439 		return ERR_PTR(ret);
440 
441 	priv->connector = drm_bridge_connector_init(drm, enc);
442 	if (IS_ERR(priv->connector))
443 		return ERR_CAST(priv->connector);
444 
445 	drm_mode_config_reset(drm);
446 
447 	return priv;
448 }
449 
450 static struct drm_bridge_chain_priv *
451 drm_test_bridge_chain_init(struct kunit *test, unsigned int num_bridges,
452 			   const struct drm_bridge_funcs **funcs)
453 {
454 	struct drm_bridge_chain_priv *priv;
455 	const struct drm_edid *edid;
456 	struct drm_bridge *prev;
457 	struct drm_encoder *enc;
458 	struct drm_bridge *bridge;
459 	struct drm_device *drm;
460 	bool has_hdmi = false;
461 	struct device *dev;
462 	unsigned int i;
463 	int ret;
464 
465 	dev = drm_kunit_helper_alloc_device(test);
466 	if (IS_ERR(dev))
467 		return ERR_CAST(dev);
468 
469 	priv = drm_kunit_helper_alloc_drm_device(test, dev, struct drm_bridge_chain_priv,
470 						 drm, DRIVER_MODESET | DRIVER_ATOMIC);
471 	if (IS_ERR(priv))
472 		return ERR_CAST(priv);
473 
474 	drm = &priv->drm;
475 
476 	priv->test_bridges = drmm_kmalloc_array(drm, num_bridges, sizeof(*priv->test_bridges),
477 						GFP_KERNEL);
478 	if (!priv->test_bridges)
479 		return ERR_PTR(-ENOMEM);
480 
481 	priv->num_bridges = num_bridges;
482 
483 	for (i = 0; i < num_bridges; i++) {
484 		priv->test_bridges[i] = devm_drm_bridge_alloc(dev, struct drm_bridge_priv,
485 							      bridge, funcs[i]);
486 		if (IS_ERR(priv->test_bridges[i]))
487 			return ERR_CAST(priv->test_bridges[i]);
488 
489 		priv->test_bridges[i]->data = priv;
490 	}
491 
492 	priv->plane = drm_kunit_helper_create_primary_plane(test, drm, NULL, NULL,
493 							    NULL, 0, NULL);
494 	if (IS_ERR(priv->plane))
495 		return ERR_CAST(priv->plane);
496 
497 	priv->crtc = drm_kunit_helper_create_crtc(test, drm, priv->plane, NULL,
498 						  NULL, NULL);
499 	if (IS_ERR(priv->crtc))
500 		return ERR_CAST(priv->crtc);
501 
502 	enc = &priv->encoder;
503 	ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL);
504 	if (ret)
505 		return ERR_PTR(ret);
506 
507 	enc->possible_crtcs = drm_crtc_mask(priv->crtc);
508 
509 	prev = NULL;
510 	for (i = 0; i < num_bridges; i++) {
511 		bridge = &priv->test_bridges[i]->bridge;
512 		bridge->type = DRM_MODE_CONNECTOR_VIRTUAL;
513 
514 		if (bridge->funcs->hdmi_write_hdmi_infoframe) {
515 			has_hdmi = true;
516 			bridge->ops |= DRM_BRIDGE_OP_HDMI;
517 			bridge->type = DRM_MODE_CONNECTOR_HDMIA;
518 			bridge->vendor = "LNX";
519 			bridge->product = "KUnit";
520 			bridge->supported_formats = (BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
521 						     BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
522 						     BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422) |
523 						     BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420));
524 		}
525 
526 		ret = drm_kunit_bridge_add(test, bridge);
527 		if (ret)
528 			return ERR_PTR(ret);
529 
530 		ret = drm_bridge_attach(enc, bridge, prev, 0);
531 		if (ret)
532 			return ERR_PTR(ret);
533 
534 		prev = bridge;
535 	}
536 
537 	priv->connector = drm_bridge_connector_init(drm, enc);
538 	if (IS_ERR(priv->connector))
539 		return ERR_CAST(priv->connector);
540 
541 	drm_connector_attach_encoder(priv->connector, enc);
542 
543 	drm_mode_config_reset(drm);
544 
545 	if (!has_hdmi)
546 		return priv;
547 
548 	scoped_guard(mutex, &drm->mode_config.mutex) {
549 		edid = drm_edid_alloc(test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz,
550 				ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz));
551 		if (!edid)
552 			return ERR_PTR(-EINVAL);
553 
554 		drm_edid_connector_update(priv->connector, edid);
555 		KUNIT_ASSERT_GT(test, drm_edid_connector_add_modes(priv->connector), 0);
556 
557 		ret = priv->connector->funcs->fill_modes(priv->connector, 4096, 4096);
558 	}
559 
560 	return priv;
561 }
562 
563 static struct drm_bridge_init_priv *
564 drm_test_bridge_hdmi_init(struct kunit *test, const struct drm_bridge_funcs *funcs,
565 			  unsigned int supported_formats, int max_bpc)
566 {
567 	struct drm_bridge_init_priv *priv;
568 	struct drm_encoder *enc;
569 	struct drm_bridge *bridge;
570 	struct drm_device *drm;
571 	struct device *dev;
572 	int ret;
573 
574 	dev = drm_kunit_helper_alloc_device(test);
575 	if (IS_ERR(dev))
576 		return ERR_CAST(dev);
577 
578 	priv = drm_kunit_helper_alloc_drm_device(test, dev,
579 						 struct drm_bridge_init_priv, drm,
580 						 DRIVER_MODESET | DRIVER_ATOMIC);
581 	if (IS_ERR(priv))
582 		return ERR_CAST(priv);
583 
584 	priv->test_bridge = devm_drm_bridge_alloc(dev, struct drm_bridge_priv, bridge, funcs);
585 	if (IS_ERR(priv->test_bridge))
586 		return ERR_CAST(priv->test_bridge);
587 
588 	priv->test_bridge->data = priv;
589 
590 	drm = &priv->drm;
591 	priv->plane = drm_kunit_helper_create_primary_plane(test, drm,
592 							    NULL,
593 							    NULL,
594 							    NULL, 0,
595 							    NULL);
596 	if (IS_ERR(priv->plane))
597 		return ERR_CAST(priv->plane);
598 
599 	priv->crtc = drm_kunit_helper_create_crtc(test, drm,
600 						  priv->plane, NULL,
601 						  NULL,
602 						  NULL);
603 	if (IS_ERR(priv->crtc))
604 		return ERR_CAST(priv->crtc);
605 
606 	enc = &priv->encoder;
607 	ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL);
608 	if (ret)
609 		return ERR_PTR(ret);
610 
611 	enc->possible_crtcs = drm_crtc_mask(priv->crtc);
612 
613 	bridge = &priv->test_bridge->bridge;
614 	bridge->type = DRM_MODE_CONNECTOR_HDMIA;
615 	bridge->supported_formats = supported_formats;
616 	bridge->max_bpc = max_bpc;
617 	bridge->ops |= DRM_BRIDGE_OP_HDMI;
618 	bridge->vendor = "LNX";
619 	bridge->product = "KUnit";
620 
621 	ret = drm_kunit_bridge_add(test, bridge);
622 	if (ret)
623 		return ERR_PTR(ret);
624 
625 	ret = drm_bridge_attach(enc, bridge, NULL, 0);
626 	if (ret)
627 		return ERR_PTR(ret);
628 
629 	priv->connector = drm_bridge_connector_init(drm, enc);
630 	if (IS_ERR(priv->connector))
631 		return ERR_CAST(priv->connector);
632 
633 	drm_connector_attach_encoder(priv->connector, enc);
634 
635 	drm_mode_config_reset(drm);
636 
637 	return priv;
638 }
639 
640 /*
641  * Test that drm_bridge_get_current_state() returns the last committed
642  * state for an atomic bridge.
643  */
644 static void drm_test_drm_bridge_get_current_state_atomic(struct kunit *test)
645 {
646 	struct drm_modeset_acquire_ctx ctx;
647 	struct drm_bridge_init_priv *priv;
648 	struct drm_bridge_state *curr_bridge_state;
649 	struct drm_bridge_state *bridge_state;
650 	struct drm_atomic_commit *state;
651 	struct drm_bridge *bridge;
652 	struct drm_device *drm;
653 	int ret;
654 
655 	priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs);
656 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
657 
658 	drm_modeset_acquire_init(&ctx, 0);
659 
660 	drm = &priv->drm;
661 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
662 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
663 
664 retry_commit:
665 	bridge = &priv->test_bridge->bridge;
666 	bridge_state = drm_atomic_get_bridge_state(state, bridge);
667 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bridge_state);
668 
669 	ret = drm_atomic_commit(state);
670 	if (ret == -EDEADLK) {
671 		drm_atomic_commit_clear(state);
672 		drm_modeset_backoff(&ctx);
673 		goto retry_commit;
674 	}
675 	KUNIT_ASSERT_EQ(test, ret, 0);
676 
677 	drm_modeset_drop_locks(&ctx);
678 	drm_modeset_acquire_fini(&ctx);
679 
680 	drm_modeset_acquire_init(&ctx, 0);
681 
682 retry_state:
683 	ret = drm_modeset_lock(&bridge->base.lock, &ctx);
684 	if (ret == -EDEADLK) {
685 		drm_modeset_backoff(&ctx);
686 		goto retry_state;
687 	}
688 
689 	curr_bridge_state = drm_bridge_get_current_state(bridge);
690 	KUNIT_EXPECT_PTR_EQ(test, curr_bridge_state, bridge_state);
691 
692 	drm_modeset_unlock(&bridge->base.lock);
693 
694 	drm_modeset_drop_locks(&ctx);
695 	drm_modeset_acquire_fini(&ctx);
696 }
697 
698 /*
699  * Test that drm_bridge_get_current_state() returns NULL for a
700  * non-atomic bridge.
701  */
702 static void drm_test_drm_bridge_get_current_state_legacy(struct kunit *test)
703 {
704 	struct drm_bridge_init_priv *priv;
705 	struct drm_bridge *bridge;
706 
707 	priv = drm_test_bridge_init(test, &drm_test_bridge_legacy_funcs);
708 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
709 
710 	/*
711 	 * NOTE: Strictly speaking, we should take the bridge->base.lock
712 	 * before calling that function. However, bridge->base is only
713 	 * initialized if the bridge is atomic, while we explicitly
714 	 * initialize one that isn't there.
715 	 *
716 	 * In order to avoid unnecessary warnings, let's skip the
717 	 * locking. The function would return NULL in all cases anyway,
718 	 * so we don't really have any concurrency to worry about.
719 	 */
720 	bridge = &priv->test_bridge->bridge;
721 	KUNIT_EXPECT_NULL(test, drm_bridge_get_current_state(bridge));
722 }
723 
724 static struct kunit_case drm_bridge_get_current_state_tests[] = {
725 	KUNIT_CASE(drm_test_drm_bridge_get_current_state_atomic),
726 	KUNIT_CASE(drm_test_drm_bridge_get_current_state_legacy),
727 	{ }
728 };
729 
730 
731 static struct kunit_suite drm_bridge_get_current_state_test_suite = {
732 	.name = "drm_test_bridge_get_current_state",
733 	.test_cases = drm_bridge_get_current_state_tests,
734 };
735 
736 /*
737  * Test that an atomic bridge is properly power-cycled when calling
738  * drm_bridge_helper_reset_crtc().
739  */
740 static void drm_test_drm_bridge_helper_reset_crtc_atomic(struct kunit *test)
741 {
742 	struct drm_modeset_acquire_ctx ctx;
743 	struct drm_bridge_init_priv *priv;
744 	struct drm_display_mode *mode;
745 	struct drm_bridge_priv *bridge_priv;
746 	int ret;
747 
748 	priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs);
749 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
750 
751 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
752 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
753 
754 	drm_modeset_acquire_init(&ctx, 0);
755 
756 retry_commit:
757 	ret = drm_kunit_helper_enable_crtc_connector(test,
758 						     &priv->drm, priv->crtc,
759 						     priv->connector,
760 						     mode,
761 						     &ctx);
762 	if (ret == -EDEADLK) {
763 		drm_modeset_backoff(&ctx);
764 		goto retry_commit;
765 	}
766 	KUNIT_ASSERT_EQ(test, ret, 0);
767 
768 	drm_modeset_drop_locks(&ctx);
769 	drm_modeset_acquire_fini(&ctx);
770 
771 	bridge_priv = priv->test_bridge;
772 	KUNIT_ASSERT_EQ(test, bridge_priv->enable_count, 1);
773 	KUNIT_ASSERT_EQ(test, bridge_priv->disable_count, 0);
774 
775 	drm_modeset_acquire_init(&ctx, 0);
776 
777 retry_reset:
778 	ret = drm_bridge_helper_reset_crtc(&bridge_priv->bridge, &ctx);
779 	if (ret == -EDEADLK) {
780 		drm_modeset_backoff(&ctx);
781 		goto retry_reset;
782 	}
783 	KUNIT_ASSERT_EQ(test, ret, 0);
784 
785 	drm_modeset_drop_locks(&ctx);
786 	drm_modeset_acquire_fini(&ctx);
787 
788 	KUNIT_EXPECT_EQ(test, bridge_priv->enable_count, 2);
789 	KUNIT_EXPECT_EQ(test, bridge_priv->disable_count, 1);
790 }
791 
792 /*
793  * Test that calling drm_bridge_helper_reset_crtc() on a disabled atomic
794  * bridge will fail and not call the enable / disable callbacks
795  */
796 static void drm_test_drm_bridge_helper_reset_crtc_atomic_disabled(struct kunit *test)
797 {
798 	struct drm_modeset_acquire_ctx ctx;
799 	struct drm_bridge_init_priv *priv;
800 	struct drm_display_mode *mode;
801 	struct drm_bridge_priv *bridge_priv;
802 	int ret;
803 
804 	priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs);
805 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
806 
807 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
808 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
809 
810 	bridge_priv = priv->test_bridge;
811 	KUNIT_ASSERT_EQ(test, bridge_priv->enable_count, 0);
812 	KUNIT_ASSERT_EQ(test, bridge_priv->disable_count, 0);
813 
814 	drm_modeset_acquire_init(&ctx, 0);
815 
816 retry_reset:
817 	ret = drm_bridge_helper_reset_crtc(&bridge_priv->bridge, &ctx);
818 	if (ret == -EDEADLK) {
819 		drm_modeset_backoff(&ctx);
820 		goto retry_reset;
821 	}
822 	KUNIT_EXPECT_LT(test, ret, 0);
823 
824 	drm_modeset_drop_locks(&ctx);
825 	drm_modeset_acquire_fini(&ctx);
826 
827 	KUNIT_EXPECT_EQ(test, bridge_priv->enable_count, 0);
828 	KUNIT_EXPECT_EQ(test, bridge_priv->disable_count, 0);
829 }
830 
831 /*
832  * Test that a non-atomic bridge is properly power-cycled when calling
833  * drm_bridge_helper_reset_crtc().
834  */
835 static void drm_test_drm_bridge_helper_reset_crtc_legacy(struct kunit *test)
836 {
837 	struct drm_modeset_acquire_ctx ctx;
838 	struct drm_bridge_init_priv *priv;
839 	struct drm_display_mode *mode;
840 	struct drm_bridge_priv *bridge_priv;
841 	int ret;
842 
843 	priv = drm_test_bridge_init(test, &drm_test_bridge_legacy_funcs);
844 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
845 
846 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
847 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
848 
849 	drm_modeset_acquire_init(&ctx, 0);
850 
851 retry_commit:
852 	ret = drm_kunit_helper_enable_crtc_connector(test,
853 						     &priv->drm, priv->crtc,
854 						     priv->connector,
855 						     mode,
856 						     &ctx);
857 	if (ret == -EDEADLK) {
858 		drm_modeset_backoff(&ctx);
859 		goto retry_commit;
860 	}
861 	KUNIT_ASSERT_EQ(test, ret, 0);
862 
863 	drm_modeset_drop_locks(&ctx);
864 	drm_modeset_acquire_fini(&ctx);
865 
866 	bridge_priv = priv->test_bridge;
867 	KUNIT_ASSERT_EQ(test, bridge_priv->enable_count, 1);
868 	KUNIT_ASSERT_EQ(test, bridge_priv->disable_count, 0);
869 
870 	drm_modeset_acquire_init(&ctx, 0);
871 
872 retry_reset:
873 	ret = drm_bridge_helper_reset_crtc(&bridge_priv->bridge, &ctx);
874 	if (ret == -EDEADLK) {
875 		drm_modeset_backoff(&ctx);
876 		goto retry_reset;
877 	}
878 	KUNIT_ASSERT_EQ(test, ret, 0);
879 
880 	drm_modeset_drop_locks(&ctx);
881 	drm_modeset_acquire_fini(&ctx);
882 
883 	KUNIT_EXPECT_EQ(test, bridge_priv->enable_count, 2);
884 	KUNIT_EXPECT_EQ(test, bridge_priv->disable_count, 1);
885 }
886 
887 /*
888  * Test that a bridge using the drm_atomic_helper_bridge_get_hdmi_output_bus_fmts()
889  * function for &drm_bridge_funcs.atomic_get_output_bus_fmts behaves as expected
890  * for an HDMI connector bridge. Does so by creating an HDMI bridge connector
891  * with RGB444, YCBCR444, and YCBCR420 (but not YCBCR422) as supported formats,
892  * sets the output depth to 8 bits per component, and then validates the returned
893  * list of bus formats.
894  */
895 static void drm_test_drm_bridge_helper_hdmi_output_bus_fmts(struct kunit *test)
896 {
897 	struct drm_connector_state *conn_state;
898 	struct drm_bridge_state *bridge_state;
899 	struct drm_modeset_acquire_ctx ctx;
900 	struct drm_bridge_init_priv *priv;
901 	struct drm_crtc_state *crtc_state;
902 	struct drm_atomic_commit *state;
903 	struct drm_display_mode *mode;
904 	unsigned int num_output_fmts;
905 	struct drm_bridge *bridge;
906 	u32 *out_bus_fmts;
907 	int ret;
908 
909 	priv = drm_test_bridge_hdmi_init(test, &drm_test_bridge_bus_fmts_funcs,
910 					 BIT(DRM_OUTPUT_COLOR_FORMAT_RGB444) |
911 					 BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444) |
912 					 BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR420),
913 					 12);
914 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
915 
916 	bridge = &priv->test_bridge->bridge;
917 
918 	drm_modeset_acquire_init(&ctx, 0);
919 
920 	state = drm_kunit_helper_atomic_state_alloc(test, &priv->drm, &ctx);
921 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
922 
923 retry_commit:
924 	conn_state = drm_atomic_get_connector_state(state, priv->connector);
925 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
926 
927 	conn_state->hdmi.output_bpc = 8;
928 
929 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
930 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
931 
932 	ret = drm_atomic_set_crtc_for_connector(conn_state, priv->crtc);
933 	if (ret == -EDEADLK) {
934 		drm_modeset_backoff(&ctx);
935 		goto retry_commit;
936 	}
937 	KUNIT_ASSERT_EQ(test, ret, 0);
938 
939 	crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
940 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
941 
942 	ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
943 	if (ret == -EDEADLK) {
944 		drm_modeset_backoff(&ctx);
945 		goto retry_commit;
946 	}
947 	KUNIT_ASSERT_EQ(test, ret, 0);
948 
949 	crtc_state->enable = true;
950 	crtc_state->active = true;
951 
952 	bridge_state = drm_atomic_get_bridge_state(state, bridge);
953 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bridge_state);
954 
955 	out_bus_fmts = bridge->funcs->atomic_get_output_bus_fmts(
956 		bridge, bridge_state, crtc_state, conn_state, &num_output_fmts);
957 	KUNIT_EXPECT_NOT_NULL(test, out_bus_fmts);
958 	KUNIT_EXPECT_EQ(test, num_output_fmts, 3);
959 
960 	KUNIT_EXPECT_EQ(test, out_bus_fmts[0], MEDIA_BUS_FMT_RGB888_1X24);
961 	KUNIT_EXPECT_EQ(test, out_bus_fmts[1], MEDIA_BUS_FMT_YUV8_1X24);
962 	KUNIT_EXPECT_EQ(test, out_bus_fmts[2], MEDIA_BUS_FMT_UYYVYY8_0_5X24);
963 
964 	drm_modeset_drop_locks(&ctx);
965 	drm_modeset_acquire_fini(&ctx);
966 
967 	kfree(out_bus_fmts);
968 }
969 
970 static struct kunit_case drm_bridge_helper_reset_crtc_tests[] = {
971 	KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_atomic),
972 	KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_atomic_disabled),
973 	KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_legacy),
974 	KUNIT_CASE(drm_test_drm_bridge_helper_hdmi_output_bus_fmts),
975 	{ }
976 };
977 
978 static struct kunit_suite drm_bridge_helper_reset_crtc_test_suite = {
979 	.name = "drm_test_bridge_helper_reset_crtc",
980 	.test_cases = drm_bridge_helper_reset_crtc_tests,
981 };
982 
983 static int drm_test_bridge_alloc_init(struct kunit *test)
984 {
985 	struct drm_bridge_init_priv *priv;
986 
987 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
988 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
989 
990 	priv->dev = kunit_device_register(test, "drm-bridge-dev");
991 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
992 
993 	test->priv = priv;
994 
995 	priv->test_bridge = devm_drm_bridge_alloc(priv->dev, struct drm_bridge_priv, bridge,
996 						  &drm_test_bridge_atomic_funcs);
997 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->test_bridge);
998 
999 	priv->test_bridge->data = priv;
1000 
1001 	KUNIT_ASSERT_FALSE(test, priv->destroyed);
1002 
1003 	return 0;
1004 }
1005 
1006 /*
1007  * Test that a bridge is freed when the device is destroyed in lack of
1008  * other drm_bridge_get/put() operations.
1009  */
1010 static void drm_test_drm_bridge_alloc_basic(struct kunit *test)
1011 {
1012 	struct drm_bridge_init_priv *priv = test->priv;
1013 
1014 	KUNIT_ASSERT_FALSE(test, priv->destroyed);
1015 
1016 	kunit_device_unregister(test, priv->dev);
1017 	KUNIT_EXPECT_TRUE(test, priv->destroyed);
1018 }
1019 
1020 /*
1021  * Test that a bridge is not freed when the device is destroyed when there
1022  * is still a reference to it, and freed when that reference is put.
1023  */
1024 static void drm_test_drm_bridge_alloc_get_put(struct kunit *test)
1025 {
1026 	struct drm_bridge_init_priv *priv = test->priv;
1027 
1028 	KUNIT_ASSERT_FALSE(test, priv->destroyed);
1029 
1030 	drm_bridge_get(&priv->test_bridge->bridge);
1031 	KUNIT_EXPECT_FALSE(test, priv->destroyed);
1032 
1033 	kunit_device_unregister(test, priv->dev);
1034 	KUNIT_EXPECT_FALSE(test, priv->destroyed);
1035 
1036 	drm_bridge_put(&priv->test_bridge->bridge);
1037 	KUNIT_EXPECT_TRUE(test, priv->destroyed);
1038 }
1039 
1040 static struct kunit_case drm_bridge_alloc_tests[] = {
1041 	KUNIT_CASE(drm_test_drm_bridge_alloc_basic),
1042 	KUNIT_CASE(drm_test_drm_bridge_alloc_get_put),
1043 	{ }
1044 };
1045 
1046 static struct kunit_suite drm_bridge_alloc_test_suite = {
1047 	.name = "drm_bridge_alloc",
1048 	.init = drm_test_bridge_alloc_init,
1049 	.test_cases = drm_bridge_alloc_tests,
1050 };
1051 
1052 /**
1053  * drm_test_bridge_chain_verify_fmt - Verify bridge chain format selection
1054  * @test: pointer to KUnit test object
1055  * @priv: pointer to a &struct drm_bridge_chain_priv for this chain
1056  * @expected: constant array of &struct fmt_tuple describing the expected
1057  *            input and output bus formats
1058  * @num_expected: number of entries in @expected
1059  *
1060  * Runs the KUNIT_EXPECT clauses to verify the bridge chain format selection
1061  * resulted in the expected formats. If %0 is given as a format in a
1062  * &struct fmt_tuple, then it is understood to mean "any".
1063  *
1064  * Must be called with the modeset lock held.
1065  */
1066 static void drm_test_bridge_chain_verify_fmt(struct kunit *test,
1067 					     struct drm_bridge_chain_priv *priv,
1068 					     const struct fmt_tuple *const expected,
1069 					     const unsigned int num_expected)
1070 {
1071 	struct drm_bridge_state *bstate;
1072 	unsigned int i = 0;
1073 
1074 	drm_for_each_bridge_in_chain_scoped(&priv->encoder, bridge) {
1075 		KUNIT_ASSERT_LT(test, i, num_expected);
1076 
1077 		bstate = drm_bridge_get_current_state(bridge);
1078 		if (expected[i].in_fmt)
1079 			KUNIT_EXPECT_EQ(test, bstate->input_bus_cfg.format,
1080 					expected[i].in_fmt);
1081 		if (expected[i].out_fmt)
1082 			KUNIT_EXPECT_EQ(test, bstate->output_bus_cfg.format,
1083 					expected[i].out_fmt);
1084 
1085 		i++;
1086 	}
1087 
1088 	KUNIT_ASSERT_EQ_MSG(test, i, num_expected,
1089 			    "Fewer bridges (%u) than expected (%u)\n", i, num_expected);
1090 }
1091 
1092 /*
1093  * Test that constructs a bridge chain in which an RGB888 producer is chained to
1094  * two bridges that will convert from RGB to YUV and from YUV to RGB respectively.
1095  *
1096  * The test requests an output color_format of RGB using the color_format property,
1097  * so to satisfy this request, the bridge chain must take a detour over YUV.
1098  */
1099 static void drm_test_bridge_rgb_yuv_rgb(struct kunit *test)
1100 {
1101 	static const struct drm_bridge_funcs *funcs[] = {
1102 		&rgb_producer_funcs,
1103 		&rgb8_to_yuv8_or_id_funcs,
1104 		&yuv8_to_rgb8_or_id_funcs,
1105 	};
1106 	static const struct fmt_tuple expected[] = {
1107 		{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB888_1X24 },
1108 		{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_YUV8_1X24 },
1109 		{ MEDIA_BUS_FMT_YUV8_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
1110 	};
1111 	struct drm_connector_state *conn_state;
1112 	struct drm_modeset_acquire_ctx ctx;
1113 	struct drm_bridge_chain_priv *priv;
1114 	struct drm_crtc_state *crtc_state;
1115 	struct drm_atomic_commit *state;
1116 	struct drm_display_mode *mode;
1117 	int ret;
1118 
1119 	priv = drm_test_bridge_chain_init(test, ARRAY_SIZE(funcs), funcs);
1120 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
1121 
1122 	drm_modeset_acquire_init(&ctx, 0);
1123 
1124 	state = drm_kunit_helper_atomic_state_alloc(test, &priv->drm, &ctx);
1125 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1126 
1127 retry_commit:
1128 	conn_state = drm_atomic_get_connector_state(state, priv->connector);
1129 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
1130 
1131 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
1132 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
1133 
1134 	conn_state->color_format = DRM_CONNECTOR_COLOR_FORMAT_RGB444;
1135 
1136 	ret = drm_atomic_set_crtc_for_connector(conn_state, priv->crtc);
1137 	if (ret == -EDEADLK) {
1138 		drm_modeset_backoff(&ctx);
1139 		goto retry_commit;
1140 	}
1141 	KUNIT_ASSERT_EQ(test, ret, 0);
1142 
1143 	crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
1144 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1145 
1146 	ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
1147 	if (ret == -EDEADLK) {
1148 		drm_modeset_backoff(&ctx);
1149 		goto retry_commit;
1150 	}
1151 	KUNIT_ASSERT_EQ(test, ret, 0);
1152 
1153 	crtc_state->enable = true;
1154 	crtc_state->active = true;
1155 
1156 	ret = drm_atomic_commit(state);
1157 	if (ret == -EDEADLK) {
1158 		drm_modeset_backoff(&ctx);
1159 		goto retry_commit;
1160 	}
1161 	KUNIT_ASSERT_EQ(test, ret, 0);
1162 
1163 	drm_test_bridge_chain_verify_fmt(test, priv, expected, ARRAY_SIZE(expected));
1164 
1165 	drm_modeset_drop_locks(&ctx);
1166 	drm_modeset_acquire_fini(&ctx);
1167 }
1168 
1169 /*
1170  * Test in which a bridge capable of producing RGB, YUV444 and YUV420 has to
1171  * produce RGB and convert with a downstream bridge in the chain to reach the
1172  * requested YUV444 color format, as no direct path exists between its YUV444
1173  * and the last bridge.
1174  *
1175  * The rationale behind this test is to devise a scenario in which naively
1176  * assuming any format the video processor can output, and the connector
1177  * requests, is the right format to pick, does not work.
1178  */
1179 static void drm_test_bridge_must_convert_to_yuv444(struct kunit *test)
1180 {
1181 	static const struct drm_bridge_funcs *funcs[] = {
1182 		&rgb_yuv444_yuv420_producer_funcs,
1183 		&rgb8_passthrough_funcs,
1184 		&rgb8_to_id_yuv8_or_yuv8_to_yuv422_yuv420_funcs,
1185 		&rgb8_yuv444_yuv422_passthrough_funcs,
1186 	};
1187 	static const struct fmt_tuple expected[] = {
1188 		{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB888_1X24 },
1189 		{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
1190 		{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_YUV8_1X24 },
1191 		{ MEDIA_BUS_FMT_YUV8_1X24, MEDIA_BUS_FMT_YUV8_1X24 },
1192 	};
1193 	struct drm_connector_state *conn_state;
1194 	struct drm_modeset_acquire_ctx ctx;
1195 	struct drm_bridge_chain_priv *priv;
1196 	struct drm_crtc_state *crtc_state;
1197 	struct drm_atomic_commit *state;
1198 	struct drm_display_mode *mode;
1199 	int ret;
1200 
1201 	priv = drm_test_bridge_chain_init(test, ARRAY_SIZE(funcs), funcs);
1202 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
1203 
1204 	drm_modeset_acquire_init(&ctx, 0);
1205 
1206 	state = drm_kunit_helper_atomic_state_alloc(test, &priv->drm, &ctx);
1207 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1208 
1209 retry_commit:
1210 	conn_state = drm_atomic_get_connector_state(state, priv->connector);
1211 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
1212 
1213 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
1214 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
1215 
1216 	conn_state->color_format = DRM_CONNECTOR_COLOR_FORMAT_YCBCR444;
1217 
1218 	ret = drm_atomic_set_crtc_for_connector(conn_state, priv->crtc);
1219 	if (ret == -EDEADLK) {
1220 		drm_modeset_backoff(&ctx);
1221 		goto retry_commit;
1222 	}
1223 	KUNIT_ASSERT_EQ(test, ret, 0);
1224 
1225 	crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
1226 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1227 
1228 	ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
1229 	if (ret == -EDEADLK) {
1230 		drm_modeset_backoff(&ctx);
1231 		goto retry_commit;
1232 	}
1233 	KUNIT_ASSERT_EQ(test, ret, 0);
1234 
1235 	crtc_state->enable = true;
1236 	crtc_state->active = true;
1237 
1238 	ret = drm_atomic_commit(state);
1239 	if (ret == -EDEADLK) {
1240 		drm_modeset_backoff(&ctx);
1241 		goto retry_commit;
1242 	}
1243 	KUNIT_ASSERT_EQ(test, ret, 0);
1244 
1245 	drm_test_bridge_chain_verify_fmt(test, priv, expected, ARRAY_SIZE(expected));
1246 
1247 	drm_modeset_drop_locks(&ctx);
1248 	drm_modeset_acquire_fini(&ctx);
1249 }
1250 
1251 /*
1252  * Test which checks that no matter the order of bus formats returned by an
1253  * HDMI bridge, RGB is preferred on DRM_CONNECTOR_COLOR_FORMAT_AUTO if it's
1254  * available.
1255  */
1256 static void drm_test_bridge_hdmi_auto_rgb(struct kunit *test)
1257 {
1258 	static const struct drm_bridge_funcs *funcs[] = {
1259 		&rgb_yuv444_yuv420_producer_funcs,
1260 		&yuv444_yuv422_rgb8_passthrough_hdmi_funcs,
1261 	};
1262 	static const struct fmt_tuple expected[] = {
1263 		{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_RGB888_1X24 },
1264 		{ MEDIA_BUS_FMT_RGB888_1X24, MEDIA_BUS_FMT_RGB888_1X24 },
1265 	};
1266 	struct drm_connector_state *conn_state;
1267 	struct drm_modeset_acquire_ctx ctx;
1268 	struct drm_bridge_chain_priv *priv;
1269 	struct drm_crtc_state *crtc_state;
1270 	struct drm_atomic_commit *state;
1271 	struct drm_display_mode *mode;
1272 	int ret;
1273 
1274 	priv = drm_test_bridge_chain_init(test, ARRAY_SIZE(funcs), funcs);
1275 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
1276 
1277 	drm_modeset_acquire_init(&ctx, 0);
1278 
1279 	state = drm_kunit_helper_atomic_state_alloc(test, &priv->drm, &ctx);
1280 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1281 
1282 retry_commit:
1283 	conn_state = drm_atomic_get_connector_state(state, priv->connector);
1284 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
1285 
1286 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
1287 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
1288 
1289 	KUNIT_ASSERT_EQ(test, conn_state->color_format, DRM_CONNECTOR_COLOR_FORMAT_AUTO);
1290 
1291 	ret = drm_atomic_set_crtc_for_connector(conn_state, priv->crtc);
1292 	if (ret == -EDEADLK) {
1293 		drm_modeset_backoff(&ctx);
1294 		goto retry_commit;
1295 	}
1296 	KUNIT_ASSERT_EQ(test, ret, 0);
1297 
1298 	crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
1299 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1300 
1301 	ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
1302 	if (ret == -EDEADLK) {
1303 		drm_modeset_backoff(&ctx);
1304 		goto retry_commit;
1305 	}
1306 	KUNIT_ASSERT_EQ(test, ret, 0);
1307 
1308 	crtc_state->enable = true;
1309 	crtc_state->active = true;
1310 
1311 	ret = drm_atomic_commit(state);
1312 	if (ret == -EDEADLK) {
1313 		drm_modeset_backoff(&ctx);
1314 		goto retry_commit;
1315 	}
1316 	KUNIT_ASSERT_EQ(test, ret, 0);
1317 
1318 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, DRM_OUTPUT_COLOR_FORMAT_RGB444);
1319 
1320 	drm_test_bridge_chain_verify_fmt(test, priv, expected, ARRAY_SIZE(expected));
1321 
1322 	drm_modeset_drop_locks(&ctx);
1323 	drm_modeset_acquire_fini(&ctx);
1324 }
1325 
1326 /*
1327  * Test which checks that DRM_CONNECTOR_COLOR_FORMAT_AUTO on non-HDMI connectors
1328  * will result in the first bus format on the output to be picked.
1329  */
1330 static void drm_test_bridge_auto_first(struct kunit *test)
1331 {
1332 	static const struct drm_bridge_funcs *funcs[] = {
1333 		&rgb_yuv444_yuv420_producer_funcs,
1334 		&yuv444_yuv422_rgb8_passthrough_funcs,
1335 	};
1336 	static const struct fmt_tuple expected[] = {
1337 		{ MEDIA_BUS_FMT_FIXED, MEDIA_BUS_FMT_YUV8_1X24 },
1338 		{ MEDIA_BUS_FMT_YUV8_1X24, MEDIA_BUS_FMT_YUV8_1X24 },
1339 	};
1340 	struct drm_connector_state *conn_state;
1341 	struct drm_modeset_acquire_ctx ctx;
1342 	struct drm_bridge_chain_priv *priv;
1343 	struct drm_crtc_state *crtc_state;
1344 	struct drm_atomic_commit *state;
1345 	struct drm_display_mode *mode;
1346 	int ret;
1347 
1348 	priv = drm_test_bridge_chain_init(test, ARRAY_SIZE(funcs), funcs);
1349 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
1350 
1351 	drm_modeset_acquire_init(&ctx, 0);
1352 
1353 	state = drm_kunit_helper_atomic_state_alloc(test, &priv->drm, &ctx);
1354 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1355 
1356 retry_commit:
1357 	conn_state = drm_atomic_get_connector_state(state, priv->connector);
1358 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
1359 
1360 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
1361 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
1362 
1363 	KUNIT_ASSERT_EQ(test, conn_state->color_format, DRM_CONNECTOR_COLOR_FORMAT_AUTO);
1364 
1365 	ret = drm_atomic_set_crtc_for_connector(conn_state, priv->crtc);
1366 	if (ret == -EDEADLK) {
1367 		drm_modeset_backoff(&ctx);
1368 		goto retry_commit;
1369 	}
1370 	KUNIT_ASSERT_EQ(test, ret, 0);
1371 
1372 	crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
1373 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1374 
1375 	ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
1376 	if (ret == -EDEADLK) {
1377 		drm_modeset_backoff(&ctx);
1378 		goto retry_commit;
1379 	}
1380 	KUNIT_ASSERT_EQ(test, ret, 0);
1381 
1382 	crtc_state->enable = true;
1383 	crtc_state->active = true;
1384 
1385 	ret = drm_atomic_commit(state);
1386 	if (ret == -EDEADLK) {
1387 		drm_modeset_backoff(&ctx);
1388 		goto retry_commit;
1389 	}
1390 	KUNIT_ASSERT_EQ(test, ret, 0);
1391 
1392 	drm_test_bridge_chain_verify_fmt(test, priv, expected, ARRAY_SIZE(expected));
1393 
1394 	drm_modeset_drop_locks(&ctx);
1395 	drm_modeset_acquire_fini(&ctx);
1396 }
1397 
1398 /*
1399  * Test which checks that in a configuration of bridge chains where an RGB
1400  * producer is hooked to a YUV444-only pass-through, the atomic commit fails as
1401  * the bridge format selection cannot find a valid sequence of bus formats.
1402  */
1403 static void drm_test_bridge_rgb_yuv_no_path(struct kunit *test)
1404 {
1405 	static const struct drm_bridge_funcs *funcs[] = {
1406 		&rgb_producer_funcs,
1407 		&yuv8_passthrough_funcs,
1408 		&rgb8_yuv444_yuv422_passthrough_funcs,
1409 	};
1410 	struct drm_connector_state *conn_state;
1411 	struct drm_modeset_acquire_ctx ctx;
1412 	struct drm_bridge_chain_priv *priv;
1413 	struct drm_crtc_state *crtc_state;
1414 	struct drm_atomic_commit *state;
1415 	struct drm_display_mode *mode;
1416 	int ret;
1417 
1418 	priv = drm_test_bridge_chain_init(test, ARRAY_SIZE(funcs), funcs);
1419 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
1420 
1421 	drm_modeset_acquire_init(&ctx, 0);
1422 
1423 	state = drm_kunit_helper_atomic_state_alloc(test, &priv->drm, &ctx);
1424 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1425 
1426 retry_commit:
1427 	conn_state = drm_atomic_get_connector_state(state, priv->connector);
1428 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
1429 
1430 	mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16);
1431 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode);
1432 
1433 	ret = drm_atomic_set_crtc_for_connector(conn_state, priv->crtc);
1434 	if (ret == -EDEADLK) {
1435 		drm_modeset_backoff(&ctx);
1436 		goto retry_commit;
1437 	}
1438 	KUNIT_ASSERT_EQ(test, ret, 0);
1439 
1440 	crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
1441 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1442 
1443 	ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
1444 	if (ret == -EDEADLK) {
1445 		drm_modeset_backoff(&ctx);
1446 		goto retry_commit;
1447 	}
1448 	KUNIT_ASSERT_EQ(test, ret, 0);
1449 
1450 	crtc_state->enable = true;
1451 	crtc_state->active = true;
1452 
1453 	ret = drm_atomic_commit(state);
1454 	if (ret == -EDEADLK) {
1455 		drm_modeset_backoff(&ctx);
1456 		goto retry_commit;
1457 	}
1458 	KUNIT_EXPECT_EQ(test, ret, -ENOTSUPP);
1459 
1460 	drm_modeset_drop_locks(&ctx);
1461 	drm_modeset_acquire_fini(&ctx);
1462 }
1463 
1464 static struct kunit_case drm_bridge_bus_fmt_tests[] = {
1465 	KUNIT_CASE(drm_test_bridge_rgb_yuv_rgb),
1466 	KUNIT_CASE(drm_test_bridge_must_convert_to_yuv444),
1467 	KUNIT_CASE(drm_test_bridge_hdmi_auto_rgb),
1468 	KUNIT_CASE(drm_test_bridge_auto_first),
1469 	KUNIT_CASE(drm_test_bridge_rgb_yuv_no_path),
1470 	{ }
1471 };
1472 
1473 static struct kunit_suite drm_bridge_bus_fmt_test_suite = {
1474 	.name = "drm_bridge_bus_fmt",
1475 	.test_cases = drm_bridge_bus_fmt_tests,
1476 };
1477 
1478 kunit_test_suites(
1479 	&drm_bridge_get_current_state_test_suite,
1480 	&drm_bridge_helper_reset_crtc_test_suite,
1481 	&drm_bridge_alloc_test_suite,
1482 	&drm_bridge_bus_fmt_test_suite,
1483 );
1484 
1485 MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
1486 MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
1487 MODULE_AUTHOR("Nicolas Frattaroli <nicolas.frattaroli@collabora.com>");
1488 
1489 MODULE_DESCRIPTION("Kunit test for drm_bridge functions");
1490 MODULE_LICENSE("GPL");
1491