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 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 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 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 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 204 struct vc4_dev *vc4_mock_device(struct kunit *test) 205 { 206 return __mock_device(test, false); 207 } 208 209 struct vc4_dev *vc5_mock_device(struct kunit *test) 210 { 211 return __mock_device(test, true); 212 } 213