Linux Audio

Check our new training course

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