| // SPDX-License-Identifier: GPL-2.0-only | |
| // | |
| // KUnit test for the Cirrus Logic cs35l56-shared module. | |
| // | |
| // Copyright (C) 2026 Cirrus Logic, Inc. and | |
| // Cirrus Logic International Semiconductor Ltd. | |
| #include <kunit/resource.h> | |
| #include <kunit/test.h> | |
| #include <kunit/static_stub.h> | |
| #include <linux/bitfield.h> | |
| #include <linux/bitops.h> | |
| #include <linux/device/faux.h> | |
| #include <linux/gpio/driver.h> | |
| #include <linux/module.h> | |
| #include <linux/random.h> | |
| #include <linux/regmap.h> | |
| #include <linux/seq_buf.h> | |
| #include <sound/cs35l56.h> | |
| 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; | |
| unsigned int reg_offset; | |
| struct cs35l56_base *cs35l56_base; | |
| u8 applied_pad_pull_state[CS35L56_MAX_GPIO]; | |
| }; | |
| struct cs35l56_shared_test_param { | |
| int spkid_gpios[4]; | |
| int spkid_pulls[4]; | |
| unsigned long gpio_status; | |
| int spkid; | |
| }; | |
| KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy, | |
| struct faux_device *) | |
| 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 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, | |
| .reg_stride = 4, | |
| .max_register = CS35L56_DSP1_PMEM_5114, | |
| .cache_type = REGCACHE_MAPLE, | |
| }; | |
| static const struct regmap_bus cs35l56_shared_test_mock_registers_regmap_bus = { | |
| /* No handlers because it is always in cache-only */ | |
| }; | |
| static unsigned int cs35l56_shared_test_read_gpio_status(struct cs35l56_shared_test_priv *priv) | |
| { | |
| const struct cs35l56_shared_test_param *param = priv->test->param_value; | |
| unsigned int reg_offs, pad_cfg, val; | |
| unsigned int status = 0; | |
| unsigned int mask = 1; | |
| for (reg_offs = 0; reg_offs < CS35L56_MAX_GPIO * sizeof(u32); reg_offs += sizeof(u32)) { | |
| regmap_read(priv->registers, CS35L56_SYNC_GPIO1_CFG + reg_offs, &pad_cfg); | |
| regmap_read(priv->registers, CS35L56_GPIO1_CTRL1 + reg_offs, &val); | |
| /* Only read a value if set as an input pin and as a GPIO */ | |
| val &= (CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_MASK); | |
| if ((pad_cfg & CS35L56_PAD_GPIO_IE) && | |
| (val == (CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_GPIO))) | |
| status |= (param->gpio_status & mask); | |
| mask <<= 1; | |
| } | |
| return status; | |
| } | |
| static int cs35l56_shared_test_updt_gpio_pres(struct cs35l56_shared_test_priv *priv, | |
| unsigned int reg, unsigned int val) | |
| { | |
| int i, ret; | |
| ret = regmap_write(priv->registers, reg, val); | |
| if (ret) | |
| return ret; | |
| if (val & CS35L56_UPDT_GPIO_PRES) { | |
| /* Simulate transferring register state to internal latches */ | |
| for (i = 0; i < ARRAY_SIZE(priv->applied_pad_pull_state); i++) { | |
| reg = CS35L56_SYNC_GPIO1_CFG + (i * sizeof(u32)); | |
| regmap_read(priv->registers, reg, &val); | |
| val = FIELD_GET(CS35L56_PAD_GPIO_PULL_MASK, val); | |
| priv->applied_pad_pull_state[i] = val; | |
| } | |
| } | |
| return 0; | |
| } | |
| static int cs35l56_shared_test_reg_read(void *context, unsigned int reg, unsigned int *val) | |
| { | |
| struct cs35l56_shared_test_priv *priv = context; | |
| reg -= priv->reg_offset; | |
| switch (reg) { | |
| case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG: | |
| case CS35L56_GPIO1_CTRL1 ... CS35L56_GPIO13_CTRL1: | |
| return regmap_read(priv->registers, reg, val); | |
| case CS35L56_UPDATE_REGS: | |
| *val = 0; | |
| return 0; | |
| case CS35L56_GPIO_STATUS1: | |
| *val = cs35l56_shared_test_read_gpio_status(priv); | |
| return 0; | |
| default: | |
| kunit_fail_current_test("Bad regmap read address %#x\n", reg); | |
| return -EINVAL; | |
| } | |
| } | |
| static int cs35l56_shared_test_reg_write(void *context, unsigned int reg, unsigned int val) | |
| { | |
| struct cs35l56_shared_test_priv *priv = context; | |
| reg -= priv->reg_offset; | |
| switch (reg) { | |
| case CS35L56_UPDATE_REGS: | |
| return cs35l56_shared_test_updt_gpio_pres(priv, reg, val); | |
| case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG: | |
| case CS35L56_GPIO1_CTRL1 ... CS35L56_GPIO13_CTRL1: | |
| return regmap_write(priv->registers, reg, val); | |
| default: | |
| kunit_fail_current_test("Bad regmap write address %#x\n", reg); | |
| return -EINVAL; | |
| } | |
| } | |
| static const struct regmap_bus cs35l56_shared_test_regmap_bus = { | |
| .reg_read = cs35l56_shared_test_reg_read, | |
| .reg_write = cs35l56_shared_test_reg_write, | |
| .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, | |
| .val_format_endian_default = REGMAP_ENDIAN_LITTLE, | |
| }; | |
| /* | |
| * Self-test that the mock GPIO registers obey the configuration bits. | |
| * Other tests rely on the mocked registers only returning a GPIO state | |
| * if the pin is correctly set as a GPIO input. | |
| */ | |
| static void cs35l56_shared_test_mock_gpio_status_selftest(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; | |
| unsigned int reg, val; | |
| KUNIT_ASSERT_NOT_NULL(test, param); | |
| /* Set all pins non-GPIO and output. Mock GPIO_STATUS should read 0 */ | |
| for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); | |
| /* Set all pads as inputs */ | |
| for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_PAD_GPIO_IE)); | |
| KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); | |
| KUNIT_EXPECT_EQ(test, val, 0); | |
| /* Set all pins as GPIO outputs. Mock GPIO_STATUS should read 0 */ | |
| for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_GPIO_FN_GPIO)); | |
| KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); | |
| KUNIT_EXPECT_EQ(test, val, 0); | |
| /* Set all pins as non-GPIO inputs. Mock GPIO_STATUS should read 0 */ | |
| for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_GPIO_DIR_MASK)); | |
| KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); | |
| KUNIT_EXPECT_EQ(test, val, 0); | |
| /* Set all pins as GPIO inputs. Mock GPIO_STATUS should match param->gpio_status */ | |
| for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, | |
| regmap_write(priv->registers, reg, | |
| CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_GPIO)); | |
| KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); | |
| KUNIT_EXPECT_EQ(test, val, param->gpio_status); | |
| /* Set all pads as outputs. Mock GPIO_STATUS should read 0 */ | |
| for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); | |
| KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); | |
| KUNIT_EXPECT_EQ(test, val, 0); | |
| } | |
| /* Test that the listed chip pins are assembled into a speaker ID integer. */ | |
| static void cs35l56_shared_test_get_onchip_speaker_id(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; | |
| unsigned int i, reg; | |
| /* Set all pins non-GPIO and output */ | |
| for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); | |
| for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); | |
| /* Init GPIO array */ | |
| for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { | |
| if (param->spkid_gpios[i] < 0) | |
| break; | |
| cs35l56_base->onchip_spkid_gpios[i] = param->spkid_gpios[i] - 1; | |
| cs35l56_base->num_onchip_spkid_gpios++; | |
| } | |
| cs35l56_base->num_onchip_spkid_pulls = 0; | |
| KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0); | |
| KUNIT_EXPECT_EQ(test, cs35l56_read_onchip_spkid(cs35l56_base), param->spkid); | |
| } | |
| /* Test that the listed chip pins and the corresponding pads are configured correctly. */ | |
| static void cs35l56_shared_test_onchip_speaker_id_pad_config(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; | |
| unsigned int i, reg, val; | |
| /* Init values in all pin registers */ | |
| for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); | |
| for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32)) | |
| KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); | |
| /* Init GPIO array */ | |
| for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { | |
| if (param->spkid_gpios[i] < 0) | |
| break; | |
| cs35l56_base->onchip_spkid_gpios[i] = param->spkid_gpios[i] - 1; | |
| cs35l56_base->num_onchip_spkid_gpios++; | |
| } | |
| /* Init pulls array */ | |
| for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) { | |
| if (param->spkid_pulls[i] < 0) | |
| break; | |
| cs35l56_base->onchip_spkid_pulls[i] = param->spkid_pulls[i]; | |
| cs35l56_base->num_onchip_spkid_pulls++; | |
| } | |
| KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0); | |
| for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { | |
| if (param->spkid_gpios[i] < 0) | |
| break; | |
| /* Pad should be an input */ | |
| reg = CS35L56_SYNC_GPIO1_CFG + ((param->spkid_gpios[i] - 1) * sizeof(u32)); | |
| KUNIT_EXPECT_EQ(test, regmap_read(priv->registers, reg, &val), 0); | |
| KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_IE, CS35L56_PAD_GPIO_IE); | |
| /* Specified pulls should be set, others should be none */ | |
| if (i < cs35l56_base->num_onchip_spkid_pulls) { | |
| KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_PULL_MASK, | |
| FIELD_PREP(CS35L56_PAD_GPIO_PULL_MASK, | |
| param->spkid_pulls[i])); | |
| } else { | |
| KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_PULL_MASK, | |
| CS35L56_PAD_PULL_NONE); | |
| } | |
| /* Pulls for all specfied GPIOs should have been transferred to AO latch */ | |
| if (i < cs35l56_base->num_onchip_spkid_pulls) { | |
| KUNIT_EXPECT_EQ(test, | |
| priv->applied_pad_pull_state[param->spkid_gpios[i] - 1], | |
| param->spkid_pulls[i]); | |
| } else { | |
| KUNIT_EXPECT_EQ(test, | |
| priv->applied_pad_pull_state[param->spkid_gpios[i] - 1], | |
| CS35L56_PAD_PULL_NONE); | |
| } | |
| } | |
| } | |
| /* Test that the listed chip pins are stashed correctly. */ | |
| static void cs35l56_shared_test_stash_onchip_spkid_pins(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; | |
| u32 gpios[5], pulls[5]; | |
| int i, num_gpios, num_pulls; | |
| static_assert(ARRAY_SIZE(gpios) >= ARRAY_SIZE(param->spkid_gpios)); | |
| static_assert(ARRAY_SIZE(pulls) >= ARRAY_SIZE(param->spkid_pulls)); | |
| num_gpios = 0; | |
| for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { | |
| if (param->spkid_gpios[i] < 0) | |
| break; | |
| gpios[i] = (u32)param->spkid_gpios[i]; | |
| num_gpios++; | |
| } | |
| num_pulls = 0; | |
| for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) { | |
| if (param->spkid_pulls[i] < 0) | |
| break; | |
| pulls[i] = (u32)param->spkid_pulls[i]; | |
| num_pulls++; | |
| } | |
| cs35l56_base->num_onchip_spkid_gpios = 0; | |
| cs35l56_base->num_onchip_spkid_pulls = 0; | |
| KUNIT_ASSERT_LE(test, num_gpios, ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios)); | |
| KUNIT_ASSERT_LE(test, num_pulls, ARRAY_SIZE(cs35l56_base->onchip_spkid_pulls)); | |
| KUNIT_EXPECT_EQ(test, | |
| cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, | |
| gpios, num_gpios, | |
| pulls, num_pulls), | |
| 0); | |
| KUNIT_EXPECT_EQ(test, cs35l56_base->num_onchip_spkid_gpios, num_gpios); | |
| KUNIT_EXPECT_EQ(test, cs35l56_base->num_onchip_spkid_pulls, num_pulls); | |
| /* GPIO numbers are adjusted from 1-based to 0-based */ | |
| for (i = 0; i < num_gpios; i++) | |
| KUNIT_EXPECT_EQ(test, cs35l56_base->onchip_spkid_gpios[i], gpios[i] - 1); | |
| for (i = 0; i < num_pulls; i++) | |
| KUNIT_EXPECT_EQ(test, cs35l56_base->onchip_spkid_pulls[i], pulls[i]); | |
| } | |
| /* Test that illegal GPIO numbers are rejected. */ | |
| static void cs35l56_shared_test_stash_onchip_spkid_pins_reject_invalid(struct kunit *test) | |
| { | |
| struct cs35l56_shared_test_priv *priv = test->priv; | |
| struct cs35l56_base *cs35l56_base = priv->cs35l56_base; | |
| u32 gpios[8] = { }, pulls[8] = { }; | |
| KUNIT_EXPECT_LE(test, | |
| cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, | |
| gpios, 1, | |
| pulls, 0), | |
| 0); | |
| switch (cs35l56_base->type) { | |
| case 0x54: | |
| case 0x56: | |
| case 0x57: | |
| gpios[0] = CS35L56_MAX_GPIO + 1; | |
| break; | |
| case 0x63: | |
| gpios[0] = CS35L63_MAX_GPIO + 1; | |
| break; | |
| default: | |
| kunit_fail_current_test("Unsupported type:%#x\n", cs35l56_base->type); | |
| return; | |
| } | |
| KUNIT_EXPECT_LE(test, | |
| cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, | |
| gpios, 1, | |
| pulls, 0), | |
| 0); | |
| gpios[0] = 1; | |
| pulls[0] = 3; | |
| KUNIT_EXPECT_LE(test, | |
| cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, | |
| gpios, 1, | |
| pulls, 1), | |
| 0); | |
| static_assert(ARRAY_SIZE(gpios) > ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios)); | |
| static_assert(ARRAY_SIZE(pulls) > ARRAY_SIZE(cs35l56_base->onchip_spkid_pulls)); | |
| KUNIT_EXPECT_EQ(test, | |
| cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, | |
| gpios, ARRAY_SIZE(gpios), | |
| pulls, 0), | |
| -EOVERFLOW); | |
| KUNIT_EXPECT_EQ(test, | |
| cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, | |
| gpios, 1, | |
| pulls, ARRAY_SIZE(pulls)), | |
| -EOVERFLOW); | |
| } | |
| static void cs35l56_shared_test_onchip_speaker_id_not_defined(struct kunit *test) | |
| { | |
| struct cs35l56_shared_test_priv *priv = test->priv; | |
| struct cs35l56_base *cs35l56_base = priv->cs35l56_base; | |
| memset(cs35l56_base->onchip_spkid_gpios, 0, sizeof(cs35l56_base->onchip_spkid_gpios)); | |
| memset(cs35l56_base->onchip_spkid_pulls, 0, sizeof(cs35l56_base->onchip_spkid_pulls)); | |
| cs35l56_base->num_onchip_spkid_gpios = 0; | |
| cs35l56_base->num_onchip_spkid_pulls = 0; | |
| KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0); | |
| 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); | |
| } | |
| /* | |
| * 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) | |
| { | |
| struct cs35l56_shared_test_priv *priv = test->priv; | |
| struct cs35l56_base *cs35l56_base; | |
| /* | |
| * Create a dummy regmap to simulate a register map by holding the | |
| * values of all simulated registers in the regmap cache. | |
| */ | |
| priv->registers = regmap_init(&priv->amp_dev->dev, | |
| &cs35l56_shared_test_mock_registers_regmap_bus, | |
| priv, | |
| &cs35l56_shared_test_mock_registers_regmap); | |
| KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->registers); | |
| KUNIT_ASSERT_EQ(test, 0, | |
| kunit_add_action_or_reset(test, regmap_exit_wrapper, | |
| priv->registers)); | |
| regcache_cache_only(priv->registers, true); | |
| /* Create dummy regmap for cs35l56 driver */ | |
| cs35l56_base = priv->cs35l56_base; | |
| cs35l56_base->regmap = regmap_init(cs35l56_base->dev, | |
| &cs35l56_shared_test_regmap_bus, | |
| priv, | |
| regmap_config); | |
| KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cs35l56_base->regmap); | |
| KUNIT_ASSERT_EQ(test, 0, | |
| kunit_add_action_or_reset(test, regmap_exit_wrapper, | |
| cs35l56_base->regmap)); | |
| return 0; | |
| } | |
| static int cs35l56_shared_test_case_base_init(struct kunit *test, u8 type, u8 rev, | |
| const struct regmap_config *regmap_config) | |
| { | |
| struct cs35l56_shared_test_priv *priv; | |
| int ret; | |
| KUNIT_ASSERT_NOT_NULL(test, cs_amp_test_hooks); | |
| priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); | |
| if (!priv) | |
| return -ENOMEM; | |
| test->priv = priv; | |
| priv->test = test; | |
| /* Create dummy amp driver dev */ | |
| priv->amp_dev = faux_device_create("cs35l56_shared_test_drv", NULL, NULL); | |
| KUNIT_ASSERT_NOT_NULL(test, priv->amp_dev); | |
| KUNIT_ASSERT_EQ(test, 0, | |
| kunit_add_action_or_reset(test, | |
| faux_device_destroy_wrapper, | |
| priv->amp_dev)); | |
| priv->cs35l56_base = kunit_kzalloc(test, sizeof(*priv->cs35l56_base), GFP_KERNEL); | |
| KUNIT_ASSERT_NOT_NULL(test, priv->cs35l56_base); | |
| priv->cs35l56_base->dev = &priv->amp_dev->dev; | |
| priv->cs35l56_base->type = type; | |
| priv->cs35l56_base->rev = rev; | |
| if (regmap_config) { | |
| priv->reg_offset = regmap_config->reg_base; | |
| ret = cs35l56_shared_test_case_regmap_init(test, regmap_config); | |
| if (ret) | |
| return ret; | |
| } | |
| return 0; | |
| } | |
| static int cs35l56_shared_test_case_regmap_init_L56_B0_sdw(struct kunit *test) | |
| { | |
| return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_sdw); | |
| } | |
| static int cs35l56_shared_test_case_regmap_init_L56_B0_spi(struct kunit *test) | |
| { | |
| return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_spi); | |
| } | |
| static int cs35l56_shared_test_case_regmap_init_L56_B0_i2c(struct kunit *test) | |
| { | |
| return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_i2c); | |
| } | |
| static int cs35l56_shared_test_case_regmap_init_L56_B2_sdw(struct kunit *test) | |
| { | |
| return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_sdw); | |
| } | |
| static int cs35l56_shared_test_case_regmap_init_L56_B2_spi(struct kunit *test) | |
| { | |
| return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_spi); | |
| } | |
| static int cs35l56_shared_test_case_regmap_init_L56_B2_i2c(struct kunit *test) | |
| { | |
| return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_i2c); | |
| } | |
| static int cs35l56_shared_test_case_regmap_init_L63_A1_sdw(struct kunit *test) | |
| { | |
| return cs35l56_shared_test_case_base_init(test, 0x63, 0xa1, &cs35l63_regmap_sdw); | |
| } | |
| static void cs35l56_shared_test_gpio_param_desc(const struct cs35l56_shared_test_param *param, | |
| char *desc) | |
| { | |
| DECLARE_SEQ_BUF(gpios, 1 + (2 * ARRAY_SIZE(param->spkid_gpios))); | |
| DECLARE_SEQ_BUF(pulls, 1 + (2 * ARRAY_SIZE(param->spkid_pulls))); | |
| int i; | |
| for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { | |
| if (param->spkid_gpios[i] < 0) | |
| break; | |
| seq_buf_printf(&gpios, "%s%d", (i == 0) ? "" : ",", param->spkid_gpios[i]); | |
| } | |
| for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) { | |
| if (param->spkid_pulls[i] < 0) | |
| break; | |
| seq_buf_printf(&pulls, "%s%d", (i == 0) ? "" : ",", param->spkid_pulls[i]); | |
| } | |
| snprintf(desc, KUNIT_PARAM_DESC_SIZE, "gpios:{%s} pulls:{%s} status:%#lx spkid:%d", | |
| seq_buf_str(&gpios), seq_buf_str(&pulls), param->gpio_status, param->spkid); | |
| } | |
| static const struct cs35l56_shared_test_param cs35l56_shared_test_gpios_selftest_cases[] = { | |
| { .spkid_gpios = { -1 }, .gpio_status = GENMASK(12, 0) }, | |
| }; | |
| KUNIT_ARRAY_PARAM(cs35l56_shared_test_gpios_selftest, | |
| cs35l56_shared_test_gpios_selftest_cases, | |
| cs35l56_shared_test_gpio_param_desc); | |
| static const struct cs35l56_shared_test_param cs35l56_shared_test_onchip_spkid_cases[] = { | |
| { .spkid_gpios = { 1, -1 }, .gpio_status = 0, .spkid = 0 }, | |
| { .spkid_gpios = { 1, -1 }, .gpio_status = ~BIT(0), .spkid = 0 }, | |
| { .spkid_gpios = { 1, -1 }, .gpio_status = BIT(0), .spkid = 1 }, | |
| { .spkid_gpios = { 7, -1 }, .gpio_status = 0, .spkid = 0 }, | |
| { .spkid_gpios = { 7, -1 }, .gpio_status = ~BIT(6), .spkid = 0 }, | |
| { .spkid_gpios = { 7, -1 }, .gpio_status = BIT(6), .spkid = 1 }, | |
| { .spkid_gpios = { 1, 7, -1 }, .gpio_status = 0, .spkid = 0 }, | |
| { .spkid_gpios = { 1, 7, -1 }, .gpio_status = ~(BIT(0) | BIT(6)), .spkid = 0 }, | |
| { .spkid_gpios = { 1, 7, -1 }, .gpio_status = BIT(6), .spkid = 1 }, | |
| { .spkid_gpios = { 1, 7, -1 }, .gpio_status = BIT(0), .spkid = 2 }, | |
| { .spkid_gpios = { 1, 7, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, | |
| { .spkid_gpios = { 7, 1, -1 }, .gpio_status = 0, .spkid = 0 }, | |
| { .spkid_gpios = { 7, 1, -1 }, .gpio_status = ~(BIT(6) | BIT(0)), .spkid = 0 }, | |
| { .spkid_gpios = { 7, 1, -1 }, .gpio_status = BIT(0), .spkid = 1 }, | |
| { .spkid_gpios = { 7, 1, -1 }, .gpio_status = BIT(6), .spkid = 2 }, | |
| { .spkid_gpios = { 7, 1, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = 0, .spkid = 0 }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(0), .spkid = 1 }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(6), .spkid = 2 }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2), .spkid = 4 }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(0), .spkid = 5 }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(6), .spkid = 6 }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(6) | BIT(0), .spkid = 7 }, | |
| }; | |
| KUNIT_ARRAY_PARAM(cs35l56_shared_test_onchip_spkid, cs35l56_shared_test_onchip_spkid_cases, | |
| cs35l56_shared_test_gpio_param_desc); | |
| static const struct cs35l56_shared_test_param cs35l56_shared_test_onchip_spkid_pull_cases[] = { | |
| { .spkid_gpios = { 1, -1 }, .spkid_pulls = { 1, -1 }, }, | |
| { .spkid_gpios = { 1, -1 }, .spkid_pulls = { 2, -1 }, }, | |
| { .spkid_gpios = { 7, -1 }, .spkid_pulls = { 1, -1 }, }, | |
| { .spkid_gpios = { 7, -1 }, .spkid_pulls = { 2, -1 }, }, | |
| { .spkid_gpios = { 1, 7, -1 }, .spkid_pulls = { 1, 1, -1 }, }, | |
| { .spkid_gpios = { 1, 7, -1 }, .spkid_pulls = { 2, 2, -1 }, }, | |
| { .spkid_gpios = { 7, 1, -1 }, .spkid_pulls = { 1, 1, -1 }, }, | |
| { .spkid_gpios = { 7, 1, -1 }, .spkid_pulls = { 2, 2, -1 }, }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .spkid_pulls = { 1, 1, 1, -1 }, }, | |
| { .spkid_gpios = { 3, 7, 1, -1 }, .spkid_pulls = { 2, 2, 2, -1 }, }, | |
| }; | |
| 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, | |
| cs35l56_shared_test_gpios_selftest_gen_params), | |
| KUNIT_CASE_PARAM(cs35l56_shared_test_get_onchip_speaker_id, | |
| cs35l56_shared_test_onchip_spkid_gen_params), | |
| KUNIT_CASE_PARAM(cs35l56_shared_test_onchip_speaker_id_pad_config, | |
| cs35l56_shared_test_onchip_spkid_gen_params), | |
| KUNIT_CASE_PARAM(cs35l56_shared_test_onchip_speaker_id_pad_config, | |
| cs35l56_shared_test_onchip_spkid_pull_gen_params), | |
| KUNIT_CASE_PARAM(cs35l56_shared_test_stash_onchip_spkid_pins, | |
| 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), | |
| KUNIT_CASE_PARAM_ATTR(cs35l56_shared_test_get_speaker_id_from_host_gpio, | |
| cs35l56_shared_test_host_gpio_spkid_gen_params, | |
| { KUNIT_SPEED_SLOW }), | |
| { } | |
| }; | |
| static struct kunit_suite cs35l56_shared_test_suite_L56_B0_sdw = { | |
| .name = "snd-soc-cs35l56-shared-test_L56_B0_sdw", | |
| .init = cs35l56_shared_test_case_regmap_init_L56_B0_sdw, | |
| .test_cases = cs35l56_shared_test_cases, | |
| }; | |
| static struct kunit_suite cs35l56_shared_test_suite_L56_B2_sdw = { | |
| .name = "snd-soc-cs35l56-shared-test_L56_B2_sdw", | |
| .init = cs35l56_shared_test_case_regmap_init_L56_B2_sdw, | |
| .test_cases = cs35l56_shared_test_cases, | |
| }; | |
| static struct kunit_suite cs35l56_shared_test_suite_L63_A1_sdw = { | |
| .name = "snd-soc-cs35l56-shared-test_L63_A1_sdw", | |
| .init = cs35l56_shared_test_case_regmap_init_L63_A1_sdw, | |
| .test_cases = cs35l56_shared_test_cases, | |
| }; | |
| static struct kunit_suite cs35l56_shared_test_suite_L56_B0_spi = { | |
| .name = "snd-soc-cs35l56-shared-test_L56_B0_spi", | |
| .init = cs35l56_shared_test_case_regmap_init_L56_B0_spi, | |
| .test_cases = cs35l56_shared_test_cases, | |
| }; | |
| static struct kunit_suite cs35l56_shared_test_suite_L56_B2_spi = { | |
| .name = "snd-soc-cs35l56-shared-test_L56_B2_spi", | |
| .init = cs35l56_shared_test_case_regmap_init_L56_B2_spi, | |
| .test_cases = cs35l56_shared_test_cases, | |
| }; | |
| static struct kunit_suite cs35l56_shared_test_suite_L56_B0_i2c = { | |
| .name = "snd-soc-cs35l56-shared-test_L56_B0_i2c", | |
| .init = cs35l56_shared_test_case_regmap_init_L56_B0_i2c, | |
| .test_cases = cs35l56_shared_test_cases, | |
| }; | |
| static struct kunit_suite cs35l56_shared_test_suite_L56_B2_i2c = { | |
| .name = "snd-soc-cs35l56-shared-test_L56_B2_i2c", | |
| .init = cs35l56_shared_test_case_regmap_init_L56_B2_i2c, | |
| .test_cases = cs35l56_shared_test_cases, | |
| }; | |
| kunit_test_suites( | |
| &cs35l56_shared_test_suite_L56_B0_sdw, | |
| &cs35l56_shared_test_suite_L56_B2_sdw, | |
| &cs35l56_shared_test_suite_L63_A1_sdw, | |
| &cs35l56_shared_test_suite_L56_B0_spi, | |
| &cs35l56_shared_test_suite_L56_B2_spi, | |
| &cs35l56_shared_test_suite_L56_B0_i2c, | |
| &cs35l56_shared_test_suite_L56_B2_i2c, | |
| ); | |
| MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED"); | |
| MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB"); | |
| MODULE_DESCRIPTION("KUnit test for cs35l56-shared module"); | |
| MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); | |
| MODULE_LICENSE("GPL"); |