File Index
Files and directories
Sign in
FILE

vc4_test_pv_muxing.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c C
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <drm/drm_atomic.h>
   4#include <drm/drm_atomic_helper.h>
   5#include <drm/drm_atomic_state_helper.h>
   6#include <drm/drm_atomic_uapi.h>
   7#include <drm/drm_crtc.h>
   8#include <drm/drm_drv.h>
   9#include <drm/drm_fourcc.h>
  10#include <drm/drm_kunit_helpers.h>
  11#include <drm/drm_mode.h>
  12#include <drm/drm_modeset_helper_vtables.h>
  13#include <drm/drm_plane.h>
  14
  15#include <kunit/test.h>
  16
  17#include "../vc4_drv.h"
  18
  19#include "vc4_mock.h"
  20
  21struct pv_muxing_priv {
  22	struct vc4_dev *vc4;
  23};
  24
  25static bool check_fifo_conflict(struct kunit *test,
  26				const struct drm_atomic_state *state)
  27{
  28	struct vc4_hvs_state *hvs_state;
  29	unsigned int used_fifos = 0;
  30	unsigned int i;
  31
  32	hvs_state = vc4_hvs_get_new_global_state(state);
  33	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hvs_state);
  34
  35	for (i = 0; i < HVS_NUM_CHANNELS; i++) {
  36		if (!hvs_state->fifo_state[i].in_use)
  37			continue;
  38
  39		KUNIT_EXPECT_FALSE(test, used_fifos & BIT(i));
  40		used_fifos |= BIT(i);
  41	}
  42
  43	return true;
  44}
  45
  46struct encoder_constraint {
  47	enum vc4_encoder_type type;
  48	unsigned int *channels;
  49	size_t nchannels;
  50};
  51
  52#define ENCODER_CONSTRAINT(_type, ...)					\
  53	{								\
  54		.type = _type,						\
  55		.channels = (unsigned int[]) { __VA_ARGS__ },		\
  56		.nchannels = sizeof((unsigned int[]) { __VA_ARGS__ }) /	\
  57			     sizeof(unsigned int),			\
  58	}
  59
  60static bool __check_encoder_constraints(const struct encoder_constraint *constraints,
  61					size_t nconstraints,
  62					enum vc4_encoder_type type,
  63					unsigned int channel)
  64{
  65	unsigned int i;
  66
  67	for (i = 0; i < nconstraints; i++) {
  68		const struct encoder_constraint *constraint = &constraints[i];
  69		unsigned int j;
  70
  71		if (constraint->type != type)
  72			continue;
  73
  74		for (j = 0; j < constraint->nchannels; j++) {
  75			unsigned int _channel = constraint->channels[j];
  76
  77			if (channel != _channel)
  78				continue;
  79
  80			return true;
  81		}
  82	}
  83
  84	return false;
  85}
  86
  87static const struct encoder_constraint vc4_encoder_constraints[] = {
  88	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0),
  89	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0),
  90	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 1),
  91	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1),
  92	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP0, 2),
  93	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 2),
  94};
  95
  96static const struct encoder_constraint vc5_encoder_constraints[] = {
  97	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0),
  98	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0),
  99	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1),
 100	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP0, 0, 2),
 101	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 0, 1, 2),
 102	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 0, 1, 2),
 103	ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 0, 1, 2),
 104};
 105
 106static bool check_vc4_encoder_constraints(enum vc4_encoder_type type, unsigned int channel)
 107{
 108	return __check_encoder_constraints(vc4_encoder_constraints,
 109					   ARRAY_SIZE(vc4_encoder_constraints),
 110					   type, channel);
 111}
 112
 113static bool check_vc5_encoder_constraints(enum vc4_encoder_type type, unsigned int channel)
 114{
 115	return __check_encoder_constraints(vc5_encoder_constraints,
 116					   ARRAY_SIZE(vc5_encoder_constraints),
 117					   type, channel);
 118}
 119
 120static struct vc4_crtc_state *
 121get_vc4_crtc_state_for_encoder(struct kunit *test,
 122			       const struct drm_atomic_state *state,
 123			       enum vc4_encoder_type type)
 124{
 125	struct drm_device *drm = state->dev;
 126	struct drm_crtc_state *new_crtc_state;
 127	struct drm_encoder *encoder;
 128	struct drm_crtc *crtc;
 129
 130	encoder = vc4_find_encoder_by_type(drm, type);
 131	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder);
 132
 133	crtc = vc4_find_crtc_for_encoder(test, drm, encoder);
 134	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
 135
 136	new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
 137	if (!new_crtc_state)
 138		return NULL;
 139
 140	return to_vc4_crtc_state(new_crtc_state);
 141}
 142
 143static bool check_channel_for_encoder(struct kunit *test,
 144				      const struct drm_atomic_state *state,
 145				      enum vc4_encoder_type type,
 146				      bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel))
 147{
 148	struct vc4_crtc_state *new_vc4_crtc_state;
 149	struct vc4_hvs_state *new_hvs_state;
 150	unsigned int channel;
 151
 152	new_hvs_state = vc4_hvs_get_new_global_state(state);
 153	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
 154
 155	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, type);
 156	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
 157
 158	channel = new_vc4_crtc_state->assigned_channel;
 159	KUNIT_EXPECT_NE(test, channel, VC4_HVS_CHANNEL_DISABLED);
 160
 161	KUNIT_EXPECT_TRUE(test, new_hvs_state->fifo_state[channel].in_use);
 162
 163	KUNIT_EXPECT_TRUE(test, check_fn(type, channel));
 164
 165	return true;
 166}
 167
 168struct pv_muxing_param {
 169	const char *name;
 170	struct vc4_dev *(*mock_fn)(struct kunit *test);
 171	bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel);
 172	enum vc4_encoder_type *encoders;
 173	size_t nencoders;
 174};
 175
 176static void vc4_test_pv_muxing_desc(const struct pv_muxing_param *t, char *desc)
 177{
 178	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
 179}
 180
 181#define PV_MUXING_TEST(_name, _mock_fn, _check_fn, ...)					\
 182	{										\
 183		.name = _name,								\
 184		.mock_fn = &_mock_fn,							\
 185		.check_fn = &_check_fn,							\
 186		.encoders = (enum vc4_encoder_type[]) { __VA_ARGS__ },			\
 187		.nencoders = sizeof((enum vc4_encoder_type[]) { __VA_ARGS__ }) /	\
 188			     sizeof(enum vc4_encoder_type),				\
 189	}
 190
 191#define VC4_PV_MUXING_TEST(_name, ...)		\
 192	PV_MUXING_TEST(_name, vc4_mock_device, check_vc4_encoder_constraints, __VA_ARGS__)
 193
 194#define VC5_PV_MUXING_TEST(_name, ...)		\
 195	PV_MUXING_TEST(_name, vc5_mock_device, check_vc5_encoder_constraints, __VA_ARGS__)
 196
 197static const struct pv_muxing_param vc4_test_pv_muxing_params[] = {
 198	VC4_PV_MUXING_TEST("1 output: DSI0",
 199			   VC4_ENCODER_TYPE_DSI0),
 200	VC4_PV_MUXING_TEST("1 output: DPI",
 201			   VC4_ENCODER_TYPE_DPI),
 202	VC4_PV_MUXING_TEST("1 output: HDMI0",
 203			   VC4_ENCODER_TYPE_HDMI0),
 204	VC4_PV_MUXING_TEST("1 output: VEC",
 205			   VC4_ENCODER_TYPE_VEC),
 206	VC4_PV_MUXING_TEST("1 output: DSI1",
 207			   VC4_ENCODER_TYPE_DSI1),
 208	VC4_PV_MUXING_TEST("1 output: TXP",
 209			   VC4_ENCODER_TYPE_TXP0),
 210	VC4_PV_MUXING_TEST("2 outputs: DSI0, HDMI0",
 211			   VC4_ENCODER_TYPE_DSI0,
 212			   VC4_ENCODER_TYPE_HDMI0),
 213	VC4_PV_MUXING_TEST("2 outputs: DSI0, VEC",
 214			   VC4_ENCODER_TYPE_DSI0,
 215			   VC4_ENCODER_TYPE_VEC),
 216	VC4_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
 217			   VC4_ENCODER_TYPE_DSI0,
 218			   VC4_ENCODER_TYPE_DSI1),
 219	VC4_PV_MUXING_TEST("2 outputs: DSI0, TXP",
 220			   VC4_ENCODER_TYPE_DSI0,
 221			   VC4_ENCODER_TYPE_TXP0),
 222	VC4_PV_MUXING_TEST("2 outputs: DPI, HDMI0",
 223			   VC4_ENCODER_TYPE_DPI,
 224			   VC4_ENCODER_TYPE_HDMI0),
 225	VC4_PV_MUXING_TEST("2 outputs: DPI, VEC",
 226			   VC4_ENCODER_TYPE_DPI,
 227			   VC4_ENCODER_TYPE_VEC),
 228	VC4_PV_MUXING_TEST("2 outputs: DPI, DSI1",
 229			   VC4_ENCODER_TYPE_DPI,
 230			   VC4_ENCODER_TYPE_DSI1),
 231	VC4_PV_MUXING_TEST("2 outputs: DPI, TXP",
 232			   VC4_ENCODER_TYPE_DPI,
 233			   VC4_ENCODER_TYPE_TXP0),
 234	VC4_PV_MUXING_TEST("2 outputs: HDMI0, DSI1",
 235			   VC4_ENCODER_TYPE_HDMI0,
 236			   VC4_ENCODER_TYPE_DSI1),
 237	VC4_PV_MUXING_TEST("2 outputs: HDMI0, TXP",
 238			   VC4_ENCODER_TYPE_HDMI0,
 239			   VC4_ENCODER_TYPE_TXP0),
 240	VC4_PV_MUXING_TEST("2 outputs: VEC, DSI1",
 241			   VC4_ENCODER_TYPE_VEC,
 242			   VC4_ENCODER_TYPE_DSI1),
 243	VC4_PV_MUXING_TEST("2 outputs: VEC, TXP",
 244			   VC4_ENCODER_TYPE_VEC,
 245			   VC4_ENCODER_TYPE_TXP0),
 246	VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, DSI1",
 247			   VC4_ENCODER_TYPE_DSI0,
 248			   VC4_ENCODER_TYPE_HDMI0,
 249			   VC4_ENCODER_TYPE_DSI1),
 250	VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, TXP",
 251			   VC4_ENCODER_TYPE_DSI0,
 252			   VC4_ENCODER_TYPE_HDMI0,
 253			   VC4_ENCODER_TYPE_TXP0),
 254	VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1",
 255			   VC4_ENCODER_TYPE_DSI0,
 256			   VC4_ENCODER_TYPE_VEC,
 257			   VC4_ENCODER_TYPE_DSI1),
 258	VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP",
 259			   VC4_ENCODER_TYPE_DSI0,
 260			   VC4_ENCODER_TYPE_VEC,
 261			   VC4_ENCODER_TYPE_TXP0),
 262	VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, DSI1",
 263			   VC4_ENCODER_TYPE_DPI,
 264			   VC4_ENCODER_TYPE_HDMI0,
 265			   VC4_ENCODER_TYPE_DSI1),
 266	VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, TXP",
 267			   VC4_ENCODER_TYPE_DPI,
 268			   VC4_ENCODER_TYPE_HDMI0,
 269			   VC4_ENCODER_TYPE_TXP0),
 270	VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1",
 271			   VC4_ENCODER_TYPE_DPI,
 272			   VC4_ENCODER_TYPE_VEC,
 273			   VC4_ENCODER_TYPE_DSI1),
 274	VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP",
 275			   VC4_ENCODER_TYPE_DPI,
 276			   VC4_ENCODER_TYPE_VEC,
 277			   VC4_ENCODER_TYPE_TXP0),
 278};
 279
 280KUNIT_ARRAY_PARAM(vc4_test_pv_muxing,
 281		  vc4_test_pv_muxing_params,
 282		  vc4_test_pv_muxing_desc);
 283
 284static const struct pv_muxing_param vc4_test_pv_muxing_invalid_params[] = {
 285	VC4_PV_MUXING_TEST("DPI/DSI0 Conflict",
 286			   VC4_ENCODER_TYPE_DPI,
 287			   VC4_ENCODER_TYPE_DSI0),
 288	VC4_PV_MUXING_TEST("TXP/DSI1 Conflict",
 289			   VC4_ENCODER_TYPE_TXP0,
 290			   VC4_ENCODER_TYPE_DSI1),
 291	VC4_PV_MUXING_TEST("HDMI0/VEC Conflict",
 292			   VC4_ENCODER_TYPE_HDMI0,
 293			   VC4_ENCODER_TYPE_VEC),
 294	VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, HDMI0, DSI1, TXP",
 295			   VC4_ENCODER_TYPE_DSI0,
 296			   VC4_ENCODER_TYPE_HDMI0,
 297			   VC4_ENCODER_TYPE_DSI1,
 298			   VC4_ENCODER_TYPE_TXP0),
 299	VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, TXP",
 300			   VC4_ENCODER_TYPE_DSI0,
 301			   VC4_ENCODER_TYPE_VEC,
 302			   VC4_ENCODER_TYPE_DSI1,
 303			   VC4_ENCODER_TYPE_TXP0),
 304	VC4_PV_MUXING_TEST("More than 3 outputs: DPI, HDMI0, DSI1, TXP",
 305			   VC4_ENCODER_TYPE_DPI,
 306			   VC4_ENCODER_TYPE_HDMI0,
 307			   VC4_ENCODER_TYPE_DSI1,
 308			   VC4_ENCODER_TYPE_TXP0),
 309	VC4_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, TXP",
 310			   VC4_ENCODER_TYPE_DPI,
 311			   VC4_ENCODER_TYPE_VEC,
 312			   VC4_ENCODER_TYPE_DSI1,
 313			   VC4_ENCODER_TYPE_TXP0),
 314};
 315
 316KUNIT_ARRAY_PARAM(vc4_test_pv_muxing_invalid,
 317		  vc4_test_pv_muxing_invalid_params,
 318		  vc4_test_pv_muxing_desc);
 319
 320static const struct pv_muxing_param vc5_test_pv_muxing_params[] = {
 321	VC5_PV_MUXING_TEST("1 output: DPI",
 322			   VC4_ENCODER_TYPE_DPI),
 323	VC5_PV_MUXING_TEST("1 output: DSI0",
 324			   VC4_ENCODER_TYPE_DSI0),
 325	VC5_PV_MUXING_TEST("1 output: DSI1",
 326			   VC4_ENCODER_TYPE_DSI1),
 327	VC5_PV_MUXING_TEST("1 output: HDMI0",
 328			   VC4_ENCODER_TYPE_HDMI0),
 329	VC5_PV_MUXING_TEST("1 output: HDMI1",
 330			   VC4_ENCODER_TYPE_HDMI1),
 331	VC5_PV_MUXING_TEST("1 output: VEC",
 332			   VC4_ENCODER_TYPE_VEC),
 333	VC5_PV_MUXING_TEST("2 outputs: DPI, DSI1",
 334			   VC4_ENCODER_TYPE_DPI,
 335			   VC4_ENCODER_TYPE_DSI1),
 336	VC5_PV_MUXING_TEST("2 outputs: DPI, HDMI0",
 337			   VC4_ENCODER_TYPE_DPI,
 338			   VC4_ENCODER_TYPE_HDMI0),
 339	VC5_PV_MUXING_TEST("2 outputs: DPI, HDMI1",
 340			   VC4_ENCODER_TYPE_DPI,
 341			   VC4_ENCODER_TYPE_HDMI1),
 342	VC5_PV_MUXING_TEST("2 outputs: DPI, TXP",
 343			   VC4_ENCODER_TYPE_DPI,
 344			   VC4_ENCODER_TYPE_TXP0),
 345	VC5_PV_MUXING_TEST("2 outputs: DPI, VEC",
 346			   VC4_ENCODER_TYPE_DPI,
 347			   VC4_ENCODER_TYPE_VEC),
 348	VC5_PV_MUXING_TEST("2 outputs: DPI, DSI1",
 349			   VC4_ENCODER_TYPE_DPI,
 350			   VC4_ENCODER_TYPE_DSI1),
 351	VC5_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
 352			   VC4_ENCODER_TYPE_DSI0,
 353			   VC4_ENCODER_TYPE_DSI1),
 354	VC5_PV_MUXING_TEST("2 outputs: DSI0, HDMI0",
 355			   VC4_ENCODER_TYPE_DSI0,
 356			   VC4_ENCODER_TYPE_HDMI0),
 357	VC5_PV_MUXING_TEST("2 outputs: DSI0, HDMI1",
 358			   VC4_ENCODER_TYPE_DSI0,
 359			   VC4_ENCODER_TYPE_HDMI1),
 360	VC5_PV_MUXING_TEST("2 outputs: DSI0, TXP",
 361			   VC4_ENCODER_TYPE_DSI0,
 362			   VC4_ENCODER_TYPE_TXP0),
 363	VC5_PV_MUXING_TEST("2 outputs: DSI0, VEC",
 364			   VC4_ENCODER_TYPE_DSI0,
 365			   VC4_ENCODER_TYPE_VEC),
 366	VC5_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
 367			   VC4_ENCODER_TYPE_DSI0,
 368			   VC4_ENCODER_TYPE_DSI1),
 369	VC5_PV_MUXING_TEST("2 outputs: DSI1, VEC",
 370			   VC4_ENCODER_TYPE_DSI1,
 371			   VC4_ENCODER_TYPE_VEC),
 372	VC5_PV_MUXING_TEST("2 outputs: DSI1, TXP",
 373			   VC4_ENCODER_TYPE_DSI1,
 374			   VC4_ENCODER_TYPE_TXP0),
 375	VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI0",
 376			   VC4_ENCODER_TYPE_DSI1,
 377			   VC4_ENCODER_TYPE_HDMI0),
 378	VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI1",
 379			   VC4_ENCODER_TYPE_DSI1,
 380			   VC4_ENCODER_TYPE_HDMI1),
 381	VC5_PV_MUXING_TEST("2 outputs: HDMI0, VEC",
 382			   VC4_ENCODER_TYPE_HDMI0,
 383			   VC4_ENCODER_TYPE_VEC),
 384	VC5_PV_MUXING_TEST("2 outputs: HDMI0, TXP",
 385			   VC4_ENCODER_TYPE_HDMI0,
 386			   VC4_ENCODER_TYPE_TXP0),
 387	VC5_PV_MUXING_TEST("2 outputs: HDMI0, HDMI1",
 388			   VC4_ENCODER_TYPE_HDMI0,
 389			   VC4_ENCODER_TYPE_HDMI1),
 390	VC5_PV_MUXING_TEST("2 outputs: HDMI1, VEC",
 391			   VC4_ENCODER_TYPE_HDMI1,
 392			   VC4_ENCODER_TYPE_VEC),
 393	VC5_PV_MUXING_TEST("2 outputs: HDMI1, TXP",
 394			   VC4_ENCODER_TYPE_HDMI1,
 395			   VC4_ENCODER_TYPE_TXP0),
 396	VC5_PV_MUXING_TEST("2 outputs: TXP, VEC",
 397			   VC4_ENCODER_TYPE_TXP0,
 398			   VC4_ENCODER_TYPE_VEC),
 399	VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP",
 400			   VC4_ENCODER_TYPE_DPI,
 401			   VC4_ENCODER_TYPE_VEC,
 402			   VC4_ENCODER_TYPE_TXP0),
 403	VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1",
 404			   VC4_ENCODER_TYPE_DPI,
 405			   VC4_ENCODER_TYPE_VEC,
 406			   VC4_ENCODER_TYPE_DSI1),
 407	VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, HDMI0",
 408			   VC4_ENCODER_TYPE_DPI,
 409			   VC4_ENCODER_TYPE_VEC,
 410			   VC4_ENCODER_TYPE_HDMI0),
 411	VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, HDMI1",
 412			   VC4_ENCODER_TYPE_DPI,
 413			   VC4_ENCODER_TYPE_VEC,
 414			   VC4_ENCODER_TYPE_HDMI1),
 415	VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, DSI1",
 416			   VC4_ENCODER_TYPE_DPI,
 417			   VC4_ENCODER_TYPE_TXP0,
 418			   VC4_ENCODER_TYPE_DSI1),
 419	VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI0",
 420			   VC4_ENCODER_TYPE_DPI,
 421			   VC4_ENCODER_TYPE_TXP0,
 422			   VC4_ENCODER_TYPE_HDMI0),
 423	VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI1",
 424			   VC4_ENCODER_TYPE_DPI,
 425			   VC4_ENCODER_TYPE_TXP0,
 426			   VC4_ENCODER_TYPE_HDMI1),
 427	VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI0",
 428			   VC4_ENCODER_TYPE_DPI,
 429			   VC4_ENCODER_TYPE_DSI1,
 430			   VC4_ENCODER_TYPE_HDMI0),
 431	VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI1",
 432			   VC4_ENCODER_TYPE_DPI,
 433			   VC4_ENCODER_TYPE_DSI1,
 434			   VC4_ENCODER_TYPE_HDMI1),
 435	VC5_PV_MUXING_TEST("3 outputs: DPI, HDMI0, HDMI1",
 436			   VC4_ENCODER_TYPE_DPI,
 437			   VC4_ENCODER_TYPE_HDMI0,
 438			   VC4_ENCODER_TYPE_HDMI1),
 439	VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP",
 440			   VC4_ENCODER_TYPE_DSI0,
 441			   VC4_ENCODER_TYPE_VEC,
 442			   VC4_ENCODER_TYPE_TXP0),
 443	VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1",
 444			   VC4_ENCODER_TYPE_DSI0,
 445			   VC4_ENCODER_TYPE_VEC,
 446			   VC4_ENCODER_TYPE_DSI1),
 447	VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, HDMI0",
 448			   VC4_ENCODER_TYPE_DSI0,
 449			   VC4_ENCODER_TYPE_VEC,
 450			   VC4_ENCODER_TYPE_HDMI0),
 451	VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, HDMI1",
 452			   VC4_ENCODER_TYPE_DSI0,
 453			   VC4_ENCODER_TYPE_VEC,
 454			   VC4_ENCODER_TYPE_HDMI1),
 455	VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, DSI1",
 456			   VC4_ENCODER_TYPE_DSI0,
 457			   VC4_ENCODER_TYPE_TXP0,
 458			   VC4_ENCODER_TYPE_DSI1),
 459	VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI0",
 460			   VC4_ENCODER_TYPE_DSI0,
 461			   VC4_ENCODER_TYPE_TXP0,
 462			   VC4_ENCODER_TYPE_HDMI0),
 463	VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI1",
 464			   VC4_ENCODER_TYPE_DSI0,
 465			   VC4_ENCODER_TYPE_TXP0,
 466			   VC4_ENCODER_TYPE_HDMI1),
 467	VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI0",
 468			   VC4_ENCODER_TYPE_DSI0,
 469			   VC4_ENCODER_TYPE_DSI1,
 470			   VC4_ENCODER_TYPE_HDMI0),
 471	VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI1",
 472			   VC4_ENCODER_TYPE_DSI0,
 473			   VC4_ENCODER_TYPE_DSI1,
 474			   VC4_ENCODER_TYPE_HDMI1),
 475	VC5_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, HDMI1",
 476			   VC4_ENCODER_TYPE_DSI0,
 477			   VC4_ENCODER_TYPE_HDMI0,
 478			   VC4_ENCODER_TYPE_HDMI1),
 479};
 480
 481KUNIT_ARRAY_PARAM(vc5_test_pv_muxing,
 482		  vc5_test_pv_muxing_params,
 483		  vc4_test_pv_muxing_desc);
 484
 485static const struct pv_muxing_param vc5_test_pv_muxing_invalid_params[] = {
 486	VC5_PV_MUXING_TEST("DPI/DSI0 Conflict",
 487			   VC4_ENCODER_TYPE_DPI,
 488			   VC4_ENCODER_TYPE_DSI0),
 489	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1",
 490			   VC4_ENCODER_TYPE_DPI,
 491			   VC4_ENCODER_TYPE_VEC,
 492			   VC4_ENCODER_TYPE_TXP0,
 493			   VC4_ENCODER_TYPE_DSI1),
 494	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0",
 495			   VC4_ENCODER_TYPE_DPI,
 496			   VC4_ENCODER_TYPE_VEC,
 497			   VC4_ENCODER_TYPE_TXP0,
 498			   VC4_ENCODER_TYPE_HDMI0),
 499	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI1",
 500			   VC4_ENCODER_TYPE_DPI,
 501			   VC4_ENCODER_TYPE_VEC,
 502			   VC4_ENCODER_TYPE_TXP0,
 503			   VC4_ENCODER_TYPE_HDMI1),
 504	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0",
 505			   VC4_ENCODER_TYPE_DPI,
 506			   VC4_ENCODER_TYPE_VEC,
 507			   VC4_ENCODER_TYPE_DSI1,
 508			   VC4_ENCODER_TYPE_HDMI0),
 509	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI1",
 510			   VC4_ENCODER_TYPE_DPI,
 511			   VC4_ENCODER_TYPE_VEC,
 512			   VC4_ENCODER_TYPE_DSI1,
 513			   VC4_ENCODER_TYPE_HDMI1),
 514	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, HDMI0, HDMI1",
 515			   VC4_ENCODER_TYPE_DPI,
 516			   VC4_ENCODER_TYPE_VEC,
 517			   VC4_ENCODER_TYPE_HDMI0,
 518			   VC4_ENCODER_TYPE_HDMI1),
 519	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0",
 520			   VC4_ENCODER_TYPE_DPI,
 521			   VC4_ENCODER_TYPE_TXP0,
 522			   VC4_ENCODER_TYPE_DSI1,
 523			   VC4_ENCODER_TYPE_HDMI0),
 524	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI1",
 525			   VC4_ENCODER_TYPE_DPI,
 526			   VC4_ENCODER_TYPE_TXP0,
 527			   VC4_ENCODER_TYPE_DSI1,
 528			   VC4_ENCODER_TYPE_HDMI1),
 529	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, HDMI0, HDMI1",
 530			   VC4_ENCODER_TYPE_DPI,
 531			   VC4_ENCODER_TYPE_TXP0,
 532			   VC4_ENCODER_TYPE_HDMI0,
 533			   VC4_ENCODER_TYPE_HDMI1),
 534	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, DSI1, HDMI0, HDMI1",
 535			   VC4_ENCODER_TYPE_DPI,
 536			   VC4_ENCODER_TYPE_DSI1,
 537			   VC4_ENCODER_TYPE_HDMI0,
 538			   VC4_ENCODER_TYPE_HDMI1),
 539	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0",
 540			   VC4_ENCODER_TYPE_DPI,
 541			   VC4_ENCODER_TYPE_VEC,
 542			   VC4_ENCODER_TYPE_TXP0,
 543			   VC4_ENCODER_TYPE_DSI1,
 544			   VC4_ENCODER_TYPE_HDMI0),
 545	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI1",
 546			   VC4_ENCODER_TYPE_DPI,
 547			   VC4_ENCODER_TYPE_VEC,
 548			   VC4_ENCODER_TYPE_TXP0,
 549			   VC4_ENCODER_TYPE_DSI1,
 550			   VC4_ENCODER_TYPE_HDMI1),
 551	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0, HDMI1",
 552			   VC4_ENCODER_TYPE_DPI,
 553			   VC4_ENCODER_TYPE_VEC,
 554			   VC4_ENCODER_TYPE_TXP0,
 555			   VC4_ENCODER_TYPE_HDMI0,
 556			   VC4_ENCODER_TYPE_HDMI1),
 557	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0, HDMI1",
 558			   VC4_ENCODER_TYPE_DPI,
 559			   VC4_ENCODER_TYPE_VEC,
 560			   VC4_ENCODER_TYPE_DSI1,
 561			   VC4_ENCODER_TYPE_HDMI0,
 562			   VC4_ENCODER_TYPE_HDMI1),
 563	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0, HDMI1",
 564			   VC4_ENCODER_TYPE_DPI,
 565			   VC4_ENCODER_TYPE_TXP0,
 566			   VC4_ENCODER_TYPE_DSI1,
 567			   VC4_ENCODER_TYPE_HDMI0,
 568			   VC4_ENCODER_TYPE_HDMI1),
 569	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1",
 570			   VC4_ENCODER_TYPE_DSI0,
 571			   VC4_ENCODER_TYPE_VEC,
 572			   VC4_ENCODER_TYPE_TXP0,
 573			   VC4_ENCODER_TYPE_DSI1),
 574	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0",
 575			   VC4_ENCODER_TYPE_DSI0,
 576			   VC4_ENCODER_TYPE_VEC,
 577			   VC4_ENCODER_TYPE_TXP0,
 578			   VC4_ENCODER_TYPE_HDMI0),
 579	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI1",
 580			   VC4_ENCODER_TYPE_DSI0,
 581			   VC4_ENCODER_TYPE_VEC,
 582			   VC4_ENCODER_TYPE_TXP0,
 583			   VC4_ENCODER_TYPE_HDMI1),
 584	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0",
 585			   VC4_ENCODER_TYPE_DSI0,
 586			   VC4_ENCODER_TYPE_VEC,
 587			   VC4_ENCODER_TYPE_DSI1,
 588			   VC4_ENCODER_TYPE_HDMI0),
 589	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI1",
 590			   VC4_ENCODER_TYPE_DSI0,
 591			   VC4_ENCODER_TYPE_VEC,
 592			   VC4_ENCODER_TYPE_DSI1,
 593			   VC4_ENCODER_TYPE_HDMI1),
 594	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, HDMI0, HDMI1",
 595			   VC4_ENCODER_TYPE_DSI0,
 596			   VC4_ENCODER_TYPE_VEC,
 597			   VC4_ENCODER_TYPE_HDMI0,
 598			   VC4_ENCODER_TYPE_HDMI1),
 599	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0",
 600			   VC4_ENCODER_TYPE_DSI0,
 601			   VC4_ENCODER_TYPE_TXP0,
 602			   VC4_ENCODER_TYPE_DSI1,
 603			   VC4_ENCODER_TYPE_HDMI0),
 604	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI1",
 605			   VC4_ENCODER_TYPE_DSI0,
 606			   VC4_ENCODER_TYPE_TXP0,
 607			   VC4_ENCODER_TYPE_DSI1,
 608			   VC4_ENCODER_TYPE_HDMI1),
 609	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, HDMI0, HDMI1",
 610			   VC4_ENCODER_TYPE_DSI0,
 611			   VC4_ENCODER_TYPE_TXP0,
 612			   VC4_ENCODER_TYPE_HDMI0,
 613			   VC4_ENCODER_TYPE_HDMI1),
 614	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, DSI1, HDMI0, HDMI1",
 615			   VC4_ENCODER_TYPE_DSI0,
 616			   VC4_ENCODER_TYPE_DSI1,
 617			   VC4_ENCODER_TYPE_HDMI0,
 618			   VC4_ENCODER_TYPE_HDMI1),
 619	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0",
 620			   VC4_ENCODER_TYPE_DSI0,
 621			   VC4_ENCODER_TYPE_VEC,
 622			   VC4_ENCODER_TYPE_TXP0,
 623			   VC4_ENCODER_TYPE_DSI1,
 624			   VC4_ENCODER_TYPE_HDMI0),
 625	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI1",
 626			   VC4_ENCODER_TYPE_DSI0,
 627			   VC4_ENCODER_TYPE_VEC,
 628			   VC4_ENCODER_TYPE_TXP0,
 629			   VC4_ENCODER_TYPE_DSI1,
 630			   VC4_ENCODER_TYPE_HDMI1),
 631	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0, HDMI1",
 632			   VC4_ENCODER_TYPE_DSI0,
 633			   VC4_ENCODER_TYPE_VEC,
 634			   VC4_ENCODER_TYPE_TXP0,
 635			   VC4_ENCODER_TYPE_HDMI0,
 636			   VC4_ENCODER_TYPE_HDMI1),
 637	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0, HDMI1",
 638			   VC4_ENCODER_TYPE_DSI0,
 639			   VC4_ENCODER_TYPE_VEC,
 640			   VC4_ENCODER_TYPE_DSI1,
 641			   VC4_ENCODER_TYPE_HDMI0,
 642			   VC4_ENCODER_TYPE_HDMI1),
 643	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0, HDMI1",
 644			   VC4_ENCODER_TYPE_DSI0,
 645			   VC4_ENCODER_TYPE_TXP0,
 646			   VC4_ENCODER_TYPE_DSI1,
 647			   VC4_ENCODER_TYPE_HDMI0,
 648			   VC4_ENCODER_TYPE_HDMI1),
 649	VC5_PV_MUXING_TEST("More than 3 outputs: VEC, TXP, DSI1, HDMI0, HDMI1",
 650			   VC4_ENCODER_TYPE_VEC,
 651			   VC4_ENCODER_TYPE_TXP0,
 652			   VC4_ENCODER_TYPE_DSI1,
 653			   VC4_ENCODER_TYPE_HDMI0,
 654			   VC4_ENCODER_TYPE_HDMI1),
 655	VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0, HDMI1",
 656			   VC4_ENCODER_TYPE_DPI,
 657			   VC4_ENCODER_TYPE_VEC,
 658			   VC4_ENCODER_TYPE_TXP0,
 659			   VC4_ENCODER_TYPE_DSI1,
 660			   VC4_ENCODER_TYPE_HDMI0,
 661			   VC4_ENCODER_TYPE_HDMI1),
 662	VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0, HDMI1",
 663			   VC4_ENCODER_TYPE_DSI0,
 664			   VC4_ENCODER_TYPE_VEC,
 665			   VC4_ENCODER_TYPE_TXP0,
 666			   VC4_ENCODER_TYPE_DSI1,
 667			   VC4_ENCODER_TYPE_HDMI0,
 668			   VC4_ENCODER_TYPE_HDMI1),
 669};
 670
 671KUNIT_ARRAY_PARAM(vc5_test_pv_muxing_invalid,
 672		  vc5_test_pv_muxing_invalid_params,
 673		  vc4_test_pv_muxing_desc);
 674
 675static void drm_vc4_test_pv_muxing(struct kunit *test)
 676{
 677	const struct pv_muxing_param *params = test->param_value;
 678	const struct pv_muxing_priv *priv = test->priv;
 679	struct drm_modeset_acquire_ctx ctx;
 680	struct drm_atomic_state *state;
 681	struct drm_device *drm;
 682	struct vc4_dev *vc4;
 683	unsigned int i;
 684	int ret;
 685
 686	drm_modeset_acquire_init(&ctx, 0);
 687
 688	vc4 = priv->vc4;
 689	drm = &vc4->base;
 690
 691retry:
 692	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
 693	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
 694	for (i = 0; i < params->nencoders; i++) {
 695		enum vc4_encoder_type enc_type = params->encoders[i];
 696
 697		ret = vc4_mock_atomic_add_output(test, state, enc_type);
 698		if (ret == -EDEADLK) {
 699			drm_atomic_state_clear(state);
 700			ret = drm_modeset_backoff(&ctx);
 701			if (!ret)
 702				goto retry;
 703		}
 704		KUNIT_ASSERT_EQ(test, ret, 0);
 705	}
 706
 707	ret = drm_atomic_check_only(state);
 708	if (ret == -EDEADLK) {
 709		drm_atomic_state_clear(state);
 710		ret = drm_modeset_backoff(&ctx);
 711		if (!ret)
 712			goto retry;
 713	}
 714	KUNIT_EXPECT_EQ(test, ret, 0);
 715
 716	KUNIT_EXPECT_TRUE(test,
 717			  check_fifo_conflict(test, state));
 718
 719	for (i = 0; i < params->nencoders; i++) {
 720		enum vc4_encoder_type enc_type = params->encoders[i];
 721
 722		KUNIT_EXPECT_TRUE(test, check_channel_for_encoder(test, state, enc_type,
 723								  params->check_fn));
 724	}
 725
 726	drm_modeset_drop_locks(&ctx);
 727	drm_modeset_acquire_fini(&ctx);
 728}
 729
 730static void drm_vc4_test_pv_muxing_invalid(struct kunit *test)
 731{
 732	const struct pv_muxing_param *params = test->param_value;
 733	const struct pv_muxing_priv *priv = test->priv;
 734	struct drm_modeset_acquire_ctx ctx;
 735	struct drm_atomic_state *state;
 736	struct drm_device *drm;
 737	struct vc4_dev *vc4;
 738	unsigned int i;
 739	int ret;
 740
 741	drm_modeset_acquire_init(&ctx, 0);
 742
 743	vc4 = priv->vc4;
 744	drm = &vc4->base;
 745
 746retry:
 747	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
 748	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
 749
 750	for (i = 0; i < params->nencoders; i++) {
 751		enum vc4_encoder_type enc_type = params->encoders[i];
 752
 753		ret = vc4_mock_atomic_add_output(test, state, enc_type);
 754		if (ret == -EDEADLK) {
 755			drm_atomic_state_clear(state);
 756			ret = drm_modeset_backoff(&ctx);
 757			if (!ret)
 758				goto retry;
 759		}
 760		KUNIT_ASSERT_EQ(test, ret, 0);
 761	}
 762
 763	ret = drm_atomic_check_only(state);
 764	if (ret == -EDEADLK) {
 765		drm_atomic_state_clear(state);
 766		ret = drm_modeset_backoff(&ctx);
 767		if (!ret)
 768			goto retry;
 769	}
 770	KUNIT_EXPECT_LT(test, ret, 0);
 771
 772	drm_modeset_drop_locks(&ctx);
 773	drm_modeset_acquire_fini(&ctx);
 774}
 775
 776static int vc4_pv_muxing_test_init(struct kunit *test)
 777{
 778	const struct pv_muxing_param *params = test->param_value;
 779	struct pv_muxing_priv *priv;
 780	struct vc4_dev *vc4;
 781
 782	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
 783	KUNIT_ASSERT_NOT_NULL(test, priv);
 784	test->priv = priv;
 785
 786	vc4 = params->mock_fn(test);
 787	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
 788	priv->vc4 = vc4;
 789
 790	return 0;
 791}
 792
 793static struct kunit_case vc4_pv_muxing_tests[] = {
 794	KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing,
 795			 vc4_test_pv_muxing_gen_params),
 796	KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid,
 797			 vc4_test_pv_muxing_invalid_gen_params),
 798	{}
 799};
 800
 801static struct kunit_suite vc4_pv_muxing_test_suite = {
 802	.name = "vc4-pv-muxing-combinations",
 803	.init = vc4_pv_muxing_test_init,
 804	.test_cases = vc4_pv_muxing_tests,
 805};
 806
 807static struct kunit_case vc5_pv_muxing_tests[] = {
 808	KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing,
 809			 vc5_test_pv_muxing_gen_params),
 810	KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid,
 811			 vc5_test_pv_muxing_invalid_gen_params),
 812	{}
 813};
 814
 815static struct kunit_suite vc5_pv_muxing_test_suite = {
 816	.name = "vc5-pv-muxing-combinations",
 817	.init = vc4_pv_muxing_test_init,
 818	.test_cases = vc5_pv_muxing_tests,
 819};
 820
 821/* See
 822 * https://lore.kernel.org/all/3e113525-aa89-b1e2-56b7-ca55bd41d057@samsung.com/
 823 * and
 824 * https://lore.kernel.org/dri-devel/20200917121623.42023-1-maxime@cerno.tech/
 825 */
 826static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *test)
 827{
 828	struct drm_modeset_acquire_ctx ctx;
 829	struct drm_atomic_state *state;
 830	struct vc4_crtc_state *new_vc4_crtc_state;
 831	struct vc4_hvs_state *new_hvs_state;
 832	unsigned int hdmi0_channel;
 833	unsigned int hdmi1_channel;
 834	struct drm_device *drm;
 835	struct vc4_dev *vc4;
 836	int ret;
 837
 838	vc4 = vc5_mock_device(test);
 839	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
 840
 841	drm_modeset_acquire_init(&ctx, 0);
 842
 843	drm = &vc4->base;
 844retry_first:
 845	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
 846	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
 847
 848	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
 849	if (ret == -EDEADLK) {
 850		drm_atomic_state_clear(state);
 851		ret = drm_modeset_backoff(&ctx);
 852		if (!ret)
 853			goto retry_first;
 854	}
 855	KUNIT_ASSERT_EQ(test, ret, 0);
 856
 857	ret = drm_atomic_check_only(state);
 858	if (ret == -EDEADLK) {
 859		drm_atomic_state_clear(state);
 860		ret = drm_modeset_backoff(&ctx);
 861		if (!ret)
 862			goto retry_first;
 863	}
 864	KUNIT_ASSERT_EQ(test, ret, 0);
 865
 866	new_hvs_state = vc4_hvs_get_new_global_state(state);
 867	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
 868
 869	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
 870							    VC4_ENCODER_TYPE_HDMI0);
 871	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
 872
 873	hdmi0_channel = new_vc4_crtc_state->assigned_channel;
 874	KUNIT_ASSERT_NE(test, hdmi0_channel, VC4_HVS_CHANNEL_DISABLED);
 875	KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi0_channel].in_use);
 876
 877	ret = drm_atomic_helper_swap_state(state, false);
 878	KUNIT_ASSERT_EQ(test, ret, 0);
 879
 880retry_second:
 881	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
 882	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
 883
 884	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
 885	if (ret == -EDEADLK) {
 886		drm_atomic_state_clear(state);
 887		ret = drm_modeset_backoff(&ctx);
 888		if (!ret)
 889			goto retry_second;
 890	}
 891	KUNIT_ASSERT_EQ(test, ret, 0);
 892
 893	ret = drm_atomic_check_only(state);
 894	if (ret == -EDEADLK) {
 895		drm_atomic_state_clear(state);
 896		ret = drm_modeset_backoff(&ctx);
 897		if (!ret)
 898			goto retry_second;
 899	}
 900	KUNIT_ASSERT_EQ(test, ret, 0);
 901
 902	new_hvs_state = vc4_hvs_get_new_global_state(state);
 903	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
 904
 905	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
 906							    VC4_ENCODER_TYPE_HDMI1);
 907	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
 908
 909	hdmi1_channel = new_vc4_crtc_state->assigned_channel;
 910	KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
 911	KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use);
 912
 913	KUNIT_EXPECT_NE(test, hdmi0_channel, hdmi1_channel);
 914
 915	drm_modeset_drop_locks(&ctx);
 916	drm_modeset_acquire_fini(&ctx);
 917}
 918
 919/*
 920 * This test makes sure that we never change the FIFO of an active HVS
 921 * channel if we disable a FIFO with a lower index.
 922 *
 923 * Doing so would result in a FIFO stall and would disrupt an output
 924 * supposed to be unaffected by the commit.
 925 */
 926static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test)
 927{
 928	struct drm_modeset_acquire_ctx ctx;
 929	struct drm_atomic_state *state;
 930	struct vc4_crtc_state *new_vc4_crtc_state;
 931	struct vc4_hvs_state *new_hvs_state;
 932	unsigned int old_hdmi0_channel;
 933	unsigned int old_hdmi1_channel;
 934	struct drm_device *drm;
 935	struct vc4_dev *vc4;
 936	int ret;
 937
 938	vc4 = vc5_mock_device(test);
 939	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
 940
 941	drm_modeset_acquire_init(&ctx, 0);
 942
 943	drm = &vc4->base;
 944retry_first:
 945	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
 946	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
 947
 948	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
 949	if (ret == -EDEADLK) {
 950		drm_atomic_state_clear(state);
 951		ret = drm_modeset_backoff(&ctx);
 952		if (!ret)
 953			goto retry_first;
 954	}
 955	KUNIT_ASSERT_EQ(test, ret, 0);
 956
 957	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
 958	if (ret == -EDEADLK) {
 959		drm_atomic_state_clear(state);
 960		ret = drm_modeset_backoff(&ctx);
 961		if (!ret)
 962			goto retry_first;
 963	}
 964	KUNIT_ASSERT_EQ(test, ret, 0);
 965
 966	ret = drm_atomic_check_only(state);
 967	if (ret == -EDEADLK) {
 968		drm_atomic_state_clear(state);
 969		ret = drm_modeset_backoff(&ctx);
 970		if (!ret)
 971			goto retry_first;
 972	}
 973	KUNIT_ASSERT_EQ(test, ret, 0);
 974
 975	new_hvs_state = vc4_hvs_get_new_global_state(state);
 976	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
 977
 978	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
 979							    VC4_ENCODER_TYPE_HDMI0);
 980	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
 981
 982	old_hdmi0_channel = new_vc4_crtc_state->assigned_channel;
 983	KUNIT_ASSERT_NE(test, old_hdmi0_channel, VC4_HVS_CHANNEL_DISABLED);
 984	KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi0_channel].in_use);
 985
 986	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
 987							    VC4_ENCODER_TYPE_HDMI1);
 988	KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
 989
 990	old_hdmi1_channel = new_vc4_crtc_state->assigned_channel;
 991	KUNIT_ASSERT_NE(test, old_hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
 992	KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi1_channel].in_use);
 993
 994	ret = drm_atomic_helper_swap_state(state, false);
 995	KUNIT_ASSERT_EQ(test, ret, 0);
 996
 997retry_second:
 998	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
 999	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1000
