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
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 *);
21
22 struct 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
28 struct 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
37 static 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
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,
73 .length_bytes = 4,
74 };
75
cs_dsp_ctl_alloc_test_string(struct kunit * test,char c,size_t len)76 static 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 */
cs_dsp_ctl_parse_no_coeffs(struct kunit * test)89 static 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 */
cs_dsp_ctl_parse_v1_name(struct kunit * test)108 static 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 */
cs_dsp_ctl_parse_empty_v1_name(struct kunit * test)138 static 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 */
cs_dsp_ctl_parse_max_v1_name(struct kunit * test)168 static 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. */
cs_dsp_ctl_parse_short_name(struct kunit * test)196 static 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 */
cs_dsp_ctl_parse_min_short_name(struct kunit * test)226 static 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 */
cs_dsp_ctl_parse_max_short_name(struct kunit * test)257 static 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 */
cs_dsp_ctl_parse_with_min_fullname(struct kunit * test)290 static 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 */
cs_dsp_ctl_parse_with_max_fullname(struct kunit * test)322 static 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 */
cs_dsp_ctl_parse_with_min_description(struct kunit * test)355 static 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 */
cs_dsp_ctl_parse_with_max_description(struct kunit * test)387 static 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 */
cs_dsp_ctl_parse_with_max_fullname_and_description(struct kunit * test)420 static 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
449 static 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 */
cs_dsp_ctl_shortname_alignment(struct kunit * test)460 static 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 */
cs_dsp_ctl_fullname_alignment(struct kunit * test)503 static 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 */
cs_dsp_ctl_description_alignment(struct kunit * test)557 static 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
607 static 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. */
cs_dsp_get_ctl_test(struct kunit * test)615 static 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 */
cs_dsp_get_ctl_test_multiple_wmfw(struct kunit * test)657 static 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. */
cs_dsp_ctl_parse_memory_type(struct kunit * test)721 static 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 */
cs_dsp_ctl_parse_alg_id(struct kunit * test)757 static 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 */
cs_dsp_ctl_parse_alg_mem(struct kunit * test)789 static 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. */
cs_dsp_ctl_parse_offset(struct kunit * test)820 static 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. */
cs_dsp_ctl_parse_length(struct kunit * test)849 static 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. */
cs_dsp_ctl_parse_ctl_type(struct kunit * test)878 static 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. */
cs_dsp_ctl_parse_flags(struct kunit * test)907 static 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 ®_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. */
cs_dsp_ctl_illegal_type_flags(struct kunit * test)946 static 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 ®_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. */
cs_dsp_ctl_parse_fw_name(struct kunit * test)979 static 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 */
cs_dsp_ctl_alg_id_uniqueness(struct kunit * test)1037 static 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 */
cs_dsp_ctl_mem_uniqueness(struct kunit * test)1082 static 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 */
cs_dsp_ctl_fw_uniqueness(struct kunit * test)1126 static 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 */
cs_dsp_ctl_squash_reloaded_controls(struct kunit * test)1189 static 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 */
cs_dsp_ctl_v2_squash_reloaded_controls(struct kunit * test)1247 static 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
1307 static 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 */
cs_dsp_ctl_v2_compare_len(struct kunit * test)1326 static 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
cs_dsp_ctl_parse_test_common_init(struct kunit * test,struct cs_dsp * dsp,int wmfw_version)1362 static 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
cs_dsp_ctl_parse_test_halo_init(struct kunit * test)1445 static 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
cs_dsp_ctl_parse_test_adsp2_32bit_init(struct kunit * test,int wmfw_ver)1464 static 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
cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1_init(struct kunit * test)1483 static 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
cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2_init(struct kunit * test)1488 static 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
cs_dsp_ctl_parse_test_adsp2_16bit_init(struct kunit * test,int wmfw_ver)1493 static 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
cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1_init(struct kunit * test)1512 static 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
cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2_init(struct kunit * test)1517 static 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
1522 static 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
cs_dsp_ctl_mem_type_desc(const struct cs_dsp_ctl_parse_test_param * param,char * desc)1528 static 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
1535 KUNIT_ARRAY_PARAM(cs_dsp_ctl_mem_type,
1536 cs_dsp_ctl_mem_type_param_cases,
1537 cs_dsp_ctl_mem_type_desc);
1538
1539 static 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
cs_dsp_ctl_alg_id_desc(const struct cs_dsp_ctl_parse_test_param * param,char * desc)1546 static 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
1552 KUNIT_ARRAY_PARAM(cs_dsp_ctl_alg_id,
1553 cs_dsp_ctl_alg_id_param_cases,
1554 cs_dsp_ctl_alg_id_desc);
1555
1556 static 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
cs_dsp_ctl_offset_desc(const struct cs_dsp_ctl_parse_test_param * param,char * desc)1571 static 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
1577 KUNIT_ARRAY_PARAM(cs_dsp_ctl_offset,
1578 cs_dsp_ctl_offset_param_cases,
1579 cs_dsp_ctl_offset_desc);
1580
1581 static 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
cs_dsp_ctl_length_desc(const struct cs_dsp_ctl_parse_test_param * param,char * desc)1588 static 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
1594 KUNIT_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 */
1599 static 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
cs_dsp_ctl_type_flags_desc(const struct cs_dsp_ctl_parse_test_param * param,char * desc)1614 static 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
1621 KUNIT_ARRAY_PARAM(cs_dsp_ctl_type,
1622 cs_dsp_ctl_type_param_cases,
1623 cs_dsp_ctl_type_flags_desc);
1624
1625 static 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
cs_dsp_ctl_flags_desc(const struct cs_dsp_ctl_parse_test_param * param,char * desc)1640 static 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
1646 KUNIT_ARRAY_PARAM(cs_dsp_ctl_flags,
1647 cs_dsp_ctl_flags_param_cases,
1648 cs_dsp_ctl_flags_desc);
1649
1650 static 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
1740 KUNIT_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
1744 static 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
1767 static 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
1804 static 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
1810 static 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
1816 static 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
1822 static 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
1828 static 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
1834 kunit_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);
1839