xref: /linux/sound/soc/codecs/cs35l56-test.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // KUnit test for the Cirrus Logic cs35l56 driver.
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/efi.h>
12 #include <linux/device/faux.h>
13 #include <linux/firmware/cirrus/cs_dsp.h>
14 #include <linux/firmware/cirrus/wmfw.h>
15 #include <linux/module.h>
16 #include <linux/overflow.h>
17 #include <linux/pci_ids.h>
18 #include <linux/property.h>
19 #include <linux/seq_buf.h>
20 #include <linux/soundwire/sdw.h>
21 #include <sound/cs35l56.h>
22 #include <sound/cs-amp-lib.h>
23 #include "cs35l56.h"
24 
25 KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
26 			    struct faux_device *)
27 
28 KUNIT_DEFINE_ACTION_WRAPPER(software_node_unregister_node_group_wrapper,
29 			    software_node_unregister_node_group,
30 			    const struct software_node * const *)
31 
32 KUNIT_DEFINE_ACTION_WRAPPER(software_node_unregister_wrapper,
33 			    software_node_unregister,
34 			    const struct software_node *)
35 
36 KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper,
37 			    device_remove_software_node,
38 			    struct device *)
39 
40 struct cs35l56_test_priv {
41 	struct faux_device *amp_dev;
42 	struct cs35l56_private *cs35l56_priv;
43 
44 	const char *ssidexv2;
45 
46 	bool read_onchip_spkid_called;
47 	bool configure_onchip_spkid_pads_called;
48 };
49 
50 struct cs35l56_test_param {
51 	u8 type;
52 	u8 rev;
53 
54 	s32 spkid_gpios[4];
55 	s32 spkid_pulls[4];
56 };
57 
58 static const struct software_node cs35l56_test_dev_sw_node =
59 	SOFTWARE_NODE("SWD1", NULL, NULL);
60 
61 static const struct software_node cs35l56_test_af01_sw_node =
62 	SOFTWARE_NODE("AF01", NULL, &cs35l56_test_dev_sw_node);
63 
64 static const struct software_node *cs35l56_test_dev_and_af01_node_group[] = {
65 	&cs35l56_test_dev_sw_node,
66 	&cs35l56_test_af01_sw_node,
67 	NULL
68 };
69 
70 static const char *cs35l56_test_devm_get_vendor_specific_variant_id_none(struct device *dev,
71 									 int ssid_vendor,
72 									 int ssid_device)
73 {
74 	return ERR_PTR(-ENOENT);
75 }
76 
77 static void cs35l56_test_l56_b0_suffix_sdw(struct kunit *test)
78 {
79 	struct cs35l56_test_priv *priv = test->priv;
80 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
81 
82 	/* Set device type info */
83 	cs35l56->base.type = 0x56;
84 	cs35l56->base.rev = 0xb0;
85 
86 	/* Set the ALSA name prefix */
87 	cs35l56->component->name_prefix = "AMP1";
88 
89 	/* Set SoundWire link and UID number */
90 	cs35l56->sdw_link_num = 1;
91 	cs35l56->sdw_unique_id = 5;
92 
93 	kunit_activate_static_stub(test,
94 				   cs35l56_test_devm_get_vendor_specific_variant_id_none,
95 				   cs_amp_devm_get_vendor_specific_variant_id);
96 
97 	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
98 
99 	/* Priority suffix should be the legacy ALSA prefix */
100 	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "AMP1");
101 
102 	/* Fallback suffix should be the new SoundWire ID */
103 	KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
104 }
105 
106 static void cs35l56_test_suffix_sdw(struct kunit *test)
107 {
108 	struct cs35l56_test_priv *priv = test->priv;
109 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
110 
111 	/* Set the ALSA name prefix */
112 	cs35l56->component->name_prefix = "AMP1";
113 
114 	/* Set SoundWire link and UID number */
115 	cs35l56->sdw_link_num = 1;
116 	cs35l56->sdw_unique_id = 5;
117 
118 	kunit_activate_static_stub(test,
119 				   cs35l56_test_devm_get_vendor_specific_variant_id_none,
120 				   cs_amp_devm_get_vendor_specific_variant_id);
121 
122 	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
123 
124 	/* Suffix should be the SoundWire ID without a fallback */
125 	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "l1u5");
126 	KUNIT_EXPECT_NULL(test, cs35l56->fallback_fw_suffix);
127 }
128 
129 static void cs35l56_test_suffix_i2cspi(struct kunit *test)
130 {
131 	struct cs35l56_test_priv *priv = test->priv;
132 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
133 
134 	/* Set the ALSA name prefix */
135 	cs35l56->component->name_prefix = "AMP1";
136 
137 	kunit_activate_static_stub(test,
138 				   cs35l56_test_devm_get_vendor_specific_variant_id_none,
139 				   cs_amp_devm_get_vendor_specific_variant_id);
140 
141 	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
142 
143 	/* Suffix strings should not be set: use default wm_adsp suffixing */
144 	KUNIT_EXPECT_NULL(test, cs35l56->dsp.fwf_suffix);
145 	KUNIT_EXPECT_NULL(test, cs35l56->fallback_fw_suffix);
146 }
147 
148 static efi_status_t cs35l56_test_get_efi_ssidexv2(efi_char16_t *name,
149 						  efi_guid_t *guid,
150 						  u32 *returned_attr,
151 						  unsigned long *size,
152 						  void *buf)
153 {
154 	struct kunit *test = kunit_get_current_test();
155 	struct cs35l56_test_priv *priv = test->priv;
156 	unsigned int len;
157 
158 	KUNIT_ASSERT_NOT_NULL(test, priv->ssidexv2);
159 	len = strlen(priv->ssidexv2);
160 
161 	if (*size < len) {
162 		*size = len;
163 		return EFI_BUFFER_TOO_SMALL;
164 	}
165 
166 	KUNIT_ASSERT_NOT_NULL(test, buf);
167 	memcpy(buf, priv->ssidexv2, len);
168 
169 	return EFI_SUCCESS;
170 }
171 
172 static void cs35l56_test_ssidexv2_suffix_sdw(struct kunit *test)
173 {
174 	struct cs35l56_test_priv *priv = test->priv;
175 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
176 
177 	/* Set the ALSA name prefix */
178 	cs35l56->component->name_prefix = "AMP1";
179 
180 	/* Set SoundWire link and UID number */
181 	cs35l56->sdw_link_num = 1;
182 	cs35l56->sdw_unique_id = 5;
183 
184 	/* Set a SSID to enable lookup of SSIDExV2 */
185 	snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
186 
187 	priv->ssidexv2 = "10281234_01_BB_CC";
188 
189 	kunit_activate_static_stub(test,
190 				   cs_amp_test_hooks->get_efi_variable,
191 				   cs35l56_test_get_efi_ssidexv2);
192 
193 	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
194 
195 	/* Priority suffix should be the SSIDExV2 string with SoundWire ID */
196 	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "01-l1u5");
197 
198 	/* Fallback suffix should be the SoundWireID */
199 	KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
200 }
201 
202 static void cs35l56_test_ssidexv2_suffix_i2cspi(struct kunit *test)
203 {
204 	struct cs35l56_test_priv *priv = test->priv;
205 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
206 
207 	/* Set the ALSA name prefix */
208 	cs35l56->component->name_prefix = "AMP1";
209 
210 	/* Set a SSID to enable lookup of SSIDExV2 */
211 	snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
212 
213 	priv->ssidexv2 = "10281234_01_BB_CC";
214 
215 	kunit_activate_static_stub(test,
216 				   cs_amp_test_hooks->get_efi_variable,
217 				   cs35l56_test_get_efi_ssidexv2);
218 
219 	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
220 
221 	/* Priority suffix should be the SSIDExV2 string with ALSA name prefix */
222 	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "01-AMP1");
223 
224 	/* Fallback suffix should be the ALSA name prefix */
225 	KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "AMP1");
226 }
227 
228 /*
229  * CS35L56 B0 SoundWire should ignore any SSIDExV2 suffix. It isn't needed
230  * on any products with B0 silicon and would interfere with the fallback
231  * to legacy naming convention for early B0-based laptops.
232  */
233 static void cs35l56_test_l56_b0_ssidexv2_ignored_suffix_sdw(struct kunit *test)
234 {
235 	struct cs35l56_test_priv *priv = test->priv;
236 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
237 
238 	/* Set device type info */
239 	cs35l56->base.type = 0x56;
240 	cs35l56->base.rev = 0xb0;
241 
242 	/* Set the ALSA name prefix */
243 	cs35l56->component->name_prefix = "AMP1";
244 
245 	/* Set SoundWire link and UID number */
246 	cs35l56->sdw_link_num = 1;
247 	cs35l56->sdw_unique_id = 5;
248 
249 	/* Set a SSID to enable lookup of SSIDExV2 */
250 	snd_soc_card_set_pci_ssid(cs35l56->component->card, PCI_VENDOR_ID_DELL, 0x1234);
251 
252 	priv->ssidexv2 = "10281234_01_BB_CC";
253 
254 	kunit_activate_static_stub(test,
255 				   cs_amp_test_hooks->get_efi_variable,
256 				   cs35l56_test_get_efi_ssidexv2);
257 
258 	KUNIT_EXPECT_EQ(test, 0, cs35l56_set_fw_suffix(cs35l56));
259 
260 	/* Priority suffix should be the legacy ALSA prefix */
261 	KUNIT_EXPECT_STREQ(test, cs35l56->dsp.fwf_suffix, "AMP1");
262 
263 	/* Fallback suffix should be the new SoundWire ID */
264 	KUNIT_EXPECT_STREQ(test, cs35l56->fallback_fw_suffix, "l1u5");
265 }
266 
267 /*
268  * Test that cs35l56_process_xu_properties() correctly parses the GPIO and
269  * pull values from properties into the arrays in struct cs35l56_base.
270  *
271  * This test creates the node tree:
272  *
273  * Node("SWD1") { // top-level device node
274  *	Node("AF01") {
275  *		Node("mipi-sdca-function-expansion-subproperties") {
276  *			property: "01fa-spk-id-gpios-onchip"
277  *			property: 01fa-spk-id-gpios-onchip-pull
278  *		}
279  *	}
280  * }
281  *
282  * Note that in ACPI "mipi-sdca-function-expansion-subproperties" is
283  * a special _DSD property that points to a Device(EXT0) node but behaves
284  * as an alias of the EXT0 node. The equivalent in software nodes is to
285  * create a Node named "mipi-sdca-function-expansion-subproperties" with
286  * the properties.
287  *
288  */
289 static void cs35l56_test_parse_xu_onchip_spkid(struct kunit *test)
290 {
291 	const struct cs35l56_test_param *param = test->param_value;
292 	struct cs35l56_test_priv *priv = test->priv;
293 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
294 	struct software_node *ext0_node;
295 	int num_gpios = 0;
296 	int num_pulls = 0;
297 	int i;
298 
299 	for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++, num_gpios++) {
300 		if (param->spkid_gpios[i] < 0)
301 			break;
302 	}
303 	KUNIT_ASSERT_LE(test, num_gpios, ARRAY_SIZE(cs35l56->base.onchip_spkid_gpios));
304 
305 	for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++, num_pulls++) {
306 		if (param->spkid_pulls[i] < 0)
307 			break;
308 	}
309 	KUNIT_ASSERT_LE(test, num_pulls, ARRAY_SIZE(cs35l56->base.onchip_spkid_pulls));
310 
311 	const struct property_entry ext0_props[] = {
312 		PROPERTY_ENTRY_U32_ARRAY_LEN("01fa-spk-id-gpios-onchip",
313 					     param->spkid_gpios, num_gpios),
314 		PROPERTY_ENTRY_U32_ARRAY_LEN("01fa-spk-id-gpios-onchip-pull",
315 					     param->spkid_pulls, num_pulls),
316 		{ }
317 	};
318 
319 	KUNIT_ASSERT_EQ(test,
320 			software_node_register_node_group(cs35l56_test_dev_and_af01_node_group),
321 			0);
322 	KUNIT_ASSERT_EQ(test,
323 			kunit_add_action_or_reset(test,
324 						  software_node_unregister_node_group_wrapper,
325 						  cs35l56_test_dev_and_af01_node_group),
326 			0);
327 
328 	ext0_node = kunit_kzalloc(test, sizeof(*ext0_node), GFP_KERNEL);
329 	KUNIT_ASSERT_NOT_NULL(test, ext0_node);
330 	*ext0_node = SOFTWARE_NODE("mipi-sdca-function-expansion-subproperties",
331 				    ext0_props, &cs35l56_test_af01_sw_node);
332 
333 	KUNIT_ASSERT_EQ(test, software_node_register(ext0_node), 0);
334 	KUNIT_ASSERT_EQ(test,
335 			kunit_add_action_or_reset(test,
336 						  software_node_unregister_wrapper,
337 						  ext0_node),
338 			0);
339 
340 	KUNIT_ASSERT_EQ(test,
341 			device_add_software_node(cs35l56->base.dev, &cs35l56_test_dev_sw_node), 0);
342 	KUNIT_ASSERT_EQ(test, 0,
343 			kunit_add_action_or_reset(test,
344 						  device_remove_software_node_wrapper,
345 						  cs35l56->base.dev));
346 
347 	KUNIT_EXPECT_EQ(test, cs35l56_process_xu_properties(cs35l56), 0);
348 
349 	KUNIT_EXPECT_EQ(test, cs35l56->base.num_onchip_spkid_gpios, num_gpios);
350 	KUNIT_EXPECT_EQ(test, cs35l56->base.num_onchip_spkid_pulls, num_pulls);
351 
352 	for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
353 		if (param->spkid_gpios[i] < 0)
354 			break;
355 
356 		/*
357 		 * cs35l56_process_xu_properties() stores the GPIO numbers
358 		 * zero-based, which is one less than the value in the property.
359 		 */
360 		KUNIT_EXPECT_EQ_MSG(test, cs35l56->base.onchip_spkid_gpios[i],
361 				    param->spkid_gpios[i] - 1,
362 				    "i=%d", i);
363 	}
364 
365 	for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) {
366 		if (param->spkid_pulls[i] < 0)
367 			break;
368 
369 		KUNIT_EXPECT_EQ_MSG(test, cs35l56->base.onchip_spkid_pulls[i],
370 				    param->spkid_pulls[i], "i=%d", i);
371 	}
372 }
373 
374 static int cs35l56_test_dummy_read_onchip_spkid(struct cs35l56_base *cs35l56_base)
375 {
376 	struct kunit *test = kunit_get_current_test();
377 	struct cs35l56_test_priv *priv = test->priv;
378 
379 	priv->read_onchip_spkid_called = true;
380 
381 	return 4;
382 }
383 
384 static int cs35l56_test_dummy_configure_onchip_spkid_pads(struct cs35l56_base *cs35l56_base)
385 {
386 	struct kunit *test = kunit_get_current_test();
387 	struct cs35l56_test_priv *priv = test->priv;
388 
389 	priv->configure_onchip_spkid_pads_called = true;
390 
391 	return 0;
392 }
393 
394 static void cs35l56_test_set_fw_name_reads_onchip_spkid(struct kunit *test)
395 {
396 	struct cs35l56_test_priv *priv = test->priv;
397 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
398 
399 	/* Provide some on-chip GPIOs for spkid */
400 	cs35l56->base.onchip_spkid_gpios[0] = 1;
401 	cs35l56->base.num_onchip_spkid_gpios = 1;
402 
403 	cs35l56->speaker_id = -ENOENT;
404 
405 	kunit_activate_static_stub(test,
406 				   cs35l56_configure_onchip_spkid_pads,
407 				   cs35l56_test_dummy_configure_onchip_spkid_pads);
408 	kunit_activate_static_stub(test,
409 				   cs35l56_read_onchip_spkid,
410 				   cs35l56_test_dummy_read_onchip_spkid);
411 
412 	priv->configure_onchip_spkid_pads_called = false;
413 	priv->read_onchip_spkid_called = false;
414 	KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
415 	KUNIT_EXPECT_TRUE(test, priv->configure_onchip_spkid_pads_called);
416 	KUNIT_EXPECT_TRUE(test, priv->read_onchip_spkid_called);
417 	KUNIT_EXPECT_EQ(test, cs35l56->speaker_id,
418 			cs35l56_test_dummy_read_onchip_spkid(&cs35l56->base));
419 }
420 
421 static void cs35l56_test_set_fw_name_preserves_spkid_with_onchip_gpios(struct kunit *test)
422 {
423 	struct cs35l56_test_priv *priv = test->priv;
424 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
425 
426 	/* Provide some on-chip GPIOs for spkid */
427 	cs35l56->base.onchip_spkid_gpios[0] = 1;
428 	cs35l56->base.num_onchip_spkid_gpios = 1;
429 
430 	/* Simulate that the driver already got a spkid from somewhere */
431 	cs35l56->speaker_id = 15;
432 
433 	KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
434 	KUNIT_EXPECT_EQ(test, cs35l56->speaker_id, 15);
435 }
436 
437 static void cs35l56_test_set_fw_name_preserves_spkid_without_onchip_gpios(struct kunit *test)
438 {
439 	struct cs35l56_test_priv *priv = test->priv;
440 	struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
441 
442 	cs35l56->base.num_onchip_spkid_gpios = 0;
443 
444 	/* Simulate that the driver already got a spkid from somewhere */
445 	cs35l56->speaker_id = 15;
446 
447 	KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
448 	KUNIT_EXPECT_EQ(test, cs35l56->speaker_id, 15);
449 }
450 
451 static int cs35l56_test_case_init_common(struct kunit *test)
452 {
453 	struct cs35l56_test_priv *priv;
454 	const struct cs35l56_test_param *param = test->param_value;
455 	struct cs35l56_private *cs35l56;
456 
457 	KUNIT_ASSERT_NOT_NULL(test, cs_amp_test_hooks);
458 
459 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
460 	if (!priv)
461 		return -ENOMEM;
462 
463 	test->priv = priv;
464 
465 	/* Create dummy amp driver dev */
466 	priv->amp_dev = faux_device_create("cs35l56_test_drv", NULL, NULL);
467 	KUNIT_ASSERT_NOT_NULL(test, priv->amp_dev);
468 	KUNIT_ASSERT_EQ(test, 0,
469 			kunit_add_action_or_reset(test,
470 						  faux_device_destroy_wrapper,
471 						  priv->amp_dev));
472 
473 	/* Construct minimal set of driver structs */
474 	priv->cs35l56_priv = kunit_kzalloc(test, sizeof(*priv->cs35l56_priv), GFP_KERNEL);
475 	KUNIT_ASSERT_NOT_NULL(test, priv->cs35l56_priv);
476 	cs35l56 = priv->cs35l56_priv;
477 	cs35l56->base.dev = &priv->amp_dev->dev;
478 
479 	cs35l56->component = kunit_kzalloc(test, sizeof(*cs35l56->component), GFP_KERNEL);
480 	KUNIT_ASSERT_NOT_NULL(test, cs35l56->component);
481 	cs35l56->component->dev = cs35l56->base.dev;
482 	snd_soc_component_set_drvdata(cs35l56->component, cs35l56);
483 
484 	cs35l56->component->card = kunit_kzalloc(test, sizeof(*cs35l56->component->card),
485 						 GFP_KERNEL);
486 	KUNIT_ASSERT_NOT_NULL(test, cs35l56->component->card);
487 
488 	if (param) {
489 		cs35l56->base.type = param->type;
490 		cs35l56->base.rev = param->rev;
491 	}
492 
493 	return 0;
494 }
495 
496 static int cs35l56_test_case_init_soundwire(struct kunit *test)
497 {
498 	struct cs35l56_test_priv *priv;
499 	struct cs35l56_private *cs35l56;
500 	int ret;
501 
502 	ret = cs35l56_test_case_init_common(test);
503 	if (ret)
504 		return ret;
505 
506 	priv = test->priv;
507 	cs35l56 = priv->cs35l56_priv;
508 
509 	/* Dummy to indicate this is Soundwire */
510 	cs35l56->sdw_peripheral = kunit_kzalloc(test, sizeof(*cs35l56->sdw_peripheral),
511 						GFP_KERNEL);
512 	if (!cs35l56->sdw_peripheral)
513 		return -ENOMEM;
514 
515 
516 	return 0;
517 }
518 
519 static void cs35l56_test_gpio_param_desc(const struct cs35l56_test_param *param, char *desc)
520 {
521 	DECLARE_SEQ_BUF(gpios, 1 + (2 * ARRAY_SIZE(param->spkid_gpios)));
522 	DECLARE_SEQ_BUF(pulls, 1 + (2 * ARRAY_SIZE(param->spkid_pulls)));
523 	int i;
524 
525 	for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) {
526 		if (param->spkid_gpios[i] < 0)
527 			break;
528 
529 		seq_buf_printf(&gpios, "%s%d", (i == 0) ? "" : ",", param->spkid_gpios[i]);
530 	}
531 
532 	for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) {
533 		if (param->spkid_pulls[i] < 0)
534 			break;
535 
536 		seq_buf_printf(&pulls, "%s%d", (i == 0) ? "" : ",", param->spkid_pulls[i]);
537 	}
538 
539 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "gpios:{%s} pulls:{%s}",
540 		 seq_buf_str(&gpios), seq_buf_str(&pulls));
541 }
542 
543 static const struct cs35l56_test_param cs35l56_test_onchip_spkid_cases[] = {
544 	{ .spkid_gpios = { 1, -1 },		.spkid_pulls = { 1, -1 }, },
545 	{ .spkid_gpios = { 1, -1 },		.spkid_pulls = { 2, -1 }, },
546 
547 	{ .spkid_gpios = { 7, -1 },		.spkid_pulls = { 1, -1 }, },
548 	{ .spkid_gpios = { 7, -1 },		.spkid_pulls = { 2, -1 }, },
549 
550 	{ .spkid_gpios = { 1, 7, -1 },		.spkid_pulls = { 1, 1, -1 }, },
551 	{ .spkid_gpios = { 1, 7, -1 },		.spkid_pulls = { 2, 2, -1 }, },
552 
553 	{ .spkid_gpios = { 7, 1, -1 },		.spkid_pulls = { 1, 1, -1 }, },
554 	{ .spkid_gpios = { 7, 1, -1 },		.spkid_pulls = { 2, 2, -1 }, },
555 
556 	{ .spkid_gpios = { 3, 7, 1, -1 },	.spkid_pulls = { 1, 1, 1, -1 }, },
557 	{ .spkid_gpios = { 3, 7, 1, -1 },	.spkid_pulls = { 2, 2, 2, -1 }, },
558 };
559 KUNIT_ARRAY_PARAM(cs35l56_test_onchip_spkid,
560 		  cs35l56_test_onchip_spkid_cases,
561 		  cs35l56_test_gpio_param_desc);
562 
563 static void cs35l56_test_type_rev_param_desc(const struct cs35l56_test_param *param,
564 					     char *desc)
565 {
566 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "type: %02x rev: %02x",
567 		 param->type, param->rev);
568 }
569 
570 static const struct cs35l56_test_param cs35l56_test_type_rev_ex_b0_param_cases[] = {
571 	{ .type = 0x56, .rev = 0xb2 },
572 	{ .type = 0x57, .rev = 0xb2 },
573 	{ .type = 0x63, .rev = 0xa1 },
574 };
575 KUNIT_ARRAY_PARAM(cs35l56_test_type_rev_ex_b0, cs35l56_test_type_rev_ex_b0_param_cases,
576 		  cs35l56_test_type_rev_param_desc);
577 
578 
579 static const struct cs35l56_test_param cs35l56_test_type_rev_all_param_cases[] = {
580 	{ .type = 0x56, .rev = 0xb0 },
581 	{ .type = 0x56, .rev = 0xb2 },
582 	{ .type = 0x57, .rev = 0xb2 },
583 	{ .type = 0x63, .rev = 0xa1 },
584 };
585 KUNIT_ARRAY_PARAM(cs35l56_test_type_rev_all, cs35l56_test_type_rev_all_param_cases,
586 		  cs35l56_test_type_rev_param_desc);
587 
588 static struct kunit_case cs35l56_test_cases_soundwire[] = {
589 	KUNIT_CASE(cs35l56_test_l56_b0_suffix_sdw),
590 	KUNIT_CASE_PARAM(cs35l56_test_suffix_sdw, cs35l56_test_type_rev_ex_b0_gen_params),
591 	KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_sdw,
592 			 cs35l56_test_type_rev_ex_b0_gen_params),
593 	KUNIT_CASE(cs35l56_test_l56_b0_ssidexv2_ignored_suffix_sdw),
594 
595 	KUNIT_CASE_PARAM(cs35l56_test_parse_xu_onchip_spkid,
596 			 cs35l56_test_onchip_spkid_gen_params),
597 
598 	KUNIT_CASE(cs35l56_test_set_fw_name_reads_onchip_spkid),
599 	KUNIT_CASE(cs35l56_test_set_fw_name_preserves_spkid_with_onchip_gpios),
600 	KUNIT_CASE(cs35l56_test_set_fw_name_preserves_spkid_without_onchip_gpios),
601 
602 	{ } /* terminator */
603 };
604 
605 static struct kunit_case cs35l56_test_cases_not_soundwire[] = {
606 	KUNIT_CASE_PARAM(cs35l56_test_suffix_i2cspi, cs35l56_test_type_rev_all_gen_params),
607 	KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_i2cspi,
608 			 cs35l56_test_type_rev_all_gen_params),
609 
610 	KUNIT_CASE(cs35l56_test_set_fw_name_reads_onchip_spkid),
611 	KUNIT_CASE(cs35l56_test_set_fw_name_preserves_spkid_with_onchip_gpios),
612 	KUNIT_CASE(cs35l56_test_set_fw_name_preserves_spkid_without_onchip_gpios),
613 
614 	{ } /* terminator */
615 };
616 
617 static struct kunit_suite cs35l56_test_suite_soundwire = {
618 	.name = "snd-soc-cs35l56-test-soundwire",
619 	.init = cs35l56_test_case_init_soundwire,
620 	.test_cases = cs35l56_test_cases_soundwire,
621 };
622 
623 static struct kunit_suite cs35l56_test_suite_not_soundwire = {
624 	.name = "snd-soc-cs35l56-test-not-soundwire",
625 	.init = cs35l56_test_case_init_common,
626 	.test_cases = cs35l56_test_cases_not_soundwire,
627 };
628 
629 kunit_test_suites(
630 	&cs35l56_test_suite_soundwire,
631 	&cs35l56_test_suite_not_soundwire,
632 );
633 
634 MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
635 MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
636 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
637 MODULE_DESCRIPTION("KUnit test for Cirrus Logic cs35l56 codec driver");
638 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
639 MODULE_LICENSE("GPL");
640