File Index
Files and directories
Sign in
FILE

cs_dsp_test_control_parse.c

File preview with syntax highlighting.

linux-6.19.14/drivers/firmware/cirrus/test/cs_dsp_test_control_parse.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2//
   3// KUnit tests for cs_dsp.
   4//
   5// Copyright (C) 2024 Cirrus Logic, Inc. and
   6//                    Cirrus Logic International Semiconductor Ltd.
   7
   8#include <kunit/device.h>
   9#include <kunit/resource.h>
  10#include <kunit/test.h>
  11#include <linux/build_bug.h>
  12#include <linux/firmware/cirrus/cs_dsp.h>
  13#include <linux/firmware/cirrus/cs_dsp_test_utils.h>
  14#include <linux/firmware/cirrus/wmfw.h>
  15#include <linux/list.h>
  16#include <linux/mutex.h>
  17#include <linux/regmap.h>
  18
  19KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
  20KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
  21
  22struct cs_dsp_test_local {
  23	struct cs_dsp_mock_xm_header *xm_header;
  24	struct cs_dsp_mock_wmfw_builder *wmfw_builder;
  25	int wmfw_version;
  26};
  27
  28struct cs_dsp_ctl_parse_test_param {
  29	int mem_type;
  30	int alg_id;
  31	unsigned int offset;
  32	unsigned int length;
  33	u16 ctl_type;
  34	u16 flags;
  35};
  36
  37static const struct cs_dsp_mock_alg_def cs_dsp_ctl_parse_test_algs[] = {
  38	{
  39		.id = 0xfafa,
  40		.ver = 0x100000,
  41		.xm_size_words = 164,
  42		.ym_size_words = 164,
  43		.zm_size_words = 164,
  44	},
  45	{
  46		.id = 0xb,
  47		.ver = 0x100001,
  48		.xm_size_words = 8,
  49		.ym_size_words = 8,
  50		.zm_size_words = 8,
  51	},
  52	{
  53		.id = 0x9f1234,
  54		.ver = 0x100500,
  55		.xm_size_words = 16,
  56		.ym_size_words = 16,
  57		.zm_size_words = 16,
  58	},
  59	{
  60		.id = 0xff00ff,
  61		.ver = 0x300113,
  62		.xm_size_words = 16,
  63		.ym_size_words = 16,
  64		.zm_size_words = 16,
  65	},
  66};
  67
  68static const struct cs_dsp_mock_coeff_def mock_coeff_template = {
  69	.shortname = "Dummy Coeff",
  70	.type = WMFW_CTL_TYPE_BYTES,
  71	.mem_type = WMFW_ADSP2_YM,
  72	.flags = WMFW_CTL_FLAG_VOLATILE,
  73	.length_bytes = 4,
  74};
  75
  76static char *cs_dsp_ctl_alloc_test_string(struct kunit *test, char c, size_t len)
  77{
  78	char *str;
  79
  80	str = kunit_kmalloc(test, len + 1, GFP_KERNEL);
  81	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str);
  82	memset(str, c, len);
  83	str[len] = '\0';
  84
  85	return str;
  86}
  87
  88/* Algorithm info block without controls should load */
  89static void cs_dsp_ctl_parse_no_coeffs(struct kunit *test)
  90{
  91	struct cs_dsp_test *priv = test->priv;
  92	struct cs_dsp_test_local *local = priv->local;
  93	struct firmware *wmfw;
  94
  95	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
  96					      cs_dsp_ctl_parse_test_algs[0].id,
  97					      "dummyalg", NULL);
  98	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
  99
 100	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 101	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 102}
 103
 104/*
 105 * V1 controls do not have names, the name field in the coefficient entry
 106 * should be ignored.
 107 */
 108static void cs_dsp_ctl_parse_v1_name(struct kunit *test)
 109{
 110	struct cs_dsp_test *priv = test->priv;
 111	struct cs_dsp_test_local *local = priv->local;
 112	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 113	struct cs_dsp_coeff_ctl *ctl;
 114	struct firmware *wmfw;
 115
 116	def.fullname = "Dummy";
 117	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 118					      cs_dsp_ctl_parse_test_algs[0].id,
 119					      "dummyalg", NULL);
 120	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 121	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 122
 123	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 124	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 125
 126	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 127	KUNIT_ASSERT_NOT_NULL(test, ctl);
 128	KUNIT_EXPECT_EQ(test, ctl->subname_len, 0);
 129	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 130	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 131	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 132}
 133
 134/*
 135 * V1 controls do not have names, the name field in the coefficient entry
 136 * should be ignored. Test with a zero-length name string.
 137 */
 138static void cs_dsp_ctl_parse_empty_v1_name(struct kunit *test)
 139{
 140	struct cs_dsp_test *priv = test->priv;
 141	struct cs_dsp_test_local *local = priv->local;
 142	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 143	struct cs_dsp_coeff_ctl *ctl;
 144	struct firmware *wmfw;
 145
 146	def.fullname = "\0";
 147	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 148					      cs_dsp_ctl_parse_test_algs[0].id,
 149					      "dummyalg", NULL);
 150	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 151	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 152
 153	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 154	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 155
 156	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 157	KUNIT_ASSERT_NOT_NULL(test, ctl);
 158	KUNIT_EXPECT_EQ(test, ctl->subname_len, 0);
 159	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 160	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 161	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 162}
 163
 164/*
 165 * V1 controls do not have names, the name field in the coefficient entry
 166 * should be ignored. Test with a maximum length name string.
 167 */
 168static void cs_dsp_ctl_parse_max_v1_name(struct kunit *test)
 169{
 170	struct cs_dsp_test *priv = test->priv;
 171	struct cs_dsp_test_local *local = priv->local;
 172	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 173	struct cs_dsp_coeff_ctl *ctl;
 174	struct firmware *wmfw;
 175
 176	def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255);
 177
 178	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 179					      cs_dsp_ctl_parse_test_algs[0].id,
 180					      "dummyalg", NULL);
 181	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 182	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 183
 184	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 185	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 186
 187	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 188	KUNIT_ASSERT_NOT_NULL(test, ctl);
 189	KUNIT_EXPECT_EQ(test, ctl->subname_len, 0);
 190	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 191	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 192	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 193}
 194
 195/* Short name from coeff descriptor should be used as control name. */
 196static void cs_dsp_ctl_parse_short_name(struct kunit *test)
 197{
 198	struct cs_dsp_test *priv = test->priv;
 199	struct cs_dsp_test_local *local = priv->local;
 200	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 201	struct cs_dsp_coeff_ctl *ctl;
 202	struct firmware *wmfw;
 203
 204	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 205					      cs_dsp_ctl_parse_test_algs[0].id,
 206					      "dummyalg", NULL);
 207	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 208	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 209
 210	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 211	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 212
 213	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 214	KUNIT_ASSERT_NOT_NULL(test, ctl);
 215	KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
 216	KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
 217	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 218	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 219	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 220}
 221
 222/*
 223 * Short name from coeff descriptor should be used as control name.
 224 * Test with a short name that is a single character.
 225 */
 226static void cs_dsp_ctl_parse_min_short_name(struct kunit *test)
 227{
 228	struct cs_dsp_test *priv = test->priv;
 229	struct cs_dsp_test_local *local = priv->local;
 230	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 231	struct cs_dsp_coeff_ctl *ctl;
 232	struct firmware *wmfw;
 233
 234	def.shortname = "Q";
 235	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 236					      cs_dsp_ctl_parse_test_algs[0].id,
 237					      "dummyalg", NULL);
 238	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 239	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 240
 241	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 242	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 243
 244	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 245	KUNIT_ASSERT_NOT_NULL(test, ctl);
 246	KUNIT_EXPECT_EQ(test, ctl->subname_len, 1);
 247	KUNIT_EXPECT_EQ(test, ctl->subname[0], 'Q');
 248	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 249	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 250	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 251}
 252
 253/*
 254 * Short name from coeff descriptor should be used as control name.
 255 * Test with a maximum length name.
 256 */
 257static void cs_dsp_ctl_parse_max_short_name(struct kunit *test)
 258{
 259	struct cs_dsp_test *priv = test->priv;
 260	struct cs_dsp_test_local *local = priv->local;
 261	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 262	struct cs_dsp_coeff_ctl *ctl;
 263	struct firmware *wmfw;
 264
 265	def.shortname = cs_dsp_ctl_alloc_test_string(test, 'A', 255);
 266
 267	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 268					      cs_dsp_ctl_parse_test_algs[0].id,
 269					      "dummyalg", NULL);
 270	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 271	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 272
 273	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 274	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 275
 276	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 277	KUNIT_ASSERT_NOT_NULL(test, ctl);
 278	KUNIT_EXPECT_EQ(test, ctl->subname_len, 255);
 279	KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
 280	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 281	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 282	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 283}
 284
 285/*
 286 * Full name from coeff descriptor should be ignored. It is a variable
 287 * length field so affects the position of subsequent fields.
 288 * Test with a 1-character full name.
 289 */
 290static void cs_dsp_ctl_parse_with_min_fullname(struct kunit *test)
 291{
 292	struct cs_dsp_test *priv = test->priv;
 293	struct cs_dsp_test_local *local = priv->local;
 294	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 295	struct cs_dsp_coeff_ctl *ctl;
 296	struct firmware *wmfw;
 297
 298	def.fullname = "Q";
 299	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 300					      cs_dsp_ctl_parse_test_algs[0].id,
 301					      "dummyalg", NULL);
 302	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 303	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 304
 305	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 306	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 307
 308	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 309	KUNIT_ASSERT_NOT_NULL(test, ctl);
 310	KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
 311	KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
 312	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 313	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 314	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 315}
 316
 317/*
 318 * Full name from coeff descriptor should be ignored. It is a variable
 319 * length field so affects the position of subsequent fields.
 320 * Test with a maximum length full name.
 321 */
 322static void cs_dsp_ctl_parse_with_max_fullname(struct kunit *test)
 323{
 324	struct cs_dsp_test *priv = test->priv;
 325	struct cs_dsp_test_local *local = priv->local;
 326	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 327	struct cs_dsp_coeff_ctl *ctl;
 328	struct firmware *wmfw;
 329
 330	def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255);
 331
 332	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 333					      cs_dsp_ctl_parse_test_algs[0].id,
 334					      "dummyalg", NULL);
 335	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 336	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 337
 338	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 339	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 340
 341	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 342	KUNIT_ASSERT_NOT_NULL(test, ctl);
 343	KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
 344	KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
 345	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 346	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 347	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 348}
 349
 350/*
 351 * Description from coeff descriptor should be ignored. It is a variable
 352 * length field so affects the position of subsequent fields.
 353 * Test with a 1-character description
 354 */
 355static void cs_dsp_ctl_parse_with_min_description(struct kunit *test)
 356{
 357	struct cs_dsp_test *priv = test->priv;
 358	struct cs_dsp_test_local *local = priv->local;
 359	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 360	struct cs_dsp_coeff_ctl *ctl;
 361	struct firmware *wmfw;
 362
 363	def.description = "Q";
 364	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 365					      cs_dsp_ctl_parse_test_algs[0].id,
 366					      "dummyalg", NULL);
 367	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 368	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 369
 370	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 371	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 372
 373	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 374	KUNIT_ASSERT_NOT_NULL(test, ctl);
 375	KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
 376	KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
 377	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 378	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 379	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 380}
 381
 382/*
 383 * Description from coeff descriptor should be ignored. It is a variable
 384 * length field so affects the position of subsequent fields.
 385 * Test with a maximum length description
 386 */
 387static void cs_dsp_ctl_parse_with_max_description(struct kunit *test)
 388{
 389	struct cs_dsp_test *priv = test->priv;
 390	struct cs_dsp_test_local *local = priv->local;
 391	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 392	struct cs_dsp_coeff_ctl *ctl;
 393	struct firmware *wmfw;
 394
 395	def.description = cs_dsp_ctl_alloc_test_string(test, 'A', 65535);
 396
 397	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 398					      cs_dsp_ctl_parse_test_algs[0].id,
 399					      "dummyalg", NULL);
 400	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 401	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 402
 403	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 404	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 405
 406	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 407	KUNIT_ASSERT_NOT_NULL(test, ctl);
 408	KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
 409	KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
 410	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 411	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 412	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 413}
 414
 415/*
 416 * Full name and description from coeff descriptor are variable length
 417 * fields so affects the position of subsequent fields.
 418 * Test with a maximum length full name and description
 419 */
 420static void cs_dsp_ctl_parse_with_max_fullname_and_description(struct kunit *test)
 421{
 422	struct cs_dsp_test *priv = test->priv;
 423	struct cs_dsp_test_local *local = priv->local;
 424	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 425	struct cs_dsp_coeff_ctl *ctl;
 426	struct firmware *wmfw;
 427
 428	def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255);
 429	def.description = cs_dsp_ctl_alloc_test_string(test, 'A', 65535);
 430
 431	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 432					      cs_dsp_ctl_parse_test_algs[0].id,
 433					      "dummyalg", NULL);
 434	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 435	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 436
 437	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 438	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 439
 440	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 441	KUNIT_ASSERT_NOT_NULL(test, ctl);
 442	KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
 443	KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
 444	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 445	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 446	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 447}
 448
 449static const char * const cs_dsp_ctl_alignment_test_names[] = {
 450	"1", "12", "123", "1234", "12345", "123456", "1234567",
 451	"12345678", "123456789", "123456789A", "123456789AB",
 452	"123456789ABC", "123456789ABCD", "123456789ABCDE",
 453	"123456789ABCDEF",
 454};
 455
 456/*
 457 * Variable-length string fields are padded to a multiple of 4-bytes.
 458 * Test this with various lengths of short name.
 459 */
 460static void cs_dsp_ctl_shortname_alignment(struct kunit *test)
 461{
 462	struct cs_dsp_test *priv = test->priv;
 463	struct cs_dsp_test_local *local = priv->local;
 464	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 465	struct cs_dsp_coeff_ctl *ctl;
 466	struct firmware *wmfw;
 467	int i;
 468
 469	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 470					      cs_dsp_ctl_parse_test_algs[0].id,
 471					      "dummyalg", NULL);
 472
 473	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
 474		def.shortname = cs_dsp_ctl_alignment_test_names[i];
 475		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 476	}
 477
 478	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 479
 480	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 481	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 482
 483	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
 484		mutex_lock(&priv->dsp->pwr_lock);
 485		ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_ctl_alignment_test_names[i],
 486				     def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
 487		mutex_unlock(&priv->dsp->pwr_lock);
 488		KUNIT_ASSERT_NOT_NULL(test, ctl);
 489		KUNIT_EXPECT_EQ(test, ctl->subname_len, i + 1);
 490		KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_ctl_alignment_test_names[i],
 491				   ctl->subname_len);
 492		/* Test fields that are parsed after the variable-length fields */
 493		KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 494		KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 495		KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 496	}
 497}
 498
 499/*
 500 * Variable-length string fields are padded to a multiple of 4-bytes.
 501 * Test this with various lengths of full name.
 502 */
 503static void cs_dsp_ctl_fullname_alignment(struct kunit *test)
 504{
 505	struct cs_dsp_test *priv = test->priv;
 506	struct cs_dsp_test_local *local = priv->local;
 507	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 508	struct cs_dsp_coeff_ctl *ctl;
 509	char ctl_name[4];
 510	struct firmware *wmfw;
 511	int i;
 512
 513	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 514					      cs_dsp_ctl_parse_test_algs[0].id,
 515					      "dummyalg", NULL);
 516
 517	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
 518		/*
 519		 * Create a unique control name of 3 characters so that
 520		 * the shortname field is exactly 4 bytes long including
 521		 * the length byte.
 522		 */
 523		snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
 524		KUNIT_ASSERT_EQ(test, strlen(ctl_name), 3);
 525		def.shortname = ctl_name;
 526
 527		def.fullname = cs_dsp_ctl_alignment_test_names[i];
 528		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 529	}
 530
 531	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 532
 533	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 534	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 535
 536	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
 537		snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
 538
 539		mutex_lock(&priv->dsp->pwr_lock);
 540		ctl = cs_dsp_get_ctl(priv->dsp, ctl_name, def.mem_type,
 541				     cs_dsp_ctl_parse_test_algs[0].id);
 542		mutex_unlock(&priv->dsp->pwr_lock);
 543		KUNIT_ASSERT_NOT_NULL(test, ctl);
 544		KUNIT_EXPECT_EQ(test, ctl->subname_len, 3);
 545		KUNIT_EXPECT_MEMEQ(test, ctl->subname, ctl_name, ctl->subname_len);
 546		/* Test fields that are parsed after the variable-length fields */
 547		KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 548		KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 549		KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 550	}
 551}
 552
 553/*
 554 * Variable-length string fields are padded to a multiple of 4-bytes.
 555 * Test this with various lengths of description.
 556 */
 557static void cs_dsp_ctl_description_alignment(struct kunit *test)
 558{
 559	struct cs_dsp_test *priv = test->priv;
 560	struct cs_dsp_test_local *local = priv->local;
 561	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 562	struct cs_dsp_coeff_ctl *ctl;
 563	char ctl_name[4];
 564	struct firmware *wmfw;
 565	int i;
 566
 567	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 568					      cs_dsp_ctl_parse_test_algs[0].id,
 569					      "dummyalg", NULL);
 570
 571	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
 572		/*
 573		 * Create a unique control name of 3 characters so that
 574		 * the shortname field is exactly 4 bytes long including
 575		 * the length byte.
 576		 */
 577		snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
 578		KUNIT_ASSERT_EQ(test, strlen(ctl_name), 3);
 579		def.shortname = ctl_name;
 580
 581		def.description = cs_dsp_ctl_alignment_test_names[i];
 582		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 583	}
 584
 585	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 586
 587	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 588	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 589
 590	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
 591		snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
 592
 593		mutex_lock(&priv->dsp->pwr_lock);
 594		ctl = cs_dsp_get_ctl(priv->dsp, ctl_name, def.mem_type,
 595				     cs_dsp_ctl_parse_test_algs[0].id);
 596		mutex_unlock(&priv->dsp->pwr_lock);
 597		KUNIT_ASSERT_NOT_NULL(test, ctl);
 598		KUNIT_EXPECT_EQ(test, ctl->subname_len, 3);
 599		KUNIT_EXPECT_MEMEQ(test, ctl->subname, ctl_name, ctl->subname_len);
 600		/* Test fields that are parsed after the variable-length fields */
 601		KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 602		KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 603		KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 604	}
 605}
 606
 607static const char * const cs_dsp_get_ctl_test_names[] = {
 608	"Up", "Down", "Switch", "Mute",
 609	"Left Up", "Left Down", "Right Up", "Right Down",
 610	"Left Mute", "Right Mute",
 611	"_trunc_1", "_trunc_2", " trunc",
 612};
 613
 614/* Test using cs_dsp_get_ctl() to lookup various controls. */
 615static void cs_dsp_get_ctl_test(struct kunit *test)
 616{
 617	struct cs_dsp_test *priv = test->priv;
 618	struct cs_dsp_test_local *local = priv->local;
 619	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 620	struct cs_dsp_coeff_ctl *ctl;
 621	struct firmware *wmfw;
 622	int i;
 623
 624	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 625					      cs_dsp_ctl_parse_test_algs[0].id,
 626					      "dummyalg", NULL);
 627
 628	for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) {
 629		def.shortname = cs_dsp_get_ctl_test_names[i];
 630		def.offset_dsp_words = i;
 631		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 632	}
 633
 634	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 635
 636	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 637	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 638
 639	for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) {
 640		mutex_lock(&priv->dsp->pwr_lock);
 641		ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_get_ctl_test_names[i],
 642				     def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
 643		mutex_unlock(&priv->dsp->pwr_lock);
 644		KUNIT_ASSERT_NOT_NULL(test, ctl);
 645		KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(cs_dsp_get_ctl_test_names[i]));
 646		KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_get_ctl_test_names[i],
 647				   ctl->subname_len);
 648		KUNIT_EXPECT_EQ(test, ctl->offset, i);
 649	}
 650}
 651
 652/*
 653 * cs_dsp_get_ctl() searches for the control in the currently loaded
 654 * firmware, so create identical controls in multiple firmware and
 655 * test that the correct one is found.
 656 */
 657static void cs_dsp_get_ctl_test_multiple_wmfw(struct kunit *test)
 658{
 659	struct cs_dsp_test *priv = test->priv;
 660	struct cs_dsp_test_local *local = priv->local;
 661	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 662	struct cs_dsp_coeff_ctl *ctl;
 663	struct cs_dsp_mock_wmfw_builder *builder2;
 664	struct firmware *wmfw;
 665
 666	def.shortname = "_A_CONTROL";
 667
 668	/* Create a second mock wmfw builder */
 669	builder2 = cs_dsp_mock_wmfw_init(priv,
 670					 cs_dsp_mock_wmfw_format_version(local->wmfw_builder));
 671	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2);
 672	cs_dsp_mock_wmfw_add_data_block(builder2,
 673					WMFW_ADSP2_XM, 0,
 674					local->xm_header->blob_data,
 675					local->xm_header->blob_size_bytes);
 676
 677	/* Load a 'misc' firmware with a control */
 678	def.offset_dsp_words = 1;
 679	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 680					      cs_dsp_ctl_parse_test_algs[0].id,
 681					      "dummyalg", NULL);
 682	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 683	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 684	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 685	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 686	cs_dsp_power_down(priv->dsp);
 687
 688	/* Load a 'mbc/vss' firmware with a control of the same name */
 689	def.offset_dsp_words = 2;
 690	cs_dsp_mock_wmfw_start_alg_info_block(builder2,
 691					      cs_dsp_ctl_parse_test_algs[0].id,
 692					      "dummyalg", NULL);
 693	cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def);
 694	cs_dsp_mock_wmfw_end_alg_info_block(builder2);
 695	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
 696	KUNIT_ASSERT_EQ(test,
 697			cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2", NULL, NULL, "mbc/vss"), 0);
 698
 699	/* A lookup should return the control for the current firmware */
 700	mutex_lock(&priv->dsp->pwr_lock);
 701	ctl = cs_dsp_get_ctl(priv->dsp, def.shortname,
 702			     def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
 703	mutex_unlock(&priv->dsp->pwr_lock);
 704	KUNIT_ASSERT_NOT_NULL(test, ctl);
 705	KUNIT_EXPECT_EQ(test, ctl->offset, 2);
 706
 707	/* Re-load the 'misc' firmware and a lookup should return its control */
 708	cs_dsp_power_down(priv->dsp);
 709	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 710	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 711
 712	mutex_lock(&priv->dsp->pwr_lock);
 713	ctl = cs_dsp_get_ctl(priv->dsp, def.shortname,
 714			     def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
 715	mutex_unlock(&priv->dsp->pwr_lock);
 716	KUNIT_ASSERT_NOT_NULL(test, ctl);
 717	KUNIT_EXPECT_EQ(test, ctl->offset, 1);
 718}
 719
 720/* Test that the value of the memory type field is parsed correctly. */
 721static void cs_dsp_ctl_parse_memory_type(struct kunit *test)
 722{
 723	const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
 724	struct cs_dsp_test *priv = test->priv;
 725	struct cs_dsp_test_local *local = priv->local;
 726	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 727	struct cs_dsp_coeff_ctl *ctl;
 728	struct firmware *wmfw;
 729
 730	/* kunit_skip() marks the test skipped forever, so just return */
 731	if ((param->mem_type == WMFW_ADSP2_ZM) && !cs_dsp_mock_has_zm(priv))
 732		return;
 733
 734	def.mem_type = param->mem_type;
 735
 736	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 737					      cs_dsp_ctl_parse_test_algs[0].id,
 738					      "dummyalg", NULL);
 739	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 740	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 741
 742	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 743	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 744
 745	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 746	KUNIT_ASSERT_NOT_NULL(test, ctl);
 747	KUNIT_EXPECT_EQ(test, ctl->alg_region.type, param->mem_type);
 748	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 749	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 750	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 751}
 752
 753/*
 754 * Test that the algorithm id from the parent alg-info block is
 755 * correctly stored in the cs_dsp_coeff_ctl.
 756 */
 757static void cs_dsp_ctl_parse_alg_id(struct kunit *test)
 758{
 759	const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
 760	struct cs_dsp_test *priv = test->priv;
 761	struct cs_dsp_test_local *local = priv->local;
 762	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 763	struct cs_dsp_coeff_ctl *ctl;
 764	struct firmware *wmfw;
 765
 766	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 767					      param->alg_id,
 768					      "dummyalg", NULL);
 769	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 770	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 771
 772	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 773	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 774
 775	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 776	KUNIT_ASSERT_NOT_NULL(test, ctl);
 777	KUNIT_EXPECT_EQ(test, ctl->alg_region.alg, param->alg_id);
 778	KUNIT_EXPECT_EQ(test, ctl->alg_region.type, def.mem_type);
 779	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 780	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 781	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 782}
 783
 784/*
 785 * Test that the values of (alg id, memory type) tuple is parsed correctly.
 786 * The alg id is parsed from the alg-info block, but the memory type is
 787 * parsed from the coefficient info descriptor.
 788 */
 789static void cs_dsp_ctl_parse_alg_mem(struct kunit *test)
 790{
 791	const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
 792	struct cs_dsp_test *priv = test->priv;
 793	struct cs_dsp_test_local *local = priv->local;
 794	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 795	struct cs_dsp_coeff_ctl *ctl;
 796	struct firmware *wmfw;
 797
 798	/* kunit_skip() marks the test skipped forever, so just return */
 799	if ((param->mem_type == WMFW_ADSP2_ZM) && !cs_dsp_mock_has_zm(priv))
 800		return;
 801
 802	def.mem_type = param->mem_type;
 803
 804	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 805					      param->alg_id,
 806					      "dummyalg", NULL);
 807	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 808	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 809
 810	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 811	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 812
 813	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 814	KUNIT_ASSERT_NOT_NULL(test, ctl);
 815	KUNIT_EXPECT_EQ(test, ctl->alg_region.alg, param->alg_id);
 816	KUNIT_EXPECT_EQ(test, ctl->alg_region.type, param->mem_type);
 817}
 818
 819/* Test that the value of the offset field is parsed correctly. */
 820static void cs_dsp_ctl_parse_offset(struct kunit *test)
 821{
 822	const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
 823	struct cs_dsp_test *priv = test->priv;
 824	struct cs_dsp_test_local *local = priv->local;
 825	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 826	struct cs_dsp_coeff_ctl *ctl;
 827	struct firmware *wmfw;
 828
 829	def.offset_dsp_words = param->offset;
 830
 831	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 832					      cs_dsp_ctl_parse_test_algs[0].id,
 833					      "dummyalg", NULL);
 834	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 835	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 836
 837	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 838	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 839
 840	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 841	KUNIT_ASSERT_NOT_NULL(test, ctl);
 842	KUNIT_EXPECT_EQ(test, ctl->offset, param->offset);
 843	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 844	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 845	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 846}
 847
 848/* Test that the value of the length field is parsed correctly. */
 849static void cs_dsp_ctl_parse_length(struct kunit *test)
 850{
 851	const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
 852	struct cs_dsp_test *priv = test->priv;
 853	struct cs_dsp_test_local *local = priv->local;
 854	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 855	struct cs_dsp_coeff_ctl *ctl;
 856	struct firmware *wmfw;
 857
 858	def.length_bytes = param->length;
 859
 860	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 861					      cs_dsp_ctl_parse_test_algs[0].id,
 862					      "dummyalg", NULL);
 863	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 864	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 865
 866	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 867	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 868
 869	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 870	KUNIT_ASSERT_NOT_NULL(test, ctl);
 871	KUNIT_EXPECT_EQ(test, ctl->offset, def.offset_dsp_words);
 872	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 873	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 874	KUNIT_EXPECT_EQ(test, ctl->len, param->length);
 875}
 876
 877/* Test that the value of the control type field is parsed correctly. */
 878static void cs_dsp_ctl_parse_ctl_type(struct kunit *test)
 879{
 880	const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
 881	struct cs_dsp_test *priv = test->priv;
 882	struct cs_dsp_test_local *local = priv->local;
 883	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 884	struct cs_dsp_coeff_ctl *ctl;
 885	struct firmware *wmfw;
 886
 887	def.type = param->ctl_type;
 888	def.flags = param->flags;
 889
 890	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 891					      cs_dsp_ctl_parse_test_algs[0].id,
 892					      "dummyalg", NULL);
 893	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 894	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 895
 896	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 897	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 898
 899	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 900	KUNIT_ASSERT_NOT_NULL(test, ctl);
 901	KUNIT_EXPECT_EQ(test, ctl->type, param->ctl_type);
 902	KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
 903	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 904}
 905
 906/* Test that the value of the flags field is parsed correctly. */
 907static void cs_dsp_ctl_parse_flags(struct kunit *test)
 908{
 909	const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
 910	struct cs_dsp_test *priv = test->priv;
 911	struct cs_dsp_test_local *local = priv->local;
 912	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 913	struct cs_dsp_coeff_ctl *ctl;
 914	struct firmware *wmfw;
 915	u32 reg_val;
 916
 917	/*
 918	 * Non volatile controls will be read to initialize the cache
 919	 * so the regmap cache must contain something to read.
 920	 */
 921	reg_val = 0xf11100;
 922	regmap_raw_write(priv->dsp->regmap,
 923			 cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM),
 924			 &reg_val, sizeof(reg_val));
 925
 926	def.flags = param->flags;
 927	def.mem_type = WMFW_ADSP2_YM;
 928
 929	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 930					      cs_dsp_ctl_parse_test_algs[0].id,
 931					      "dummyalg", NULL);
 932	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 933	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 934
 935	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 936	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 937
 938	ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
 939	KUNIT_ASSERT_NOT_NULL(test, ctl);
 940	KUNIT_EXPECT_EQ(test, ctl->type, def.type);
 941	KUNIT_EXPECT_EQ(test, ctl->flags, param->flags);
 942	KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
 943}
 944
 945/* Test that invalid combinations of (control type, flags) are rejected. */
 946static void cs_dsp_ctl_illegal_type_flags(struct kunit *test)
 947{
 948	const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
 949	struct cs_dsp_test *priv = test->priv;
 950	struct cs_dsp_test_local *local = priv->local;
 951	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 952	struct firmware *wmfw;
 953	u32 reg_val;
 954
 955	/*
 956	 * Non volatile controls will be read to initialize the cache
 957	 * so the regmap cache must contain something to read.
 958	 */
 959	reg_val = 0xf11100;
 960	regmap_raw_write(priv->dsp->regmap,
 961			 cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM),
 962			 &reg_val, sizeof(reg_val));
 963
 964	def.type = param->ctl_type;
 965	def.flags = param->flags;
 966	def.mem_type = WMFW_ADSP2_YM;
 967
 968	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
 969					      cs_dsp_ctl_parse_test_algs[0].id,
 970					      "dummyalg", NULL);
 971	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
 972	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
 973
 974	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
 975	KUNIT_ASSERT_LT(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
 976}
 977
 978/* Test that the correct firmware name is entered in the cs_dsp_coeff_ctl. */
 979static void cs_dsp_ctl_parse_fw_name(struct kunit *test)
 980{
 981	struct cs_dsp_test *priv = test->priv;
 982	struct cs_dsp_test_local *local = priv->local;
 983	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
 984	struct cs_dsp_coeff_ctl *walkctl, *ctl1, *ctl2;
 985	struct cs_dsp_mock_wmfw_builder *builder2;
 986	struct firmware *wmfw;
 987
 988	/* Create a second mock wmfw builder */
 989	builder2 = cs_dsp_mock_wmfw_init(priv,
 990					 cs_dsp_mock_wmfw_format_version(local->wmfw_builder));
 991	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2);
 992	cs_dsp_mock_wmfw_add_data_block(builder2,
 993					WMFW_ADSP2_XM, 0,
 994					local->xm_header->blob_data,
 995					local->xm_header->blob_size_bytes);
 996
 997	/* Load a 'misc' firmware with a control */
 998	def.offset_dsp_words = 1;
 999	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1000					      cs_dsp_ctl_parse_test_algs[0].id,
