From bae6668c526018af45b70e7825b61e6edb528f41 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 4 Mar 2026 16:23:59 +0000 Subject: [PATCH 1/3] ASoC: cs35l56: KUnit tests for setting dsp.system_name Add KUnit tests for setting the dsp.system_name string. There are two sources of the string: 1. PCI SSID from struct snd_soc_card. 2. "cirrus,firmware-uid" property. Either of these can then be qualified by a speaker ID integer. Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20260304162402.1714759-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-test.c | 80 +++++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l56.c | 3 +- sound/soc/codecs/cs35l56.h | 1 + 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l56-test.c b/sound/soc/codecs/cs35l56-test.c index b6c8c08e3ade..2732b65fc372 100644 --- a/sound/soc/codecs/cs35l56-test.c +++ b/sound/soc/codecs/cs35l56-test.c @@ -74,6 +74,78 @@ static const char *cs35l56_test_devm_get_vendor_specific_variant_id_none(struct return ERR_PTR(-ENOENT); } +static void cs35l56_test_system_name_from_ssid(struct kunit *test) +{ + struct cs35l56_test_priv *priv = test->priv; + struct cs35l56_private *cs35l56 = priv->cs35l56_priv; + + cs35l56->speaker_id = -1; + snd_soc_card_set_pci_ssid(cs35l56->component->card, 0x12b4, 0xa7c8); + + KUNIT_EXPECT_EQ(test, cs35l56_get_firmware_uid(cs35l56), 0); + KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0); + KUNIT_EXPECT_STREQ(test, cs35l56->dsp.system_name, "12b4a7c8"); +} + +static void cs35l56_test_system_name_from_ssid_and_spkid(struct kunit *test) +{ + struct cs35l56_test_priv *priv = test->priv; + struct cs35l56_private *cs35l56 = priv->cs35l56_priv; + + cs35l56->speaker_id = 1; + snd_soc_card_set_pci_ssid(cs35l56->component->card, 0x12b4, 0xa7c8); + + KUNIT_EXPECT_EQ(test, cs35l56_get_firmware_uid(cs35l56), 0); + KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0); + KUNIT_EXPECT_STREQ(test, cs35l56->dsp.system_name, "12b4a7c8-spkid1"); +} + +static void cs35l56_test_system_name_from_property(struct kunit *test) +{ + struct cs35l56_test_priv *priv = test->priv; + struct cs35l56_private *cs35l56 = priv->cs35l56_priv; + const struct property_entry dev_props[] = { + PROPERTY_ENTRY_STRING("cirrus,firmware-uid", "acme"), + { } + }; + const struct software_node dev_node = SOFTWARE_NODE("SPK1", dev_props, NULL); + + cs35l56->speaker_id = -1; + + KUNIT_ASSERT_EQ(test, device_add_software_node(cs35l56->base.dev, &dev_node), 0); + KUNIT_ASSERT_EQ(test, 0, + kunit_add_action_or_reset(test, + device_remove_software_node_wrapper, + cs35l56->base.dev)); + + KUNIT_EXPECT_EQ(test, cs35l56_get_firmware_uid(cs35l56), 0); + KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0); + KUNIT_EXPECT_STREQ(test, cs35l56->dsp.system_name, "acme"); +} + +static void cs35l56_test_system_name_from_property_and_spkid(struct kunit *test) +{ + struct cs35l56_test_priv *priv = test->priv; + struct cs35l56_private *cs35l56 = priv->cs35l56_priv; + const struct property_entry dev_props[] = { + PROPERTY_ENTRY_STRING("cirrus,firmware-uid", "acme"), + { } + }; + const struct software_node dev_node = SOFTWARE_NODE("SPK1", dev_props, NULL); + + cs35l56->speaker_id = 1; + + KUNIT_ASSERT_EQ(test, device_add_software_node(cs35l56->base.dev, &dev_node), 0); + KUNIT_ASSERT_EQ(test, 0, + kunit_add_action_or_reset(test, + device_remove_software_node_wrapper, + cs35l56->base.dev)); + + KUNIT_EXPECT_EQ(test, cs35l56_get_firmware_uid(cs35l56), 0); + KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0); + KUNIT_EXPECT_STREQ(test, cs35l56->dsp.system_name, "acme-spkid1"); +} + static void cs35l56_test_l56_b0_suffix_sdw(struct kunit *test) { struct cs35l56_test_priv *priv = test->priv; @@ -586,6 +658,10 @@ KUNIT_ARRAY_PARAM(cs35l56_test_type_rev_all, cs35l56_test_type_rev_all_param_cas cs35l56_test_type_rev_param_desc); static struct kunit_case cs35l56_test_cases_soundwire[] = { + KUNIT_CASE(cs35l56_test_system_name_from_ssid), + KUNIT_CASE(cs35l56_test_system_name_from_ssid_and_spkid), + KUNIT_CASE(cs35l56_test_system_name_from_property), + KUNIT_CASE(cs35l56_test_system_name_from_property_and_spkid), KUNIT_CASE(cs35l56_test_l56_b0_suffix_sdw), KUNIT_CASE_PARAM(cs35l56_test_suffix_sdw, cs35l56_test_type_rev_ex_b0_gen_params), KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_sdw, @@ -603,6 +679,10 @@ static struct kunit_case cs35l56_test_cases_soundwire[] = { }; static struct kunit_case cs35l56_test_cases_not_soundwire[] = { + KUNIT_CASE(cs35l56_test_system_name_from_ssid), + KUNIT_CASE(cs35l56_test_system_name_from_ssid_and_spkid), + KUNIT_CASE(cs35l56_test_system_name_from_property), + KUNIT_CASE(cs35l56_test_system_name_from_property_and_spkid), KUNIT_CASE_PARAM(cs35l56_test_suffix_i2cspi, cs35l56_test_type_rev_all_gen_params), KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_i2cspi, cs35l56_test_type_rev_all_gen_params), diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 2ff8b172b76e..ffaa5fca8d50 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -1661,7 +1661,7 @@ VISIBLE_IF_KUNIT int cs35l56_process_xu_properties(struct cs35l56_private *cs35l } EXPORT_SYMBOL_IF_KUNIT(cs35l56_process_xu_properties); -static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) +VISIBLE_IF_KUNIT int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) { struct device *dev = cs35l56->base.dev; const char *prop; @@ -1686,6 +1686,7 @@ static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) return 0; } +EXPORT_SYMBOL_IF_KUNIT(cs35l56_get_firmware_uid); /* * Some SoundWire laptops have a spk-id-gpios property but it points to diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index 691f857d0bd8..747529be3e2e 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -78,6 +78,7 @@ void cs35l56_remove(struct cs35l56_private *cs35l56); int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56); int cs35l56_set_fw_name(struct snd_soc_component *component); int cs35l56_process_xu_properties(struct cs35l56_private *cs35l56); +int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56); #endif #endif /* ifndef CS35L56_H */ From 72e1c4704844766c46725d6b043ba04559054d02 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 4 Mar 2026 16:24:00 +0000 Subject: [PATCH 2/3] ASoC: cs35l56: Some KUnit testing of cs35l56_get_speaker_id() Add some KUnit tests for cs35l56_get_speaker_id(). These only test the simpler cases of reading the speaker ID from cs_amp_get_vendor_spkid() or the "cirrus,speaker-id" property. The untested case is reading it from GPIOs, which would require a dummy implementation of a GPIO driver. Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20260304162402.1714759-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs-amp-lib.c | 2 ++ sound/soc/codecs/cs35l56-shared-test.c | 43 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c index 8b131975143d..b34b1f5f121f 100644 --- a/sound/soc/codecs/cs-amp-lib.c +++ b/sound/soc/codecs/cs-amp-lib.c @@ -716,6 +716,8 @@ int cs_amp_get_vendor_spkid(struct device *dev) { int i, ret; + KUNIT_STATIC_STUB_REDIRECT(cs_amp_get_vendor_spkid, dev); + if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE) && !IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS)) return -ENOENT; diff --git a/sound/soc/codecs/cs35l56-shared-test.c b/sound/soc/codecs/cs35l56-shared-test.c index 94db02aef7dc..d510893dcd44 100644 --- a/sound/soc/codecs/cs35l56-shared-test.c +++ b/sound/soc/codecs/cs35l56-shared-test.c @@ -37,6 +37,10 @@ KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy, KUNIT_DEFINE_ACTION_WRAPPER(regmap_exit_wrapper, regmap_exit, struct regmap *) +KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper, + device_remove_software_node, + struct device *) + static const struct regmap_config cs35l56_shared_test_mock_registers_regmap = { .reg_bits = 32, .val_bits = 32, @@ -410,6 +414,41 @@ static void cs35l56_shared_test_onchip_speaker_id_not_defined(struct kunit *test KUNIT_EXPECT_EQ(test, cs35l56_read_onchip_spkid(cs35l56_base), -ENOENT); } +/* simulate cs_amp_get_vendor_spkid() reading a vendor-specific ID of 1 */ +static int cs35l56_shared_test_get_vendor_spkid_1(struct device *dev) +{ + return 1; +} + +static void cs35l56_shared_test_get_speaker_id_vendor(struct kunit *test) +{ + struct cs35l56_shared_test_priv *priv = test->priv; + + /* Hook cs_amp_get_vendor_spkid() to return an ID of 1 */ + kunit_activate_static_stub(test, cs_amp_get_vendor_spkid, + cs35l56_shared_test_get_vendor_spkid_1); + + KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), 1); +} + +static void cs35l56_shared_test_get_speaker_id_property(struct kunit *test) +{ + struct cs35l56_shared_test_priv *priv = test->priv; + const struct property_entry dev_props[] = { + PROPERTY_ENTRY_U32("cirrus,speaker-id", 2), + { } + }; + const struct software_node dev_node = SOFTWARE_NODE("SPK1", dev_props, NULL); + + KUNIT_ASSERT_EQ(test, device_add_software_node(priv->cs35l56_base->dev, &dev_node), 0); + KUNIT_ASSERT_EQ(test, 0, + kunit_add_action_or_reset(test, + device_remove_software_node_wrapper, + priv->cs35l56_base->dev)); + + KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), 2); +} + static int cs35l56_shared_test_case_regmap_init(struct kunit *test, const struct regmap_config *regmap_config) { @@ -616,6 +655,10 @@ static struct kunit_case cs35l56_shared_test_cases[] = { cs35l56_shared_test_onchip_spkid_pull_gen_params), KUNIT_CASE(cs35l56_shared_test_stash_onchip_spkid_pins_reject_invalid), KUNIT_CASE(cs35l56_shared_test_onchip_speaker_id_not_defined), + + KUNIT_CASE(cs35l56_shared_test_get_speaker_id_vendor), + KUNIT_CASE(cs35l56_shared_test_get_speaker_id_property), + { } }; From ef0b4783afc211a4b120e72b5a57f3d0340a9981 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 4 Mar 2026 16:24:01 +0000 Subject: [PATCH 3/3] ASoC: cs35l56: KUnit tests for reading speaker ID from host GPIOs Add test cases for the spk-id-gpios property used to read an integer speaker ID value from a set of GPIO inputs. There is a single parameterized test function, cs35l56_shared_test_get_speaker_id_from_host_gpio() that does the following: - Create a mock GPIO driver to simulate real GPIO inputs. - Create an array of struct software_node_ref_args to provide the content of the spk-id-gpios property. Each entry is a reference to a GPIO on the mock GPIO driver. The GPIO indexes are taken from test case parameterization. - Create a software node containing the spk-id-gpios property and set this as the node of the pseudo codec driver device. - Call cs35l56_get_speaker_id() and assert that the returned value matches the expected value defined in the test case parameterization. Signed-off-by: Richard Fitzgerald Link: https://patch.msgid.link/20260304162402.1714759-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-shared-test.c | 197 +++++++++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/sound/soc/codecs/cs35l56-shared-test.c b/sound/soc/codecs/cs35l56-shared-test.c index d510893dcd44..cfe7938065f9 100644 --- a/sound/soc/codecs/cs35l56-shared-test.c +++ b/sound/soc/codecs/cs35l56-shared-test.c @@ -11,15 +11,23 @@ #include #include #include +#include #include #include #include #include #include +struct cs35l56_shared_test_mock_gpio { + unsigned int pin_state; + struct gpio_chip chip; +}; + struct cs35l56_shared_test_priv { struct kunit *test; struct faux_device *amp_dev; + struct faux_device *gpio_dev; + struct cs35l56_shared_test_mock_gpio *gpio_priv; struct regmap *registers; struct cs35l56_base *cs35l56_base; u8 applied_pad_pull_state[CS35L56_MAX_GPIO]; @@ -41,6 +49,90 @@ KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper, device_remove_software_node, struct device *) +static int cs35l56_shared_test_mock_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + return GPIO_LINE_DIRECTION_IN; +} + +static int cs35l56_shared_test_mock_gpio_direction_in(struct gpio_chip *chip, + unsigned int offset) +{ + return 0; +} + +static int cs35l56_shared_test_mock_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct cs35l56_shared_test_mock_gpio *gpio_priv = gpiochip_get_data(chip); + + return !!(gpio_priv->pin_state & BIT(offset)); +} + +static const struct gpio_chip cs35l56_shared_test_mock_gpio_chip = { + .label = "cs35l56_shared_test_mock_gpio", + .owner = THIS_MODULE, + .get_direction = cs35l56_shared_test_mock_gpio_get_direction, + .direction_input = cs35l56_shared_test_mock_gpio_direction_in, + .get = cs35l56_shared_test_mock_gpio_get, + .base = -1, + .ngpio = 32, +}; + +/* software_node referencing the gpio driver */ +static const struct software_node cs35l56_shared_test_mock_gpio_swnode = { + .name = "cs35l56_shared_test_mock_gpio", +}; + +static int cs35l56_shared_test_mock_gpio_probe(struct faux_device *fdev) +{ + struct cs35l56_shared_test_mock_gpio *gpio_priv; + struct device *dev = &fdev->dev; + int ret; + + gpio_priv = devm_kzalloc(dev, sizeof(*gpio_priv), GFP_KERNEL); + if (!gpio_priv) + return -ENOMEM; + + ret = device_add_software_node(dev, &cs35l56_shared_test_mock_gpio_swnode); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, device_remove_software_node_wrapper, dev); + if (ret) + return ret; + + /* GPIO core modifies our struct gpio_chip so use a copy */ + gpio_priv->chip = cs35l56_shared_test_mock_gpio_chip; + gpio_priv->chip.parent = dev; + ret = devm_gpiochip_add_data(dev, &gpio_priv->chip, gpio_priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to add gpiochip\n"); + + dev_set_drvdata(dev, gpio_priv); + + return 0; +} + +static struct faux_device_ops cs35l56_shared_test_mock_gpio_drv = { + .probe = cs35l56_shared_test_mock_gpio_probe, +}; + +static void _cs35l56_shared_test_create_dummy_gpio(struct kunit *test) +{ + struct cs35l56_shared_test_priv *priv = test->priv; + + priv->gpio_dev = faux_device_create("cs35l56_shared_test_mock_gpio", NULL, + &cs35l56_shared_test_mock_gpio_drv); + KUNIT_ASSERT_NOT_NULL(test, priv->gpio_dev); + KUNIT_ASSERT_EQ(test, 0, + kunit_add_action_or_reset(test, + faux_device_destroy_wrapper, + priv->gpio_dev)); + + priv->gpio_priv = dev_get_drvdata(&priv->gpio_dev->dev); + KUNIT_ASSERT_NOT_NULL(test, priv->gpio_priv); +} + static const struct regmap_config cs35l56_shared_test_mock_registers_regmap = { .reg_bits = 32, .val_bits = 32, @@ -449,6 +541,74 @@ static void cs35l56_shared_test_get_speaker_id_property(struct kunit *test) KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), 2); } +/* + * Create software nodes equivalent to ACPI structure + * + * Device(GSPK) { + * Name(_DSD, ...) { + * Package() { + * cs-gpios { + * GPIO, n, 0, + * ... + * } + * } + */ +static void _cs35l56_shared_test_create_spkid_swnode(struct kunit *test, + struct device *dev, + const struct software_node_ref_args *args, + int num_args) +{ + struct cs35l56_shared_test_priv *priv = test->priv; + const struct property_entry props_template[] = { + PROPERTY_ENTRY_REF_ARRAY_LEN("spk-id-gpios", args, num_args), + { } + }; + struct property_entry *props; + struct software_node *node; + + props = kunit_kzalloc(test, sizeof(props_template), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, props); + memcpy(props, props_template, sizeof(props_template)); + + node = kunit_kzalloc(test, sizeof(*node), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, node); + *node = SOFTWARE_NODE("GSPK", props, NULL); + + KUNIT_ASSERT_EQ(test, device_add_software_node(dev, node), 0); + KUNIT_ASSERT_EQ(test, 0, + kunit_add_action_or_reset(test, + device_remove_software_node_wrapper, + priv->cs35l56_base->dev)); +} + +static void cs35l56_shared_test_get_speaker_id_from_host_gpio(struct kunit *test) +{ + const struct cs35l56_shared_test_param *param = test->param_value; + struct cs35l56_shared_test_priv *priv = test->priv; + struct cs35l56_base *cs35l56_base = priv->cs35l56_base; + struct software_node_ref_args *ref; + int i; + + if (!IS_REACHABLE(CONFIG_GPIOLIB)) { + kunit_skip(test, "Requires CONFIG_GPIOLIB"); + return; + } + + _cs35l56_shared_test_create_dummy_gpio(test); + + ref = kunit_kcalloc(test, ARRAY_SIZE(param->spkid_gpios), sizeof(*ref), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, ref); + + for (i = 0; param->spkid_gpios[i] >= 0; i++) { + ref[i] = SOFTWARE_NODE_REFERENCE(&cs35l56_shared_test_mock_gpio_swnode, + param->spkid_gpios[i], 0); + } + _cs35l56_shared_test_create_spkid_swnode(test, cs35l56_base->dev, ref, i); + + priv->gpio_priv->pin_state = param->gpio_status; + KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), param->spkid); +} + static int cs35l56_shared_test_case_regmap_init(struct kunit *test, const struct regmap_config *regmap_config) { @@ -641,6 +801,40 @@ KUNIT_ARRAY_PARAM(cs35l56_shared_test_onchip_spkid_pull, cs35l56_shared_test_onchip_spkid_pull_cases, cs35l56_shared_test_gpio_param_desc); +/* Note: spk-id-gpios property bit order is LSbit...MSbit */ +static const struct cs35l56_shared_test_param cs35l56_shared_test_host_gpio_spkid_cases[] = { + { .spkid_gpios = { 0, -1 }, .gpio_status = 0, .spkid = 0 }, + { .spkid_gpios = { 0, -1 }, .gpio_status = ~BIT(0), .spkid = 0 }, + { .spkid_gpios = { 0, -1 }, .gpio_status = BIT(0), .spkid = 1 }, + + { .spkid_gpios = { 6, -1 }, .gpio_status = 0, .spkid = 0 }, + { .spkid_gpios = { 6, -1 }, .gpio_status = ~BIT(6), .spkid = 0 }, + { .spkid_gpios = { 6, -1 }, .gpio_status = BIT(6), .spkid = 1 }, + + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = 0, .spkid = 0 }, + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = ~(BIT(0) | BIT(6)), .spkid = 0 }, + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(6), .spkid = 1 }, + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(0), .spkid = 2 }, + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, + + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = 0, .spkid = 0 }, + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = ~(BIT(6) | BIT(0)), .spkid = 0 }, + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(0), .spkid = 1 }, + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(6), .spkid = 2 }, + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, + + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = 0, .spkid = 0 }, + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(0), .spkid = 1 }, + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(6), .spkid = 2 }, + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2), .spkid = 4 }, + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(0), .spkid = 5 }, + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(6), .spkid = 6 }, + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(6) | BIT(0), .spkid = 7 }, +}; +KUNIT_ARRAY_PARAM(cs35l56_shared_test_host_gpio_spkid, cs35l56_shared_test_host_gpio_spkid_cases, + cs35l56_shared_test_gpio_param_desc); + static struct kunit_case cs35l56_shared_test_cases[] = { /* Tests for speaker id */ KUNIT_CASE_PARAM(cs35l56_shared_test_mock_gpio_status_selftest, @@ -658,6 +852,9 @@ static struct kunit_case cs35l56_shared_test_cases[] = { KUNIT_CASE(cs35l56_shared_test_get_speaker_id_vendor), KUNIT_CASE(cs35l56_shared_test_get_speaker_id_property), + KUNIT_CASE_PARAM_ATTR(cs35l56_shared_test_get_speaker_id_from_host_gpio, + cs35l56_shared_test_host_gpio_spkid_gen_params, + { KUNIT_SPEED_SLOW }), { } };