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