1001					      "dummyalg", NULL);
1002	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1003	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1004	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1005	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1006	cs_dsp_power_down(priv->dsp);
1007
1008	/* Load a 'mbc/vss' firmware with a control */
1009	def.offset_dsp_words = 2;
1010	cs_dsp_mock_wmfw_start_alg_info_block(builder2,
1011					      cs_dsp_ctl_parse_test_algs[0].id,
1012					      "dummyalg", NULL);
1013	cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def);
1014	cs_dsp_mock_wmfw_end_alg_info_block(builder2);
1015	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1016	KUNIT_ASSERT_EQ(test,
1017			cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2", NULL, NULL, "mbc/vss"), 0);
1018
1019	/* Both controls should be in the list (order not guaranteed) */
1020	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1021	ctl1 = NULL;
1022	ctl2 = NULL;
1023	list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1024		if (strcmp(walkctl->fw_name, "misc") == 0)
1025			ctl1 = walkctl;
1026		else if (strcmp(walkctl->fw_name, "mbc/vss") == 0)
1027			ctl2 = walkctl;
1028	}
1029
1030	KUNIT_EXPECT_NOT_NULL(test, ctl1);
1031	KUNIT_EXPECT_NOT_NULL(test, ctl2);
1032	KUNIT_EXPECT_EQ(test, ctl1->offset, 1);
1033	KUNIT_EXPECT_EQ(test, ctl2->offset, 2);
1034}
1035
1036/* Controls are unique if the algorithm ID is different */
1037static void cs_dsp_ctl_alg_id_uniqueness(struct kunit *test)
1038{
1039	struct cs_dsp_test *priv = test->priv;
1040	struct cs_dsp_test_local *local = priv->local;
1041	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1042	struct cs_dsp_coeff_ctl *ctl1, *ctl2;
1043	struct firmware *wmfw;
1044
1045	/* Create an algorithm containing the control */
1046	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1047					      cs_dsp_ctl_parse_test_algs[0].id,
1048					      "dummyalg", NULL);
1049	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1050	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1051
1052	/* Create a different algorithm containing an identical control */
1053	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1054					      cs_dsp_ctl_parse_test_algs[1].id,
1055					      "dummyalg", NULL);
1056	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1057	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1058
1059	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1060	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1061	cs_dsp_power_down(priv->dsp);
1062
1063	/* Both controls should be in the list */
1064	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1065	ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1066	ctl2 = list_next_entry(ctl1, list);
1067	KUNIT_EXPECT_NOT_NULL(test, ctl1);
1068	KUNIT_EXPECT_NOT_NULL(test, ctl2);
1069	KUNIT_EXPECT_NE(test, ctl1->alg_region.alg, ctl2->alg_region.alg);
1070	KUNIT_EXPECT_EQ(test, ctl1->alg_region.type, ctl2->alg_region.type);
1071	KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset);
1072	KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type);
1073	KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags);
1074	KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len);
1075	KUNIT_EXPECT_STREQ(test, ctl1->fw_name, ctl2->fw_name);
1076	KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len);
1077	if (ctl1->subname_len)
1078		KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len);
1079}
1080
1081/* Controls are unique if the memory region is different */
1082static void cs_dsp_ctl_mem_uniqueness(struct kunit *test)
1083{
1084	struct cs_dsp_test *priv = test->priv;
1085	struct cs_dsp_test_local *local = priv->local;
1086	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1087	struct cs_dsp_coeff_ctl *ctl1, *ctl2;
1088	struct firmware *wmfw;
1089
1090	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1091					      cs_dsp_ctl_parse_test_algs[0].id,
1092					      "dummyalg", NULL);
1093	/* Create control in XM */
1094	def.mem_type = WMFW_ADSP2_XM;
1095	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1096
1097	/* Create control in YM */
1098	def.mem_type = WMFW_ADSP2_YM;
1099	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1100
1101	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1102
1103	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1104	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1105	cs_dsp_power_down(priv->dsp);
1106
1107	/* Both controls should be in the list */
1108	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1109	ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1110	ctl2 = list_next_entry(ctl1, list);
1111	KUNIT_EXPECT_NOT_NULL(test, ctl1);
1112	KUNIT_EXPECT_NOT_NULL(test, ctl2);
1113	KUNIT_EXPECT_EQ(test, ctl1->alg_region.alg, ctl2->alg_region.alg);
1114	KUNIT_EXPECT_NE(test, ctl1->alg_region.type, ctl2->alg_region.type);
1115	KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset);
1116	KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type);
1117	KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags);
1118	KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len);
1119	KUNIT_EXPECT_STREQ(test, ctl1->fw_name, ctl2->fw_name);
1120	KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len);
1121	if (ctl1->subname_len)
1122		KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len);
1123}
1124
1125/* Controls are unique if they are in different firmware */
1126static void cs_dsp_ctl_fw_uniqueness(struct kunit *test)
1127{
1128	struct cs_dsp_test *priv = test->priv;
1129	struct cs_dsp_test_local *local = priv->local;
1130	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1131	struct cs_dsp_coeff_ctl *ctl1, *ctl2;
1132	struct cs_dsp_mock_wmfw_builder *builder2;
1133	struct firmware *wmfw;
1134
1135	/* Create a second mock wmfw builder */
1136	builder2 = cs_dsp_mock_wmfw_init(priv,
1137					 cs_dsp_mock_wmfw_format_version(local->wmfw_builder));
1138	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2);
1139	cs_dsp_mock_wmfw_add_data_block(builder2,
1140					WMFW_ADSP2_XM, 0,
1141					local->xm_header->blob_data,
1142					local->xm_header->blob_size_bytes);
1143
1144	/* Load a 'misc' firmware with a control */
1145	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1146					      cs_dsp_ctl_parse_test_algs[0].id,
1147					      "dummyalg", NULL);
1148	cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1149	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1150	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1151	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1152	cs_dsp_power_down(priv->dsp);
1153
1154	/* Load a 'mbc/vss' firmware with the same control */
1155	cs_dsp_mock_wmfw_start_alg_info_block(builder2,
1156					      cs_dsp_ctl_parse_test_algs[0].id,
1157					      "dummyalg", NULL);
1158	cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def);
1159	cs_dsp_mock_wmfw_end_alg_info_block(builder2);
1160	wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1161	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2",
1162			NULL, NULL, "mbc/vss"), 0);
1163	cs_dsp_power_down(priv->dsp);
1164
1165	/* Both controls should be in the list */
1166	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1167	ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1168	ctl2 = list_next_entry(ctl1, list);
1169	KUNIT_EXPECT_NOT_NULL(test, ctl1);
1170	KUNIT_EXPECT_NOT_NULL(test, ctl2);
1171	KUNIT_EXPECT_EQ(test, ctl1->alg_region.alg, ctl2->alg_region.alg);
1172	KUNIT_EXPECT_EQ(test, ctl1->alg_region.type, ctl2->alg_region.type);
1173	KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset);
1174	KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type);
1175	KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags);
1176	KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len);
1177	KUNIT_EXPECT_STRNEQ(test, ctl1->fw_name, ctl2->fw_name);
1178	KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len);
1179	if (ctl1->subname_len)
1180		KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len);
1181}
1182
1183/*
1184 * Controls from a wmfw are only added to the list once. If the same
1185 * wmfw is reloaded the controls are not added again.
1186 * This creates multiple algorithms with one control each, which will
1187 * work on both V1 format and >=V2 format controls.
1188 */
1189static void cs_dsp_ctl_squash_reloaded_controls(struct kunit *test)
1190{
1191	struct cs_dsp_test *priv = test->priv;
1192	struct cs_dsp_test_local *local = priv->local;
1193	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1194	struct cs_dsp_coeff_ctl *ctls[ARRAY_SIZE(cs_dsp_ctl_parse_test_algs)];
1195	struct cs_dsp_coeff_ctl *walkctl;
1196	struct firmware *wmfw;
1197	int i;
1198
1199	/* Create some algorithms with a control */
1200	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_parse_test_algs); i++) {
1201		cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1202						      cs_dsp_ctl_parse_test_algs[i].id,
1203						      "dummyalg", NULL);
1204		def.mem_type = WMFW_ADSP2_YM;
1205		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1206		cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1207	}
1208
1209	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1210	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1211	cs_dsp_power_down(priv->dsp);
1212
1213	/* All controls should be in the list */
1214	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
1215			ARRAY_SIZE(cs_dsp_ctl_parse_test_algs));
1216
1217	/* Take a copy of the pointers to controls to compare against. */
1218	i = 0;
1219	list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1220		KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1221		ctls[i++] = walkctl;
1222	}
1223
1224
1225	/* Load the wmfw again */
1226	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1227	cs_dsp_power_down(priv->dsp);
1228
1229	/* The number of controls should be the same */
1230	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
1231			ARRAY_SIZE(cs_dsp_ctl_parse_test_algs));
1232
1233	/* And they should be the same objects */
1234	i = 0;
1235	list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1236		KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1237		KUNIT_ASSERT_PTR_EQ(test, walkctl, ctls[i++]);
1238	}
1239}
1240
1241/*
1242 * Controls from a wmfw are only added to the list once. If the same
1243 * wmfw is reloaded the controls are not added again.
1244 * This tests >=V2 firmware that can have multiple named controls in
1245 * the same algorithm.
1246 */
1247static void cs_dsp_ctl_v2_squash_reloaded_controls(struct kunit *test)
1248{
1249	struct cs_dsp_test *priv = test->priv;
1250	struct cs_dsp_test_local *local = priv->local;
1251	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1252	struct cs_dsp_coeff_ctl *ctls[ARRAY_SIZE(cs_dsp_get_ctl_test_names)];
1253	struct cs_dsp_coeff_ctl *walkctl;
1254	struct firmware *wmfw;
1255	int i;
1256
1257	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1258					      cs_dsp_ctl_parse_test_algs[0].id,
1259					      "dummyalg", NULL);
1260
1261	/* Create some controls */
1262	for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) {
1263		def.shortname = cs_dsp_get_ctl_test_names[i];
1264		def.offset_dsp_words = i;
1265		if (i & BIT(0))
1266			def.mem_type = WMFW_ADSP2_XM;
1267		else
1268			def.mem_type = WMFW_ADSP2_YM;
1269
1270		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1271	}
1272
1273	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1274
1275	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1276	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1277	cs_dsp_power_down(priv->dsp);
1278
1279	/* All controls should be in the list */
1280	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
1281			ARRAY_SIZE(cs_dsp_get_ctl_test_names));
1282
1283	/* Take a copy of the pointers to controls to compare against. */
1284	i = 0;
1285	list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1286		KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1287		ctls[i++] = walkctl;
1288	}
1289
1290
1291	/* Load the wmfw again */
1292	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1293	cs_dsp_power_down(priv->dsp);
1294
1295	/* The number of controls should be the same */
1296	KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
1297			ARRAY_SIZE(cs_dsp_get_ctl_test_names));
1298
1299	/* And they should be the same objects */
1300	i = 0;
1301	list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1302		KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1303		KUNIT_ASSERT_PTR_EQ(test, walkctl, ctls[i++]);
1304	}
1305}
1306
1307static const char * const cs_dsp_ctl_v2_compare_len_names[] = {
1308	"LEFT",
1309	"LEFT_",
1310	"LEFT_SPK",
1311	"LEFT_SPK_V",
1312	"LEFT_SPK_VOL",
1313	"LEFT_SPK_MUTE",
1314	"LEFT_SPK_1",
1315	"LEFT_X",
1316	"LEFT2",
1317};
1318
1319/*
1320 * When comparing shortnames the full length of both strings is
1321 * considered, not only the characters in of the shortest string.
1322 * So that "LEFT" is not the same as "LEFT2".
1323 * This is specifically to test for the bug that was fixed by commit:
1324 * 7ac1102b227b ("firmware: cs_dsp: Fix new control name check")
1325 */
1326static void cs_dsp_ctl_v2_compare_len(struct kunit *test)
1327{
1328	struct cs_dsp_test *priv = test->priv;
1329	struct cs_dsp_test_local *local = priv->local;
1330	struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1331	struct cs_dsp_coeff_ctl *ctl;
1332	struct firmware *wmfw;
1333	int i;
1334
1335	cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1336					      cs_dsp_ctl_parse_test_algs[0].id,
1337					      "dummyalg", NULL);
1338
1339	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_v2_compare_len_names); i++) {
1340		def.shortname = cs_dsp_ctl_v2_compare_len_names[i];
1341		cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1342	}
1343
1344	cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1345
1346	wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1347	KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1348
1349	for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_v2_compare_len_names); i++) {
1350		mutex_lock(&priv->dsp->pwr_lock);
1351		ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_ctl_v2_compare_len_names[i],
1352				     def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
1353		mutex_unlock(&priv->dsp->pwr_lock);
1354		KUNIT_ASSERT_NOT_NULL(test, ctl);
1355		KUNIT_EXPECT_EQ(test, ctl->subname_len,
1356				strlen(cs_dsp_ctl_v2_compare_len_names[i]));
1357		KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_ctl_v2_compare_len_names[i],
1358				   ctl->subname_len);
1359	}
1360}
1361
1362static int cs_dsp_ctl_parse_test_common_init(struct kunit *test, struct cs_dsp *dsp,
1363					     int wmfw_version)
1364{
1365	struct cs_dsp_test *priv;
1366	struct cs_dsp_test_local *local;
1367	struct device *test_dev;
1368	int ret;
1369
1370	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
1371	if (!priv)
1372		return -ENOMEM;
1373
1374	local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
1375	if (!local)
1376		return -ENOMEM;
1377
1378	priv->test = test;
1379	priv->dsp = dsp;
1380	test->priv = priv;
1381	priv->local = local;
1382	priv->local->wmfw_version = wmfw_version;
1383
1384	/* Create dummy struct device */
1385	test_dev = kunit_device_register(test, "cs_dsp_test_drv");
1386	if (IS_ERR(test_dev))
1387		return PTR_ERR(test_dev);
1388
1389	dsp->dev = get_device(test_dev);
1390	if (!dsp->dev)
1391		return -ENODEV;
1392
1393	ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
1394	if (ret)
1395		return ret;
1396
1397	dev_set_drvdata(dsp->dev, priv);
1398
1399	/* Allocate regmap */
1400	ret = cs_dsp_mock_regmap_init(priv);
1401	if (ret)
1402		return ret;
1403
1404	/*
1405	 * There must always be a XM header with at least 1 algorithm, so create
1406	 * a dummy one that tests can use and extract it to a data blob.
1407	 */
1408	local->xm_header = cs_dsp_create_mock_xm_header(priv,
1409							cs_dsp_ctl_parse_test_algs,
1410							ARRAY_SIZE(cs_dsp_ctl_parse_test_algs));
1411	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
1412
1413	local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, priv->local->wmfw_version);
1414	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->wmfw_builder);
1415
1416	/* Add dummy XM header blob to wmfw */
1417	cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1418					WMFW_ADSP2_XM, 0,
1419					local->xm_header->blob_data,
1420					local->xm_header->blob_size_bytes);
1421
1422	/* Init cs_dsp */
1423	dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
1424	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
1425
1426	switch (dsp->type) {
1427	case WMFW_ADSP2:
1428		ret = cs_dsp_adsp2_init(dsp);
1429		break;
1430	case WMFW_HALO:
1431		ret = cs_dsp_halo_init(dsp);
1432		break;
1433	default:
1434		KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
1435		return -EINVAL;
1436	}
1437
1438	if (ret)
1439		return ret;
1440
1441	/* Automatically call cs_dsp_remove() when test case ends */
1442	return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
1443}
1444
1445static int cs_dsp_ctl_parse_test_halo_init(struct kunit *test)
1446{
1447	struct cs_dsp *dsp;
1448
1449	/* Fill in cs_dsp and initialize */
1450	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1451	if (!dsp)
1452		return -ENOMEM;
1453
1454	dsp->num = 1;
1455	dsp->type = WMFW_HALO;
1456	dsp->mem = cs_dsp_mock_halo_dsp1_regions;
1457	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
1458	dsp->base = cs_dsp_mock_halo_core_base;
1459	dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
1460
1461	return cs_dsp_ctl_parse_test_common_init(test, dsp, 3);
1462}
1463
1464static int cs_dsp_ctl_parse_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
1465{
1466	struct cs_dsp *dsp;
1467
1468	/* Fill in cs_dsp and initialize */
1469	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1470	if (!dsp)
1471		return -ENOMEM;
1472
1473	dsp->num = 1;
1474	dsp->type = WMFW_ADSP2;
1475	dsp->rev = 1;
1476	dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
1477	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
1478	dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
1479
1480	return cs_dsp_ctl_parse_test_common_init(test, dsp, wmfw_ver);
1481}
1482
1483static int cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1_init(struct kunit *test)
1484{
1485	return cs_dsp_ctl_parse_test_adsp2_32bit_init(test, 1);
1486}
1487
1488static int cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2_init(struct kunit *test)
1489{
1490	return cs_dsp_ctl_parse_test_adsp2_32bit_init(test, 2);
1491}
1492
1493static int cs_dsp_ctl_parse_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
1494{
1495	struct cs_dsp *dsp;
1496
1497	/* Fill in cs_dsp and initialize */
1498	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1499	if (!dsp)
1500		return -ENOMEM;
1501
1502	dsp->num = 1;
1503	dsp->type = WMFW_ADSP2;
1504	dsp->rev = 0;
1505	dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
1506	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
1507	dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
1508
1509	return cs_dsp_ctl_parse_test_common_init(test, dsp, wmfw_ver);
1510}
1511
1512static int cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1_init(struct kunit *test)
1513{
1514	return cs_dsp_ctl_parse_test_adsp2_16bit_init(test, 1);
1515}
1516
1517static int cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2_init(struct kunit *test)
1518{
1519	return cs_dsp_ctl_parse_test_adsp2_16bit_init(test, 2);
1520}
1521
1522static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_mem_type_param_cases[] = {
1523	{ .mem_type = WMFW_ADSP2_XM },
1524	{ .mem_type = WMFW_ADSP2_YM },
1525	{ .mem_type = WMFW_ADSP2_ZM },
1526};
1527
1528static void cs_dsp_ctl_mem_type_desc(const struct cs_dsp_ctl_parse_test_param *param,
1529				     char *desc)
1530{
1531	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s",
1532		 cs_dsp_mem_region_name(param->mem_type));
1533}
1534
1535KUNIT_ARRAY_PARAM(cs_dsp_ctl_mem_type,
1536		  cs_dsp_ctl_mem_type_param_cases,
1537		  cs_dsp_ctl_mem_type_desc);
1538
1539static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_alg_id_param_cases[] = {
1540	{ .alg_id = 0xb },
1541	{ .alg_id = 0xfafa },
1542	{ .alg_id = 0x9f1234 },
1543	{ .alg_id = 0xff00ff },
1544};
1545
1546static void cs_dsp_ctl_alg_id_desc(const struct cs_dsp_ctl_parse_test_param *param,
1547				   char *desc)
1548{
1549	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg_id:%#x", param->alg_id);
1550}
1551
1552KUNIT_ARRAY_PARAM(cs_dsp_ctl_alg_id,
1553		  cs_dsp_ctl_alg_id_param_cases,
1554		  cs_dsp_ctl_alg_id_desc);
1555
1556static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_offset_param_cases[] = {
1557	{ .offset = 0x0 },
1558	{ .offset = 0x1 },
1559	{ .offset = 0x2 },
1560	{ .offset = 0x3 },
1561	{ .offset = 0x4 },
1562	{ .offset = 0x5 },
1563	{ .offset = 0x6 },
1564	{ .offset = 0x7 },
1565	{ .offset = 0xe0 },
1566	{ .offset = 0xf1 },
1567	{ .offset = 0xfffe },
1568	{ .offset = 0xffff },
1569};
1570
1571static void cs_dsp_ctl_offset_desc(const struct cs_dsp_ctl_parse_test_param *param,
1572				   char *desc)
1573{
1574	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "offset:%#x", param->offset);
1575}
1576
1577KUNIT_ARRAY_PARAM(cs_dsp_ctl_offset,
1578		  cs_dsp_ctl_offset_param_cases,
1579		  cs_dsp_ctl_offset_desc);
1580
1581static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_length_param_cases[] = {
1582	{ .length = 0x4 },
1583	{ .length = 0x8 },
1584	{ .length = 0x18 },
1585	{ .length = 0xf000 },
1586};
1587
1588static void cs_dsp_ctl_length_desc(const struct cs_dsp_ctl_parse_test_param *param,
1589				   char *desc)
1590{
1591	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "length:%#x", param->length);
1592}
1593
1594KUNIT_ARRAY_PARAM(cs_dsp_ctl_length,
1595		  cs_dsp_ctl_length_param_cases,
1596		  cs_dsp_ctl_length_desc);
1597
1598/* Note: some control types mandate specific flags settings */
1599static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_type_param_cases[] = {
1600	{ .ctl_type = WMFW_CTL_TYPE_BYTES,
1601	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1602	{ .ctl_type = WMFW_CTL_TYPE_ACKED,
1603	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1604	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1605	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE |
1606		   WMFW_CTL_FLAG_SYS },
1607	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1608	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_SYS },
1609	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1610	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE |
1611		   WMFW_CTL_FLAG_SYS },
1612};
1613
1614static void cs_dsp_ctl_type_flags_desc(const struct cs_dsp_ctl_parse_test_param *param,
1615				       char *desc)
1616{
1617	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "ctl_type:%#x flags:%#x",
1618		 param->ctl_type, param->flags);
1619}
1620
1621KUNIT_ARRAY_PARAM(cs_dsp_ctl_type,
1622		  cs_dsp_ctl_type_param_cases,
1623		  cs_dsp_ctl_type_flags_desc);
1624
1625static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_flags_param_cases[] = {
1626	{ .flags = 0 },
1627	{ .flags = WMFW_CTL_FLAG_READABLE },
1628	{ .flags = WMFW_CTL_FLAG_WRITEABLE },
1629	{ .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1630	{ .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1631	{ .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1632	{ .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE },
1633	{ .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE },
1634	{ .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1635	{ .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1636	{ .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE |
1637		   WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1638};
1639
1640static void cs_dsp_ctl_flags_desc(const struct cs_dsp_ctl_parse_test_param *param,
1641				  char *desc)
1642{
1643	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "flags:%#x", param->flags);
1644}
1645
1646KUNIT_ARRAY_PARAM(cs_dsp_ctl_flags,
1647		  cs_dsp_ctl_flags_param_cases,
1648		  cs_dsp_ctl_flags_desc);
1649
1650static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_illegal_type_flags_param_cases[] = {
1651	/* ACKED control must be volatile + read + write */
1652	{ .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = 0 },
1653	{ .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_READABLE },
1654	{ .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_WRITEABLE },
1655	{ .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_VOLATILE },
1656	{ .ctl_type = WMFW_CTL_TYPE_ACKED,
1657	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1658	{ .ctl_type = WMFW_CTL_TYPE_ACKED,
1659	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1660
1661	/* HOSTEVENT must be system + volatile + read + write */
1662	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = 0 },
1663	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_READABLE },
1664	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_WRITEABLE },
1665	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1666	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1667	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_VOLATILE },
1668	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1669	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1670	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1671	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1672	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1673	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1674	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_SYS },
1675	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1676	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE },
1677	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1678	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE },
1679	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1680	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE },
1681	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1682	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1683	{ .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1684	  .flags = WMFW_CTL_FLAG_SYS |  WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1685
1686	/* FWEVENT rules same as HOSTEVENT */
1687	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = 0 },
1688	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_READABLE },
1689	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_WRITEABLE },
1690	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1691	  .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1692	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_VOLATILE },
1693	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1694	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1695	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1696	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1697	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1698	  .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1699	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_SYS },
1700	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1701	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE },
1702	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1703	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE },
1704	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1705	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE },
1706	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1707	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1708	{ .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1709	  .flags = WMFW_CTL_FLAG_SYS |  WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1710
1711	/*
1712	 * HOSTBUFFER must be system + volatile + readable or
1713	 * system + volatile + readable + writeable
1714	 */
1715	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = 0 },
1716	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_READABLE },
1717	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_WRITEABLE },
1718	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1719	   .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE},
1720	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_VOLATILE },
1721	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1722	   .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1723	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1724	   .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1725	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1726	   .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1727	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_SYS },
1728	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1729	   .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE },
1730	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1731	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE },
1732	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1733	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1734	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1735	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE },
1736	{ .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1737	  .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1738};
1739
1740KUNIT_ARRAY_PARAM(cs_dsp_ctl_illegal_type_flags,
1741		  cs_dsp_ctl_illegal_type_flags_param_cases,
1742		  cs_dsp_ctl_type_flags_desc);
1743
1744static struct kunit_case cs_dsp_ctl_parse_test_cases_v1[] = {
1745	KUNIT_CASE(cs_dsp_ctl_parse_no_coeffs),
1746	KUNIT_CASE(cs_dsp_ctl_parse_v1_name),
1747	KUNIT_CASE(cs_dsp_ctl_parse_empty_v1_name),
1748	KUNIT_CASE(cs_dsp_ctl_parse_max_v1_name),
1749
1750	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_memory_type, cs_dsp_ctl_mem_type_gen_params),
1751	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_id, cs_dsp_ctl_alg_id_gen_params),
1752	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_mem, cs_dsp_ctl_mem_type_gen_params),
1753	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_offset, cs_dsp_ctl_offset_gen_params),
1754	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_length, cs_dsp_ctl_length_gen_params),
1755	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_ctl_type, cs_dsp_ctl_type_gen_params),
1756	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_flags, cs_dsp_ctl_flags_gen_params),
1757	KUNIT_CASE(cs_dsp_ctl_parse_fw_name),
1758
1759	KUNIT_CASE(cs_dsp_ctl_alg_id_uniqueness),
1760	KUNIT_CASE(cs_dsp_ctl_mem_uniqueness),
1761	KUNIT_CASE(cs_dsp_ctl_fw_uniqueness),
1762	KUNIT_CASE(cs_dsp_ctl_squash_reloaded_controls),
1763
1764	{ } /* terminator */
1765};
1766
1767static struct kunit_case cs_dsp_ctl_parse_test_cases_v2_v3[] = {
1768	KUNIT_CASE(cs_dsp_ctl_parse_no_coeffs),
1769	KUNIT_CASE(cs_dsp_ctl_parse_short_name),
1770	KUNIT_CASE(cs_dsp_ctl_parse_min_short_name),
1771	KUNIT_CASE(cs_dsp_ctl_parse_max_short_name),
1772	KUNIT_CASE(cs_dsp_ctl_parse_with_min_fullname),
1773	KUNIT_CASE(cs_dsp_ctl_parse_with_max_fullname),
1774	KUNIT_CASE(cs_dsp_ctl_parse_with_min_description),
1775	KUNIT_CASE(cs_dsp_ctl_parse_with_max_description),
1776	KUNIT_CASE(cs_dsp_ctl_parse_with_max_fullname_and_description),
1777	KUNIT_CASE(cs_dsp_ctl_shortname_alignment),
1778	KUNIT_CASE(cs_dsp_ctl_fullname_alignment),
1779	KUNIT_CASE(cs_dsp_ctl_description_alignment),
1780	KUNIT_CASE(cs_dsp_get_ctl_test),
1781	KUNIT_CASE(cs_dsp_get_ctl_test_multiple_wmfw),
1782
1783	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_memory_type, cs_dsp_ctl_mem_type_gen_params),
1784	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_id, cs_dsp_ctl_alg_id_gen_params),
1785	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_mem, cs_dsp_ctl_mem_type_gen_params),
1786	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_offset, cs_dsp_ctl_offset_gen_params),
1787	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_length, cs_dsp_ctl_length_gen_params),
1788	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_ctl_type, cs_dsp_ctl_type_gen_params),
1789	KUNIT_CASE_PARAM(cs_dsp_ctl_parse_flags, cs_dsp_ctl_flags_gen_params),
1790	KUNIT_CASE_PARAM(cs_dsp_ctl_illegal_type_flags,
1791			 cs_dsp_ctl_illegal_type_flags_gen_params),
1792	KUNIT_CASE(cs_dsp_ctl_parse_fw_name),
1793
1794	KUNIT_CASE(cs_dsp_ctl_alg_id_uniqueness),
1795	KUNIT_CASE(cs_dsp_ctl_mem_uniqueness),
1796	KUNIT_CASE(cs_dsp_ctl_fw_uniqueness),
1797	KUNIT_CASE(cs_dsp_ctl_squash_reloaded_controls),
1798	KUNIT_CASE(cs_dsp_ctl_v2_squash_reloaded_controls),
1799	KUNIT_CASE(cs_dsp_ctl_v2_compare_len),
1800
1801	{ } /* terminator */
1802};
1803
1804static struct kunit_suite cs_dsp_ctl_parse_test_halo = {
1805	.name = "cs_dsp_ctl_parse_wmfwV3_halo",
1806	.init = cs_dsp_ctl_parse_test_halo_init,
1807	.test_cases = cs_dsp_ctl_parse_test_cases_v2_v3,
1808};
1809
1810static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1 = {
1811	.name = "cs_dsp_ctl_parse_wmfwV1_adsp2_32bit",
1812	.init = cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1_init,
1813	.test_cases = cs_dsp_ctl_parse_test_cases_v1,
1814};
1815
1816static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2 = {
1817	.name = "cs_dsp_ctl_parse_wmfwV2_adsp2_32bit",
1818	.init = cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2_init,
1819	.test_cases = cs_dsp_ctl_parse_test_cases_v2_v3,
1820};
1821
1822static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1 = {
1823	.name = "cs_dsp_ctl_parse_wmfwV1_adsp2_16bit",
1824	.init = cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1_init,
1825	.test_cases = cs_dsp_ctl_parse_test_cases_v1,
1826};
1827
1828static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2 = {
1829	.name = "cs_dsp_ctl_parse_wmfwV2_adsp2_16bit",
1830	.init = cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2_init,
1831	.test_cases = cs_dsp_ctl_parse_test_cases_v2_v3,
1832};
1833
1834kunit_test_suites(&cs_dsp_ctl_parse_test_halo,
1835		  &cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1,
1836		  &cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2,
1837		  &cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1,
1838		  &cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2);
~/ Read-only file preview.