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
kunit_action_drm_dev_unregister(void * ptr)156 static void kunit_action_drm_dev_unregister(void *ptr)
157 {
158 struct drm_device *drm = ptr;
159
160 drm_dev_unregister(drm);
161 }
162
__mock_device(struct kunit * test,bool is_vc5)163 static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5)
164 {
165 struct drm_device *drm;
166 const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver;
167 const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock;
168 struct vc4_dev *vc4;
169 struct device *dev;
170 int ret;
171
172 dev = drm_kunit_helper_alloc_device(test);
173 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
174
175 vc4 = drm_kunit_helper_alloc_drm_device_with_driver(test, dev,
176 struct vc4_dev, base,
177 drv);
178 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
179
180 vc4->dev = dev;
181 vc4->is_vc5 = is_vc5;
182
183 vc4->hvs = __vc4_hvs_alloc(vc4, NULL);
184 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs);
185
186 drm = &vc4->base;
187 ret = __build_mock(test, drm, desc);
188 KUNIT_ASSERT_EQ(test, ret, 0);
189
190 ret = vc4_kms_load(drm);
191 KUNIT_ASSERT_EQ(test, ret, 0);
192
193 ret = drm_dev_register(drm, 0);
194 KUNIT_ASSERT_EQ(test, ret, 0);
195
196 ret = kunit_add_action_or_reset(test,
197 kunit_action_drm_dev_unregister,
198 drm);
199 KUNIT_ASSERT_EQ(test, ret, 0);
200
201 return vc4;
202 }
203
vc4_mock_device(struct kunit * test)204 struct vc4_dev *vc4_mock_device(struct kunit *test)
205 {
206 return __mock_device(test, false);
207 }
208
vc5_mock_device(struct kunit * test)209 struct vc4_dev *vc5_mock_device(struct kunit *test)
210 {
211 return __mock_device(test, true);
212 }
213