diff options
Diffstat (limited to 'drivers/firmware/cirrus/test/cs_dsp_test_callbacks.c')
-rw-r--r-- | drivers/firmware/cirrus/test/cs_dsp_test_callbacks.c | 688 |
1 files changed, 688 insertions, 0 deletions
diff --git a/drivers/firmware/cirrus/test/cs_dsp_test_callbacks.c b/drivers/firmware/cirrus/test/cs_dsp_test_callbacks.c new file mode 100644 index 000000000000..8a9b66a3b7d3 --- /dev/null +++ b/drivers/firmware/cirrus/test/cs_dsp_test_callbacks.c @@ -0,0 +1,688 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// KUnit tests for cs_dsp. +// +// Copyright (C) 2024 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. +// + +#include <kunit/device.h> +#include <kunit/resource.h> +#include <kunit/test.h> +#include <kunit/test-bug.h> +#include <linux/build_bug.h> +#include <linux/firmware/cirrus/cs_dsp.h> +#include <linux/firmware/cirrus/cs_dsp_test_utils.h> +#include <linux/firmware/cirrus/wmfw.h> +#include <linux/random.h> +#include <linux/regmap.h> +#include <linux/string.h> +#include <linux/vmalloc.h> + +#define ADSP2_LOCK_REGION_CTRL 0x7A +#define ADSP2_WDT_TIMEOUT_STS_MASK 0x2000 + +KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *) +KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *) + +struct cs_dsp_test_local { + struct cs_dsp_mock_wmfw_builder *wmfw_builder; + + int num_control_add; + int num_control_remove; + int num_pre_run; + int num_post_run; + int num_pre_stop; + int num_post_stop; + int num_watchdog_expired; + + struct cs_dsp_coeff_ctl *passed_ctl[16]; + struct cs_dsp *passed_dsp; +}; + +struct cs_dsp_callbacks_test_param { + const struct cs_dsp_client_ops *ops; + const char *case_name; +}; + +static const struct cs_dsp_mock_alg_def cs_dsp_callbacks_test_mock_algs[] = { + { + .id = 0xfafa, + .ver = 0x100000, + .xm_size_words = 164, + .ym_size_words = 164, + .zm_size_words = 164, + }, +}; + +static const struct cs_dsp_mock_coeff_def mock_coeff_template = { + .shortname = "Dummy Coeff", + .type = WMFW_CTL_TYPE_BYTES, + .mem_type = WMFW_ADSP2_YM, + .flags = WMFW_CTL_FLAG_VOLATILE, + .length_bytes = 4, +}; + +static int cs_dsp_test_control_add_callback(struct cs_dsp_coeff_ctl *ctl) +{ + struct kunit *test = kunit_get_current_test(); + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + + local->passed_ctl[local->num_control_add] = ctl; + local->num_control_add++; + + return 0; +} + +static void cs_dsp_test_control_remove_callback(struct cs_dsp_coeff_ctl *ctl) +{ + struct kunit *test = kunit_get_current_test(); + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + + local->passed_ctl[local->num_control_remove] = ctl; + local->num_control_remove++; +} + +static int cs_dsp_test_pre_run_callback(struct cs_dsp *dsp) +{ + struct kunit *test = kunit_get_current_test(); + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + + local->passed_dsp = dsp; + local->num_pre_run++; + + return 0; +} + +static int cs_dsp_test_post_run_callback(struct cs_dsp *dsp) +{ + struct kunit *test = kunit_get_current_test(); + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + + local->passed_dsp = dsp; + local->num_post_run++; + + return 0; +} + +static void cs_dsp_test_pre_stop_callback(struct cs_dsp *dsp) +{ + struct kunit *test = kunit_get_current_test(); + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + + local->passed_dsp = dsp; + local->num_pre_stop++; +} + +static void cs_dsp_test_post_stop_callback(struct cs_dsp *dsp) +{ + struct kunit *test = kunit_get_current_test(); + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + + local->passed_dsp = dsp; + local->num_post_stop++; +} + +static void cs_dsp_test_watchdog_expired_callback(struct cs_dsp *dsp) +{ + struct kunit *test = kunit_get_current_test(); + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + + local->passed_dsp = dsp; + local->num_watchdog_expired++; +} + +static const struct cs_dsp_client_ops cs_dsp_callback_test_client_ops = { + .control_add = cs_dsp_test_control_add_callback, + .control_remove = cs_dsp_test_control_remove_callback, + .pre_run = cs_dsp_test_pre_run_callback, + .post_run = cs_dsp_test_post_run_callback, + .pre_stop = cs_dsp_test_pre_stop_callback, + .post_stop = cs_dsp_test_post_stop_callback, + .watchdog_expired = cs_dsp_test_watchdog_expired_callback, +}; + +static const struct cs_dsp_client_ops cs_dsp_callback_test_empty_client_ops = { + /* No entries */ +}; + +static void cs_dsp_test_run_stop_callbacks(struct kunit *test) +{ + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + struct firmware *wmfw; + + wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); + + KUNIT_EXPECT_EQ(test, + cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"), + 0); + + KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0); + KUNIT_EXPECT_EQ(test, local->num_pre_run, 1); + KUNIT_EXPECT_EQ(test, local->num_post_run, 1); + KUNIT_EXPECT_EQ(test, local->num_pre_stop, 0); + KUNIT_EXPECT_EQ(test, local->num_post_stop, 0); + KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp); + local->passed_dsp = NULL; + + cs_dsp_stop(priv->dsp); + KUNIT_EXPECT_EQ(test, local->num_pre_run, 1); + KUNIT_EXPECT_EQ(test, local->num_post_run, 1); + KUNIT_EXPECT_EQ(test, local->num_pre_stop, 1); + KUNIT_EXPECT_EQ(test, local->num_post_stop, 1); + KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp); + local->passed_dsp = NULL; + + KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0); + KUNIT_EXPECT_EQ(test, local->num_pre_run, 2); + KUNIT_EXPECT_EQ(test, local->num_post_run, 2); + KUNIT_EXPECT_EQ(test, local->num_pre_stop, 1); + KUNIT_EXPECT_EQ(test, local->num_post_stop, 1); + KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp); + local->passed_dsp = NULL; + + cs_dsp_stop(priv->dsp); + KUNIT_EXPECT_EQ(test, local->num_pre_run, 2); + KUNIT_EXPECT_EQ(test, local->num_post_run, 2); + KUNIT_EXPECT_EQ(test, local->num_pre_stop, 2); + KUNIT_EXPECT_EQ(test, local->num_post_stop, 2); + KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp); + local->passed_dsp = NULL; +} + +static void cs_dsp_test_ctl_v1_callbacks(struct kunit *test) +{ + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + struct cs_dsp_mock_coeff_def def = mock_coeff_template; + struct cs_dsp_coeff_ctl *ctl; + struct firmware *wmfw; + int i; + + /* Add a control for each memory */ + cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, + cs_dsp_callbacks_test_mock_algs[0].id, + "dummyalg", NULL); + def.shortname = "zm"; + def.mem_type = WMFW_ADSP2_ZM; + cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); + + def.shortname = "ym"; + def.mem_type = WMFW_ADSP2_YM; + cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); + + def.shortname = "xm"; + def.mem_type = WMFW_ADSP2_XM; + cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); + + cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); + + wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); + KUNIT_EXPECT_EQ(test, + cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"), + 0); + + /* There should have been an add callback for each control */ + KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 3); + KUNIT_EXPECT_EQ(test, local->num_control_add, 3); + KUNIT_EXPECT_EQ(test, local->num_control_remove, 0); + + i = 0; + list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list) + KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl); + + /* + * Call cs_dsp_remove() and there should be a remove callback + * for each control + */ + memset(local->passed_ctl, 0, sizeof(local->passed_ctl)); + cs_dsp_remove(priv->dsp); + + /* Prevent double cleanup */ + kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp); + + KUNIT_EXPECT_EQ(test, local->num_control_add, 3); + KUNIT_EXPECT_EQ(test, local->num_control_remove, 3); + + i = 0; + list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list) + KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl); +} + +static void cs_dsp_test_ctl_v2_callbacks(struct kunit *test) +{ + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + struct cs_dsp_mock_coeff_def def = mock_coeff_template; + struct cs_dsp_coeff_ctl *ctl; + struct firmware *wmfw; + char name[2] = { }; + int i; + + /* Add some controls */ + def.shortname = name; + cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, + cs_dsp_callbacks_test_mock_algs[0].id, + "dummyalg", NULL); + for (i = 0; i < ARRAY_SIZE(local->passed_ctl); ++i) { + name[0] = 'A' + i; + def.offset_dsp_words = i; + cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); + } + cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); + + wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); + KUNIT_EXPECT_EQ(test, + cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"), + 0); + + /* There should have been an add callback for each control */ + KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), + ARRAY_SIZE(local->passed_ctl)); + KUNIT_EXPECT_EQ(test, local->num_control_add, ARRAY_SIZE(local->passed_ctl)); + KUNIT_EXPECT_EQ(test, local->num_control_remove, 0); + + i = 0; + list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list) + KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl); + + /* + * Call cs_dsp_remove() and there should be a remove callback + * for each control + */ + memset(local->passed_ctl, 0, sizeof(local->passed_ctl)); + cs_dsp_remove(priv->dsp); + + /* Prevent double cleanup */ + kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp); + + KUNIT_EXPECT_EQ(test, local->num_control_add, ARRAY_SIZE(local->passed_ctl)); + KUNIT_EXPECT_EQ(test, local->num_control_remove, ARRAY_SIZE(local->passed_ctl)); + + i = 0; + list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list) + KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl); +} + +static void cs_dsp_test_no_callbacks(struct kunit *test) +{ + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + struct cs_dsp_mock_coeff_def def = mock_coeff_template; + struct firmware *wmfw; + + /* Add a controls */ + def.shortname = "A"; + cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, + cs_dsp_callbacks_test_mock_algs[0].id, + "dummyalg", NULL); + cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); + cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); + + wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); + + /* Run a sequence of ops that would invoke callbacks */ + KUNIT_EXPECT_EQ(test, + cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"), + 0); + KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0); + cs_dsp_stop(priv->dsp); + cs_dsp_remove(priv->dsp); + + /* Prevent double cleanup */ + kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp); + + /* Something went very wrong if any of our callbacks were called */ + KUNIT_EXPECT_EQ(test, local->num_control_add, 0); + KUNIT_EXPECT_EQ(test, local->num_control_remove, 0); + KUNIT_EXPECT_EQ(test, local->num_pre_run, 0); + KUNIT_EXPECT_EQ(test, local->num_post_run, 0); + KUNIT_EXPECT_EQ(test, local->num_pre_stop, 0); + KUNIT_EXPECT_EQ(test, local->num_post_stop, 0); +} + +static void cs_dsp_test_adsp2v2_watchdog_callback(struct kunit *test) +{ + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + struct firmware *wmfw; + + wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); + + KUNIT_EXPECT_EQ(test, + cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"), + 0); + + KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0); + + /* Set the watchdog timeout bit */ + regmap_write(priv->dsp->regmap, priv->dsp->base + ADSP2_LOCK_REGION_CTRL, + ADSP2_WDT_TIMEOUT_STS_MASK); + + /* Notify an interrupt and the watchdog callback should be called */ + cs_dsp_adsp2_bus_error(priv->dsp); + KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 1); + KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp); +} + +static void cs_dsp_test_adsp2v2_watchdog_no_callbacks(struct kunit *test) +{ + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + struct firmware *wmfw; + + wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); + KUNIT_EXPECT_EQ(test, + cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"), + 0); + KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0); + + /* Set the watchdog timeout bit */ + regmap_write(priv->dsp->regmap, priv->dsp->base + ADSP2_LOCK_REGION_CTRL, + ADSP2_WDT_TIMEOUT_STS_MASK); + + /* Notify an interrupt, which will look for a watchdog callback */ + cs_dsp_adsp2_bus_error(priv->dsp); + KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 0); +} + +static void cs_dsp_test_halo_watchdog_callback(struct kunit *test) +{ + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + struct firmware *wmfw; + + wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); + + KUNIT_EXPECT_EQ(test, + cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"), + 0); + + KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0); + + /* Notify an interrupt and the watchdog callback should be called */ + cs_dsp_halo_wdt_expire(priv->dsp); + KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 1); + KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp); +} + +static void cs_dsp_test_halo_watchdog_no_callbacks(struct kunit *test) +{ + struct cs_dsp_test *priv = test->priv; + struct cs_dsp_test_local *local = priv->local; + struct firmware *wmfw; + + wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); + KUNIT_EXPECT_EQ(test, + cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"), + 0); + KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0); + + /* Notify an interrupt, which will look for a watchdog callback */ + cs_dsp_halo_wdt_expire(priv->dsp); + KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 0); +} + +static int cs_dsp_callbacks_test_common_init(struct kunit *test, struct cs_dsp *dsp, + int wmfw_version) +{ + const struct cs_dsp_callbacks_test_param *param = test->param_value; + struct cs_dsp_test *priv; + struct cs_dsp_test_local *local; + struct device *test_dev; + struct cs_dsp_mock_xm_header *xm_header; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL); + if (!local) + return -ENOMEM; + + priv->test = test; + priv->dsp = dsp; + test->priv = priv; + priv->local = local; + + /* Create dummy struct device */ + test_dev = kunit_device_register(test, "cs_dsp_test_drv"); + if (IS_ERR(test_dev)) + return PTR_ERR(test_dev); + + dsp->dev = get_device(test_dev); + if (!dsp->dev) + return -ENODEV; + + ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev); + if (ret) + return ret; + + dev_set_drvdata(dsp->dev, priv); + + /* Allocate regmap */ + ret = cs_dsp_mock_regmap_init(priv); + if (ret) + return ret; + + /* + * There must always be a XM header with at least 1 algorithm, + * so create a dummy one and pre-populate XM so the wmfw doesn't + * have to contain an XM blob. + */ + xm_header = cs_dsp_create_mock_xm_header(priv, + cs_dsp_callbacks_test_mock_algs, + ARRAY_SIZE(cs_dsp_callbacks_test_mock_algs)); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xm_header); + cs_dsp_mock_xm_header_write_to_regmap(xm_header); + + local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, wmfw_version); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->wmfw_builder); + + /* Add dummy XM header payload to wmfw */ + cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder, + WMFW_ADSP2_XM, 0, + xm_header->blob_data, + xm_header->blob_size_bytes); + + /* Init cs_dsp */ + dsp->client_ops = param->ops; + + switch (dsp->type) { + case WMFW_ADSP2: + ret = cs_dsp_adsp2_init(dsp); + break; + case WMFW_HALO: + ret = cs_dsp_halo_init(dsp); + break; + default: + KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type); + return -EINVAL; + } + + if (ret) + return ret; + + /* Automatically call cs_dsp_remove() when test case ends */ + return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp); +} + +static int cs_dsp_callbacks_test_halo_init(struct kunit *test) +{ + struct cs_dsp *dsp; + + /* Fill in cs_dsp and initialize */ + dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); + if (!dsp) + return -ENOMEM; + + dsp->num = 1; + dsp->type = WMFW_HALO; + dsp->mem = cs_dsp_mock_halo_dsp1_regions; + dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes); + dsp->base = cs_dsp_mock_halo_core_base; + dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base; + + return cs_dsp_callbacks_test_common_init(test, dsp, 3); +} + +static int cs_dsp_callbacks_test_adsp2_32bit_init(struct kunit *test, int rev) +{ + struct cs_dsp *dsp; + + /* Fill in cs_dsp and initialize */ + dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); + if (!dsp) + return -ENOMEM; + + dsp->num = 1; + dsp->type = WMFW_ADSP2; + dsp->rev = rev; + dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions; + dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes); + dsp->base = cs_dsp_mock_adsp2_32bit_sysbase; + + return cs_dsp_callbacks_test_common_init(test, dsp, 2); +} + +static int cs_dsp_callbacks_test_adsp2v2_32bit_init(struct kunit *test) +{ + return cs_dsp_callbacks_test_adsp2_32bit_init(test, 2); +} + +static int cs_dsp_callbacks_test_adsp2v1_32bit_init(struct kunit *test) +{ + return cs_dsp_callbacks_test_adsp2_32bit_init(test, 1); +} + +static int cs_dsp_callbacks_test_adsp2_16bit_init(struct kunit *test) +{ + struct cs_dsp *dsp; + + /* Fill in cs_dsp and initialize */ + dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); + if (!dsp) + return -ENOMEM; + + dsp->num = 1; + dsp->type = WMFW_ADSP2; + dsp->rev = 0; + dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions; + dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes); + dsp->base = cs_dsp_mock_adsp2_16bit_sysbase; + + return cs_dsp_callbacks_test_common_init(test, dsp, 1); +} + +static void cs_dsp_callbacks_param_desc(const struct cs_dsp_callbacks_test_param *param, + char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", param->case_name); +} + +/* Parameterize on different client callback ops tables */ +static const struct cs_dsp_callbacks_test_param cs_dsp_callbacks_ops_cases[] = { + { .ops = &cs_dsp_callback_test_client_ops, .case_name = "all ops" }, +}; + +KUNIT_ARRAY_PARAM(cs_dsp_callbacks_ops, + cs_dsp_callbacks_ops_cases, + cs_dsp_callbacks_param_desc); + +static const struct cs_dsp_callbacks_test_param cs_dsp_no_callbacks_cases[] = { + { .ops = &cs_dsp_callback_test_empty_client_ops, .case_name = "empty ops" }, +}; + +KUNIT_ARRAY_PARAM(cs_dsp_no_callbacks, + cs_dsp_no_callbacks_cases, + cs_dsp_callbacks_param_desc); + +static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv1_test_cases[] = { + KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params), + KUNIT_CASE_PARAM(cs_dsp_test_ctl_v1_callbacks, cs_dsp_callbacks_ops_gen_params), + KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params), + + { } /* terminator */ +}; + +static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv2_test_cases[] = { + KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params), + KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params), + KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params), + + { } /* terminator */ +}; + +static struct kunit_case cs_dsp_callbacks_halo_test_cases[] = { + KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params), + KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params), + KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params), + + { } /* terminator */ +}; + +static struct kunit_case cs_dsp_watchdog_adsp2v2_test_cases[] = { + KUNIT_CASE_PARAM(cs_dsp_test_adsp2v2_watchdog_callback, cs_dsp_callbacks_ops_gen_params), + KUNIT_CASE_PARAM(cs_dsp_test_adsp2v2_watchdog_no_callbacks, cs_dsp_no_callbacks_gen_params), + + { } /* terminator */ +}; + +static struct kunit_case cs_dsp_watchdog_halo_test_cases[] = { + KUNIT_CASE_PARAM(cs_dsp_test_halo_watchdog_callback, cs_dsp_callbacks_ops_gen_params), + KUNIT_CASE_PARAM(cs_dsp_test_halo_watchdog_no_callbacks, cs_dsp_no_callbacks_gen_params), + + { } /* terminator */ +}; + +static struct kunit_suite cs_dsp_callbacks_test_halo = { + .name = "cs_dsp_callbacks_halo", + .init = cs_dsp_callbacks_test_halo_init, + .test_cases = cs_dsp_callbacks_halo_test_cases, +}; + +static struct kunit_suite cs_dsp_callbacks_test_adsp2v2_32bit = { + .name = "cs_dsp_callbacks_adsp2v2_32bit_wmfwv2", + .init = cs_dsp_callbacks_test_adsp2v2_32bit_init, + .test_cases = cs_dsp_callbacks_adsp2_wmfwv2_test_cases, +}; + +static struct kunit_suite cs_dsp_callbacks_test_adsp2v1_32bit = { + .name = "cs_dsp_callbacks_adsp2v1_32bit_wmfwv2", + .init = cs_dsp_callbacks_test_adsp2v1_32bit_init, + .test_cases = cs_dsp_callbacks_adsp2_wmfwv2_test_cases, +}; + +static struct kunit_suite cs_dsp_callbacks_test_adsp2_16bit = { + .name = "cs_dsp_callbacks_adsp2_16bit_wmfwv1", + .init = cs_dsp_callbacks_test_adsp2_16bit_init, + .test_cases = cs_dsp_callbacks_adsp2_wmfwv1_test_cases, +}; + +static struct kunit_suite cs_dsp_watchdog_test_adsp2v2_32bit = { + .name = "cs_dsp_watchdog_adsp2v2_32bit", + .init = cs_dsp_callbacks_test_adsp2v2_32bit_init, + .test_cases = cs_dsp_watchdog_adsp2v2_test_cases, +}; + +static struct kunit_suite cs_dsp_watchdog_test_halo_32bit = { + .name = "cs_dsp_watchdog_halo", + .init = cs_dsp_callbacks_test_halo_init, + .test_cases = cs_dsp_watchdog_halo_test_cases, +}; + +kunit_test_suites(&cs_dsp_callbacks_test_halo, + &cs_dsp_callbacks_test_adsp2v2_32bit, + &cs_dsp_callbacks_test_adsp2v1_32bit, + &cs_dsp_callbacks_test_adsp2_16bit, + &cs_dsp_watchdog_test_adsp2v2_32bit, + &cs_dsp_watchdog_test_halo_32bit); |