]> Git Repo - linux.git/blob - drivers/firmware/cirrus/test/cs_dsp_test_control_parse.c
Linux 6.14-rc3
[linux.git] / drivers / firmware / cirrus / test / cs_dsp_test_control_parse.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // KUnit tests for cs_dsp.
4 //
5 // Copyright (C) 2024 Cirrus Logic, Inc. and
6 //                    Cirrus Logic International Semiconductor Ltd.
7
8 #include <kunit/device.h>
9 #include <kunit/resource.h>
10 #include <kunit/test.h>
11 #include <linux/build_bug.h>
12 #include <linux/firmware/cirrus/cs_dsp.h>
13 #include <linux/firmware/cirrus/cs_dsp_test_utils.h>
14 #include <linux/firmware/cirrus/wmfw.h>
15 #include <linux/list.h>
16 #include <linux/mutex.h>
17 #include <linux/regmap.h>
18
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
76 /* Algorithm info block without controls should load */
77 static void cs_dsp_ctl_parse_no_coeffs(struct kunit *test)
78 {
79         struct cs_dsp_test *priv = test->priv;
80         struct cs_dsp_test_local *local = priv->local;
81         struct firmware *wmfw;
82
83         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
84                                               cs_dsp_ctl_parse_test_algs[0].id,
85                                               "dummyalg", NULL);
86         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
87
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);
90 }
91
92 /*
93  * V1 controls do not have names, the name field in the coefficient entry
94  * should be ignored.
95  */
96 static void cs_dsp_ctl_parse_v1_name(struct kunit *test)
97 {
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;
103
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,
107                                               "dummyalg", NULL);
108         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
109         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
110
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);
113
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);
120 }
121
122 /*
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.
125  */
126 static void cs_dsp_ctl_parse_empty_v1_name(struct kunit *test)
127 {
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;
133
134         def.fullname = "\0";
135         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
136                                               cs_dsp_ctl_parse_test_algs[0].id,
137                                               "dummyalg", NULL);
138         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
139         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
140
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);
143
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);
150 }
151
152 /*
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.
155  */
156 static void cs_dsp_ctl_parse_max_v1_name(struct kunit *test)
157 {
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;
163         char *name;
164
165         name = kunit_kzalloc(test, 256, GFP_KERNEL);
166         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, name);
167         memset(name, 'A', 255);
168         def.fullname = name;
169
170         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
171                                               cs_dsp_ctl_parse_test_algs[0].id,
172                                               "dummyalg", NULL);
173         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
174         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
175
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);
178
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);
185 }
186
187 /* Short name from coeff descriptor should be used as control name. */
188 static void cs_dsp_ctl_parse_short_name(struct kunit *test)
189 {
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;
195
196         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
197                                               cs_dsp_ctl_parse_test_algs[0].id,
198                                               "dummyalg", NULL);
199         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
200         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
201
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);
204
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);
212 }
213
214 /*
215  * Short name from coeff descriptor should be used as control name.
216  * Test with a short name that is a single character.
217  */
218 static void cs_dsp_ctl_parse_min_short_name(struct kunit *test)
219 {
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;
225
226         def.shortname = "Q";
227         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
228                                               cs_dsp_ctl_parse_test_algs[0].id,
229                                               "dummyalg", NULL);
230         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
231         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
232
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);
235
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);
243 }
244
245 /*
246  * Short name from coeff descriptor should be used as control name.
247  * Test with a maximum length name.
248  */
249 static void cs_dsp_ctl_parse_max_short_name(struct kunit *test)
250 {
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;
255         char *name;
256         struct firmware *wmfw;
257
258         name = kunit_kmalloc(test, 255, GFP_KERNEL);
259         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, name);
260         memset(name, 'A', 255);
261
262         def.shortname = name;
263
264         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
265                                               cs_dsp_ctl_parse_test_algs[0].id,
266                                               "dummyalg", NULL);
267         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
268         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
269
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);
272
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);
280 }
281
282 /*
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.
286  */
287 static void cs_dsp_ctl_parse_with_min_fullname(struct kunit *test)
288 {
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;
294
295         def.fullname = "Q";
296         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
297                                               cs_dsp_ctl_parse_test_algs[0].id,
298                                               "dummyalg", NULL);
299         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
300         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
301
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);
304
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);
312 }
313
314 /*
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.
318  */
319 static void cs_dsp_ctl_parse_with_max_fullname(struct kunit *test)
320 {
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;
326         char *fullname;
327
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;
332
333         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
334                                               cs_dsp_ctl_parse_test_algs[0].id,
335                                               "dummyalg", NULL);
336         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
337         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
338
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);
341
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);
349 }
350
351 /*
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
355  */
356 static void cs_dsp_ctl_parse_with_min_description(struct kunit *test)
357 {
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;
363
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,
367                                               "dummyalg", NULL);
368         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
369         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
370
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);
373
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);
381 }
382
383 /*
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
387  */
388 static void cs_dsp_ctl_parse_with_max_description(struct kunit *test)
389 {
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;
395         char *description;
396
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;
401
402         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
403                                               cs_dsp_ctl_parse_test_algs[0].id,
404                                               "dummyalg", NULL);
405         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
406         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
407
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);
410
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);
418 }
419
420 /*
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
424  */
425 static void cs_dsp_ctl_parse_with_max_fullname_and_description(struct kunit *test)
426 {
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;
433
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;
438
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;
443
444         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
445                                               cs_dsp_ctl_parse_test_algs[0].id,
446                                               "dummyalg", NULL);
447         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
448         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
449
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);
452
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);
460 }
461
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",
466         "123456789ABCDEF",
467 };
468
469 /*
470  * Variable-length string fields are padded to a multiple of 4-bytes.
471  * Test this with various lengths of short name.
472  */
473 static void cs_dsp_ctl_shortname_alignment(struct kunit *test)
474 {
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;
480         int i;
481
482         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
483                                               cs_dsp_ctl_parse_test_algs[0].id,
484                                               "dummyalg", NULL);
485
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);
489         }
490
491         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
492
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);
495
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],
504                                    ctl->subname_len);
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);
509         }
510 }
511
512 /*
513  * Variable-length string fields are padded to a multiple of 4-bytes.
514  * Test this with various lengths of full name.
515  */
516 static void cs_dsp_ctl_fullname_alignment(struct kunit *test)
517 {
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;
522         char ctl_name[4];
523         struct firmware *wmfw;
524         int i;
525
526         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
527                                               cs_dsp_ctl_parse_test_algs[0].id,
528                                               "dummyalg", NULL);
529
530         for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
531                 /*
532                  * Create a unique control name of 3 characters so that
533                  * the shortname field is exactly 4 bytes long including
534                  * the length byte.
535                  */
536                 snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
537                 KUNIT_ASSERT_EQ(test, strlen(ctl_name), 3);
538                 def.shortname = ctl_name;
539
540                 def.fullname = cs_dsp_ctl_alignment_test_names[i];
541                 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
542         }
543
544         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
545
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);
548
549         for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
550                 snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
551
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);
563         }
564 }
565
566 /*
567  * Variable-length string fields are padded to a multiple of 4-bytes.
568  * Test this with various lengths of description.
569  */
570 static void cs_dsp_ctl_description_alignment(struct kunit *test)
571 {
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;
576         char ctl_name[4];
577         struct firmware *wmfw;
578         int i;
579
580         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
581                                               cs_dsp_ctl_parse_test_algs[0].id,
582                                               "dummyalg", NULL);
583
584         for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
585                 /*
586                  * Create a unique control name of 3 characters so that
587                  * the shortname field is exactly 4 bytes long including
588                  * the length byte.
589                  */
590                 snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
591                 KUNIT_ASSERT_EQ(test, strlen(ctl_name), 3);
592                 def.shortname = ctl_name;
593
594                 def.description = cs_dsp_ctl_alignment_test_names[i];
595                 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
596         }
597
598         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
599
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);
602
603         for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) {
604                 snprintf(ctl_name, sizeof(ctl_name), "%03d", i);
605
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);
617         }
618 }
619
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",
625 };
626
627 /* Test using cs_dsp_get_ctl() to lookup various controls. */
628 static void cs_dsp_get_ctl_test(struct kunit *test)
629 {
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;
635         int i;
636
637         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
638                                               cs_dsp_ctl_parse_test_algs[0].id,
639                                               "dummyalg", NULL);
640
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);
645         }
646
647         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
648
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);
651
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],
660                                    ctl->subname_len);
661                 KUNIT_EXPECT_EQ(test, ctl->offset, i);
662         }
663 }
664
665 /*
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.
669  */
670 static void cs_dsp_get_ctl_test_multiple_wmfw(struct kunit *test)
671 {
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;
678
679         def.shortname = "_A_CONTROL";
680
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,
686                                         WMFW_ADSP2_XM, 0,
687                                         local->xm_header->blob_data,
688                                         local->xm_header->blob_size_bytes);
689
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,
694                                               "dummyalg", NULL);
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);
700
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,
705                                               "dummyalg", NULL);
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);
711
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);
719
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);
724
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);
731 }
732
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)
735 {
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;
742
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))
745                 return;
746
747         def.mem_type = param->mem_type;
748
749         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
750                                               cs_dsp_ctl_parse_test_algs[0].id,
751                                               "dummyalg", NULL);
752         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
753         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
754
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);
757
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);
764 }
765
766 /*
767  * Test that the algorithm id from the parent alg-info block is
768  * correctly stored in the cs_dsp_coeff_ctl.
769  */
770 static void cs_dsp_ctl_parse_alg_id(struct kunit *test)
771 {
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;
778
779         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
780                                               param->alg_id,
781                                               "dummyalg", NULL);
782         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
783         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
784
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);
787
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);
795 }
796
797 /*
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.
801  */
802 static void cs_dsp_ctl_parse_alg_mem(struct kunit *test)
803 {
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;
810
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))
813                 return;
814
815         def.mem_type = param->mem_type;
816
817         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
818                                               param->alg_id,
819                                               "dummyalg", NULL);
820         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
821         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
822
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);
825
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);
830 }
831
832 /* Test that the value of the offset field is parsed correctly. */
833 static void cs_dsp_ctl_parse_offset(struct kunit *test)
834 {
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;
841
842         def.offset_dsp_words = param->offset;
843
844         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
845                                               cs_dsp_ctl_parse_test_algs[0].id,
846                                               "dummyalg", NULL);
847         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
848         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
849
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);
852
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);
859 }
860
861 /* Test that the value of the length field is parsed correctly. */
862 static void cs_dsp_ctl_parse_length(struct kunit *test)
863 {
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;
870
871         def.length_bytes = param->length;
872
873         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
874                                               cs_dsp_ctl_parse_test_algs[0].id,
875                                               "dummyalg", NULL);
876         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
877         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
878
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);
881
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);
888 }
889
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)
892 {
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;
899
900         def.type = param->ctl_type;
901         def.flags = param->flags;
902
903         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
904                                               cs_dsp_ctl_parse_test_algs[0].id,
905                                               "dummyalg", NULL);
906         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
907         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
908
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);
911
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);
917 }
918
919 /* Test that the value of the flags field is parsed correctly. */
920 static void cs_dsp_ctl_parse_flags(struct kunit *test)
921 {
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;
928         u32 reg_val;
929
930         /*
931          * Non volatile controls will be read to initialize the cache
932          * so the regmap cache must contain something to read.
933          */
934         reg_val = 0xf11100;
935         regmap_raw_write(priv->dsp->regmap,
936                          cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM),
937                          &reg_val, sizeof(reg_val));
938
939         def.flags = param->flags;
940         def.mem_type = WMFW_ADSP2_YM;
941
942         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
943                                               cs_dsp_ctl_parse_test_algs[0].id,
944                                               "dummyalg", NULL);
945         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
946         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
947
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);
950
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);
956 }
957
958 /* Test that invalid combinations of (control type, flags) are rejected. */
959 static void cs_dsp_ctl_illegal_type_flags(struct kunit *test)
960 {
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;
966         u32 reg_val;
967
968         /*
969          * Non volatile controls will be read to initialize the cache
970          * so the regmap cache must contain something to read.
971          */
972         reg_val = 0xf11100;
973         regmap_raw_write(priv->dsp->regmap,
974                          cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM),
975                          &reg_val, sizeof(reg_val));
976
977         def.type = param->ctl_type;
978         def.flags = param->flags;
979         def.mem_type = WMFW_ADSP2_YM;
980
981         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
982                                               cs_dsp_ctl_parse_test_algs[0].id,
983                                               "dummyalg", NULL);
984         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
985         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
986
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);
989 }
990
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)
993 {
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;
1000
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,
1006                                         WMFW_ADSP2_XM, 0,
1007                                         local->xm_header->blob_data,
1008                                         local->xm_header->blob_size_bytes);
1009
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,
1014                                               "dummyalg", NULL);
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);
1020
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,
1025                                               "dummyalg", NULL);
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);
1031
1032         /* Both controls should be in the list (order not guaranteed) */
1033         KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2);
1034         ctl1 = NULL;
1035         ctl2 = NULL;
1036         list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1037                 if (strcmp(walkctl->fw_name, "misc") == 0)
1038                         ctl1 = walkctl;
1039                 else if (strcmp(walkctl->fw_name, "mbc/vss") == 0)
1040                         ctl2 = walkctl;
1041         }
1042
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);
1047 }
1048
1049 /* Controls are unique if the algorithm ID is different */
1050 static void cs_dsp_ctl_alg_id_uniqueness(struct kunit *test)
1051 {
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;
1057
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,
1061                                               "dummyalg", NULL);
1062         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1063         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1064
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,
1068                                               "dummyalg", NULL);
1069         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1070         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1071
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);
1075
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);
1092 }
1093
1094 /* Controls are unique if the memory region is different */
1095 static void cs_dsp_ctl_mem_uniqueness(struct kunit *test)
1096 {
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;
1102
1103         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1104                                               cs_dsp_ctl_parse_test_algs[0].id,
1105                                               "dummyalg", NULL);
1106         /* Create control in XM */
1107         def.mem_type = WMFW_ADSP2_XM;
1108         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1109
1110         /* Create control in YM */
1111         def.mem_type = WMFW_ADSP2_YM;
1112         cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1113
1114         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1115
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);
1119
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);
1136 }
1137
1138 /* Controls are unique if they are in different firmware */
1139 static void cs_dsp_ctl_fw_uniqueness(struct kunit *test)
1140 {
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;
1147
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,
1153                                         WMFW_ADSP2_XM, 0,
1154                                         local->xm_header->blob_data,
1155                                         local->xm_header->blob_size_bytes);
1156
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,
1160                                               "dummyalg", NULL);
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);
1166
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,
1170                                               "dummyalg", NULL);
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);
1177
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);
1194 }
1195
1196 /*
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.
1201  */
1202 static void cs_dsp_ctl_squash_reloaded_controls(struct kunit *test)
1203 {
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;
1210         int i;
1211
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,
1216                                                       "dummyalg", NULL);
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);
1220         }
1221
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);
1225
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));
1229
1230         /* Take a copy of the pointers to controls to compare against. */
1231         i = 0;
1232         list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1233                 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1234                 ctls[i++] = walkctl;
1235         }
1236
1237
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);
1241
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));
1245
1246         /* And they should be the same objects */
1247         i = 0;
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++]);
1251         }
1252 }
1253
1254 /*
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.
1259  */
1260 static void cs_dsp_ctl_v2_squash_reloaded_controls(struct kunit *test)
1261 {
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;
1268         int i;
1269
1270         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1271                                               cs_dsp_ctl_parse_test_algs[0].id,
1272                                               "dummyalg", NULL);
1273
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;
1278                 if (i & BIT(0))
1279                         def.mem_type = WMFW_ADSP2_XM;
1280                 else
1281                         def.mem_type = WMFW_ADSP2_YM;
1282
1283                 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1284         }
1285
1286         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1287
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);
1291
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));
1295
1296         /* Take a copy of the pointers to controls to compare against. */
1297         i = 0;
1298         list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) {
1299                 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls));
1300                 ctls[i++] = walkctl;
1301         }
1302
1303
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);
1307
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));
1311
1312         /* And they should be the same objects */
1313         i = 0;
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++]);
1317         }
1318 }
1319
1320 static const char * const cs_dsp_ctl_v2_compare_len_names[] = {
1321         "LEFT",
1322         "LEFT_",
1323         "LEFT_SPK",
1324         "LEFT_SPK_V",
1325         "LEFT_SPK_VOL",
1326         "LEFT_SPK_MUTE",
1327         "LEFT_SPK_1",
1328         "LEFT_X",
1329         "LEFT2",
1330 };
1331
1332 /*
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")
1338  */
1339 static void cs_dsp_ctl_v2_compare_len(struct kunit *test)
1340 {
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;
1346         int i;
1347
1348         cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1349                                               cs_dsp_ctl_parse_test_algs[0].id,
1350                                               "dummyalg", NULL);
1351
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);
1355         }
1356
1357         cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1358
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);
1361
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],
1371                                    ctl->subname_len);
1372         }
1373 }
1374
1375 static int cs_dsp_ctl_parse_test_common_init(struct kunit *test, struct cs_dsp *dsp,
1376                                              int wmfw_version)
1377 {
1378         struct cs_dsp_test *priv;
1379         struct cs_dsp_test_local *local;
1380         struct device *test_dev;
1381         int ret;
1382
1383         priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
1384         if (!priv)
1385                 return -ENOMEM;
1386
1387         local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
1388         if (!local)
1389                 return -ENOMEM;
1390
1391         priv->test = test;
1392         priv->dsp = dsp;
1393         test->priv = priv;
1394         priv->local = local;
1395         priv->local->wmfw_version = wmfw_version;
1396
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);
1401
1402         dsp->dev = get_device(test_dev);
1403         if (!dsp->dev)
1404                 return -ENODEV;
1405
1406         ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
1407         if (ret)
1408                 return ret;
1409
1410         dev_set_drvdata(dsp->dev, priv);
1411
1412         /* Allocate regmap */
1413         ret = cs_dsp_mock_regmap_init(priv);
1414         if (ret)
1415                 return ret;
1416
1417         /*
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.
1420          */
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);
1425
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);
1428
1429         /* Add dummy XM header blob to wmfw */
1430         cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
1431                                         WMFW_ADSP2_XM, 0,
1432                                         local->xm_header->blob_data,
1433                                         local->xm_header->blob_size_bytes);
1434
1435         /* Init cs_dsp */
1436         dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
1437         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
1438
1439         switch (dsp->type) {
1440         case WMFW_ADSP2:
1441                 ret = cs_dsp_adsp2_init(dsp);
1442                 break;
1443         case WMFW_HALO:
1444                 ret = cs_dsp_halo_init(dsp);
1445                 break;
1446         default:
1447                 KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
1448                 return -EINVAL;
1449         }
1450
1451         if (ret)
1452                 return ret;
1453
1454         /* Automatically call cs_dsp_remove() when test case ends */
1455         return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
1456 }
1457
1458 static int cs_dsp_ctl_parse_test_halo_init(struct kunit *test)
1459 {
1460         struct cs_dsp *dsp;
1461
1462         /* Fill in cs_dsp and initialize */
1463         dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1464         if (!dsp)
1465                 return -ENOMEM;
1466
1467         dsp->num = 1;
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;
1473
1474         return cs_dsp_ctl_parse_test_common_init(test, dsp, 3);
1475 }
1476
1477 static int cs_dsp_ctl_parse_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
1478 {
1479         struct cs_dsp *dsp;
1480
1481         /* Fill in cs_dsp and initialize */
1482         dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1483         if (!dsp)
1484                 return -ENOMEM;
1485
1486         dsp->num = 1;
1487         dsp->type = WMFW_ADSP2;
1488         dsp->rev = 1;
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;
1492
1493         return cs_dsp_ctl_parse_test_common_init(test, dsp, wmfw_ver);
1494 }
1495
1496 static int cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1_init(struct kunit *test)
1497 {
1498         return cs_dsp_ctl_parse_test_adsp2_32bit_init(test, 1);
1499 }
1500
1501 static int cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2_init(struct kunit *test)
1502 {
1503         return cs_dsp_ctl_parse_test_adsp2_32bit_init(test, 2);
1504 }
1505
1506 static int cs_dsp_ctl_parse_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
1507 {
1508         struct cs_dsp *dsp;
1509
1510         /* Fill in cs_dsp and initialize */
1511         dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
1512         if (!dsp)
1513                 return -ENOMEM;
1514
1515         dsp->num = 1;
1516         dsp->type = WMFW_ADSP2;
1517         dsp->rev = 0;
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;
1521
1522         return cs_dsp_ctl_parse_test_common_init(test, dsp, wmfw_ver);
1523 }
1524
1525 static int cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1_init(struct kunit *test)
1526 {
1527         return cs_dsp_ctl_parse_test_adsp2_16bit_init(test, 1);
1528 }
1529
1530 static int cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2_init(struct kunit *test)
1531 {
1532         return cs_dsp_ctl_parse_test_adsp2_16bit_init(test, 2);
1533 }
1534
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 },
1539 };
1540
1541 static void cs_dsp_ctl_mem_type_desc(const struct cs_dsp_ctl_parse_test_param *param,
1542                                      char *desc)
1543 {
1544         snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s",
1545                  cs_dsp_mem_region_name(param->mem_type));
1546 }
1547
1548 KUNIT_ARRAY_PARAM(cs_dsp_ctl_mem_type,
1549                   cs_dsp_ctl_mem_type_param_cases,
1550                   cs_dsp_ctl_mem_type_desc);
1551
1552 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_alg_id_param_cases[] = {
1553         { .alg_id = 0xb },
1554         { .alg_id = 0xfafa },
1555         { .alg_id = 0x9f1234 },
1556         { .alg_id = 0xff00ff },
1557 };
1558
1559 static void cs_dsp_ctl_alg_id_desc(const struct cs_dsp_ctl_parse_test_param *param,
1560                                    char *desc)
1561 {
1562         snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg_id:%#x", param->alg_id);
1563 }
1564
1565 KUNIT_ARRAY_PARAM(cs_dsp_ctl_alg_id,
1566                   cs_dsp_ctl_alg_id_param_cases,
1567                   cs_dsp_ctl_alg_id_desc);
1568
1569 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_offset_param_cases[] = {
1570         { .offset = 0x0 },
1571         { .offset = 0x1 },
1572         { .offset = 0x2 },
1573         { .offset = 0x3 },
1574         { .offset = 0x4 },
1575         { .offset = 0x5 },
1576         { .offset = 0x6 },
1577         { .offset = 0x7 },
1578         { .offset = 0xe0 },
1579         { .offset = 0xf1 },
1580         { .offset = 0xfffe },
1581         { .offset = 0xffff },
1582 };
1583
1584 static void cs_dsp_ctl_offset_desc(const struct cs_dsp_ctl_parse_test_param *param,
1585                                    char *desc)
1586 {
1587         snprintf(desc, KUNIT_PARAM_DESC_SIZE, "offset:%#x", param->offset);
1588 }
1589
1590 KUNIT_ARRAY_PARAM(cs_dsp_ctl_offset,
1591                   cs_dsp_ctl_offset_param_cases,
1592                   cs_dsp_ctl_offset_desc);
1593
1594 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_length_param_cases[] = {
1595         { .length = 0x4 },
1596         { .length = 0x8 },
1597         { .length = 0x18 },
1598         { .length = 0xf000 },
1599 };
1600
1601 static void cs_dsp_ctl_length_desc(const struct cs_dsp_ctl_parse_test_param *param,
1602                                    char *desc)
1603 {
1604         snprintf(desc, KUNIT_PARAM_DESC_SIZE, "length:%#x", param->length);
1605 }
1606
1607 KUNIT_ARRAY_PARAM(cs_dsp_ctl_length,
1608                   cs_dsp_ctl_length_param_cases,
1609                   cs_dsp_ctl_length_desc);
1610
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 },
1625 };
1626
1627 static void cs_dsp_ctl_type_flags_desc(const struct cs_dsp_ctl_parse_test_param *param,
1628                                        char *desc)
1629 {
1630         snprintf(desc, KUNIT_PARAM_DESC_SIZE, "ctl_type:%#x flags:%#x",
1631                  param->ctl_type, param->flags);
1632 }
1633
1634 KUNIT_ARRAY_PARAM(cs_dsp_ctl_type,
1635                   cs_dsp_ctl_type_param_cases,
1636                   cs_dsp_ctl_type_flags_desc);
1637
1638 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_flags_param_cases[] = {
1639         { .flags = 0 },
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 },
1651 };
1652
1653 static void cs_dsp_ctl_flags_desc(const struct cs_dsp_ctl_parse_test_param *param,
1654                                   char *desc)
1655 {
1656         snprintf(desc, KUNIT_PARAM_DESC_SIZE, "flags:%#x", param->flags);
1657 }
1658
1659 KUNIT_ARRAY_PARAM(cs_dsp_ctl_flags,
1660                   cs_dsp_ctl_flags_param_cases,
1661                   cs_dsp_ctl_flags_desc);
1662
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 },
1673
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 },
1698
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 },
1723
1724         /*
1725          * HOSTBUFFER must be system + volatile + readable or
1726          * system + volatile + readable + writeable
1727          */
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 },
1751 };
1752
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);
1756
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),
1762
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),
1771
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),
1776
1777         { } /* terminator */
1778 };
1779
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),
1795
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),
1806
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),
1813
1814         { } /* terminator */
1815 };
1816
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,
1821 };
1822
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,
1827 };
1828
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,
1833 };
1834
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,
1839 };
1840
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,
1845 };
1846
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);
This page took 0.149896 seconds and 4 git commands to generate.