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 drm_plane *plane;
113 struct vc4_dummy_crtc *dummy_crtc;
114 struct drm_crtc *crtc;
115 unsigned int i;
116
117 plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY);
118 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);
119
120 dummy_crtc = vc4_mock_pv(test, drm, plane, pipe->data);
121 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_crtc);
122
123 crtc = &dummy_crtc->crtc.base;
124 for (i = 0; i < pipe->noutputs; i++) {
125 const struct vc4_mock_output_desc *mock_output = &pipe->outputs[i];
126 struct vc4_dummy_output *dummy_output;
127
128 dummy_output = vc4_dummy_output(test, drm, crtc,
129 mock_output->vc4_encoder_type,
130 mock_output->encoder_type,
131 mock_output->connector_type);
132 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_output);
133 }
134
135 return 0;
136 }
137
__build_mock(struct kunit * test,struct drm_device * drm,const struct vc4_mock_desc * mock)138 static int __build_mock(struct kunit *test, struct drm_device *drm,
139 const struct vc4_mock_desc *mock)
140 {
141 unsigned int i;
142
143 for (i = 0; i < mock->npipes; i++) {
144 const struct vc4_mock_pipe_desc *pipe = &mock->pipes[i];
145 int ret;
146
147 ret = __build_one_pipe(test, drm, pipe);
148 KUNIT_ASSERT_EQ(test, ret, 0);
149 }
150
151 return 0;
152 }
153
154 KUNIT_DEFINE_ACTION_WRAPPER(kunit_action_drm_dev_unregister,
155 drm_dev_unregister,
156 struct drm_device *);
157
__mock_device(struct kunit * test,bool is_vc5)158 static struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5)
159 {
160 struct drm_device *drm;
161 const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver;
162 const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock;
163 struct vc4_dev *vc4;
164 struct device *dev;
165 int ret;
166
167 dev = drm_kunit_helper_alloc_device(test);
168 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
169
170 vc4 = drm_kunit_helper_alloc_drm_device_with_driver(test, dev,
171 struct vc4_dev, base,
172 drv);
173 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
174
175 vc4->dev = dev;
176 vc4->is_vc5 = is_vc5;
177
178 vc4->hvs = __vc4_hvs_alloc(vc4, NULL);
179 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs);
180
181 drm = &vc4->base;
182 ret = __build_mock(test, drm, desc);
183 KUNIT_ASSERT_EQ(test, ret, 0);
184
185 ret = vc4_kms_load(drm);
186 KUNIT_ASSERT_EQ(test, ret, 0);
187
188 ret = drm_dev_register(drm, 0);
189 KUNIT_ASSERT_EQ(test, ret, 0);
190
191 ret = kunit_add_action_or_reset(test,
192 kunit_action_drm_dev_unregister,
193 drm);
194 KUNIT_ASSERT_EQ(test, ret, 0);
195
196 return vc4;
197 }
198
vc4_mock_device(struct kunit * test)199 struct vc4_dev *vc4_mock_device(struct kunit *test)
200 {
201 return __mock_device(test, false);
202 }
203
vc5_mock_device(struct kunit * test)204 struct vc4_dev *vc5_mock_device(struct kunit *test)
205 {
206 return __mock_device(test, true);
207 }
208