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 
10 struct 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 
23 struct 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 
40 struct 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 
52 static 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 
78 static 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 
__build_one_pipe(struct kunit * test,struct drm_device * drm,const struct vc4_mock_pipe_desc * pipe)109 static 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 
__build_mock(struct kunit * test,struct drm_device * drm,const struct vc4_mock_desc * mock)140 static 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 
__mock_device(struct kunit * test,bool is_vc5)156 static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5)
157 {
158 	struct drm_device *drm;
159 	const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver;
160 	const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock;
161 	struct vc4_dev *vc4;
162 	struct device *dev;
163 	int ret;
164 
165 	dev = drm_kunit_helper_alloc_device(test);
166 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
167 
168 	vc4 = drm_kunit_helper_alloc_drm_device_with_driver(test, dev,
169 							    struct vc4_dev, base,
170 							    drv);
171 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
172 
173 	vc4->dev = dev;
174 	vc4->is_vc5 = is_vc5;
175 
176 	vc4->hvs = __vc4_hvs_alloc(vc4, NULL);
177 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs);
178 
179 	drm = &vc4->base;
180 	ret = __build_mock(test, drm, desc);
181 	KUNIT_ASSERT_EQ(test, ret, 0);
182 
183 	ret = vc4_kms_load(drm);
184 	KUNIT_ASSERT_EQ(test, ret, 0);
185 
186 	ret = drm_dev_register(drm, 0);
187 	KUNIT_ASSERT_EQ(test, ret, 0);
188 
189 	return vc4;
190 }
191 
vc4_mock_device(struct kunit * test)192 struct vc4_dev *vc4_mock_device(struct kunit *test)
193 {
194 	return __mock_device(test, false);
195 }
196 
vc5_mock_device(struct kunit * test)197 struct vc4_dev *vc5_mock_device(struct kunit *test)
198 {
199 	return __mock_device(test, true);
200 }
201