Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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.

+325 -1
+2
sound/soc/codecs/cs-amp-lib.c
··· 716 716 { 717 717 int i, ret; 718 718 719 + KUNIT_STATIC_STUB_REDIRECT(cs_amp_get_vendor_spkid, dev); 720 + 719 721 if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE) && 720 722 !IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST_HOOKS)) 721 723 return -ENOENT;
+240
sound/soc/codecs/cs35l56-shared-test.c
··· 11 11 #include <linux/bitfield.h> 12 12 #include <linux/bitops.h> 13 13 #include <linux/device/faux.h> 14 + #include <linux/gpio/driver.h> 14 15 #include <linux/module.h> 15 16 #include <linux/random.h> 16 17 #include <linux/regmap.h> 17 18 #include <linux/seq_buf.h> 18 19 #include <sound/cs35l56.h> 19 20 21 + struct cs35l56_shared_test_mock_gpio { 22 + unsigned int pin_state; 23 + struct gpio_chip chip; 24 + }; 25 + 20 26 struct cs35l56_shared_test_priv { 21 27 struct kunit *test; 22 28 struct faux_device *amp_dev; 29 + struct faux_device *gpio_dev; 30 + struct cs35l56_shared_test_mock_gpio *gpio_priv; 23 31 struct regmap *registers; 24 32 struct cs35l56_base *cs35l56_base; 25 33 u8 applied_pad_pull_state[CS35L56_MAX_GPIO]; ··· 44 36 struct faux_device *) 45 37 46 38 KUNIT_DEFINE_ACTION_WRAPPER(regmap_exit_wrapper, regmap_exit, struct regmap *) 39 + 40 + KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper, 41 + device_remove_software_node, 42 + struct device *) 43 + 44 + static int cs35l56_shared_test_mock_gpio_get_direction(struct gpio_chip *chip, 45 + unsigned int offset) 46 + { 47 + return GPIO_LINE_DIRECTION_IN; 48 + } 49 + 50 + static int cs35l56_shared_test_mock_gpio_direction_in(struct gpio_chip *chip, 51 + unsigned int offset) 52 + { 53 + return 0; 54 + } 55 + 56 + static int cs35l56_shared_test_mock_gpio_get(struct gpio_chip *chip, unsigned int offset) 57 + { 58 + struct cs35l56_shared_test_mock_gpio *gpio_priv = gpiochip_get_data(chip); 59 + 60 + return !!(gpio_priv->pin_state & BIT(offset)); 61 + } 62 + 63 + static const struct gpio_chip cs35l56_shared_test_mock_gpio_chip = { 64 + .label = "cs35l56_shared_test_mock_gpio", 65 + .owner = THIS_MODULE, 66 + .get_direction = cs35l56_shared_test_mock_gpio_get_direction, 67 + .direction_input = cs35l56_shared_test_mock_gpio_direction_in, 68 + .get = cs35l56_shared_test_mock_gpio_get, 69 + .base = -1, 70 + .ngpio = 32, 71 + }; 72 + 73 + /* software_node referencing the gpio driver */ 74 + static const struct software_node cs35l56_shared_test_mock_gpio_swnode = { 75 + .name = "cs35l56_shared_test_mock_gpio", 76 + }; 77 + 78 + static int cs35l56_shared_test_mock_gpio_probe(struct faux_device *fdev) 79 + { 80 + struct cs35l56_shared_test_mock_gpio *gpio_priv; 81 + struct device *dev = &fdev->dev; 82 + int ret; 83 + 84 + gpio_priv = devm_kzalloc(dev, sizeof(*gpio_priv), GFP_KERNEL); 85 + if (!gpio_priv) 86 + return -ENOMEM; 87 + 88 + ret = device_add_software_node(dev, &cs35l56_shared_test_mock_gpio_swnode); 89 + if (ret) 90 + return ret; 91 + 92 + ret = devm_add_action_or_reset(dev, device_remove_software_node_wrapper, dev); 93 + if (ret) 94 + return ret; 95 + 96 + /* GPIO core modifies our struct gpio_chip so use a copy */ 97 + gpio_priv->chip = cs35l56_shared_test_mock_gpio_chip; 98 + gpio_priv->chip.parent = dev; 99 + ret = devm_gpiochip_add_data(dev, &gpio_priv->chip, gpio_priv); 100 + if (ret) 101 + return dev_err_probe(dev, ret, "Failed to add gpiochip\n"); 102 + 103 + dev_set_drvdata(dev, gpio_priv); 104 + 105 + return 0; 106 + } 107 + 108 + static struct faux_device_ops cs35l56_shared_test_mock_gpio_drv = { 109 + .probe = cs35l56_shared_test_mock_gpio_probe, 110 + }; 111 + 112 + static void _cs35l56_shared_test_create_dummy_gpio(struct kunit *test) 113 + { 114 + struct cs35l56_shared_test_priv *priv = test->priv; 115 + 116 + priv->gpio_dev = faux_device_create("cs35l56_shared_test_mock_gpio", NULL, 117 + &cs35l56_shared_test_mock_gpio_drv); 118 + KUNIT_ASSERT_NOT_NULL(test, priv->gpio_dev); 119 + KUNIT_ASSERT_EQ(test, 0, 120 + kunit_add_action_or_reset(test, 121 + faux_device_destroy_wrapper, 122 + priv->gpio_dev)); 123 + 124 + priv->gpio_priv = dev_get_drvdata(&priv->gpio_dev->dev); 125 + KUNIT_ASSERT_NOT_NULL(test, priv->gpio_priv); 126 + } 47 127 48 128 static const struct regmap_config cs35l56_shared_test_mock_registers_regmap = { 49 129 .reg_bits = 32, ··· 506 410 KUNIT_EXPECT_EQ(test, cs35l56_read_onchip_spkid(cs35l56_base), -ENOENT); 507 411 } 508 412 413 + /* simulate cs_amp_get_vendor_spkid() reading a vendor-specific ID of 1 */ 414 + static int cs35l56_shared_test_get_vendor_spkid_1(struct device *dev) 415 + { 416 + return 1; 417 + } 418 + 419 + static void cs35l56_shared_test_get_speaker_id_vendor(struct kunit *test) 420 + { 421 + struct cs35l56_shared_test_priv *priv = test->priv; 422 + 423 + /* Hook cs_amp_get_vendor_spkid() to return an ID of 1 */ 424 + kunit_activate_static_stub(test, cs_amp_get_vendor_spkid, 425 + cs35l56_shared_test_get_vendor_spkid_1); 426 + 427 + KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), 1); 428 + } 429 + 430 + static void cs35l56_shared_test_get_speaker_id_property(struct kunit *test) 431 + { 432 + struct cs35l56_shared_test_priv *priv = test->priv; 433 + const struct property_entry dev_props[] = { 434 + PROPERTY_ENTRY_U32("cirrus,speaker-id", 2), 435 + { } 436 + }; 437 + const struct software_node dev_node = SOFTWARE_NODE("SPK1", dev_props, NULL); 438 + 439 + KUNIT_ASSERT_EQ(test, device_add_software_node(priv->cs35l56_base->dev, &dev_node), 0); 440 + KUNIT_ASSERT_EQ(test, 0, 441 + kunit_add_action_or_reset(test, 442 + device_remove_software_node_wrapper, 443 + priv->cs35l56_base->dev)); 444 + 445 + KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), 2); 446 + } 447 + 448 + /* 449 + * Create software nodes equivalent to ACPI structure 450 + * 451 + * Device(GSPK) { 452 + * Name(_DSD, ...) { 453 + * Package() { 454 + * cs-gpios { 455 + * GPIO, n, 0, 456 + * ... 457 + * } 458 + * } 459 + */ 460 + static void _cs35l56_shared_test_create_spkid_swnode(struct kunit *test, 461 + struct device *dev, 462 + const struct software_node_ref_args *args, 463 + int num_args) 464 + { 465 + struct cs35l56_shared_test_priv *priv = test->priv; 466 + const struct property_entry props_template[] = { 467 + PROPERTY_ENTRY_REF_ARRAY_LEN("spk-id-gpios", args, num_args), 468 + { } 469 + }; 470 + struct property_entry *props; 471 + struct software_node *node; 472 + 473 + props = kunit_kzalloc(test, sizeof(props_template), GFP_KERNEL); 474 + KUNIT_ASSERT_NOT_NULL(test, props); 475 + memcpy(props, props_template, sizeof(props_template)); 476 + 477 + node = kunit_kzalloc(test, sizeof(*node), GFP_KERNEL); 478 + KUNIT_ASSERT_NOT_NULL(test, node); 479 + *node = SOFTWARE_NODE("GSPK", props, NULL); 480 + 481 + KUNIT_ASSERT_EQ(test, device_add_software_node(dev, node), 0); 482 + KUNIT_ASSERT_EQ(test, 0, 483 + kunit_add_action_or_reset(test, 484 + device_remove_software_node_wrapper, 485 + priv->cs35l56_base->dev)); 486 + } 487 + 488 + static void cs35l56_shared_test_get_speaker_id_from_host_gpio(struct kunit *test) 489 + { 490 + const struct cs35l56_shared_test_param *param = test->param_value; 491 + struct cs35l56_shared_test_priv *priv = test->priv; 492 + struct cs35l56_base *cs35l56_base = priv->cs35l56_base; 493 + struct software_node_ref_args *ref; 494 + int i; 495 + 496 + if (!IS_REACHABLE(CONFIG_GPIOLIB)) { 497 + kunit_skip(test, "Requires CONFIG_GPIOLIB"); 498 + return; 499 + } 500 + 501 + _cs35l56_shared_test_create_dummy_gpio(test); 502 + 503 + ref = kunit_kcalloc(test, ARRAY_SIZE(param->spkid_gpios), sizeof(*ref), GFP_KERNEL); 504 + KUNIT_ASSERT_NOT_NULL(test, ref); 505 + 506 + for (i = 0; param->spkid_gpios[i] >= 0; i++) { 507 + ref[i] = SOFTWARE_NODE_REFERENCE(&cs35l56_shared_test_mock_gpio_swnode, 508 + param->spkid_gpios[i], 0); 509 + } 510 + _cs35l56_shared_test_create_spkid_swnode(test, cs35l56_base->dev, ref, i); 511 + 512 + priv->gpio_priv->pin_state = param->gpio_status; 513 + KUNIT_EXPECT_EQ(test, cs35l56_get_speaker_id(priv->cs35l56_base), param->spkid); 514 + } 515 + 509 516 static int cs35l56_shared_test_case_regmap_init(struct kunit *test, 510 517 const struct regmap_config *regmap_config) 511 518 { ··· 801 602 cs35l56_shared_test_onchip_spkid_pull_cases, 802 603 cs35l56_shared_test_gpio_param_desc); 803 604 605 + /* Note: spk-id-gpios property bit order is LSbit...MSbit */ 606 + static const struct cs35l56_shared_test_param cs35l56_shared_test_host_gpio_spkid_cases[] = { 607 + { .spkid_gpios = { 0, -1 }, .gpio_status = 0, .spkid = 0 }, 608 + { .spkid_gpios = { 0, -1 }, .gpio_status = ~BIT(0), .spkid = 0 }, 609 + { .spkid_gpios = { 0, -1 }, .gpio_status = BIT(0), .spkid = 1 }, 610 + 611 + { .spkid_gpios = { 6, -1 }, .gpio_status = 0, .spkid = 0 }, 612 + { .spkid_gpios = { 6, -1 }, .gpio_status = ~BIT(6), .spkid = 0 }, 613 + { .spkid_gpios = { 6, -1 }, .gpio_status = BIT(6), .spkid = 1 }, 614 + 615 + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = 0, .spkid = 0 }, 616 + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = ~(BIT(0) | BIT(6)), .spkid = 0 }, 617 + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(6), .spkid = 1 }, 618 + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(0), .spkid = 2 }, 619 + { .spkid_gpios = { 6, 0, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, 620 + 621 + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = 0, .spkid = 0 }, 622 + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = ~(BIT(6) | BIT(0)), .spkid = 0 }, 623 + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(0), .spkid = 1 }, 624 + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(6), .spkid = 2 }, 625 + { .spkid_gpios = { 0, 6, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, 626 + 627 + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = 0, .spkid = 0 }, 628 + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(0), .spkid = 1 }, 629 + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(6), .spkid = 2 }, 630 + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, 631 + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2), .spkid = 4 }, 632 + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(0), .spkid = 5 }, 633 + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(6), .spkid = 6 }, 634 + { .spkid_gpios = { 0, 6, 2, -1 }, .gpio_status = BIT(2) | BIT(6) | BIT(0), .spkid = 7 }, 635 + }; 636 + KUNIT_ARRAY_PARAM(cs35l56_shared_test_host_gpio_spkid, cs35l56_shared_test_host_gpio_spkid_cases, 637 + cs35l56_shared_test_gpio_param_desc); 638 + 804 639 static struct kunit_case cs35l56_shared_test_cases[] = { 805 640 /* Tests for speaker id */ 806 641 KUNIT_CASE_PARAM(cs35l56_shared_test_mock_gpio_status_selftest, ··· 849 616 cs35l56_shared_test_onchip_spkid_pull_gen_params), 850 617 KUNIT_CASE(cs35l56_shared_test_stash_onchip_spkid_pins_reject_invalid), 851 618 KUNIT_CASE(cs35l56_shared_test_onchip_speaker_id_not_defined), 619 + 620 + KUNIT_CASE(cs35l56_shared_test_get_speaker_id_vendor), 621 + KUNIT_CASE(cs35l56_shared_test_get_speaker_id_property), 622 + KUNIT_CASE_PARAM_ATTR(cs35l56_shared_test_get_speaker_id_from_host_gpio, 623 + cs35l56_shared_test_host_gpio_spkid_gen_params, 624 + { KUNIT_SPEED_SLOW }), 625 + 852 626 { } 853 627 }; 854 628
+80
sound/soc/codecs/cs35l56-test.c
··· 74 74 return ERR_PTR(-ENOENT); 75 75 } 76 76 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 + 77 149 static void cs35l56_test_l56_b0_suffix_sdw(struct kunit *test) 78 150 { 79 151 struct cs35l56_test_priv *priv = test->priv; ··· 668 596 cs35l56_test_type_rev_param_desc); 669 597 670 598 static struct kunit_case cs35l56_test_cases_soundwire[] = { 599 + KUNIT_CASE(cs35l56_test_system_name_from_ssid), 600 + KUNIT_CASE(cs35l56_test_system_name_from_ssid_and_spkid), 601 + KUNIT_CASE(cs35l56_test_system_name_from_property), 602 + KUNIT_CASE(cs35l56_test_system_name_from_property_and_spkid), 671 603 KUNIT_CASE(cs35l56_test_l56_b0_suffix_sdw), 672 604 KUNIT_CASE_PARAM(cs35l56_test_suffix_sdw, cs35l56_test_type_rev_ex_b0_gen_params), 673 605 KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_sdw, ··· 689 613 }; 690 614 691 615 static struct kunit_case cs35l56_test_cases_not_soundwire[] = { 616 + KUNIT_CASE(cs35l56_test_system_name_from_ssid), 617 + KUNIT_CASE(cs35l56_test_system_name_from_ssid_and_spkid), 618 + KUNIT_CASE(cs35l56_test_system_name_from_property), 619 + KUNIT_CASE(cs35l56_test_system_name_from_property_and_spkid), 692 620 KUNIT_CASE_PARAM(cs35l56_test_suffix_i2cspi, cs35l56_test_type_rev_all_gen_params), 693 621 KUNIT_CASE_PARAM(cs35l56_test_ssidexv2_suffix_i2cspi, 694 622 cs35l56_test_type_rev_all_gen_params),
+2 -1
sound/soc/codecs/cs35l56.c
··· 1661 1661 } 1662 1662 EXPORT_SYMBOL_IF_KUNIT(cs35l56_process_xu_properties); 1663 1663 1664 - static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) 1664 + VISIBLE_IF_KUNIT int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) 1665 1665 { 1666 1666 struct device *dev = cs35l56->base.dev; 1667 1667 const char *prop; ··· 1686 1686 1687 1687 return 0; 1688 1688 } 1689 + EXPORT_SYMBOL_IF_KUNIT(cs35l56_get_firmware_uid); 1689 1690 1690 1691 /* 1691 1692 * Some SoundWire laptops have a spk-id-gpios property but it points to
+1
sound/soc/codecs/cs35l56.h
··· 78 78 int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56); 79 79 int cs35l56_set_fw_name(struct snd_soc_component *component); 80 80 int cs35l56_process_xu_properties(struct cs35l56_private *cs35l56); 81 + int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56); 81 82 #endif 82 83 83 84 #endif /* ifndef CS35L56_H */