Skip to content

Commit a2614f2

Browse files
committed
ASoC: cs35l56: More KUnit tests for speaker ID
Merge series from Richard Fitzgerald <rf@opensource.cirrus.com>: The first 3 patches in this series add some more KUnit testing for fetching speaker ID and combining it with the system name to create part of the qualifier for a firmware filename. Patch #4 enables GPIOLIB in KUnit 'alltests' builds. This can be taken separately from the first 3 patches. The GPIO tests will skip if GPIOLIB is not enabled, but obviously it would be ideal for 'kunit.py --alltests' runs to include these new test cases.
2 parents 2adac91 + ef0b478 commit a2614f2

5 files changed

Lines changed: 325 additions & 1 deletion

File tree

sound/soc/codecs/cs-amp-lib.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,8 @@ int cs_amp_get_vendor_spkid(struct device *dev)
716716
{
717717
int i, ret;
718718

719+
KUNIT_STATIC_STUB_REDIRECT(cs_amp_get_vendor_spkid, dev);
720+
719721
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE) &&
720722
!IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS))
721723
return -ENOENT;

sound/soc/codecs/cs35l56-shared-test.c

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,23 @@
1111
#include <linux/bitfield.h>
1212
#include <linux/bitops.h>
1313
#include <linux/device/faux.h>
14+
#include <linux/gpio/driver.h>
1415
#include <linux/module.h>
1516
#include <linux/random.h>
1617
#include <linux/regmap.h>
1718
#include <linux/seq_buf.h>
1819
#include <sound/cs35l56.h>
1920

