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+
2026struct 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
3846KUNIT_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+
40136static 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+
413612static 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+
605838static 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
0 commit comments