Skip to content

Commit ef0b478

Browse files
rfvirgilbroonie
authored andcommitted
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 <rf@opensource.cirrus.com> Link: https://patch.msgid.link/20260304162402.1714759-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 72e1c47 commit ef0b478

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

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

Lines changed: 197 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];
@@ -41,6 +49,90 @@ KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper,
4149
device_remove_software_node,
4250
struct device *)
4351

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+
44136
static const struct regmap_config cs35l56_shared_test_mock_registers_regmap = {
45137
.reg_bits = 32,
46138
.val_bits = 32,
@@ -449,6 +541,74 @@ static void cs35l56_shared_test_get_speaker_id_property(struct kunit *test)
449541
KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), 2);
450542
}
451543

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+
452612
static int cs35l56_shared_test_case_regmap_init(struct kunit *test,
453613
const struct regmap_config *regmap_config)
454614
{
@@ -641,6 +801,40 @@ KUNIT_ARRAY_PARAM(cs35l56_shared_test_onchip_spkid_pull,
641801
cs35l56_shared_test_onchip_spkid_pull_cases,
642802
cs35l56_shared_test_gpio_param_desc);
643803

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+
644838
static struct kunit_case cs35l56_shared_test_cases[] = {
645839
/* Tests for speaker id */
646840
KUNIT_CASE_PARAM(cs35l56_shared_test_mock_gpio_status_selftest,
@@ -658,6 +852,9 @@ static struct kunit_case cs35l56_shared_test_cases[] = {
658852

659853
KUNIT_CASE(cs35l56_shared_test_get_speaker_id_vendor),
660854
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 }),
661858

662859
{ }
663860
};

0 commit comments

Comments
 (0)