1// SPDX-License-Identifier: GPL-2.0
2
3#include <drm/drm_drv.h>
4#include <drm/drm_kunit_helpers.h>
5
6#include <kunit/test.h>
7
8#include "vc4_mock.h"
9
10struct vc4_mock_output_desc {
11	enum vc4_encoder_type	vc4_encoder_type;
12	unsigned int		encoder_type;
13	unsigned int		connector_type;
14};
15
16#define VC4_MOCK_OUTPUT_DESC(_vc4_type, _etype, _ctype)					\
17	{										\
18		.vc4_encoder_type = _vc4_type,						\
19		.encoder_type = _etype,							\
20		.connector_type = _ctype,						\
21	}
22
23struct vc4_mock_pipe_desc {
24	const struct vc4_crtc_data *data;
25	const struct vc4_mock_output_desc *outputs;
26	unsigned int noutputs;
27};
28
29#define VC4_MOCK_CRTC_DESC(_data, ...)							\
30	{										\
31		.data = _data,								\
32		.outputs = (struct vc4_mock_output_desc[]) { __VA_ARGS__ },		\
33		.noutputs = sizeof((struct vc4_mock_output_desc[]) { __VA_ARGS__ }) /	\
34			     sizeof(struct vc4_mock_output_desc),			\
35	}
36
37#define VC4_MOCK_PIXELVALVE_DESC(_data, ...)						\
38	VC4_MOCK_CRTC_DESC(&(_data)->base, __VA_ARGS__)
39
40struct vc4_mock_desc {
41	const struct vc4_mock_pipe_desc *pipes;
42	unsigned int npipes;
43};
44
45#define VC4_MOCK_DESC(...)								\
46	{										\
47		.pipes = (struct vc4_mock_pipe_desc[]) { __VA_ARGS__ },			\
48		.npipes = sizeof((struct vc4_mock_pipe_desc[]) { __VA_ARGS__ }) /	\
49			     sizeof(struct vc4_mock_pipe_desc),				\
50	}
51
52static const struct vc4_mock_desc vc4_mock =
53	VC4_MOCK_DESC(
54		VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data,
55				   VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP,
56							DRM_MODE_ENCODER_VIRTUAL,
57							DRM_MODE_CONNECTOR_WRITEBACK)),
58		VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv0_data,
59					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI0,
60							      DRM_MODE_ENCODER_DSI,
61							      DRM_MODE_CONNECTOR_DSI),
62					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DPI,
63							      DRM_MODE_ENCODER_DPI,
64							      DRM_MODE_CONNECTOR_DPI)),
65		VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv1_data,
66					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI1,
67							      DRM_MODE_ENCODER_DSI,
68							      DRM_MODE_CONNECTOR_DSI)),
69		VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv2_data,
70					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI0,
71							      DRM_MODE_ENCODER_TMDS,
72							      DRM_MODE_CONNECTOR_HDMIA),
73					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_VEC,
74							      DRM_MODE_ENCODER_TVDAC,
75							      DRM_MODE_CONNECTOR_Composite)),
76);
77
78static const struct vc4_mock_desc vc5_mock =
79	VC4_MOCK_DESC(
80		VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data,
81				   VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP,
82							DRM_MODE_ENCODER_VIRTUAL,
83							DRM_MODE_CONNECTOR_WRITEBACK)),
84		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv0_data,
85					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI0,
86							      DRM_MODE_ENCODER_DSI,
87							      DRM_MODE_CONNECTOR_DSI),
88					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DPI,
89							      DRM_MODE_ENCODER_DPI,
90							      DRM_MODE_CONNECTOR_DPI)),
91		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv1_data,
92					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI1,
93							      DRM_MODE_ENCODER_DSI,
94							      DRM_MODE_CONNECTOR_DSI)),
95		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv2_data,
96					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI0,
97							      DRM_MODE_ENCODER_TMDS,
98							      DRM_MODE_CONNECTOR_HDMIA)),
99		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv3_data,
100					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_VEC,
101							      DRM_MODE_ENCODER_TVDAC,
102							      DRM_MODE_CONNECTOR_Composite)),
103		VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv4_data,
104					 VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI1,
105							      DRM_MODE_ENCODER_TMDS,
106							      DRM_MODE_CONNECTOR_HDMIA)),
107);
108
109static int __build_one_pipe(struct kunit *test, struct drm_device *drm,
110			    const struct vc4_mock_pipe_desc *pipe)
111{
112	struct vc4_dummy_plane *dummy_plane;
113	struct drm_plane *plane;
114	struct vc4_dummy_crtc *dummy_crtc;
115	struct drm_crtc *crtc;
116	unsigned int i;
117
118	dummy_plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
119	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane);
120
121	plane = &dummy_plane->plane.base;
122	dummy_crtc = vc4_mock_pv(test, drm, plane, pipe->data);
123	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_crtc);
124
125	crtc = &dummy_crtc->crtc.base;
126	for (i = 0; i < pipe->noutputs; i++) {
127		const struct vc4_mock_output_desc *mock_output = &pipe->outputs[i];
128		struct vc4_dummy_output *dummy_output;
129
130		dummy_output = vc4_dummy_output(test, drm, crtc,
131						mock_output->vc4_encoder_type,
132						mock_output->encoder_type,
133						mock_output->connector_type);
134		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_output);
135	}
136
137	return 0;
138}
139
140static int __build_mock(struct kunit *test, struct drm_device *drm,
141			const struct vc4_mock_desc *mock)
142{
143	unsigned int i;
144
145	for (i = 0; i < mock->npipes; i++) {
146		const struct vc4_mock_pipe_desc *pipe = &mock->pipes[i];
147		int ret;
148
149		ret = __build_one_pipe(test, drm, pipe);
150		KUNIT_ASSERT_EQ(test, ret, 0);
151	}
152
153	return 0;
154}
155
156KUNIT_DEFINE_ACTION_WRAPPER(kunit_action_drm_dev_unregister,
157			    drm_dev_unregister,
158			    struct drm_device *);
159
160static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5)
161{
162	struct drm_device *drm;
163	const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver;
164	const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock;
165	struct vc4_dev *vc4;
166	struct device *dev;
167	int ret;
168
169	dev = drm_kunit_helper_alloc_device(test);
170	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
171
172	vc4 = drm_kunit_helper_alloc_drm_device_with_driver(test, dev,
173							    struct vc4_dev, base,
174							    drv);
175	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
176
177	vc4->dev = dev;
178	vc4->is_vc5 = is_vc5;
179
180	vc4->hvs = __vc4_hvs_alloc(vc4, NULL);
181	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs);
182
183	drm = &vc4->base;
184	ret = __build_mock(test, drm, desc);
185	KUNIT_ASSERT_EQ(test, ret, 0);
186
187	ret = vc4_kms_load(drm);
188	KUNIT_ASSERT_EQ(test, ret, 0);
189
190	ret = drm_dev_register(drm, 0);
191	KUNIT_ASSERT_EQ(test, ret, 0);
192
193	ret = kunit_add_action_or_reset(test,
194					kunit_action_drm_dev_unregister,
195					drm);
196	KUNIT_ASSERT_EQ(test, ret, 0);
197
198	return vc4;
199}
200
201struct vc4_dev *vc4_mock_device(struct kunit *test)
202{
203	return __mock_device(test, false);
204}
205
206struct vc4_dev *vc5_mock_device(struct kunit *test)
207{
208	return __mock_device(test, true);
209}
210