1 // SPDX-License-Identifier: GPL-2.0-only
3 // KUnit tests for cs_dsp.
5 // Copyright (C) 2024 Cirrus Logic, Inc. and
6 // Cirrus Logic International Semiconductor Ltd.
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>
19 KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *);
20 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
22 struct cs_dsp_test_local {
23 struct cs_dsp_mock_xm_header *xm_header;
24 struct cs_dsp_mock_wmfw_builder *wmfw_builder;
28 struct cs_dsp_ctl_parse_test_param {
37 static const struct cs_dsp_mock_alg_def cs_dsp_ctl_parse_test_algs[] = {
68 static 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,
76 /* Algorithm info block without controls should load */
77 static void cs_dsp_ctl_parse_no_coeffs(struct kunit *test)
79 struct cs_dsp_test *priv = test->priv;
80 struct cs_dsp_test_local *local = priv->local;
81 struct firmware *wmfw;
83 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
84 cs_dsp_ctl_parse_test_algs[0].id,
86 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
88 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
89 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
93 * V1 controls do not have names, the name field in the coefficient entry
96 static void cs_dsp_ctl_parse_v1_name(struct kunit *test)
98 struct cs_dsp_test *priv = test->priv;
99 struct cs_dsp_test_local *local = priv->local;
100 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
101 struct cs_dsp_coeff_ctl *ctl;
102 struct firmware *wmfw;
104 def.fullname = "Dummy";
105 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
106 cs_dsp_ctl_parse_test_algs[0].id,
108 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
109 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
111 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
112 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
114 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
115 KUNIT_ASSERT_NOT_NULL(test, ctl);
116 KUNIT_EXPECT_EQ(test, ctl->subname_len, 0);
117 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
118 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
119 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
123 * V1 controls do not have names, the name field in the coefficient entry
124 * should be ignored. Test with a zero-length name string.
126 static void cs_dsp_ctl_parse_empty_v1_name(struct kunit *test)
128 struct cs_dsp_test *priv = test->priv;
129 struct cs_dsp_test_local *local = priv->local;
130 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
131 struct cs_dsp_coeff_ctl *ctl;
132 struct firmware *wmfw;
135 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
136 cs_dsp_ctl_parse_test_algs[0].id,
138 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
139 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
141 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
142 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
144 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
145 KUNIT_ASSERT_NOT_NULL(test, ctl);
146 KUNIT_EXPECT_EQ(test, ctl->subname_len, 0);
147 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
148 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
149 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
153 * V1 controls do not have names, the name field in the coefficient entry
154 * should be ignored. Test with a maximum length name string.
156 static void cs_dsp_ctl_parse_max_v1_name(struct kunit *test)
158 struct cs_dsp_test *priv = test->priv;
159 struct cs_dsp_test_local *local = priv->local;
160 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
161 struct cs_dsp_coeff_ctl *ctl;
162 struct firmware *wmfw;
165 name = kunit_kzalloc(test, 256, GFP_KERNEL);
166 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, name);
167 memset(name, 'A', 255);
170 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
171 cs_dsp_ctl_parse_test_algs[0].id,
173 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
174 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
176 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
177 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
179 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
180 KUNIT_ASSERT_NOT_NULL(test, ctl);
181 KUNIT_EXPECT_EQ(test, ctl->subname_len, 0);
182 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
183 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
184 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
187 /* Short name from coeff descriptor should be used as control name. */
188 static void cs_dsp_ctl_parse_short_name(struct kunit *test)
190 struct cs_dsp_test *priv = test->priv;
191 struct cs_dsp_test_local *local = priv->local;
192 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
193 struct cs_dsp_coeff_ctl *ctl;
194 struct firmware *wmfw;
196 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
197 cs_dsp_ctl_parse_test_algs[0].id,
199 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
200 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
202 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
203 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
205 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
206 KUNIT_ASSERT_NOT_NULL(test, ctl);
207 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
208 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
209 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
210 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
211 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
215 * Short name from coeff descriptor should be used as control name.
216 * Test with a short name that is a single character.
218 static void cs_dsp_ctl_parse_min_short_name(struct kunit *test)
220 struct cs_dsp_test *priv = test->priv;
221 struct cs_dsp_test_local *local = priv->local;
222 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
223 struct cs_dsp_coeff_ctl *ctl;
224 struct firmware *wmfw;
227 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
228 cs_dsp_ctl_parse_test_algs[0].id,
230 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
231 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
233 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
234 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
236 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
237 KUNIT_ASSERT_NOT_NULL(test, ctl);
238 KUNIT_EXPECT_EQ(test, ctl->subname_len, 1);
239 KUNIT_EXPECT_EQ(test, ctl->subname[0], 'Q');
240 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
241 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
242 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
246 * Short name from coeff descriptor should be used as control name.
247 * Test with a maximum length name.
249 static void cs_dsp_ctl_parse_max_short_name(struct kunit *test)
251 struct cs_dsp_test *priv = test->priv;
252 struct cs_dsp_test_local *local = priv->local;
253 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
254 struct cs_dsp_coeff_ctl *ctl;
256 struct firmware *wmfw;
258 name = kunit_kmalloc(test, 255, GFP_KERNEL);
259 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, name);
260 memset(name, 'A', 255);
262 def.shortname = name;
264 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
265 cs_dsp_ctl_parse_test_algs[0].id,
267 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
268 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
270 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
271 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
273 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
274 KUNIT_ASSERT_NOT_NULL(test, ctl);
275 KUNIT_EXPECT_EQ(test, ctl->subname_len, 255);
276 KUNIT_EXPECT_MEMEQ(test, ctl->subname, name, ctl->subname_len);
277 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
278 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
279 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
283 * Full name from coeff descriptor should be ignored. It is a variable
284 * length field so affects the position of subsequent fields.
285 * Test with a 1-character full name.
287 static void cs_dsp_ctl_parse_with_min_fullname(struct kunit *test)
289 struct cs_dsp_test *priv = test->priv;
290 struct cs_dsp_test_local *local = priv->local;
291 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
292 struct cs_dsp_coeff_ctl *ctl;
293 struct firmware *wmfw;
296 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
297 cs_dsp_ctl_parse_test_algs[0].id,
299 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
300 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
302 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
303 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
305 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
306 KUNIT_ASSERT_NOT_NULL(test, ctl);
307 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
308 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
309 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
310 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
311 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
315 * Full name from coeff descriptor should be ignored. It is a variable
316 * length field so affects the position of subsequent fields.
317 * Test with a maximum length full name.
319 static void cs_dsp_ctl_parse_with_max_fullname(struct kunit *test)
321 struct cs_dsp_test *priv = test->priv;
322 struct cs_dsp_test_local *local = priv->local;
323 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
324 struct cs_dsp_coeff_ctl *ctl;
325 struct firmware *wmfw;
328 fullname = kunit_kmalloc(test, 255, GFP_KERNEL);
329 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fullname);
330 memset(fullname, 'A', 255);
331 def.fullname = fullname;
333 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
334 cs_dsp_ctl_parse_test_algs[0].id,
336 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
337 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
339 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
340 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
342 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
343 KUNIT_ASSERT_NOT_NULL(test, ctl);
344 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
345 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
346 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
347 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
348 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
352 * Description from coeff descriptor should be ignored. It is a variable
353 * length field so affects the position of subsequent fields.
354 * Test with a 1-character description
356 static void cs_dsp_ctl_parse_with_min_description(struct kunit *test)
358 struct cs_dsp_test *priv = test->priv;
359 struct cs_dsp_test_local *local = priv->local;
360 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
361 struct cs_dsp_coeff_ctl *ctl;
362 struct firmware *wmfw;
364 def.description = "Q";
365 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
366 cs_dsp_ctl_parse_test_algs[0].id,
368 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
369 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
371 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
372 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
374 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
375 KUNIT_ASSERT_NOT_NULL(test, ctl);
376 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
377 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
378 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
379 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
380 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
384 * Description from coeff descriptor should be ignored. It is a variable
385 * length field so affects the position of subsequent fields.
386 * Test with a maximum length description
388 static void cs_dsp_ctl_parse_with_max_description(struct kunit *test)
390 struct cs_dsp_test *priv = test->priv;
391 struct cs_dsp_test_local *local = priv->local;
392 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
393 struct cs_dsp_coeff_ctl *ctl;
394 struct firmware *wmfw;
397 description = kunit_kmalloc(test, 65535, GFP_KERNEL);
398 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, description);
399 memset(description, 'A', 65535);
400 def.description = description;
402 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
403 cs_dsp_ctl_parse_test_algs[0].id,
405 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
406 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
408 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
409 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
411 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
412 KUNIT_ASSERT_NOT_NULL(test, ctl);
413 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
414 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
415 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
416 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
417 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
421 * Full name and description from coeff descriptor are variable length
422 * fields so affects the position of subsequent fields.
423 * Test with a maximum length full name and description
425 static void cs_dsp_ctl_parse_with_max_fullname_and_description(struct kunit *test)
427 struct cs_dsp_test *priv = test->priv;
428 struct cs_dsp_test_local *local = priv->local;
429 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
430 struct cs_dsp_coeff_ctl *ctl;
431 struct firmware *wmfw;
432 char *fullname, *description;
434 fullname = kunit_kmalloc(test, 255, GFP_KERNEL);
435 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fullname);
436 memset(fullname, 'A', 255);
437 def.fullname = fullname;
439 description = kunit_kmalloc(test, 65535, GFP_KERNEL);
440 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, description);
441 memset(description, 'A', 65535);
442 def.description = description;
444 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
445 cs_dsp_ctl_parse_test_algs[0].id,
447 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
448 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
450 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
451 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
453 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
454 KUNIT_ASSERT_NOT_NULL(test, ctl);
455 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname));
456 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len);
457 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
458 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
459 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
462 static const char * const cs_dsp_ctl_alignment_test_names[] = {
463 "1", "12", "123", "1234", "12345", "123456", "1234567",
464 "12345678", "123456789", "123456789A", "123456789AB",
465 "123456789ABC", "123456789ABCD", "123456789ABCDE",
470 * Variable-length string fields are padded to a multiple of 4-bytes.
471 * Test this with various lengths of short name.
473 static void cs_dsp_ctl_shortname_alignment(struct kunit *test)
475 struct cs_dsp_test *priv = test->priv;
476 struct cs_dsp_test_local *local = priv->local;
477 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
478 struct cs_dsp_coeff_ctl *ctl;
479 struct firmware *wmfw;
482 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
483 cs_dsp_ctl_parse_test_algs[0].id,
486 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
487 def.shortname = cs_dsp_ctl_alignment_test_names[i];
488 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
491 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
493 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
494 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
496 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
497 mutex_lock(&priv->dsp->pwr_lock);
498 ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_ctl_alignment_test_names[i],
499 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
500 mutex_unlock(&priv->dsp->pwr_lock);
501 KUNIT_ASSERT_NOT_NULL(test, ctl);
502 KUNIT_EXPECT_EQ(test, ctl->subname_len, i + 1);
503 KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_ctl_alignment_test_names[i],
505 /* Test fields that are parsed after the variable-length fields */
506 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
507 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
508 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
513 * Variable-length string fields are padded to a multiple of 4-bytes.
514 * Test this with various lengths of full name.
516 static void cs_dsp_ctl_fullname_alignment(struct kunit *test)
518 struct cs_dsp_test *priv = test->priv;
519 struct cs_dsp_test_local *local = priv->local;
520 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
521 struct cs_dsp_coeff_ctl *ctl;
523 struct firmware *wmfw;
526 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
527 cs_dsp_ctl_parse_test_algs[0].id,
530 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
532 * Create a unique control name of 3 characters so that
533 * the shortname field is exactly 4 bytes long including
536 snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
537 KUNIT_ASSERT_EQ(test, strlen(ctl_name), 3);
538 def.shortname = ctl_name;
540 def.fullname = cs_dsp_ctl_alignment_test_names[i];
541 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
544 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
546 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
547 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
549 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
550 snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
552 mutex_lock(&priv->dsp->pwr_lock);
553 ctl = cs_dsp_get_ctl(priv->dsp, ctl_name, def.mem_type,
554 cs_dsp_ctl_parse_test_algs[0].id);
555 mutex_unlock(&priv->dsp->pwr_lock);
556 KUNIT_ASSERT_NOT_NULL(test, ctl);
557 KUNIT_EXPECT_EQ(test, ctl->subname_len, 3);
558 KUNIT_EXPECT_MEMEQ(test, ctl->subname, ctl_name, ctl->subname_len);
559 /* Test fields that are parsed after the variable-length fields */
560 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
561 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
562 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
567 * Variable-length string fields are padded to a multiple of 4-bytes.
568 * Test this with various lengths of description.
570 static void cs_dsp_ctl_description_alignment(struct kunit *test)
572 struct cs_dsp_test *priv = test->priv;
573 struct cs_dsp_test_local *local = priv->local;
574 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
575 struct cs_dsp_coeff_ctl *ctl;
577 struct firmware *wmfw;
580 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
581 cs_dsp_ctl_parse_test_algs[0].id,
584 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
586 * Create a unique control name of 3 characters so that
587 * the shortname field is exactly 4 bytes long including
590 snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
591 KUNIT_ASSERT_EQ(test, strlen(ctl_name), 3);
592 def.shortname = ctl_name;
594 def.description = cs_dsp_ctl_alignment_test_names[i];
595 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
598 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
600 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
601 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
603 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
604 snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
606 mutex_lock(&priv->dsp->pwr_lock);
607 ctl = cs_dsp_get_ctl(priv->dsp, ctl_name, def.mem_type,
608 cs_dsp_ctl_parse_test_algs[0].id);
609 mutex_unlock(&priv->dsp->pwr_lock);
610 KUNIT_ASSERT_NOT_NULL(test, ctl);
611 KUNIT_EXPECT_EQ(test, ctl->subname_len, 3);
612 KUNIT_EXPECT_MEMEQ(test, ctl->subname, ctl_name, ctl->subname_len);
613 /* Test fields that are parsed after the variable-length fields */
614 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
615 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
616 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
620 static const char * const cs_dsp_get_ctl_test_names[] = {
621 "Up", "Down", "Switch", "Mute",
622 "Left Up", "Left Down", "Right Up", "Right Down",
623 "Left Mute", "Right Mute",
624 "_trunc_1", "_trunc_2", " trunc",
627 /* Test using cs_dsp_get_ctl() to lookup various controls. */
628 static void cs_dsp_get_ctl_test(struct kunit *test)
630 struct cs_dsp_test *priv = test->priv;
631 struct cs_dsp_test_local *local = priv->local;
632 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
633 struct cs_dsp_coeff_ctl *ctl;
634 struct firmware *wmfw;
637 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
638 cs_dsp_ctl_parse_test_algs[0].id,
641 for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) {
642 def.shortname = cs_dsp_get_ctl_test_names[i];
643 def.offset_dsp_words = i;
644 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
647 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
649 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
650 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
652 for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) {
653 mutex_lock(&priv->dsp->pwr_lock);
654 ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_get_ctl_test_names[i],
655 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
656 mutex_unlock(&priv->dsp->pwr_lock);
657 KUNIT_ASSERT_NOT_NULL(test, ctl);
658 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(cs_dsp_get_ctl_test_names[i]));
659 KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_get_ctl_test_names[i],
661 KUNIT_EXPECT_EQ(test, ctl->offset, i);
666 * cs_dsp_get_ctl() searches for the control in the currently loaded
667 * firmware, so create identical controls in multiple firmware and
668 * test that the correct one is found.
670 static void cs_dsp_get_ctl_test_multiple_wmfw(struct kunit *test)
672 struct cs_dsp_test *priv = test->priv;
673 struct cs_dsp_test_local *local = priv->local;
674 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
675 struct cs_dsp_coeff_ctl *ctl;
676 struct cs_dsp_mock_wmfw_builder *builder2;
677 struct firmware *wmfw;
679 def.shortname = "_A_CONTROL";
681 /* Create a second mock wmfw builder */
682 builder2 = cs_dsp_mock_wmfw_init(priv,
683 cs_dsp_mock_wmfw_format_version(local->wmfw_builder));
684 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2);
685 cs_dsp_mock_wmfw_add_data_block(builder2,
687 local->xm_header->blob_data,
688 local->xm_header->blob_size_bytes);
690 /* Load a 'misc' firmware with a control */
691 def.offset_dsp_words = 1;
692 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
693 cs_dsp_ctl_parse_test_algs[0].id,
695 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
696 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
697 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
698 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
699 cs_dsp_power_down(priv->dsp);
701 /* Load a 'mbc/vss' firmware with a control of the same name */
702 def.offset_dsp_words = 2;
703 cs_dsp_mock_wmfw_start_alg_info_block(builder2,
704 cs_dsp_ctl_parse_test_algs[0].id,
706 cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def);
707 cs_dsp_mock_wmfw_end_alg_info_block(builder2);
708 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
709 KUNIT_ASSERT_EQ(test,
710 cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2", NULL, NULL, "mbc/vss"), 0);
712 /* A lookup should return the control for the current firmware */
713 mutex_lock(&priv->dsp->pwr_lock);
714 ctl = cs_dsp_get_ctl(priv->dsp, def.shortname,
715 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
716 mutex_unlock(&priv->dsp->pwr_lock);
717 KUNIT_ASSERT_NOT_NULL(test, ctl);
718 KUNIT_EXPECT_EQ(test, ctl->offset, 2);
720 /* Re-load the 'misc' firmware and a lookup should return its control */
721 cs_dsp_power_down(priv->dsp);
722 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
723 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
725 mutex_lock(&priv->dsp->pwr_lock);
726 ctl = cs_dsp_get_ctl(priv->dsp, def.shortname,
727 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
728 mutex_unlock(&priv->dsp->pwr_lock);
729 KUNIT_ASSERT_NOT_NULL(test, ctl);
730 KUNIT_EXPECT_EQ(test, ctl->offset, 1);
733 /* Test that the value of the memory type field is parsed correctly. */
734 static void cs_dsp_ctl_parse_memory_type(struct kunit *test)
736 const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
737 struct cs_dsp_test *priv = test->priv;
738 struct cs_dsp_test_local *local = priv->local;
739 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
740 struct cs_dsp_coeff_ctl *ctl;
741 struct firmware *wmfw;
743 /* kunit_skip() marks the test skipped forever, so just return */
744 if ((param->mem_type == WMFW_ADSP2_ZM) && !cs_dsp_mock_has_zm(priv))
747 def.mem_type = param->mem_type;
749 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
750 cs_dsp_ctl_parse_test_algs[0].id,
752 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
753 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
755 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
756 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
758 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
759 KUNIT_ASSERT_NOT_NULL(test, ctl);
760 KUNIT_EXPECT_EQ(test, ctl->alg_region.type, param->mem_type);
761 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
762 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
763 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
767 * Test that the algorithm id from the parent alg-info block is
768 * correctly stored in the cs_dsp_coeff_ctl.
770 static void cs_dsp_ctl_parse_alg_id(struct kunit *test)
772 const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
773 struct cs_dsp_test *priv = test->priv;
774 struct cs_dsp_test_local *local = priv->local;
775 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
776 struct cs_dsp_coeff_ctl *ctl;
777 struct firmware *wmfw;
779 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
782 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
783 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
785 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
786 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
788 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
789 KUNIT_ASSERT_NOT_NULL(test, ctl);
790 KUNIT_EXPECT_EQ(test, ctl->alg_region.alg, param->alg_id);
791 KUNIT_EXPECT_EQ(test, ctl->alg_region.type, def.mem_type);
792 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
793 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
794 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
798 * Test that the values of (alg id, memory type) tuple is parsed correctly.
799 * The alg id is parsed from the alg-info block, but the memory type is
800 * parsed from the coefficient info descriptor.
802 static void cs_dsp_ctl_parse_alg_mem(struct kunit *test)
804 const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
805 struct cs_dsp_test *priv = test->priv;
806 struct cs_dsp_test_local *local = priv->local;
807 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
808 struct cs_dsp_coeff_ctl *ctl;
809 struct firmware *wmfw;
811 /* kunit_skip() marks the test skipped forever, so just return */
812 if ((param->mem_type == WMFW_ADSP2_ZM) && !cs_dsp_mock_has_zm(priv))
815 def.mem_type = param->mem_type;
817 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
820 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
821 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
823 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
824 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
826 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
827 KUNIT_ASSERT_NOT_NULL(test, ctl);
828 KUNIT_EXPECT_EQ(test, ctl->alg_region.alg, param->alg_id);
829 KUNIT_EXPECT_EQ(test, ctl->alg_region.type, param->mem_type);
832 /* Test that the value of the offset field is parsed correctly. */
833 static void cs_dsp_ctl_parse_offset(struct kunit *test)
835 const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
836 struct cs_dsp_test *priv = test->priv;
837 struct cs_dsp_test_local *local = priv->local;
838 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
839 struct cs_dsp_coeff_ctl *ctl;
840 struct firmware *wmfw;
842 def.offset_dsp_words = param->offset;
844 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
845 cs_dsp_ctl_parse_test_algs[0].id,
847 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
848 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
850 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
851 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
853 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
854 KUNIT_ASSERT_NOT_NULL(test, ctl);
855 KUNIT_EXPECT_EQ(test, ctl->offset, param->offset);
856 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
857 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
858 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
861 /* Test that the value of the length field is parsed correctly. */
862 static void cs_dsp_ctl_parse_length(struct kunit *test)
864 const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
865 struct cs_dsp_test *priv = test->priv;
866 struct cs_dsp_test_local *local = priv->local;
867 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
868 struct cs_dsp_coeff_ctl *ctl;
869 struct firmware *wmfw;
871 def.length_bytes = param->length;
873 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
874 cs_dsp_ctl_parse_test_algs[0].id,
876 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
877 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
879 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
880 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
882 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
883 KUNIT_ASSERT_NOT_NULL(test, ctl);
884 KUNIT_EXPECT_EQ(test, ctl->offset, def.offset_dsp_words);
885 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
886 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
887 KUNIT_EXPECT_EQ(test, ctl->len, param->length);
890 /* Test that the value of the control type field is parsed correctly. */
891 static void cs_dsp_ctl_parse_ctl_type(struct kunit *test)
893 const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
894 struct cs_dsp_test *priv = test->priv;
895 struct cs_dsp_test_local *local = priv->local;
896 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
897 struct cs_dsp_coeff_ctl *ctl;
898 struct firmware *wmfw;
900 def.type = param->ctl_type;
901 def.flags = param->flags;
903 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
904 cs_dsp_ctl_parse_test_algs[0].id,
906 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
907 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
909 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
910 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
912 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
913 KUNIT_ASSERT_NOT_NULL(test, ctl);
914 KUNIT_EXPECT_EQ(test, ctl->type, param->ctl_type);
915 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags);
916 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
919 /* Test that the value of the flags field is parsed correctly. */
920 static void cs_dsp_ctl_parse_flags(struct kunit *test)
922 const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
923 struct cs_dsp_test *priv = test->priv;
924 struct cs_dsp_test_local *local = priv->local;
925 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
926 struct cs_dsp_coeff_ctl *ctl;
927 struct firmware *wmfw;
931 * Non volatile controls will be read to initialize the cache
932 * so the regmap cache must contain something to read.
935 regmap_raw_write(priv->dsp->regmap,
936 cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM),
937 ®_val, sizeof(reg_val));
939 def.flags = param->flags;
940 def.mem_type = WMFW_ADSP2_YM;
942 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
943 cs_dsp_ctl_parse_test_algs[0].id,
945 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
946 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
948 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
949 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
951 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
952 KUNIT_ASSERT_NOT_NULL(test, ctl);
953 KUNIT_EXPECT_EQ(test, ctl->type, def.type);
954 KUNIT_EXPECT_EQ(test, ctl->flags, param->flags);
955 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes);
958 /* Test that invalid combinations of (control type, flags) are rejected. */
959 static void cs_dsp_ctl_illegal_type_flags(struct kunit *test)
961 const struct cs_dsp_ctl_parse_test_param *param = test->param_value;
962 struct cs_dsp_test *priv = test->priv;
963 struct cs_dsp_test_local *local = priv->local;
964 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
965 struct firmware *wmfw;
969 * Non volatile controls will be read to initialize the cache
970 * so the regmap cache must contain something to read.
973 regmap_raw_write(priv->dsp->regmap,
974 cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM),
975 ®_val, sizeof(reg_val));
977 def.type = param->ctl_type;
978 def.flags = param->flags;
979 def.mem_type = WMFW_ADSP2_YM;
981 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
982 cs_dsp_ctl_parse_test_algs[0].id,
984 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
985 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
987 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
988 KUNIT_ASSERT_LT(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
991 /* Test that the correct firmware name is entered in the cs_dsp_coeff_ctl. */
992 static void cs_dsp_ctl_parse_fw_name(struct kunit *test)
994 struct cs_dsp_test *priv = test->priv;
995 struct cs_dsp_test_local *local = priv->local;
996 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
997 struct cs_dsp_coeff_ctl *walkctl, *ctl1, *ctl2;
998 struct cs_dsp_mock_wmfw_builder *builder2;
999 struct firmware *wmfw;
1001 /* Create a second mock wmfw builder */
1002 builder2 = cs_dsp_mock_wmfw_init(priv,
1003 cs_dsp_mock_wmfw_format_version(local->wmfw_builder));
1004 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2);
1005 cs_dsp_mock_wmfw_add_data_block(builder2,
1007 local->xm_header->blob_data,
1008 local->xm_header->blob_size_bytes);
1010 /* Load a 'misc' firmware with a control */
1011 def.offset_dsp_words = 1;
1012 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1013 cs_dsp_ctl_parse_test_algs[0].id,
1015 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1016 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1017 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1018 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1019 cs_dsp_power_down(priv->dsp);
1021 /* Load a 'mbc/vss' firmware with a control */
1022 def.offset_dsp_words = 2;
1023 cs_dsp_mock_wmfw_start_alg_info_block(builder2,
1024 cs_dsp_ctl_parse_test_algs[0].id,
1026 cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def);
1027 cs_dsp_mock_wmfw_end_alg_info_block(builder2);
1028 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1029 KUNIT_ASSERT_EQ(test,
1030 cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2", NULL, NULL, "mbc/vss"), 0);
1032 /* Both controls should be in the list (order not guaranteed) */
1033 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1036 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1037 if (strcmp(walkctl->fw_name, "misc") == 0)
1039 else if (strcmp(walkctl->fw_name, "mbc/vss") == 0)
1043 KUNIT_EXPECT_NOT_NULL(test, ctl1);
1044 KUNIT_EXPECT_NOT_NULL(test, ctl2);
1045 KUNIT_EXPECT_EQ(test, ctl1->offset, 1);
1046 KUNIT_EXPECT_EQ(test, ctl2->offset, 2);
1049 /* Controls are unique if the algorithm ID is different */
1050 static void cs_dsp_ctl_alg_id_uniqueness(struct kunit *test)
1052 struct cs_dsp_test *priv = test->priv;
1053 struct cs_dsp_test_local *local = priv->local;
1054 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1055 struct cs_dsp_coeff_ctl *ctl1, *ctl2;
1056 struct firmware *wmfw;
1058 /* Create an algorithm containing the control */
1059 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1060 cs_dsp_ctl_parse_test_algs[0].id,
1062 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1063 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1065 /* Create a different algorithm containing an identical control */
1066 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1067 cs_dsp_ctl_parse_test_algs[1].id,
1069 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1070 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1072 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1073 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1074 cs_dsp_power_down(priv->dsp);
1076 /* Both controls should be in the list */
1077 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1078 ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1079 ctl2 = list_next_entry(ctl1, list);
1080 KUNIT_EXPECT_NOT_NULL(test, ctl1);
1081 KUNIT_EXPECT_NOT_NULL(test, ctl2);
1082 KUNIT_EXPECT_NE(test, ctl1->alg_region.alg, ctl2->alg_region.alg);
1083 KUNIT_EXPECT_EQ(test, ctl1->alg_region.type, ctl2->alg_region.type);
1084 KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset);
1085 KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type);
1086 KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags);
1087 KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len);
1088 KUNIT_EXPECT_STREQ(test, ctl1->fw_name, ctl2->fw_name);
1089 KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len);
1090 if (ctl1->subname_len)
1091 KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len);
1094 /* Controls are unique if the memory region is different */
1095 static void cs_dsp_ctl_mem_uniqueness(struct kunit *test)
1097 struct cs_dsp_test *priv = test->priv;
1098 struct cs_dsp_test_local *local = priv->local;
1099 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1100 struct cs_dsp_coeff_ctl *ctl1, *ctl2;
1101 struct firmware *wmfw;
1103 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1104 cs_dsp_ctl_parse_test_algs[0].id,
1106 /* Create control in XM */
1107 def.mem_type = WMFW_ADSP2_XM;
1108 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1110 /* Create control in YM */
1111 def.mem_type = WMFW_ADSP2_YM;
1112 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1114 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1116 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1117 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1118 cs_dsp_power_down(priv->dsp);
1120 /* Both controls should be in the list */
1121 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1122 ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1123 ctl2 = list_next_entry(ctl1, list);
1124 KUNIT_EXPECT_NOT_NULL(test, ctl1);
1125 KUNIT_EXPECT_NOT_NULL(test, ctl2);
1126 KUNIT_EXPECT_EQ(test, ctl1->alg_region.alg, ctl2->alg_region.alg);
1127 KUNIT_EXPECT_NE(test, ctl1->alg_region.type, ctl2->alg_region.type);
1128 KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset);
1129 KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type);
1130 KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags);
1131 KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len);
1132 KUNIT_EXPECT_STREQ(test, ctl1->fw_name, ctl2->fw_name);
1133 KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len);
1134 if (ctl1->subname_len)
1135 KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len);
1138 /* Controls are unique if they are in different firmware */
1139 static void cs_dsp_ctl_fw_uniqueness(struct kunit *test)
1141 struct cs_dsp_test *priv = test->priv;
1142 struct cs_dsp_test_local *local = priv->local;
1143 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1144 struct cs_dsp_coeff_ctl *ctl1, *ctl2;
1145 struct cs_dsp_mock_wmfw_builder *builder2;
1146 struct firmware *wmfw;
1148 /* Create a second mock wmfw builder */
1149 builder2 = cs_dsp_mock_wmfw_init(priv,
1150 cs_dsp_mock_wmfw_format_version(local->wmfw_builder));
1151 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2);
1152 cs_dsp_mock_wmfw_add_data_block(builder2,
1154 local->xm_header->blob_data,
1155 local->xm_header->blob_size_bytes);
1157 /* Load a 'misc' firmware with a control */
1158 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1159 cs_dsp_ctl_parse_test_algs[0].id,
1161 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1162 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1163 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1164 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1165 cs_dsp_power_down(priv->dsp);
1167 /* Load a 'mbc/vss' firmware with the same control */
1168 cs_dsp_mock_wmfw_start_alg_info_block(builder2,
1169 cs_dsp_ctl_parse_test_algs[0].id,
1171 cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def);
1172 cs_dsp_mock_wmfw_end_alg_info_block(builder2);
1173 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1174 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2",
1175 NULL, NULL, "mbc/vss"), 0);
1176 cs_dsp_power_down(priv->dsp);
1178 /* Both controls should be in the list */
1179 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1180 ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1181 ctl2 = list_next_entry(ctl1, list);
1182 KUNIT_EXPECT_NOT_NULL(test, ctl1);
1183 KUNIT_EXPECT_NOT_NULL(test, ctl2);
1184 KUNIT_EXPECT_EQ(test, ctl1->alg_region.alg, ctl2->alg_region.alg);
1185 KUNIT_EXPECT_EQ(test, ctl1->alg_region.type, ctl2->alg_region.type);
1186 KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset);
1187 KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type);
1188 KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags);
1189 KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len);
1190 KUNIT_EXPECT_STRNEQ(test, ctl1->fw_name, ctl2->fw_name);
1191 KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len);
1192 if (ctl1->subname_len)
1193 KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len);
1197 * Controls from a wmfw are only added to the list once. If the same
1198 * wmfw is reloaded the controls are not added again.
1199 * This creates multiple algorithms with one control each, which will
1200 * work on both V1 format and >=V2 format controls.
1202 static void cs_dsp_ctl_squash_reloaded_controls(struct kunit *test)
1204 struct cs_dsp_test *priv = test->priv;
1205 struct cs_dsp_test_local *local = priv->local;
1206 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1207 struct cs_dsp_coeff_ctl *ctls[ARRAY_SIZE(cs_dsp_ctl_parse_test_algs)];
1208 struct cs_dsp_coeff_ctl *walkctl;
1209 struct firmware *wmfw;
1212 /* Create some algorithms with a control */
1213 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_parse_test_algs); i++) {
1214 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1215 cs_dsp_ctl_parse_test_algs[i].id,
1217 def.mem_type = WMFW_ADSP2_YM;
1218 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1219 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1222 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1223 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1224 cs_dsp_power_down(priv->dsp);
1226 /* All controls should be in the list */
1227 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
1228 ARRAY_SIZE(cs_dsp_ctl_parse_test_algs));
1230 /* Take a copy of the pointers to controls to compare against. */
1232 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1233 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1234 ctls[i++] = walkctl;
1238 /* Load the wmfw again */
1239 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1240 cs_dsp_power_down(priv->dsp);
1242 /* The number of controls should be the same */
1243 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
1244 ARRAY_SIZE(cs_dsp_ctl_parse_test_algs));
1246 /* And they should be the same objects */
1248 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1249 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1250 KUNIT_ASSERT_PTR_EQ(test, walkctl, ctls[i++]);
1255 * Controls from a wmfw are only added to the list once. If the same
1256 * wmfw is reloaded the controls are not added again.
1257 * This tests >=V2 firmware that can have multiple named controls in
1258 * the same algorithm.
1260 static void cs_dsp_ctl_v2_squash_reloaded_controls(struct kunit *test)
1262 struct cs_dsp_test *priv = test->priv;
1263 struct cs_dsp_test_local *local = priv->local;
1264 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1265 struct cs_dsp_coeff_ctl *ctls[ARRAY_SIZE(cs_dsp_get_ctl_test_names)];
1266 struct cs_dsp_coeff_ctl *walkctl;
1267 struct firmware *wmfw;
1270 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1271 cs_dsp_ctl_parse_test_algs[0].id,
1274 /* Create some controls */
1275 for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) {
1276 def.shortname = cs_dsp_get_ctl_test_names[i];
1277 def.offset_dsp_words = i;
1279 def.mem_type = WMFW_ADSP2_XM;
1281 def.mem_type = WMFW_ADSP2_YM;
1283 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1286 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1288 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1289 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1290 cs_dsp_power_down(priv->dsp);
1292 /* All controls should be in the list */
1293 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
1294 ARRAY_SIZE(cs_dsp_get_ctl_test_names));
1296 /* Take a copy of the pointers to controls to compare against. */
1298 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1299 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1300 ctls[i++] = walkctl;
1304 /* Load the wmfw again */
1305 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1306 cs_dsp_power_down(priv->dsp);
1308 /* The number of controls should be the same */
1309 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
1310 ARRAY_SIZE(cs_dsp_get_ctl_test_names));
1312 /* And they should be the same objects */
1314 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1315 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1316 KUNIT_ASSERT_PTR_EQ(test, walkctl, ctls[i++]);
1320 static const char * const cs_dsp_ctl_v2_compare_len_names[] = {
1333 * When comparing shortnames the full length of both strings is
1334 * considered, not only the characters in of the shortest string.
1335 * So that "LEFT" is not the same as "LEFT2".
1336 * This is specifically to test for the bug that was fixed by commit:
1337 * 7ac1102b227b ("firmware: cs_dsp: Fix new control name check")
1339 static void cs_dsp_ctl_v2_compare_len(struct kunit *test)
1341 struct cs_dsp_test *priv = test->priv;
1342 struct cs_dsp_test_local *local = priv->local;
1343 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1344 struct cs_dsp_coeff_ctl *ctl;
1345 struct firmware *wmfw;
1348 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1349 cs_dsp_ctl_parse_test_algs[0].id,
1352 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_v2_compare_len_names); i++) {
1353 def.shortname = cs_dsp_ctl_v2_compare_len_names[i];
1354 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1357 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1359 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1360 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1362 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_v2_compare_len_names); i++) {
1363 mutex_lock(&priv->dsp->pwr_lock);
1364 ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_ctl_v2_compare_len_names[i],
1365 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id);
1366 mutex_unlock(&priv->dsp->pwr_lock);
1367 KUNIT_ASSERT_NOT_NULL(test, ctl);
1368 KUNIT_EXPECT_EQ(test, ctl->subname_len,
1369 strlen(cs_dsp_ctl_v2_compare_len_names[i]));
1370 KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_ctl_v2_compare_len_names[i],
1375 static int cs_dsp_ctl_parse_test_common_init(struct kunit *test, struct cs_dsp *dsp,
1378 struct cs_dsp_test *priv;
1379 struct cs_dsp_test_local *local;
1380 struct device *test_dev;
1383 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
1387 local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
1394 priv->local = local;
1395 priv->local->wmfw_version = wmfw_version;
1397 /* Create dummy struct device */
1398 test_dev = kunit_device_register(test, "cs_dsp_test_drv");
1399 if (IS_ERR(test_dev))
1400 return PTR_ERR(test_dev);
1402 dsp->dev = get_device(test_dev);
1406 ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
1410 dev_set_drvdata(dsp->dev, priv);
1412 /* Allocate regmap */
1413 ret = cs_dsp_mock_regmap_init(priv);
1418 * There must always be a XM header with at least 1 algorithm, so create
1419 * a dummy one that tests can use and extract it to a data blob.
1421 local->xm_header = cs_dsp_create_mock_xm_header(priv,
1422 cs_dsp_ctl_parse_test_algs,
1423 ARRAY_SIZE(cs_dsp_ctl_parse_test_algs));
1424 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
1426 local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, priv->local->wmfw_version);
1427 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->wmfw_builder);
1429 /* Add dummy XM header blob to wmfw */
1430 cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1432 local->xm_header->blob_data,
1433 local->xm_header->blob_size_bytes);
1436 dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
1437 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
1439 switch (dsp->type) {
1441 ret = cs_dsp_adsp2_init(dsp);
1444 ret = cs_dsp_halo_init(dsp);
1447 KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
1454 /* Automatically call cs_dsp_remove() when test case ends */
1455 return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
1458 static int cs_dsp_ctl_parse_test_halo_init(struct kunit *test)
1462 /* Fill in cs_dsp and initialize */
1463 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1468 dsp->type = WMFW_HALO;
1469 dsp->mem = cs_dsp_mock_halo_dsp1_regions;
1470 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
1471 dsp->base = cs_dsp_mock_halo_core_base;
1472 dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
1474 return cs_dsp_ctl_parse_test_common_init(test, dsp, 3);
1477 static int cs_dsp_ctl_parse_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
1481 /* Fill in cs_dsp and initialize */
1482 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1487 dsp->type = WMFW_ADSP2;
1489 dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
1490 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
1491 dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
1493 return cs_dsp_ctl_parse_test_common_init(test, dsp, wmfw_ver);
1496 static int cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1_init(struct kunit *test)
1498 return cs_dsp_ctl_parse_test_adsp2_32bit_init(test, 1);
1501 static int cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2_init(struct kunit *test)
1503 return cs_dsp_ctl_parse_test_adsp2_32bit_init(test, 2);
1506 static int cs_dsp_ctl_parse_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
1510 /* Fill in cs_dsp and initialize */
1511 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1516 dsp->type = WMFW_ADSP2;
1518 dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
1519 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
1520 dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
1522 return cs_dsp_ctl_parse_test_common_init(test, dsp, wmfw_ver);
1525 static int cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1_init(struct kunit *test)
1527 return cs_dsp_ctl_parse_test_adsp2_16bit_init(test, 1);
1530 static int cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2_init(struct kunit *test)
1532 return cs_dsp_ctl_parse_test_adsp2_16bit_init(test, 2);
1535 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_mem_type_param_cases[] = {
1536 { .mem_type = WMFW_ADSP2_XM },
1537 { .mem_type = WMFW_ADSP2_YM },
1538 { .mem_type = WMFW_ADSP2_ZM },
1541 static void cs_dsp_ctl_mem_type_desc(const struct cs_dsp_ctl_parse_test_param *param,
1544 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s",
1545 cs_dsp_mem_region_name(param->mem_type));
1548 KUNIT_ARRAY_PARAM(cs_dsp_ctl_mem_type,
1549 cs_dsp_ctl_mem_type_param_cases,
1550 cs_dsp_ctl_mem_type_desc);
1552 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_alg_id_param_cases[] = {
1554 { .alg_id = 0xfafa },
1555 { .alg_id = 0x9f1234 },
1556 { .alg_id = 0xff00ff },
1559 static void cs_dsp_ctl_alg_id_desc(const struct cs_dsp_ctl_parse_test_param *param,
1562 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg_id:%#x", param->alg_id);
1565 KUNIT_ARRAY_PARAM(cs_dsp_ctl_alg_id,
1566 cs_dsp_ctl_alg_id_param_cases,
1567 cs_dsp_ctl_alg_id_desc);
1569 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_offset_param_cases[] = {
1580 { .offset = 0xfffe },
1581 { .offset = 0xffff },
1584 static void cs_dsp_ctl_offset_desc(const struct cs_dsp_ctl_parse_test_param *param,
1587 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "offset:%#x", param->offset);
1590 KUNIT_ARRAY_PARAM(cs_dsp_ctl_offset,
1591 cs_dsp_ctl_offset_param_cases,
1592 cs_dsp_ctl_offset_desc);
1594 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_length_param_cases[] = {
1598 { .length = 0xf000 },
1601 static void cs_dsp_ctl_length_desc(const struct cs_dsp_ctl_parse_test_param *param,
1604 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "length:%#x", param->length);
1607 KUNIT_ARRAY_PARAM(cs_dsp_ctl_length,
1608 cs_dsp_ctl_length_param_cases,
1609 cs_dsp_ctl_length_desc);
1611 /* Note: some control types mandate specific flags settings */
1612 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_type_param_cases[] = {
1613 { .ctl_type = WMFW_CTL_TYPE_BYTES,
1614 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1615 { .ctl_type = WMFW_CTL_TYPE_ACKED,
1616 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1617 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1618 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE |
1619 WMFW_CTL_FLAG_SYS },
1620 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1621 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_SYS },
1622 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1623 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE |
1624 WMFW_CTL_FLAG_SYS },
1627 static void cs_dsp_ctl_type_flags_desc(const struct cs_dsp_ctl_parse_test_param *param,
1630 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "ctl_type:%#x flags:%#x",
1631 param->ctl_type, param->flags);
1634 KUNIT_ARRAY_PARAM(cs_dsp_ctl_type,
1635 cs_dsp_ctl_type_param_cases,
1636 cs_dsp_ctl_type_flags_desc);
1638 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_flags_param_cases[] = {
1640 { .flags = WMFW_CTL_FLAG_READABLE },
1641 { .flags = WMFW_CTL_FLAG_WRITEABLE },
1642 { .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1643 { .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1644 { .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1645 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE },
1646 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE },
1647 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1648 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1649 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE |
1650 WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1653 static void cs_dsp_ctl_flags_desc(const struct cs_dsp_ctl_parse_test_param *param,
1656 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "flags:%#x", param->flags);
1659 KUNIT_ARRAY_PARAM(cs_dsp_ctl_flags,
1660 cs_dsp_ctl_flags_param_cases,
1661 cs_dsp_ctl_flags_desc);
1663 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_illegal_type_flags_param_cases[] = {
1664 /* ACKED control must be volatile + read + write */
1665 { .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = 0 },
1666 { .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_READABLE },
1667 { .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_WRITEABLE },
1668 { .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_VOLATILE },
1669 { .ctl_type = WMFW_CTL_TYPE_ACKED,
1670 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1671 { .ctl_type = WMFW_CTL_TYPE_ACKED,
1672 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1674 /* HOSTEVENT must be system + volatile + read + write */
1675 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = 0 },
1676 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_READABLE },
1677 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_WRITEABLE },
1678 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1679 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1680 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_VOLATILE },
1681 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1682 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1683 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1684 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1685 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1686 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1687 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_SYS },
1688 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1689 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE },
1690 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1691 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE },
1692 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1693 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE },
1694 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1695 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1696 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT,
1697 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1699 /* FWEVENT rules same as HOSTEVENT */
1700 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = 0 },
1701 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_READABLE },
1702 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_WRITEABLE },
1703 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1704 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1705 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_VOLATILE },
1706 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1707 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1708 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1709 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1710 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1711 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1712 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_SYS },
1713 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1714 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE },
1715 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1716 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE },
1717 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1718 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE },
1719 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1720 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1721 { .ctl_type = WMFW_CTL_TYPE_FWEVENT,
1722 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1725 * HOSTBUFFER must be system + volatile + readable or
1726 * system + volatile + readable + writeable
1728 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = 0 },
1729 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_READABLE },
1730 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_WRITEABLE },
1731 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1732 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE},
1733 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_VOLATILE },
1734 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1735 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE },
1736 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1737 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1738 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1739 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1740 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_SYS },
1741 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1742 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE },
1743 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1744 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE },
1745 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1746 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE },
1747 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1748 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE },
1749 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER,
1750 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE },
1753 KUNIT_ARRAY_PARAM(cs_dsp_ctl_illegal_type_flags,
1754 cs_dsp_ctl_illegal_type_flags_param_cases,
1755 cs_dsp_ctl_type_flags_desc);
1757 static struct kunit_case cs_dsp_ctl_parse_test_cases_v1[] = {
1758 KUNIT_CASE(cs_dsp_ctl_parse_no_coeffs),
1759 KUNIT_CASE(cs_dsp_ctl_parse_v1_name),
1760 KUNIT_CASE(cs_dsp_ctl_parse_empty_v1_name),
1761 KUNIT_CASE(cs_dsp_ctl_parse_max_v1_name),
1763 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_memory_type, cs_dsp_ctl_mem_type_gen_params),
1764 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_id, cs_dsp_ctl_alg_id_gen_params),
1765 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_mem, cs_dsp_ctl_mem_type_gen_params),
1766 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_offset, cs_dsp_ctl_offset_gen_params),
1767 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_length, cs_dsp_ctl_length_gen_params),
1768 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_ctl_type, cs_dsp_ctl_type_gen_params),
1769 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_flags, cs_dsp_ctl_flags_gen_params),
1770 KUNIT_CASE(cs_dsp_ctl_parse_fw_name),
1772 KUNIT_CASE(cs_dsp_ctl_alg_id_uniqueness),
1773 KUNIT_CASE(cs_dsp_ctl_mem_uniqueness),
1774 KUNIT_CASE(cs_dsp_ctl_fw_uniqueness),
1775 KUNIT_CASE(cs_dsp_ctl_squash_reloaded_controls),
1777 { } /* terminator */
1780 static struct kunit_case cs_dsp_ctl_parse_test_cases_v2_v3[] = {
1781 KUNIT_CASE(cs_dsp_ctl_parse_no_coeffs),
1782 KUNIT_CASE(cs_dsp_ctl_parse_short_name),
1783 KUNIT_CASE(cs_dsp_ctl_parse_min_short_name),
1784 KUNIT_CASE(cs_dsp_ctl_parse_max_short_name),
1785 KUNIT_CASE(cs_dsp_ctl_parse_with_min_fullname),
1786 KUNIT_CASE(cs_dsp_ctl_parse_with_max_fullname),
1787 KUNIT_CASE(cs_dsp_ctl_parse_with_min_description),
1788 KUNIT_CASE(cs_dsp_ctl_parse_with_max_description),
1789 KUNIT_CASE(cs_dsp_ctl_parse_with_max_fullname_and_description),
1790 KUNIT_CASE(cs_dsp_ctl_shortname_alignment),
1791 KUNIT_CASE(cs_dsp_ctl_fullname_alignment),
1792 KUNIT_CASE(cs_dsp_ctl_description_alignment),
1793 KUNIT_CASE(cs_dsp_get_ctl_test),
1794 KUNIT_CASE(cs_dsp_get_ctl_test_multiple_wmfw),
1796 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_memory_type, cs_dsp_ctl_mem_type_gen_params),
1797 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_id, cs_dsp_ctl_alg_id_gen_params),
1798 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_mem, cs_dsp_ctl_mem_type_gen_params),
1799 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_offset, cs_dsp_ctl_offset_gen_params),
1800 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_length, cs_dsp_ctl_length_gen_params),
1801 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_ctl_type, cs_dsp_ctl_type_gen_params),
1802 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_flags, cs_dsp_ctl_flags_gen_params),
1803 KUNIT_CASE_PARAM(cs_dsp_ctl_illegal_type_flags,
1804 cs_dsp_ctl_illegal_type_flags_gen_params),
1805 KUNIT_CASE(cs_dsp_ctl_parse_fw_name),
1807 KUNIT_CASE(cs_dsp_ctl_alg_id_uniqueness),
1808 KUNIT_CASE(cs_dsp_ctl_mem_uniqueness),
1809 KUNIT_CASE(cs_dsp_ctl_fw_uniqueness),
1810 KUNIT_CASE(cs_dsp_ctl_squash_reloaded_controls),
1811 KUNIT_CASE(cs_dsp_ctl_v2_squash_reloaded_controls),
1812 KUNIT_CASE(cs_dsp_ctl_v2_compare_len),
1814 { } /* terminator */
1817 static struct kunit_suite cs_dsp_ctl_parse_test_halo = {
1818 .name = "cs_dsp_ctl_parse_wmfwV3_halo",
1819 .init = cs_dsp_ctl_parse_test_halo_init,
1820 .test_cases = cs_dsp_ctl_parse_test_cases_v2_v3,
1823 static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1 = {
1824 .name = "cs_dsp_ctl_parse_wmfwV1_adsp2_32bit",
1825 .init = cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1_init,
1826 .test_cases = cs_dsp_ctl_parse_test_cases_v1,
1829 static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2 = {
1830 .name = "cs_dsp_ctl_parse_wmfwV2_adsp2_32bit",
1831 .init = cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2_init,
1832 .test_cases = cs_dsp_ctl_parse_test_cases_v2_v3,
1835 static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1 = {
1836 .name = "cs_dsp_ctl_parse_wmfwV1_adsp2_16bit",
1837 .init = cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1_init,
1838 .test_cases = cs_dsp_ctl_parse_test_cases_v1,
1841 static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2 = {
1842 .name = "cs_dsp_ctl_parse_wmfwV2_adsp2_16bit",
1843 .init = cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2_init,
1844 .test_cases = cs_dsp_ctl_parse_test_cases_v2_v3,
1847 kunit_test_suites(&cs_dsp_ctl_parse_test_halo,
1848 &cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1,
1849 &cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2,
1850 &cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1,
1851 &cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2);