21+
struct cs35l56_shared_test_mock_gpio {
22+
unsigned int pin_state;
23+
struct gpio_chip chip;
24+
};
25+
2026
struct cs35l56_shared_test_priv {
2127
struct kunit *test;
2228
struct faux_device *amp_dev;
29+
struct faux_device *gpio_dev;
30+
struct cs35l56_shared_test_mock_gpio *gpio_priv;
2331
struct regmap *registers;
2432
struct cs35l56_base *cs35l56_base;
2533
u8 applied_pad_pull_state[CS35L56_MAX_GPIO];
@@ -37,6 +45,94 @@ KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
3745

3846
KUNIT_DEFINE_ACTION_WRAPPER(regmap_exit_wrapper, regmap_exit, struct regmap *)
3947

48+
KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper,
49+
device_remove_software_node,
50+
struct device *)
51+
52+
static int cs35l56_shared_test_mock_gpio_get_direction(struct gpio_chip *chip,
53+
unsigned int offset)
54+
{
55+
return GPIO_LINE_DIRECTION_IN;
56+
}
57+
58+
static int cs35l56_shared_test_mock_gpio_direction_in(struct gpio_chip *chip,
59+
unsigned int offset)
60+
{
61+
return 0;
62+
}
63+
64+
static int cs35l56_shared_test_mock_gpio_get(struct gpio_chip *chip, unsigned int offset)
65+
{
66+
struct cs35l56_shared_test_mock_gpio *gpio_priv = gpiochip_get_data(chip);
67+
68+
return !!(gpio_priv->pin_state & BIT(offset));
69+
}
70+
71+
static const struct gpio_chip cs35l56_shared_test_mock_gpio_chip = {
72+
.label = "cs35l56_shared_test_mock_gpio",
73+
.owner = THIS_MODULE,
74+
.get_direction = cs35l56_shared_test_mock_gpio_get_direction,
75+
.direction_input = cs35l56_shared_test_mock_gpio_direction_in,
76+
.get = cs35l56_shared_test_mock_gpio_get,
77+
.base = -1,
78+
.ngpio = 32,
79+
};
80+
81+
/* software_node referencing the gpio driver */
82+
static const struct software_node cs35l56_shared_test_mock_gpio_swnode = {
83+
.name = "cs35l56_shared_test_mock_gpio",
84+
};
85+
86+
static int cs35l56_shared_test_mock_gpio_probe(struct faux_device *fdev)
87+
{
88+
struct cs35l56_shared_test_mock_gpio *gpio_priv;
89+
struct device *dev = &fdev->dev;
90+
int ret;
91+
92+
gpio_priv = devm_kzalloc(dev, sizeof(*gpio_priv), GFP_KERNEL);
93+
if (!gpio_priv)
94+
return -ENOMEM;
95+
96+
ret = device_add_software_node(dev, &cs35l56_shared_test_mock_gpio_swnode);
97+
if (ret)
98+
return ret;
99+
100+
ret = devm_add_action_or_reset(dev, device_remove_software_node_wrapper, dev);
101+
if (ret)
102+
return ret;
103+
104+
/* GPIO core modifies our struct gpio_chip so use a copy */
105+
gpio_priv->chip = cs35l56_shared_test_mock_gpio_chip;
106+
gpio_priv->chip.parent = dev;
107+
ret = devm_gpiochip_add_data(dev, &gpio_priv->chip, gpio_priv);
108+
if (ret)
109+
return dev_err_probe(dev, ret, "Failed to add gpiochip\n");
110+
111+
dev_set_drvdata(dev, gpio_priv);
112+
113+
return 0;
114+
}
115+
116+
static struct faux_device_ops cs35l56_shared_test_mock_gpio_drv = {
117+
.probe = cs35l56_shared_test_mock_gpio_probe,
118+
};
119+
120+
static void _cs35l56_shared_test_create_dummy_gpio(struct kunit *test)
121+
{
122+
struct cs35l56_shared_test_priv *priv = test->priv;
123+
124+
priv->gpio_dev = faux_device_create("cs35l56_shared_test_mock_gpio", NULL,
125+
&cs35l56_shared_test_mock_gpio_drv);
126+
KUNIT_ASSERT_NOT_NULL(test, priv->gpio_dev);
127+
KUNIT_ASSERT_EQ(test, 0,
128+
kunit_add_action_or_reset(test,
129+
faux_device_destroy_wrapper,
130+
priv->gpio_dev));
131+
132+
priv->gpio_priv = dev_get_drvdata(&priv->gpio_dev->dev);
133+
KUNIT_ASSERT_NOT_NULL(test, priv->gpio_priv);
134+
}
135+
40136
static const struct regmap_config cs35l56_shared_test_mock_registers_regmap = {
41137
.reg_bits = 32,
42138
.val_bits = 32,
@@ -410,6 +506,109 @@ static void cs35l56_shared_test_onchip_speaker_id_not_defined(struct kunit *test
410506
KUNIT_EXPECT_EQ(test, cs35l56_read_onchip_spkid(cs35l56_base), -ENOENT);
411507
}
412508

509+
/* simulate cs_amp_get_vendor_spkid() reading a vendor-specific ID of 1 */
510+
static int cs35l56_shared_test_get_vendor_spkid_1(struct device *dev)
511+
{
512+
return 1;
513+
}
514+
515+
static void cs35l56_shared_test_get_speaker_id_vendor(struct kunit *test)
516+
{
517+
struct cs35l56_shared_test_priv *priv = test->priv;
518+
519+
/* Hook cs_amp_get_vendor_spkid() to return an ID of 1 */
520+
kunit_activate_static_stub(test, cs_amp_get_vendor_spkid,
521+
cs35l56_shared_test_get_vendor_spkid_1);
522+
523+
KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), 1);
524+
}
525+
526+
static void cs35l56_shared_test_get_speaker_id_property(struct kunit *test)
527+
{
528+
struct cs35l56_shared_test_priv *priv = test->priv;
529+
const struct property_entry dev_props[] = {
530+
PROPERTY_ENTRY_U32("cirrus,speaker-id", 2),
531+
{ }
532+
};
533+
const struct software_node dev_node = SOFTWARE_NODE("SPK1", dev_props, NULL);
534+
535+
KUNIT_ASSERT_EQ(test, device_add_software_node(priv->cs35l56_base->dev, &dev_node), 0);
536+
KUNIT_ASSERT_EQ(test, 0,
537+
kunit_add_action_or_reset(test,
538+
device_remove_software_node_wrapper,
539+
priv->cs35l56_base->dev));
540+
541+
KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), 2);
542+
}
543+
544+
/*
545+
* Create software nodes equivalent to ACPI structure
546+
*
547+
* Device(GSPK) {
548+
* Name(_DSD, ...) {
549+
* Package() {
550+
* cs-gpios {
551+
* GPIO, n, 0,
552+
* ...
553+
* }
554+
* }
555+
*/
556+
static void _cs35l56_shared_test_create_spkid_swnode(struct kunit *test,
557+
struct device *dev,
558+
const struct software_node_ref_args *args,
559+
int num_args)
560+
{
561+
struct cs35l56_shared_test_priv *priv = test->priv;
562+
const struct property_entry props_template[] = {
563+
PROPERTY_ENTRY_REF_ARRAY_LEN("spk-id-gpios", args, num_args),
564+
{ }
565+
};
566+
struct property_entry *props;
567+
struct software_node *node;
568+
569+
props = kunit_kzalloc(test, sizeof(props_template), GFP_KERNEL);
570+
KUNIT_ASSERT_NOT_NULL(test, props);
571+
memcpy(props, props_template, sizeof(props_template));
572+
573+
node = kunit_kzalloc(test, sizeof(*node), GFP_KERNEL);
574+
KUNIT_ASSERT_NOT_NULL(test, node);
575+
*node = SOFTWARE_NODE("GSPK", props, NULL);
576+
577+
KUNIT_ASSERT_EQ(test, device_add_software_node(dev, node), 0);
578+
KUNIT_ASSERT_EQ(test, 0,
579+
kunit_add_action_or_reset(test,
580+
device_remove_software_node_wrapper,
581+
priv->cs35l56_base->dev));
582+
}
583+
584+
static void cs35l56_shared_test_get_speaker_id_from_host_gpio(struct kunit *test)
585+
{
586+
const struct cs35l56_shared_test_param *param = test->param_value;
587+
struct cs35l56_shared_test_priv *priv = test->priv;
588+
struct cs35l56_base *cs35l56_base = priv->cs35l56_base;
589+
struct software_node_ref_args *ref;
590+
int i;
591+
592+
if (!IS_REACHABLE(CONFIG_GPIOLIB)) {
593+
kunit_skip(test, "Requires CONFIG_GPIOLIB");
594+
return;
595+
}
596+
597+
_cs35l56_shared_test_create_dummy_gpio(test);
598+
599+
ref = kunit_kcalloc(test, ARRAY_SIZE(param->spkid_gpios), sizeof(*ref), GFP_KERNEL);
600+
KUNIT_ASSERT_NOT_NULL(test, ref);
601+
602+
for (i = 0; param->spkid_gpios[i] >= 0; i++) {
603+
ref[i] = SOFTWARE_NODE_REFERENCE(&cs35l56_shared_test_mock_gpio_swnode,
604+
param->spkid_gpios[i], 0);
605+
}
606+
_cs35l56_shared_test_create_spkid_swnode(test, cs35l56_base->dev, ref, i);
607+
608+
priv->gpio_priv->pin_state = param->gpio_status;
609+
KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), param->spkid);
610+
}
611+
413612
static int cs35l56_shared_test_case_regmap_init(struct kunit *test,
414613
const struct regmap_config *regmap_config)
415614
{
@@ -602,6 +801,40 @@ KUNIT_ARRAY_PARAM(cs35l56_shared_test_onchip_spkid_pull,
602801
cs35l56_shared_test_onchip_spkid_pull_cases,
603802
cs35l56_shared_test_gpio_param_desc);
604803

804+
/* Note: spk-id-gpios property bit order is LSbit...MSbit */
805+
static const struct cs35l56_shared_test_param cs35l56_shared_test_host_gpio_spkid_cases[] = {
806+
{ .spkid_gpios = { 0, -1 }, .gpio_status = 0, .spkid = 0 },
807+
{ .spkid_gpios = { 0, -1 }, .gpio_status = ~BIT(0), .spkid = 0 },
808+
{ .spkid_gpios = { 0, -1 }, .gpio_status = BIT(0), .spkid = 1 },
809+
810+
{ .spkid_gpios = { 6, -1 }, .gpio_status = 0, .spkid = 0 },
811+
{ .spkid_gpios = { 6, -1 }, .gpio_status = ~BIT(6), .spkid = 0 },
812+
{ .spkid_gpios = { 6, -1 }, .gpio_status = BIT(6), .spkid = 1 },
813+
814+
{ .spkid_gpios = { 6, 0, -1 }, .gpio_status = 0, .spkid = 0 },
815+
{ .spkid_gpios = { 6, 0, -1 }, .gpio_status = ~(BIT(0) | BIT(6)), .spkid = 0 },
816+
{ .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(6), .spkid = 1 },
817+
{ .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(0), .spkid = 2 },
818+
{ .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 },
819+
820+
{ .spkid_gpios = { 0, 6, -1 }, .gpio_status = 0, .spkid = 0 },
821+
{ .spkid_gpios = { 0, 6, -1 }, .gpio_status = ~(BIT(6) | BIT(0)), .spkid = 0 },
822+
{ .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(0), .spkid = 1 },
823+
{ .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(6), .spkid = 2 },
824+
{ .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 },
825+
826+
{ .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = 0, .spkid = 0 },
827+
{ .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(0), .spkid = 1 },
828+
{ .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(6), .spkid = 2 },
829+
{ .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 },
830+
{ .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2), .spkid = 4 },
831+
{ .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(0), .spkid = 5 },
832+
{ .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(6), .spkid = 6 },
833+
{ .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(6) | BIT(0), .spkid = 7 },
834+
};
835+
KUNIT_ARRAY_PARAM(cs35l56_shared_test_host_gpio_spkid, cs35l56_shared_test_host_gpio_spkid_cases,
836+
cs35l56_shared_test_gpio_param_desc);
837+
605838
static struct kunit_case cs35l56_shared_test_cases[] = {
606839
/* Tests for speaker id */
607840
KUNIT_CASE_PARAM(cs35l56_shared_test_mock_gpio_status_selftest,
@@ -616,6 +849,13 @@ static struct kunit_case cs35l56_shared_test_cases[] = {
616849
cs35l56_shared_test_onchip_spkid_pull_gen_params),
617850
KUNIT_CASE(cs35l56_shared_test_stash_onchip_spkid_pins_reject_invalid),
618851
KUNIT_CASE(cs35l56_shared_test_onchip_speaker_id_not_defined),
852+
853+
KUNIT_CASE(cs35l56_shared_test_get_speaker_id_vendor),
854+
KUNIT_CASE(cs35l56_shared_test_get_speaker_id_property),
855+
KUNIT_CASE_PARAM_ATTR(cs35l56_shared_test_get_speaker_id_from_host_gpio,
856+
cs35l56_shared_test_host_gpio_spkid_gen_params,
857+
{ KUNIT_SPEED_SLOW }),
858+
619859
{ }
620860
};
621861

sound/soc/codecs/cs35l56-test.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,78 @@ static const char *cs35l56_test_devm_get_vendor_specific_variant_id_none(struct
7474
return ERR_PTR(-ENOENT);
7575
}
7676

77+
static void cs35l56_test_system_name_from_ssid(struct kunit *test)
78+
{
79+
struct cs35l56_test_priv *priv = test->priv;
80+
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
81+
82+
cs35l56->speaker_id = -1;
83+
snd_soc_card_set_pci_ssid(cs35l56->component->card, 0x12b4, 0xa7c8);
84+
85+
KUNIT_EXPECT_EQ(test, cs35l56_get_firmware_uid(cs35l56), 0);
86+
KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
87+
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.system_name, "12b4a7c8");
88+
}
89+
90+
static void cs35l56_test_system_name_from_ssid_and_spkid(struct kunit *test)
91+
{
92+
struct cs35l56_test_priv *priv = test->priv;
93+
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
94+
95+
cs35l56->speaker_id = 1;
96+
snd_soc_card_set_pci_ssid(cs35l56->component->card, 0x12b4, 0xa7c8);
97+
98+
KUNIT_EXPECT_EQ(test, cs35l56_get_firmware_uid(cs35l56), 0);
99+
KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
100+
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.system_name, "12b4a7c8-spkid1");
101+
}
102+
103+
static void cs35l56_test_system_name_from_property(struct kunit *test)
104+
{
105+
struct cs35l56_test_priv *priv = test->priv;
106+
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
107+
const struct property_entry dev_props[] = {
108+
PROPERTY_ENTRY_STRING("cirrus,firmware-uid", "acme"),
109+
{ }
110+
};
111+
const struct software_node dev_node = SOFTWARE_NODE("SPK1", dev_props, NULL);
112+
113+
cs35l56->speaker_id = -1;
114+
115+
KUNIT_ASSERT_EQ(test, device_add_software_node(cs35l56->base.dev, &dev_node), 0);
116+
KUNIT_ASSERT_EQ(test, 0,
117+
kunit_add_action_or_reset(test,
118+
device_remove_software_node_wrapper,
119+
cs35l56->base.dev));
120+
121+
KUNIT_EXPECT_EQ(test, cs35l56_get_firmware_uid(cs35l56), 0);
122+
KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
123+
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.system_name, "acme");
124+
}
125+
126+
static void cs35l56_test_system_name_from_property_and_spkid(struct kunit *test)
127+
{
128+
struct cs35l56_test_priv *priv = test->priv;
129+
struct cs35l56_private *cs35l56 = priv->cs35l56_priv;
130+
const struct property_entry dev_props[] = {
131+
PROPERTY_ENTRY_STRING("cirrus,firmware-uid", "acme"),
132+
{ }
133+
};
134+
const struct software_node dev_node = SOFTWARE_NODE("SPK1", dev_props, NULL);
135+
136+
cs35l56->speaker_id = 1;
137+
138+
KUNIT_ASSERT_EQ(test, device_add_software_node(cs35l56->base.dev, &dev_node), 0);
139+
KUNIT_ASSERT_EQ(test, 0,
140+
kunit_add_action_or_reset(test,
141+
device_remove_software_node_wrapper,
142+
cs35l56->base.dev));
143+
144+
KUNIT_EXPECT_EQ(test, cs35l56_get_firmware_uid(cs35l56), 0);
145+
KUNIT_EXPECT_EQ(test, cs35l56_set_fw_name(cs35l56->component), 0);
146+
KUNIT_EXPECT_STREQ(test, cs35l56->dsp.system_name, "acme-spkid1");
147+
}
148+
77149
static void cs35l56_test_l56_b0_suffix_sdw(struct kunit *test)
78150
{
79151
struct cs35l56_test_priv *priv = test->priv;
@@ -596,6 +668,10 @@ KUNIT_ARRAY_PARAM(cs35l56_test_type_rev_all, cs35l56_test_type_rev_all_param_cas
596668
cs35l56_test_type_rev_param_desc);
597669

598670
static struct kunit_case cs35l56_test_cases_soundwire[] = {
671+
KUNIT_CASE(cs35l56_test_system_name_from_ssid),
672+
KUNIT_CASE(cs35l56_test_system_name_from_ssid_and_spkid),
673+
KUNIT_CASE(cs35l56_test_system_name_from_property),
674+
KUNIT_CASE(cs35l56_test_system_name_from_property_and_spkid),
599675
KUNIT_CASE(cs35l56_test_l56_b0_suffix_sdw),
600676
KUNIT_CASE_PARAM(cs35l56_test_suffix_sdw, cs35l56_test_type_rev_ex_b0_gen_params),
601677
KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_sdw,
@@ -613,6 +689,10 @@ static struct kunit_case cs35l56_test_cases_soundwire[] = {
613689
};
614690

615691
static struct kunit_case cs35l56_test_cases_not_soundwire[] = {
692+
KUNIT_CASE(cs35l56_test_system_name_from_ssid),
693+
KUNIT_CASE(cs35l56_test_system_name_from_ssid_and_spkid),
694+
KUNIT_CASE(cs35l56_test_system_name_from_property),
695+
KUNIT_CASE(cs35l56_test_system_name_from_property_and_spkid),
616696
KUNIT_CASE_PARAM(cs35l56_test_suffix_i2cspi, cs35l56_test_type_rev_all_gen_params),
617697
KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_i2cspi,
618698
cs35l56_test_type_rev_all_gen_params),

0 commit comments

Comments
 (0)