1001	ret = vc4_mock_atomic_del_output(test, state, VC4_ENCODER_TYPE_HDMI0);
1002	if (ret == -EDEADLK) {
1003		drm_atomic_state_clear(state);
1004		ret = drm_modeset_backoff(&ctx);
1005		if (!ret)
1006			goto retry_second;
1007	}
1008	KUNIT_ASSERT_EQ(test, ret, 0);
1009
1010	ret = drm_atomic_check_only(state);
1011	if (ret == -EDEADLK) {
1012		drm_atomic_state_clear(state);
1013		ret = drm_modeset_backoff(&ctx);
1014		if (!ret)
1015			goto retry_second;
1016	}
1017	KUNIT_ASSERT_EQ(test, ret, 0);
1018
1019	new_hvs_state = vc4_hvs_get_new_global_state(state);
1020	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
1021
1022	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
1023							    VC4_ENCODER_TYPE_HDMI1);
1024
1025	if (new_vc4_crtc_state) {
1026		unsigned int hdmi1_channel;
1027
1028		hdmi1_channel = new_vc4_crtc_state->assigned_channel;
1029		KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
1030		KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use);
1031
1032		KUNIT_EXPECT_EQ(test, old_hdmi1_channel, hdmi1_channel);
1033	}
1034
1035	drm_modeset_drop_locks(&ctx);
1036	drm_modeset_acquire_fini(&ctx);
1037}
1038
1039/*
1040 * Test that if we affect a single output, only the CRTC state of that
1041 * output will be pulled in the global atomic state.
1042 *
1043 * This is relevant for two things:
1044 *
1045 *   - If we don't have that state at all, we are unlikely to affect the
1046 *     FIFO muxing. This is somewhat redundant with
1047 *     drm_test_vc5_pv_muxing_bugs_stable_fifo()
1048 *
1049 *   - KMS waits for page flips to occur on all the CRTC found in the
1050 *     CRTC state. Since the CRTC is unaffected, we would over-wait, but
1051 *     most importantly run into corner cases like waiting on an
1052 *     inactive CRTC that never completes.
1053 */
1054static void
1055drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state(struct kunit *test)
1056{
1057	struct drm_modeset_acquire_ctx ctx;
1058	struct drm_atomic_state *state;
1059	struct vc4_crtc_state *new_vc4_crtc_state;
1060	struct drm_device *drm;
1061	struct vc4_dev *vc4;
1062	int ret;
1063
1064	vc4 = vc5_mock_device(test);
1065	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
1066
1067	drm_modeset_acquire_init(&ctx, 0);
1068
1069	drm = &vc4->base;
1070retry_first:
1071	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
1072	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1073
1074	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
1075	if (ret == -EDEADLK) {
1076		drm_atomic_state_clear(state);
1077		ret = drm_modeset_backoff(&ctx);
1078		if (!ret)
1079			goto retry_first;
1080	}
1081	KUNIT_ASSERT_EQ(test, ret, 0);
1082
1083	ret = drm_atomic_check_only(state);
1084	if (ret == -EDEADLK) {
1085		drm_atomic_state_clear(state);
1086		ret = drm_modeset_backoff(&ctx);
1087		if (!ret)
1088			goto retry_first;
1089	}
1090	KUNIT_ASSERT_EQ(test, ret, 0);
1091	ret = drm_atomic_helper_swap_state(state, false);
1092	KUNIT_ASSERT_EQ(test, ret, 0);
1093
1094retry_second:
1095	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
1096	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1097
1098	ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
1099	if (ret == -EDEADLK) {
1100		drm_atomic_state_clear(state);
1101		ret = drm_modeset_backoff(&ctx);
1102		if (!ret)
1103			goto retry_second;
1104	}
1105	KUNIT_ASSERT_EQ(test, ret, 0);
1106
1107	ret = drm_atomic_check_only(state);
1108	if (ret == -EDEADLK) {
1109		drm_atomic_state_clear(state);
1110		ret = drm_modeset_backoff(&ctx);
1111		if (!ret)
1112			goto retry_second;
1113	}
1114	KUNIT_ASSERT_EQ(test, ret, 0);
1115
1116	new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
1117							    VC4_ENCODER_TYPE_HDMI0);
1118	KUNIT_EXPECT_NULL(test, new_vc4_crtc_state);
1119
1120	drm_modeset_drop_locks(&ctx);
1121	drm_modeset_acquire_fini(&ctx);
1122}
1123
1124static struct kunit_case vc5_pv_muxing_bugs_tests[] = {
1125	KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable),
1126	KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state),
1127	KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_stable_fifo),
1128	{}
1129};
1130
1131static struct kunit_suite vc5_pv_muxing_bugs_test_suite = {
1132	.name = "vc5-pv-muxing-bugs",
1133	.test_cases = vc5_pv_muxing_bugs_tests,
1134};
1135
1136kunit_test_suites(
1137	&vc4_pv_muxing_test_suite,
1138	&vc5_pv_muxing_test_suite,
1139	&vc5_pv_muxing_bugs_test_suite
1140);
~/ Read-only file preview.