162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <drm/drm_drv.h> 462306a36Sopenharmony_ci#include <drm/drm_kunit_helpers.h> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <kunit/test.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "vc4_mock.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistruct vc4_mock_output_desc { 1162306a36Sopenharmony_ci enum vc4_encoder_type vc4_encoder_type; 1262306a36Sopenharmony_ci unsigned int encoder_type; 1362306a36Sopenharmony_ci unsigned int connector_type; 1462306a36Sopenharmony_ci}; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define VC4_MOCK_OUTPUT_DESC(_vc4_type, _etype, _ctype) \ 1762306a36Sopenharmony_ci { \ 1862306a36Sopenharmony_ci .vc4_encoder_type = _vc4_type, \ 1962306a36Sopenharmony_ci .encoder_type = _etype, \ 2062306a36Sopenharmony_ci .connector_type = _ctype, \ 2162306a36Sopenharmony_ci } 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct vc4_mock_pipe_desc { 2462306a36Sopenharmony_ci const struct vc4_crtc_data *data; 2562306a36Sopenharmony_ci const struct vc4_mock_output_desc *outputs; 2662306a36Sopenharmony_ci unsigned int noutputs; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define VC4_MOCK_CRTC_DESC(_data, ...) \ 3062306a36Sopenharmony_ci { \ 3162306a36Sopenharmony_ci .data = _data, \ 3262306a36Sopenharmony_ci .outputs = (struct vc4_mock_output_desc[]) { __VA_ARGS__ }, \ 3362306a36Sopenharmony_ci .noutputs = sizeof((struct vc4_mock_output_desc[]) { __VA_ARGS__ }) / \ 3462306a36Sopenharmony_ci sizeof(struct vc4_mock_output_desc), \ 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define VC4_MOCK_PIXELVALVE_DESC(_data, ...) \ 3862306a36Sopenharmony_ci VC4_MOCK_CRTC_DESC(&(_data)->base, __VA_ARGS__) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct vc4_mock_desc { 4162306a36Sopenharmony_ci const struct vc4_mock_pipe_desc *pipes; 4262306a36Sopenharmony_ci unsigned int npipes; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define VC4_MOCK_DESC(...) \ 4662306a36Sopenharmony_ci { \ 4762306a36Sopenharmony_ci .pipes = (struct vc4_mock_pipe_desc[]) { __VA_ARGS__ }, \ 4862306a36Sopenharmony_ci .npipes = sizeof((struct vc4_mock_pipe_desc[]) { __VA_ARGS__ }) / \ 4962306a36Sopenharmony_ci sizeof(struct vc4_mock_pipe_desc), \ 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic const struct vc4_mock_desc vc4_mock = 5362306a36Sopenharmony_ci VC4_MOCK_DESC( 5462306a36Sopenharmony_ci VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data, 5562306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, 5662306a36Sopenharmony_ci DRM_MODE_ENCODER_VIRTUAL, 5762306a36Sopenharmony_ci DRM_MODE_CONNECTOR_WRITEBACK)), 5862306a36Sopenharmony_ci VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv0_data, 5962306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI0, 6062306a36Sopenharmony_ci DRM_MODE_ENCODER_DSI, 6162306a36Sopenharmony_ci DRM_MODE_CONNECTOR_DSI), 6262306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DPI, 6362306a36Sopenharmony_ci DRM_MODE_ENCODER_DPI, 6462306a36Sopenharmony_ci DRM_MODE_CONNECTOR_DPI)), 6562306a36Sopenharmony_ci VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv1_data, 6662306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI1, 6762306a36Sopenharmony_ci DRM_MODE_ENCODER_DSI, 6862306a36Sopenharmony_ci DRM_MODE_CONNECTOR_DSI)), 6962306a36Sopenharmony_ci VC4_MOCK_PIXELVALVE_DESC(&bcm2835_pv2_data, 7062306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI0, 7162306a36Sopenharmony_ci DRM_MODE_ENCODER_TMDS, 7262306a36Sopenharmony_ci DRM_MODE_CONNECTOR_HDMIA), 7362306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_VEC, 7462306a36Sopenharmony_ci DRM_MODE_ENCODER_TVDAC, 7562306a36Sopenharmony_ci DRM_MODE_CONNECTOR_Composite)), 7662306a36Sopenharmony_ci); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic const struct vc4_mock_desc vc5_mock = 7962306a36Sopenharmony_ci VC4_MOCK_DESC( 8062306a36Sopenharmony_ci VC4_MOCK_CRTC_DESC(&vc4_txp_crtc_data, 8162306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_TXP, 8262306a36Sopenharmony_ci DRM_MODE_ENCODER_VIRTUAL, 8362306a36Sopenharmony_ci DRM_MODE_CONNECTOR_WRITEBACK)), 8462306a36Sopenharmony_ci VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv0_data, 8562306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI0, 8662306a36Sopenharmony_ci DRM_MODE_ENCODER_DSI, 8762306a36Sopenharmony_ci DRM_MODE_CONNECTOR_DSI), 8862306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DPI, 8962306a36Sopenharmony_ci DRM_MODE_ENCODER_DPI, 9062306a36Sopenharmony_ci DRM_MODE_CONNECTOR_DPI)), 9162306a36Sopenharmony_ci VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv1_data, 9262306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_DSI1, 9362306a36Sopenharmony_ci DRM_MODE_ENCODER_DSI, 9462306a36Sopenharmony_ci DRM_MODE_CONNECTOR_DSI)), 9562306a36Sopenharmony_ci VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv2_data, 9662306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI0, 9762306a36Sopenharmony_ci DRM_MODE_ENCODER_TMDS, 9862306a36Sopenharmony_ci DRM_MODE_CONNECTOR_HDMIA)), 9962306a36Sopenharmony_ci VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv3_data, 10062306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_VEC, 10162306a36Sopenharmony_ci DRM_MODE_ENCODER_TVDAC, 10262306a36Sopenharmony_ci DRM_MODE_CONNECTOR_Composite)), 10362306a36Sopenharmony_ci VC4_MOCK_PIXELVALVE_DESC(&bcm2711_pv4_data, 10462306a36Sopenharmony_ci VC4_MOCK_OUTPUT_DESC(VC4_ENCODER_TYPE_HDMI1, 10562306a36Sopenharmony_ci DRM_MODE_ENCODER_TMDS, 10662306a36Sopenharmony_ci DRM_MODE_CONNECTOR_HDMIA)), 10762306a36Sopenharmony_ci); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic int __build_one_pipe(struct kunit *test, struct drm_device *drm, 11062306a36Sopenharmony_ci const struct vc4_mock_pipe_desc *pipe) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci struct vc4_dummy_plane *dummy_plane; 11362306a36Sopenharmony_ci struct drm_plane *plane; 11462306a36Sopenharmony_ci struct vc4_dummy_crtc *dummy_crtc; 11562306a36Sopenharmony_ci struct drm_crtc *crtc; 11662306a36Sopenharmony_ci unsigned int i; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci dummy_plane = vc4_dummy_plane(test, drm, DRM_PLANE_TYPE_PRIMARY); 11962306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_plane); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci plane = &dummy_plane->plane.base; 12262306a36Sopenharmony_ci dummy_crtc = vc4_mock_pv(test, drm, plane, pipe->data); 12362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_crtc); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci crtc = &dummy_crtc->crtc.base; 12662306a36Sopenharmony_ci for (i = 0; i < pipe->noutputs; i++) { 12762306a36Sopenharmony_ci const struct vc4_mock_output_desc *mock_output = &pipe->outputs[i]; 12862306a36Sopenharmony_ci struct vc4_dummy_output *dummy_output; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci dummy_output = vc4_dummy_output(test, drm, crtc, 13162306a36Sopenharmony_ci mock_output->vc4_encoder_type, 13262306a36Sopenharmony_ci mock_output->encoder_type, 13362306a36Sopenharmony_ci mock_output->connector_type); 13462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dummy_output); 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci return 0; 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic int __build_mock(struct kunit *test, struct drm_device *drm, 14162306a36Sopenharmony_ci const struct vc4_mock_desc *mock) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci unsigned int i; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci for (i = 0; i < mock->npipes; i++) { 14662306a36Sopenharmony_ci const struct vc4_mock_pipe_desc *pipe = &mock->pipes[i]; 14762306a36Sopenharmony_ci int ret; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci ret = __build_one_pipe(test, drm, pipe); 15062306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci return 0; 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic void kunit_action_drm_dev_unregister(void *ptr) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct drm_device *drm = ptr; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci drm_dev_unregister(drm); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic struct vc4_dev *__mock_device(struct kunit *test, bool is_vc5) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct drm_device *drm; 16662306a36Sopenharmony_ci const struct drm_driver *drv = is_vc5 ? &vc5_drm_driver : &vc4_drm_driver; 16762306a36Sopenharmony_ci const struct vc4_mock_desc *desc = is_vc5 ? &vc5_mock : &vc4_mock; 16862306a36Sopenharmony_ci struct vc4_dev *vc4; 16962306a36Sopenharmony_ci struct device *dev; 17062306a36Sopenharmony_ci int ret; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci dev = drm_kunit_helper_alloc_device(test); 17362306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci vc4 = drm_kunit_helper_alloc_drm_device_with_driver(test, dev, 17662306a36Sopenharmony_ci struct vc4_dev, base, 17762306a36Sopenharmony_ci drv); 17862306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci vc4->dev = dev; 18162306a36Sopenharmony_ci vc4->is_vc5 = is_vc5; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci vc4->hvs = __vc4_hvs_alloc(vc4, NULL); 18462306a36Sopenharmony_ci KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4->hvs); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci drm = &vc4->base; 18762306a36Sopenharmony_ci ret = __build_mock(test, drm, desc); 18862306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci ret = vc4_kms_load(drm); 19162306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci ret = drm_dev_register(drm, 0); 19462306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci ret = kunit_add_action_or_reset(test, 19762306a36Sopenharmony_ci kunit_action_drm_dev_unregister, 19862306a36Sopenharmony_ci drm); 19962306a36Sopenharmony_ci KUNIT_ASSERT_EQ(test, ret, 0); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci return vc4; 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistruct vc4_dev *vc4_mock_device(struct kunit *test) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci return __mock_device(test, false); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistruct vc4_dev *vc5_mock_device(struct kunit *test) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci return __mock_device(test, true); 21262306a36Sopenharmony_ci} 213