xref: /linux/sound/soc/codecs/cs35l56-shared-test.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // KUnit test for the Cirrus Logic cs35l56-shared module.
4 //
5 // Copyright (C) 2026 Cirrus Logic, Inc. and
6 //                    Cirrus Logic International Semiconductor Ltd.
7 
8 #include <kunit/resource.h>
9 #include <kunit/test.h>
10 #include <kunit/static_stub.h>
11 #include <linux/bitfield.h>
12 #include <linux/bitops.h>
13 #include <linux/device/faux.h>
14 #include <linux/module.h>
15 #include <linux/random.h>
16 #include <linux/regmap.h>
17 #include <linux/seq_buf.h>
18 #include <sound/cs35l56.h>
19 
20 struct cs35l56_shared_test_priv {
21 	struct kunit *test;
22 	struct faux_device *amp_dev;
23 	struct regmap *registers;
24 	struct cs35l56_base *cs35l56_base;
25 	u8 applied_pad_pull_state[CS35L56_MAX_GPIO];
26 };
27 
28 struct cs35l56_shared_test_param {
29 	int spkid_gpios[4];
30 	int spkid_pulls[4];
31 	unsigned long gpio_status;
32 	int spkid;
33 };
34 
35 KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
36 			    struct faux_device *)
37 
38 KUNIT_DEFINE_ACTION_WRAPPER(regmap_exit_wrapper, regmap_exit, struct regmap *)
39 
40 static const struct regmap_config cs35l56_shared_test_mock_registers_regmap = {
41 	.reg_bits = 32,
42 	.val_bits = 32,
43 	.reg_stride = 4,
44 	.max_register = CS35L56_DSP1_PMEM_5114,
45 	.cache_type = REGCACHE_MAPLE,
46 };
47 
48 static const struct regmap_bus cs35l56_shared_test_mock_registers_regmap_bus = {
49 	/* No handlers because it is always in cache-only */
50 };
51 
52 static unsigned int cs35l56_shared_test_read_gpio_status(struct cs35l56_shared_test_priv *priv)
53 {
54 	const struct cs35l56_shared_test_param *param = priv->test->param_value;
55 	unsigned int reg_offs, pad_cfg, val;
56 	unsigned int status = 0;
57 	unsigned int mask = 1;
58 
59 	for (reg_offs = 0; reg_offs < CS35L56_MAX_GPIO * sizeof(u32); reg_offs += sizeof(u32)) {
60 		regmap_read(priv->registers, CS35L56_SYNC_GPIO1_CFG + reg_offs, &pad_cfg);
61 		regmap_read(priv->registers, CS35L56_GPIO1_CTRL1 + reg_offs, &val);
62 
63 		/* Only read a value if set as an input pin and as a GPIO */
64 		val &= (CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_MASK);
65 		if ((pad_cfg & CS35L56_PAD_GPIO_IE) &&
66 		    (val == (CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_GPIO)))
67 			status |= (param->gpio_status & mask);
68 
69 		mask <<= 1;
70 	}
71 
72 	return status;
73 }
74 
75 static int cs35l56_shared_test_updt_gpio_pres(struct cs35l56_shared_test_priv *priv,
76 					      unsigned int reg, unsigned int val)
77 {
78 	int i, ret;
79 
80 	ret = regmap_write(priv->registers, reg, val);
81 	if (ret)
82 		return ret;
83 
84 	if (val & CS35L56_UPDT_GPIO_PRES) {
85 		/* Simulate transferring register state to internal latches */
86 		for (i = 0; i < ARRAY_SIZE(priv->applied_pad_pull_state); i++) {
87 			reg = CS35L56_SYNC_GPIO1_CFG + (i * sizeof(u32));
88 			regmap_read(priv->registers, reg, &val);
89 			val = FIELD_GET(CS35L56_PAD_GPIO_PULL_MASK, val);
90 			priv->applied_pad_pull_state[i] = val;
91 		}
92 	}
93 
94 	return 0;
95 }
96 
97 static int cs35l56_shared_test_reg_read(void *context, unsigned int reg, unsigned int *val)
98 {
99 	struct cs35l56_shared_test_priv *priv = context;
100 
101 	switch (reg) {
102 	case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG:
103 	case CS35L56_GPIO1_CTRL1 ... CS35L56_GPIO13_CTRL1:
104 		return regmap_read(priv->registers, reg, val);
105 	case CS35L56_UPDATE_REGS:
106 		*val = 0;
107 		return 0;
108 	case CS35L56_GPIO_STATUS1:
109 		*val = cs35l56_shared_test_read_gpio_status(priv);
110 		return 0;
111 	default:
112 		kunit_fail_current_test("Bad regmap read address %#x\n", reg);
113 		return -EINVAL;
114 	}
115 }
116 
117 static int cs35l56_shared_test_reg_write(void *context, unsigned int reg, unsigned int val)
118 {
119 	struct cs35l56_shared_test_priv *priv = context;
120 
121 	switch (reg) {
122 	case CS35L56_UPDATE_REGS:
123 		return cs35l56_shared_test_updt_gpio_pres(priv, reg, val);
124 	case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG:
125 	case CS35L56_GPIO1_CTRL1 ... CS35L56_GPIO13_CTRL1:
126 		return regmap_write(priv->registers, reg, val);
127 	default:
128 		kunit_fail_current_test("Bad regmap write address %#x\n", reg);
129 		return -EINVAL;
130 	}
131 }
132 
133 static const struct regmap_bus cs35l56_shared_test_regmap_bus = {
134 	.reg_read = cs35l56_shared_test_reg_read,
135 	.reg_write = cs35l56_shared_test_reg_write,
136 	.reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
137 	.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
138 };
139 
140 /*
141  * Self-test that the mock GPIO registers obey the configuration bits.
142  * Other tests rely on the mocked registers only returning a GPIO state
143  * if the pin is correctly set as a GPIO input.
144  */
145 static void cs35l56_shared_test_mock_gpio_status_selftest(struct kunit *test)
146 {
147 	const struct cs35l56_shared_test_param *param = test->param_value;
148 	struct cs35l56_shared_test_priv *priv = test->priv;
149 	struct cs35l56_base *cs35l56_base = priv->cs35l56_base;
150 	unsigned int reg, val;
151 
152 	KUNIT_ASSERT_NOT_NULL(test, param);
153 
154 	/* Set all pins non-GPIO and output. Mock GPIO_STATUS should read 0 */
155 	for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32))
156 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0));
157 
158 	/* Set all pads as inputs */
159 	for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32))
160 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_PAD_GPIO_IE));
161 
162 	KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val));
163 	KUNIT_EXPECT_EQ(test, val, 0);
164 
165 	/* Set all pins as GPIO outputs. Mock GPIO_STATUS should read 0 */
166 	for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32))
167 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_GPIO_FN_GPIO));
168 
169 	KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val));
170 	KUNIT_EXPECT_EQ(test, val, 0);
171 
172 	/* Set all pins as non-GPIO inputs. Mock GPIO_STATUS should read 0 */
173 	for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32))
174 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_GPIO_DIR_MASK));
175 
176 	KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val));
177 	KUNIT_EXPECT_EQ(test, val, 0);
178 
179 	/* Set all pins as GPIO inputs. Mock GPIO_STATUS should match param->gpio_status */
180 	for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32))
181 		KUNIT_ASSERT_EQ(test, 0,
182 				regmap_write(priv->registers, reg,
183 					     CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_GPIO));
184 
185 	KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val));
186 	KUNIT_EXPECT_EQ(test, val, param->gpio_status);
187 
188 	/* Set all pads as outputs. Mock GPIO_STATUS should read 0 */
189 	for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32))
190 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0));
191 
192 	KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val));
193 	KUNIT_EXPECT_EQ(test, val, 0);
194 }
195 
196 /* Test that the listed chip pins are assembled into a speaker ID integer. */
197 static void cs35l56_shared_test_get_onchip_speaker_id(struct kunit *test)
198 {
199 	const struct cs35l56_shared_test_param *param = test->param_value;
200 	struct cs35l56_shared_test_priv *priv = test->priv;
201 	struct cs35l56_base *cs35l56_base = priv->cs35l56_base;
202 	unsigned int i, reg;
203 
204 	/* Set all pins non-GPIO and output */
205 	for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32))
206 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0));
207 
208 	for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32))
209 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0));
210 
211 	/* Init GPIO array */
212 	for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
213 		if (param->spkid_gpios[i] < 0)
214 			break;
215 
216 		cs35l56_base->onchip_spkid_gpios[i] = param->spkid_gpios[i] - 1;
217 		cs35l56_base->num_onchip_spkid_gpios++;
218 	}
219 
220 	cs35l56_base->num_onchip_spkid_pulls = 0;
221 
222 	KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0);
223 	KUNIT_EXPECT_EQ(test, cs35l56_read_onchip_spkid(cs35l56_base), param->spkid);
224 }
225 
226 /* Test that the listed chip pins and the corresponding pads are configured correctly. */
227 static void cs35l56_shared_test_onchip_speaker_id_pad_config(struct kunit *test)
228 {
229 	const struct cs35l56_shared_test_param *param = test->param_value;
230 	struct cs35l56_shared_test_priv *priv = test->priv;
231 	struct cs35l56_base *cs35l56_base = priv->cs35l56_base;
232 	unsigned int i, reg, val;
233 
234 	/* Init values in all pin registers */
235 	for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32))
236 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0));
237 
238 	for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32))
239 		KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0));
240 
241 	/* Init GPIO array */
242 	for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
243 		if (param->spkid_gpios[i] < 0)
244 			break;
245 
246 		cs35l56_base->onchip_spkid_gpios[i] = param->spkid_gpios[i] - 1;
247 		cs35l56_base->num_onchip_spkid_gpios++;
248 	}
249 
250 	/* Init pulls array */
251 	for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) {
252 		if (param->spkid_pulls[i] < 0)
253 			break;
254 
255 		cs35l56_base->onchip_spkid_pulls[i] = param->spkid_pulls[i];
256 		cs35l56_base->num_onchip_spkid_pulls++;
257 	}
258 
259 	KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0);
260 
261 	for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
262 		if (param->spkid_gpios[i] < 0)
263 			break;
264 
265 		/* Pad should be an input */
266 		reg = CS35L56_SYNC_GPIO1_CFG + ((param->spkid_gpios[i] - 1) * sizeof(u32));
267 		KUNIT_EXPECT_EQ(test, regmap_read(priv->registers, reg, &val), 0);
268 		KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_IE, CS35L56_PAD_GPIO_IE);
269 
270 		/* Specified pulls should be set, others should be none */
271 		if (i < cs35l56_base->num_onchip_spkid_pulls) {
272 			KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_PULL_MASK,
273 					FIELD_PREP(CS35L56_PAD_GPIO_PULL_MASK,
274 						   param->spkid_pulls[i]));
275 		} else {
276 			KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_PULL_MASK,
277 					CS35L56_PAD_PULL_NONE);
278 		}
279 
280 		/* Pulls for all specfied GPIOs should have been transferred to AO latch */
281 		if (i < cs35l56_base->num_onchip_spkid_pulls) {
282 			KUNIT_EXPECT_EQ(test,
283 					priv->applied_pad_pull_state[param->spkid_gpios[i] - 1],
284 					param->spkid_pulls[i]);
285 		} else {
286 			KUNIT_EXPECT_EQ(test,
287 					priv->applied_pad_pull_state[param->spkid_gpios[i] - 1],
288 					CS35L56_PAD_PULL_NONE);
289 		}
290 	}
291 }
292 
293 /* Test that the listed chip pins are stashed correctly. */
294 static void cs35l56_shared_test_stash_onchip_spkid_pins(struct kunit *test)
295 {
296 	const struct cs35l56_shared_test_param *param = test->param_value;
297 	struct cs35l56_shared_test_priv *priv = test->priv;
298 	struct cs35l56_base *cs35l56_base = priv->cs35l56_base;
299 	u32 gpios[5], pulls[5];
300 	int i, num_gpios, num_pulls;
301 
302 	static_assert(ARRAY_SIZE(gpios) >= ARRAY_SIZE(param->spkid_gpios));
303 	static_assert(ARRAY_SIZE(pulls) >= ARRAY_SIZE(param->spkid_pulls));
304 
305 	num_gpios = 0;
306 	for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
307 		if (param->spkid_gpios[i] < 0)
308 			break;
309 
310 		gpios[i] = (u32)param->spkid_gpios[i];
311 		num_gpios++;
312 	}
313 
314 	num_pulls = 0;
315 	for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) {
316 		if (param->spkid_pulls[i] < 0)
317 			break;
318 
319 		pulls[i] = (u32)param->spkid_pulls[i];
320 		num_pulls++;
321 	}
322 
323 	cs35l56_base->num_onchip_spkid_gpios = 0;
324 	cs35l56_base->num_onchip_spkid_pulls = 0;
325 
326 	KUNIT_ASSERT_LE(test, num_gpios, ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios));
327 	KUNIT_ASSERT_LE(test, num_pulls, ARRAY_SIZE(cs35l56_base->onchip_spkid_pulls));
328 
329 	KUNIT_EXPECT_EQ(test,
330 			cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base,
331 								  gpios, num_gpios,
332 								  pulls, num_pulls),
333 			0);
334 
335 	KUNIT_EXPECT_EQ(test, cs35l56_base->num_onchip_spkid_gpios, num_gpios);
336 	KUNIT_EXPECT_EQ(test, cs35l56_base->num_onchip_spkid_pulls, num_pulls);
337 
338 	/* GPIO numbers are adjusted from 1-based to 0-based */
339 	for (i = 0; i < num_gpios; i++)
340 		KUNIT_EXPECT_EQ(test, cs35l56_base->onchip_spkid_gpios[i], gpios[i] - 1);
341 
342 	for (i = 0; i < num_pulls; i++)
343 		KUNIT_EXPECT_EQ(test, cs35l56_base->onchip_spkid_pulls[i], pulls[i]);
344 }
345 
346 /* Test that illegal GPIO numbers are rejected. */
347 static void cs35l56_shared_test_stash_onchip_spkid_pins_reject_invalid(struct kunit *test)
348 {
349 	struct cs35l56_shared_test_priv *priv = test->priv;
350 	struct cs35l56_base *cs35l56_base = priv->cs35l56_base;
351 	u32 gpios[8] = { }, pulls[8] = { };
352 
353 	KUNIT_EXPECT_LE(test,
354 			cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base,
355 								  gpios, 1,
356 								  pulls, 0),
357 			0);
358 
359 	switch (cs35l56_base->type) {
360 	case 0x54:
361 	case 0x56:
362 	case 0x57:
363 		gpios[0] = CS35L56_MAX_GPIO + 1;
364 		break;
365 	case 0x63:
366 		gpios[0] = CS35L63_MAX_GPIO + 1;
367 		break;
368 	default:
369 		kunit_fail_current_test("Unsupported type:%#x\n", cs35l56_base->type);
370 		return;
371 	}
372 	KUNIT_EXPECT_LE(test,
373 			cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base,
374 								  gpios, 1,
375 								  pulls, 0),
376 			0);
377 
378 	gpios[0] = 1;
379 	pulls[0] = 3;
380 	KUNIT_EXPECT_LE(test,
381 			cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base,
382 								  gpios, 1,
383 								  pulls, 1),
384 			0);
385 
386 	static_assert(ARRAY_SIZE(gpios) > ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios));
387 	static_assert(ARRAY_SIZE(pulls) > ARRAY_SIZE(cs35l56_base->onchip_spkid_pulls));
388 	KUNIT_EXPECT_EQ(test,
389 			cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base,
390 								  gpios, ARRAY_SIZE(gpios),
391 								  pulls, 0),
392 			-EOVERFLOW);
393 	KUNIT_EXPECT_EQ(test,
394 			cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base,
395 								  gpios, 1,
396 								  pulls, ARRAY_SIZE(pulls)),
397 			-EOVERFLOW);
398 }
399 
400 static void cs35l56_shared_test_onchip_speaker_id_not_defined(struct kunit *test)
401 {
402 	struct cs35l56_shared_test_priv *priv = test->priv;
403 	struct cs35l56_base *cs35l56_base = priv->cs35l56_base;
404 
405 	memset(cs35l56_base->onchip_spkid_gpios, 0, sizeof(cs35l56_base->onchip_spkid_gpios));
406 	memset(cs35l56_base->onchip_spkid_pulls, 0, sizeof(cs35l56_base->onchip_spkid_pulls));
407 	cs35l56_base->num_onchip_spkid_gpios = 0;
408 	cs35l56_base->num_onchip_spkid_pulls = 0;
409 	KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0);
410 	KUNIT_EXPECT_EQ(test, cs35l56_read_onchip_spkid(cs35l56_base), -ENOENT);
411 }
412 
413 static int cs35l56_shared_test_case_regmap_init(struct kunit *test,
414 						const struct regmap_config *regmap_config)
415 {
416 	struct cs35l56_shared_test_priv *priv = test->priv;
417 	struct cs35l56_base *cs35l56_base;
418 
419 	/*
420 	 * Create a dummy regmap to simulate a register map by holding the
421 	 * values of all simulated registers in the regmap cache.
422 	 */
423 	priv->registers = regmap_init(&priv->amp_dev->dev,
424 				      &cs35l56_shared_test_mock_registers_regmap_bus,
425 				      priv,
426 				      &cs35l56_shared_test_mock_registers_regmap);
427 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->registers);
428 	KUNIT_ASSERT_EQ(test, 0,
429 			kunit_add_action_or_reset(test, regmap_exit_wrapper,
430 						  priv->registers));
431 	regcache_cache_only(priv->registers, true);
432 
433 	/* Create dummy regmap for cs35l56 driver */
434 	cs35l56_base = priv->cs35l56_base;
435 	cs35l56_base->regmap = regmap_init(cs35l56_base->dev,
436 					   &cs35l56_shared_test_regmap_bus,
437 					   priv,
438 					   regmap_config);
439 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cs35l56_base->regmap);
440 	KUNIT_ASSERT_EQ(test, 0,
441 			kunit_add_action_or_reset(test, regmap_exit_wrapper,
442 						  cs35l56_base->regmap));
443 
444 	return 0;
445 }
446 
447 static int cs35l56_shared_test_case_base_init(struct kunit *test, u8 type, u8 rev,
448 					      const struct regmap_config *regmap_config)
449 {
450 	struct cs35l56_shared_test_priv *priv;
451 	int ret;
452 
453 	KUNIT_ASSERT_NOT_NULL(test, cs_amp_test_hooks);
454 
455 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
456 	if (!priv)
457 		return -ENOMEM;
458 
459 	test->priv = priv;
460 	priv->test = test;
461 
462 	/* Create dummy amp driver dev */
463 	priv->amp_dev = faux_device_create("cs35l56_shared_test_drv", NULL, NULL);
464 	KUNIT_ASSERT_NOT_NULL(test, priv->amp_dev);
465 	KUNIT_ASSERT_EQ(test, 0,
466 			kunit_add_action_or_reset(test,
467 						  faux_device_destroy_wrapper,
468 						  priv->amp_dev));
469 
470 	priv->cs35l56_base = kunit_kzalloc(test, sizeof(*priv->cs35l56_base), GFP_KERNEL);
471 	KUNIT_ASSERT_NOT_NULL(test, priv->cs35l56_base);
472 	priv->cs35l56_base->dev = &priv->amp_dev->dev;
473 	priv->cs35l56_base->type = type;
474 	priv->cs35l56_base->rev = rev;
475 
476 	if (regmap_config) {
477 		ret = cs35l56_shared_test_case_regmap_init(test, regmap_config);
478 		if (ret)
479 			return ret;
480 	}
481 
482 	return 0;
483 }
484 
485 static int cs35l56_shared_test_case_regmap_init_L56_B0_sdw(struct kunit *test)
486 {
487 	return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_sdw);
488 }
489 
490 static int cs35l56_shared_test_case_regmap_init_L56_B0_spi(struct kunit *test)
491 {
492 	return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_spi);
493 }
494 
495 static int cs35l56_shared_test_case_regmap_init_L56_B0_i2c(struct kunit *test)
496 {
497 	return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_i2c);
498 }
499 
500 static int cs35l56_shared_test_case_regmap_init_L56_B2_sdw(struct kunit *test)
501 {
502 	return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_sdw);
503 }
504 
505 static int cs35l56_shared_test_case_regmap_init_L56_B2_spi(struct kunit *test)
506 {
507 	return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_spi);
508 }
509 
510 static int cs35l56_shared_test_case_regmap_init_L56_B2_i2c(struct kunit *test)
511 {
512 	return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_i2c);
513 }
514 
515 static int cs35l56_shared_test_case_regmap_init_L63_A1_sdw(struct kunit *test)
516 {
517 	return cs35l56_shared_test_case_base_init(test, 0x63, 0xa1, &cs35l63_regmap_sdw);
518 }
519 
520 static void cs35l56_shared_test_gpio_param_desc(const struct cs35l56_shared_test_param *param,
521 						char *desc)
522 {
523 	DECLARE_SEQ_BUF(gpios, 1 + (2 * ARRAY_SIZE(param->spkid_gpios)));
524 	DECLARE_SEQ_BUF(pulls, 1 + (2 * ARRAY_SIZE(param->spkid_pulls)));
525 	int i;
526 
527 	for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
528 		if (param->spkid_gpios[i] < 0)
529 			break;
530 
531 		seq_buf_printf(&gpios, "%s%d", (i == 0) ? "" : ",", param->spkid_gpios[i]);
532 	}
533 
534 	for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) {
535 		if (param->spkid_pulls[i] < 0)
536 			break;
537 
538 		seq_buf_printf(&pulls, "%s%d", (i == 0) ? "" : ",", param->spkid_pulls[i]);
539 	}
540 
541 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "gpios:{%s} pulls:{%s} status:%#lx spkid:%d",
542 		 seq_buf_str(&gpios), seq_buf_str(&pulls), param->gpio_status, param->spkid);
543 }
544 
545 static const struct cs35l56_shared_test_param cs35l56_shared_test_gpios_selftest_cases[] = {
546 	{ .spkid_gpios = { -1 }, .gpio_status = GENMASK(12, 0) },
547 };
548 KUNIT_ARRAY_PARAM(cs35l56_shared_test_gpios_selftest,
549 		  cs35l56_shared_test_gpios_selftest_cases,
550 		  cs35l56_shared_test_gpio_param_desc);
551 
552 static const struct cs35l56_shared_test_param cs35l56_shared_test_onchip_spkid_cases[] = {
553 	{ .spkid_gpios = { 1, -1 },	  .gpio_status = 0,			.spkid = 0 },
554 	{ .spkid_gpios = { 1, -1 },	  .gpio_status = ~BIT(0),		.spkid = 0 },
555 	{ .spkid_gpios = { 1, -1 },	  .gpio_status = BIT(0),		.spkid = 1 },
556 
557 	{ .spkid_gpios = { 7, -1 },	  .gpio_status = 0,			.spkid = 0 },
558 	{ .spkid_gpios = { 7, -1 },	  .gpio_status = ~BIT(6),		.spkid = 0 },
559 	{ .spkid_gpios = { 7, -1 },	  .gpio_status = BIT(6),		.spkid = 1 },
560 
561 	{ .spkid_gpios = { 1, 7, -1 },	  .gpio_status = 0,			.spkid = 0 },
562 	{ .spkid_gpios = { 1, 7, -1 },	  .gpio_status = ~(BIT(0) | BIT(6)),	.spkid = 0 },
563 	{ .spkid_gpios = { 1, 7, -1 },	  .gpio_status = BIT(6),		.spkid = 1 },
564 	{ .spkid_gpios = { 1, 7, -1 },	  .gpio_status = BIT(0),		.spkid = 2 },
565 	{ .spkid_gpios = { 1, 7, -1 },	  .gpio_status = BIT(6) | BIT(0),	.spkid = 3 },
566 
567 	{ .spkid_gpios = { 7, 1, -1 },	  .gpio_status = 0,			.spkid = 0 },
568 	{ .spkid_gpios = { 7, 1, -1 },	  .gpio_status = ~(BIT(6) | BIT(0)),	.spkid = 0 },
569 	{ .spkid_gpios = { 7, 1, -1 },	  .gpio_status = BIT(0),		.spkid = 1 },
570 	{ .spkid_gpios = { 7, 1, -1 },	  .gpio_status = BIT(6),		.spkid = 2 },
571 	{ .spkid_gpios = { 7, 1, -1 },	  .gpio_status = BIT(6) | BIT(0),	.spkid = 3 },
572 
573 	{ .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = 0,			   .spkid = 0 },
574 	{ .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(0),		   .spkid = 1 },
575 	{ .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(6),		   .spkid = 2 },
576 	{ .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(6) | BIT(0),	   .spkid = 3 },
577 	{ .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2),		   .spkid = 4 },
578 	{ .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(0),	   .spkid = 5 },
579 	{ .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(6),	   .spkid = 6 },
580 	{ .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(6) | BIT(0), .spkid = 7 },
581 };
582 KUNIT_ARRAY_PARAM(cs35l56_shared_test_onchip_spkid, cs35l56_shared_test_onchip_spkid_cases,
583 		  cs35l56_shared_test_gpio_param_desc);
584 
585 static const struct cs35l56_shared_test_param cs35l56_shared_test_onchip_spkid_pull_cases[] = {
586 	{ .spkid_gpios = { 1, -1 },		.spkid_pulls = { 1, -1 }, },
587 	{ .spkid_gpios = { 1, -1 },		.spkid_pulls = { 2, -1 }, },
588 
589 	{ .spkid_gpios = { 7, -1 },		.spkid_pulls = { 1, -1 }, },
590 	{ .spkid_gpios = { 7, -1 },		.spkid_pulls = { 2, -1 }, },
591 
592 	{ .spkid_gpios = { 1, 7, -1 },		.spkid_pulls = { 1, 1, -1 }, },
593 	{ .spkid_gpios = { 1, 7, -1 },		.spkid_pulls = { 2, 2, -1 }, },
594 
595 	{ .spkid_gpios = { 7, 1, -1 },		.spkid_pulls = { 1, 1, -1 }, },
596 	{ .spkid_gpios = { 7, 1, -1 },		.spkid_pulls = { 2, 2, -1 }, },
597 
598 	{ .spkid_gpios = { 3, 7, 1, -1 },	.spkid_pulls = { 1, 1, 1, -1 }, },
599 	{ .spkid_gpios = { 3, 7, 1, -1 },	.spkid_pulls = { 2, 2, 2, -1 }, },
600 };
601 KUNIT_ARRAY_PARAM(cs35l56_shared_test_onchip_spkid_pull,
602 		  cs35l56_shared_test_onchip_spkid_pull_cases,
603 		  cs35l56_shared_test_gpio_param_desc);
604 
605 static struct kunit_case cs35l56_shared_test_cases[] = {
606 	/* Tests for speaker id */
607 	KUNIT_CASE_PARAM(cs35l56_shared_test_mock_gpio_status_selftest,
608 			 cs35l56_shared_test_gpios_selftest_gen_params),
609 	KUNIT_CASE_PARAM(cs35l56_shared_test_get_onchip_speaker_id,
610 			 cs35l56_shared_test_onchip_spkid_gen_params),
611 	KUNIT_CASE_PARAM(cs35l56_shared_test_onchip_speaker_id_pad_config,
612 			 cs35l56_shared_test_onchip_spkid_gen_params),
613 	KUNIT_CASE_PARAM(cs35l56_shared_test_onchip_speaker_id_pad_config,
614 			 cs35l56_shared_test_onchip_spkid_pull_gen_params),
615 	KUNIT_CASE_PARAM(cs35l56_shared_test_stash_onchip_spkid_pins,
616 			 cs35l56_shared_test_onchip_spkid_pull_gen_params),
617 	KUNIT_CASE(cs35l56_shared_test_stash_onchip_spkid_pins_reject_invalid),
618 	KUNIT_CASE(cs35l56_shared_test_onchip_speaker_id_not_defined),
619 	{ }
620 };
621 
622 static struct kunit_suite cs35l56_shared_test_suite_L56_B0_sdw = {
623 	.name = "snd-soc-cs35l56-shared-test_L56_B0_sdw",
624 	.init = cs35l56_shared_test_case_regmap_init_L56_B0_sdw,
625 	.test_cases = cs35l56_shared_test_cases,
626 };
627 
628 static struct kunit_suite cs35l56_shared_test_suite_L56_B2_sdw = {
629 	.name = "snd-soc-cs35l56-shared-test_L56_B2_sdw",
630 	.init = cs35l56_shared_test_case_regmap_init_L56_B2_sdw,
631 	.test_cases = cs35l56_shared_test_cases,
632 };
633 
634 static struct kunit_suite cs35l56_shared_test_suite_L63_A1_sdw = {
635 	.name = "snd-soc-cs35l56-shared-test_L63_A1_sdw",
636 	.init = cs35l56_shared_test_case_regmap_init_L63_A1_sdw,
637 	.test_cases = cs35l56_shared_test_cases,
638 };
639 
640 static struct kunit_suite cs35l56_shared_test_suite_L56_B0_spi = {
641 	.name = "snd-soc-cs35l56-shared-test_L56_B0_spi",
642 	.init = cs35l56_shared_test_case_regmap_init_L56_B0_spi,
643 	.test_cases = cs35l56_shared_test_cases,
644 };
645 
646 static struct kunit_suite cs35l56_shared_test_suite_L56_B2_spi = {
647 	.name = "snd-soc-cs35l56-shared-test_L56_B2_spi",
648 	.init = cs35l56_shared_test_case_regmap_init_L56_B2_spi,
649 	.test_cases = cs35l56_shared_test_cases,
650 };
651 
652 static struct kunit_suite cs35l56_shared_test_suite_L56_B0_i2c = {
653 	.name = "snd-soc-cs35l56-shared-test_L56_B0_i2c",
654 	.init = cs35l56_shared_test_case_regmap_init_L56_B0_i2c,
655 	.test_cases = cs35l56_shared_test_cases,
656 };
657 
658 static struct kunit_suite cs35l56_shared_test_suite_L56_B2_i2c = {
659 	.name = "snd-soc-cs35l56-shared-test_L56_B2_i2c",
660 	.init = cs35l56_shared_test_case_regmap_init_L56_B2_i2c,
661 	.test_cases = cs35l56_shared_test_cases,
662 };
663 
664 kunit_test_suites(
665 	&cs35l56_shared_test_suite_L56_B0_sdw,
666 	&cs35l56_shared_test_suite_L56_B2_sdw,
667 	&cs35l56_shared_test_suite_L63_A1_sdw,
668 
669 	&cs35l56_shared_test_suite_L56_B0_spi,
670 	&cs35l56_shared_test_suite_L56_B2_spi,
671 
672 	&cs35l56_shared_test_suite_L56_B0_i2c,
673 	&cs35l56_shared_test_suite_L56_B2_i2c,
674 );
675 
676 MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
677 MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
678 MODULE_DESCRIPTION("KUnit test for cs35l56-shared module");
679 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
680 MODULE_LICENSE("GPL");
681