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/random.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_stop_wrapper, cs_dsp_stop, struct cs_dsp *);
21 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *);
22
23 struct cs_dsp_test_local {
24 struct cs_dsp_mock_xm_header *xm_header;
25 struct cs_dsp_mock_wmfw_builder *wmfw_builder;
26 int wmfw_version;
27 };
28
29 struct cs_dsp_ctl_cache_test_param {
30 int mem_type;
31 int alg_id;
32 unsigned int offs_words;
33 unsigned int len_bytes;
34 u16 ctl_type;
35 u16 flags;
36 };
37
38 static const struct cs_dsp_mock_alg_def cs_dsp_ctl_cache_test_algs[] = {
39 {
40 .id = 0xfafa,
41 .ver = 0x100000,
42 .xm_base_words = 60,
43 .xm_size_words = 1000,
44 .ym_base_words = 0,
45 .ym_size_words = 1000,
46 .zm_base_words = 0,
47 .zm_size_words = 1000,
48 },
49 {
50 .id = 0xb,
51 .ver = 0x100001,
52 .xm_base_words = 1060,
53 .xm_size_words = 1000,
54 .ym_base_words = 1000,
55 .ym_size_words = 1000,
56 .zm_base_words = 1000,
57 .zm_size_words = 1000,
58 },
59 {
60 .id = 0x9f1234,
61 .ver = 0x100500,
62 .xm_base_words = 2060,
63 .xm_size_words = 32,
64 .ym_base_words = 2000,
65 .ym_size_words = 32,
66 .zm_base_words = 2000,
67 .zm_size_words = 32,
68 },
69 {
70 .id = 0xff00ff,
71 .ver = 0x300113,
72 .xm_base_words = 2100,
73 .xm_size_words = 32,
74 .ym_base_words = 2032,
75 .ym_size_words = 32,
76 .zm_base_words = 2032,
77 .zm_size_words = 32,
78 },
79 };
80
81 static const struct cs_dsp_mock_coeff_def mock_coeff_template = {
82 .shortname = "Dummy Coeff",
83 .type = WMFW_CTL_TYPE_BYTES,
84 .mem_type = WMFW_ADSP2_YM,
85 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
86 .length_bytes = 4,
87 };
88
89 static const char * const cs_dsp_ctl_cache_test_fw_names[] = {
90 "misc", "mbc/vss", "haps",
91 };
92
_find_alg_entry(struct kunit * test,unsigned int alg_id)93 static int _find_alg_entry(struct kunit *test, unsigned int alg_id)
94 {
95 int i;
96
97 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_cache_test_algs); ++i) {
98 if (cs_dsp_ctl_cache_test_algs[i].id == alg_id)
99 break;
100 }
101
102 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
103
104 return i;
105 }
106
_get_alg_mem_base_words(struct kunit * test,int alg_index,int mem_type)107 static int _get_alg_mem_base_words(struct kunit *test, int alg_index, int mem_type)
108 {
109 switch (mem_type) {
110 case WMFW_ADSP2_XM:
111 return cs_dsp_ctl_cache_test_algs[alg_index].xm_base_words;
112 case WMFW_ADSP2_YM:
113 return cs_dsp_ctl_cache_test_algs[alg_index].ym_base_words;
114 case WMFW_ADSP2_ZM:
115 return cs_dsp_ctl_cache_test_algs[alg_index].zm_base_words;
116 default:
117 KUNIT_FAIL(test, "Bug in test: illegal memory type %d\n", mem_type);
118 return 0;
119 }
120 }
121
_create_dummy_wmfw(struct kunit * test)122 static struct cs_dsp_mock_wmfw_builder *_create_dummy_wmfw(struct kunit *test)
123 {
124 struct cs_dsp_test *priv = test->priv;
125 struct cs_dsp_test_local *local = priv->local;
126 struct cs_dsp_mock_wmfw_builder *builder;
127
128 builder = cs_dsp_mock_wmfw_init(priv, local->wmfw_version);
129 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder);
130
131 /* Init an XM header */
132 cs_dsp_mock_wmfw_add_data_block(builder,
133 WMFW_ADSP2_XM, 0,
134 local->xm_header->blob_data,
135 local->xm_header->blob_size_bytes);
136
137 return builder;
138 }
139
140 /*
141 * Memory allocated for control cache must be large enough.
142 * This creates multiple controls of different sizes so only works on
143 * wmfw V2 and later.
144 */
cs_dsp_ctl_v2_cache_alloc(struct kunit * test)145 static void cs_dsp_ctl_v2_cache_alloc(struct kunit *test)
146 {
147 struct cs_dsp_test *priv = test->priv;
148 struct cs_dsp_test_local *local = priv->local;
149 struct cs_dsp *dsp = priv->dsp;
150 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
151 unsigned int reg, alg_base_words, alg_size_bytes;
152 struct cs_dsp_coeff_ctl *ctl;
153 struct firmware *wmfw;
154 char ctl_name[4];
155 u32 *reg_vals;
156 int num_ctls;
157
158 /* Create some DSP data to initialize the control cache */
159 alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_YM);
160 alg_size_bytes = cs_dsp_ctl_cache_test_algs[0].ym_size_words *
161 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
162 reg_vals = kunit_kzalloc(test, alg_size_bytes, GFP_KERNEL);
163 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
164 reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);
165 reg += alg_base_words * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
166 regmap_raw_write(dsp->regmap, reg, reg_vals, alg_size_bytes);
167
168 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
169 cs_dsp_ctl_cache_test_algs[0].id,
170 "dummyalg", NULL);
171
172 /* Create controls of different sizes */
173 def.mem_type = WMFW_ADSP2_YM;
174 def.shortname = ctl_name;
175 num_ctls = 0;
176 for (def.length_bytes = 4; def.length_bytes <= 64; def.length_bytes += 4) {
177 snprintf(ctl_name, ARRAY_SIZE(ctl_name), "%x", def.length_bytes);
178 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
179 num_ctls++;
180 def.offset_dsp_words += def.length_bytes / sizeof(u32);
181 }
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(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
186
187 KUNIT_EXPECT_EQ(test, list_count_nodes(&dsp->ctl_list), num_ctls);
188
189 /* Check that the block allocated for the cache is large enough */
190 list_for_each_entry(ctl, &dsp->ctl_list, list)
191 KUNIT_EXPECT_GE(test, ksize(ctl->cache), ctl->len);
192 }
193
194 /*
195 * Content of registers backing a control should be read into the
196 * control cache when the firmware is downloaded.
197 */
cs_dsp_ctl_cache_init(struct kunit * test)198 static void cs_dsp_ctl_cache_init(struct kunit *test)
199 {
200 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
201 struct cs_dsp_test *priv = test->priv;
202 struct cs_dsp_test_local *local = priv->local;
203 struct cs_dsp *dsp = priv->dsp;
204 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
205 int alg_idx = _find_alg_entry(test, param->alg_id);
206 unsigned int reg, alg_base_words;
207 struct cs_dsp_coeff_ctl *ctl;
208 struct firmware *wmfw;
209 u32 *reg_vals, *readback;
210
211 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
212 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
213
214 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
215 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
216
217 /* Create some DSP data to be read into the control cache */
218 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
219 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
220 reg += (alg_base_words + param->offs_words) *
221 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
222 get_random_bytes(reg_vals, param->len_bytes);
223 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
224
225 /* Create control pointing to this data */
226 def.flags = param->flags;
227 def.mem_type = param->mem_type;
228 def.offset_dsp_words = param->offs_words;
229 def.length_bytes = param->len_bytes;
230
231 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
232 cs_dsp_ctl_cache_test_algs[alg_idx].id,
233 "dummyalg", NULL);
234 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
235 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
236
237 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
238 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
239
240 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
241 KUNIT_ASSERT_NOT_NULL(test, ctl);
242
243 /*
244 * The data should have been populated into the control cache
245 * so should be readable through the control.
246 */
247 KUNIT_EXPECT_EQ(test,
248 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
249 0);
250 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
251 }
252
253 /*
254 * For a non-volatile write-only control the cache should be zero-filled
255 * when the firmware is downloaded.
256 */
cs_dsp_ctl_cache_init_write_only(struct kunit * test)257 static void cs_dsp_ctl_cache_init_write_only(struct kunit *test)
258 {
259 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
260 struct cs_dsp_test *priv = test->priv;
261 struct cs_dsp_test_local *local = priv->local;
262 struct cs_dsp *dsp = priv->dsp;
263 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
264 int alg_idx = _find_alg_entry(test, param->alg_id);
265 struct cs_dsp_coeff_ctl *ctl;
266 struct firmware *wmfw;
267 u32 *readback, *zeros;
268
269 zeros = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
270 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, zeros);
271
272 readback = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
273 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
274
275 /* Create a non-volatile write-only control */
276 def.flags = param->flags & ~WMFW_CTL_FLAG_VOLATILE;
277 def.mem_type = param->mem_type;
278 def.offset_dsp_words = param->offs_words;
279 def.length_bytes = param->len_bytes;
280
281 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
282 cs_dsp_ctl_cache_test_algs[alg_idx].id,
283 "dummyalg", NULL);
284 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
285 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
286
287 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
288 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
289
290 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
291 KUNIT_ASSERT_NOT_NULL(test, ctl);
292
293 /*
294 * The control cache should have been zero-filled so should be
295 * readable through the control.
296 */
297 get_random_bytes(readback, param->len_bytes);
298 KUNIT_EXPECT_EQ(test,
299 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
300 0);
301 KUNIT_EXPECT_MEMEQ(test, readback, zeros, param->len_bytes);
302 }
303
304 /*
305 * Multiple different firmware with identical controls.
306 * This is legal because different firmwares could contain the same
307 * algorithm.
308 * The control cache should be initialized only with the data from
309 * the firmware containing it.
310 */
cs_dsp_ctl_cache_init_multiple_fw_same_controls(struct kunit * test)311 static void cs_dsp_ctl_cache_init_multiple_fw_same_controls(struct kunit *test)
312 {
313 struct cs_dsp_test *priv = test->priv;
314 struct cs_dsp *dsp = priv->dsp;
315 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
316 struct cs_dsp_mock_wmfw_builder *builder[3];
317 unsigned int reg, alg_base_words;
318 struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
319 struct firmware *wmfw;
320 u32 *reg_vals[3], *readback;
321 int i;
322
323 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(builder));
324 static_assert(ARRAY_SIZE(reg_vals) == ARRAY_SIZE(builder));
325 static_assert(ARRAY_SIZE(cs_dsp_ctl_cache_test_fw_names) >= ARRAY_SIZE(builder));
326
327 /* Create an identical control in each firmware but with different alg id */
328 for (i = 0; i < ARRAY_SIZE(builder); i++) {
329 builder[i] = _create_dummy_wmfw(test);
330 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder[i]);
331
332 cs_dsp_mock_wmfw_start_alg_info_block(builder[i],
333 cs_dsp_ctl_cache_test_algs[0].id,
334 "dummyalg", NULL);
335 cs_dsp_mock_wmfw_add_coeff_desc(builder[i], &def);
336 cs_dsp_mock_wmfw_end_alg_info_block(builder[i]);
337 }
338
339 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
340 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
341 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
342 }
343
344 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
345 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
346
347 /*
348 * For each firmware create random content in the register backing
349 * the control. Then download, start, stop and power-down.
350 */
351 for (i = 0; i < ARRAY_SIZE(builder); i++) {
352 alg_base_words = _get_alg_mem_base_words(test, 0, def.mem_type);
353 reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
354 reg += (alg_base_words + def.offset_dsp_words) *
355 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
356
357 get_random_bytes(reg_vals[i], def.length_bytes);
358 regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes);
359 wmfw = cs_dsp_mock_wmfw_get_firmware(builder[i]);
360 KUNIT_ASSERT_EQ(test,
361 cs_dsp_power_up(dsp, wmfw,
362 cs_dsp_ctl_cache_test_fw_names[i],
363 NULL, NULL,
364 cs_dsp_ctl_cache_test_fw_names[i]),
365 0);
366 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
367 cs_dsp_stop(dsp);
368 cs_dsp_power_down(dsp);
369 }
370
371 /* There should now be 3 controls */
372 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
373
374 /*
375 * There's no requirement for the control list to be in any
376 * particular order, so don't assume the order.
377 */
378 for (i = 0; i < ARRAY_SIZE(ctl); i++)
379 ctl[i] = NULL;
380
381 list_for_each_entry(walkctl, &dsp->ctl_list, list) {
382 if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[0]) == 0)
383 ctl[0] = walkctl;
384 else if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[1]) == 0)
385 ctl[1] = walkctl;
386 else if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[2]) == 0)
387 ctl[2] = walkctl;
388 }
389
390 KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
391 KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
392 KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
393
394 /*
395 * The data should have been populated into the control cache
396 * so should be readable through the control.
397 */
398 KUNIT_EXPECT_EQ(test,
399 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
400 0);
401 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
402
403 KUNIT_EXPECT_EQ(test,
404 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
405 0);
406 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
407
408 KUNIT_EXPECT_EQ(test,
409 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, def.length_bytes),
410 0);
411 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
412 }
413
414 /*
415 * Multiple different firmware with controls identical except for alg id.
416 * This is legal because the controls are qualified by algorithm id.
417 * The control cache should be initialized only with the data from
418 * the firmware containing it.
419 */
cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls(struct kunit * test)420 static void cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls(struct kunit *test)
421 {
422 struct cs_dsp_test *priv = test->priv;
423 struct cs_dsp *dsp = priv->dsp;
424 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
425 struct cs_dsp_mock_wmfw_builder *builder[3];
426 unsigned int reg, alg_base_words;
427 struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
428 struct firmware *wmfw;
429 u32 *reg_vals[3], *readback;
430 int i;
431
432 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(builder));
433 static_assert(ARRAY_SIZE(reg_vals) == ARRAY_SIZE(builder));
434 static_assert(ARRAY_SIZE(cs_dsp_ctl_cache_test_fw_names) >= ARRAY_SIZE(builder));
435
436 /* Create an identical control in each firmware but with different alg id */
437 for (i = 0; i < ARRAY_SIZE(builder); i++) {
438 builder[i] = _create_dummy_wmfw(test);
439 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder[i]);
440
441 cs_dsp_mock_wmfw_start_alg_info_block(builder[i],
442 cs_dsp_ctl_cache_test_algs[i].id,
443 "dummyalg", NULL);
444 cs_dsp_mock_wmfw_add_coeff_desc(builder[i], &def);
445 cs_dsp_mock_wmfw_end_alg_info_block(builder[i]);
446 }
447
448 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
449 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
450 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
451 }
452
453 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
454 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
455
456 /*
457 * For each firmware create random content in the register backing
458 * the control. Then download, start, stop and power-down.
459 */
460 for (i = 0; i < ARRAY_SIZE(builder); i++) {
461 alg_base_words = _get_alg_mem_base_words(test, i, def.mem_type);
462 reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
463 reg += (alg_base_words + def.offset_dsp_words) *
464 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
465
466 get_random_bytes(reg_vals[i], def.length_bytes);
467 regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes);
468 wmfw = cs_dsp_mock_wmfw_get_firmware(builder[i]);
469 KUNIT_ASSERT_EQ(test,
470 cs_dsp_power_up(dsp, wmfw,
471 cs_dsp_ctl_cache_test_fw_names[i],
472 NULL, NULL,
473 cs_dsp_ctl_cache_test_fw_names[i]),
474 0);
475 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
476 cs_dsp_stop(dsp);
477 cs_dsp_power_down(dsp);
478 }
479
480 /* There should now be 3 controls */
481 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
482
483 /*
484 * There's no requirement for the control list to be in any
485 * particular order, so don't assume the order.
486 */
487 for (i = 0; i < ARRAY_SIZE(ctl); i++)
488 ctl[i] = NULL;
489
490 list_for_each_entry(walkctl, &dsp->ctl_list, list) {
491 if (cs_dsp_ctl_cache_test_algs[0].id == walkctl->alg_region.alg)
492 ctl[0] = walkctl;
493 else if (cs_dsp_ctl_cache_test_algs[1].id == walkctl->alg_region.alg)
494 ctl[1] = walkctl;
495 else if (cs_dsp_ctl_cache_test_algs[2].id == walkctl->alg_region.alg)
496 ctl[2] = walkctl;
497 }
498
499 KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
500 KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
501 KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
502
503 /*
504 * The data should have been populated into the control cache
505 * so should be readable through the control.
506 */
507 KUNIT_EXPECT_EQ(test,
508 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
509 0);
510 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
511
512 KUNIT_EXPECT_EQ(test,
513 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
514 0);
515 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
516
517 KUNIT_EXPECT_EQ(test,
518 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, def.length_bytes),
519 0);
520 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
521 }
522
523 /*
524 * Firmware with controls at the same position in different memories.
525 * The control cache should be initialized with content from the
526 * correct memory region.
527 */
cs_dsp_ctl_cache_init_multiple_mems(struct kunit * test)528 static void cs_dsp_ctl_cache_init_multiple_mems(struct kunit *test)
529 {
530 struct cs_dsp_test *priv = test->priv;
531 struct cs_dsp *dsp = priv->dsp;
532 struct cs_dsp_test_local *local = priv->local;
533 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
534 unsigned int reg, alg_base_words;
535 struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
536 struct firmware *wmfw;
537 u32 *reg_vals[3], *readback;
538 int i;
539
540 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(reg_vals));
541
542 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
543 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
544 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
545 get_random_bytes(reg_vals[i], def.length_bytes);
546 }
547
548 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
549 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
550
551 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
552 cs_dsp_ctl_cache_test_algs[0].id,
553 "dummyalg", NULL);
554
555 /* Create controls identical except for memory region */
556 def.mem_type = WMFW_ADSP2_YM;
557 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
558
559 def.mem_type = WMFW_ADSP2_XM;
560 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
561
562 if (cs_dsp_mock_has_zm(priv)) {
563 def.mem_type = WMFW_ADSP2_ZM;
564 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
565 }
566
567 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
568
569 /* Create random content in the registers backing each control */
570 alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_YM);
571 reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);
572 reg += (alg_base_words + def.offset_dsp_words) *
573 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
574 regmap_raw_write(dsp->regmap, reg, reg_vals[0], def.length_bytes);
575
576 alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_XM);
577 reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM);
578 reg += (alg_base_words + def.offset_dsp_words) *
579 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
580 regmap_raw_write(dsp->regmap, reg, reg_vals[1], def.length_bytes);
581
582 if (cs_dsp_mock_has_zm(priv)) {
583 alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_ZM);
584 reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_ZM);
585 reg += (alg_base_words + def.offset_dsp_words) *
586 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
587 regmap_raw_write(dsp->regmap, reg, reg_vals[2], def.length_bytes);
588 }
589
590 /* Download, run, stop and power-down the firmware */
591 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
592 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
593 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
594 cs_dsp_stop(dsp);
595 cs_dsp_power_down(dsp);
596
597 /* There should now be 2 or 3 controls */
598 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list),
599 cs_dsp_mock_has_zm(priv) ? 3 : 2);
600
601 /*
602 * There's no requirement for the control list to be in any
603 * particular order, so don't assume the order.
604 */
605 for (i = 0; i < ARRAY_SIZE(ctl); i++)
606 ctl[i] = NULL;
607
608 list_for_each_entry(walkctl, &dsp->ctl_list, list) {
609 if (walkctl->alg_region.type == WMFW_ADSP2_YM)
610 ctl[0] = walkctl;
611 if (walkctl->alg_region.type == WMFW_ADSP2_XM)
612 ctl[1] = walkctl;
613 if (walkctl->alg_region.type == WMFW_ADSP2_ZM)
614 ctl[2] = walkctl;
615 }
616
617
618 /*
619 * The data should have been populated into the control cache
620 * so should be readable through the control.
621 */
622 KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
623 KUNIT_EXPECT_EQ(test,
624 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
625 0);
626 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
627
628 KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
629 KUNIT_EXPECT_EQ(test,
630 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
631 0);
632 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
633
634 if (cs_dsp_mock_has_zm(priv)) {
635 KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
636 KUNIT_EXPECT_EQ(test,
637 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback,
638 def.length_bytes),
639 0);
640 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
641 }
642 }
643
644 /*
645 * Firmware with controls at the same position in different algorithms
646 * The control cache should be initialized with content from the
647 * memory of the algorithm it points to.
648 */
cs_dsp_ctl_cache_init_multiple_algs(struct kunit * test)649 static void cs_dsp_ctl_cache_init_multiple_algs(struct kunit *test)
650 {
651 struct cs_dsp_test *priv = test->priv;
652 struct cs_dsp *dsp = priv->dsp;
653 struct cs_dsp_test_local *local = priv->local;
654 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
655 unsigned int reg, alg_base_words;
656 struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
657 struct firmware *wmfw;
658 u32 *reg_vals[3], *readback;
659 int i;
660
661 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(reg_vals));
662 static_assert(ARRAY_SIZE(reg_vals) <= ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
663
664 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
665 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
666 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
667 get_random_bytes(reg_vals[i], def.length_bytes);
668 }
669
670 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
671 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
672
673 /* Create controls identical except for algorithm */
674 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
675 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
676 cs_dsp_ctl_cache_test_algs[i].id,
677 "dummyalg", NULL);
678 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
679 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
680 }
681
682 /* Create random content in the registers backing each control */
683 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
684 alg_base_words = _get_alg_mem_base_words(test, i, def.mem_type);
685 reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
686 reg += (alg_base_words + def.offset_dsp_words) *
687 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
688 regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes);
689 }
690
691 /* Download, run, stop and power-down the firmware */
692 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
693 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
694 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
695 cs_dsp_stop(dsp);
696 cs_dsp_power_down(dsp);
697
698 /* There should now be 3 controls */
699 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
700
701 /*
702 * There's no requirement for the control list to be in any
703 * particular order, so don't assume the order.
704 */
705 for (i = 0; i < ARRAY_SIZE(ctl); i++)
706 ctl[i] = NULL;
707
708 list_for_each_entry(walkctl, &dsp->ctl_list, list) {
709 if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[0].id)
710 ctl[0] = walkctl;
711 if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[1].id)
712 ctl[1] = walkctl;
713 if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[2].id)
714 ctl[2] = walkctl;
715 }
716
717 KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
718 KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
719 KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
720
721 /*
722 * The data should have been populated into the control cache
723 * so should be readable through the control.
724 */
725 KUNIT_EXPECT_EQ(test,
726 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
727 0);
728 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
729
730 KUNIT_EXPECT_EQ(test,
731 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
732 0);
733 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
734
735 KUNIT_EXPECT_EQ(test,
736 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback,
737 def.length_bytes),
738 0);
739 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
740 }
741
742 /*
743 * Firmware with controls in the same algorithm and memory but at
744 * different offsets.
745 * The control cache should be initialized with content from the
746 * correct offset.
747 * Only for wmfw format V2 and later. V1 only supports one control per
748 * memory per algorithm.
749 */
cs_dsp_ctl_cache_init_multiple_offsets(struct kunit * test)750 static void cs_dsp_ctl_cache_init_multiple_offsets(struct kunit *test)
751 {
752 struct cs_dsp_test *priv = test->priv;
753 struct cs_dsp *dsp = priv->dsp;
754 struct cs_dsp_test_local *local = priv->local;
755 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
756 unsigned int reg, alg_base_words, alg_base_reg;
757 struct cs_dsp_coeff_ctl *walkctl, *ctl[3];
758 struct firmware *wmfw;
759 u32 *reg_vals[3], *readback;
760 int i;
761
762 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(reg_vals));
763 static_assert(ARRAY_SIZE(reg_vals) <= ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
764
765 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
766 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL);
767 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]);
768 get_random_bytes(reg_vals[i], def.length_bytes);
769 }
770
771 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL);
772 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
773
774 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
775 cs_dsp_ctl_cache_test_algs[0].id,
776 "dummyalg", NULL);
777
778 /* Create controls identical except for offset */
779 def.length_bytes = 8;
780 def.offset_dsp_words = 0;
781 def.shortname = "CtlA";
782 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
783
784 def.offset_dsp_words = 5;
785 def.shortname = "CtlB";
786 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
787
788 def.offset_dsp_words = 8;
789 def.shortname = "CtlC";
790 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
791
792 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
793
794 /* Create random content in the registers backing each control */
795 alg_base_words = _get_alg_mem_base_words(test, 0, def.mem_type);
796 alg_base_reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
797 alg_base_reg += alg_base_words * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
798
799 reg = alg_base_reg;
800 regmap_raw_write(dsp->regmap, reg, reg_vals[0], def.length_bytes);
801 reg = alg_base_reg + (5 * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv));
802 regmap_raw_write(dsp->regmap, reg, reg_vals[1], def.length_bytes);
803 reg = alg_base_reg + (8 * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv));
804 regmap_raw_write(dsp->regmap, reg, reg_vals[2], def.length_bytes);
805
806 /* Download, run, stop and power-down the firmware */
807 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
808 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
809 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
810 cs_dsp_stop(dsp);
811 cs_dsp_power_down(dsp);
812
813 /* There should now be 3 controls */
814 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
815
816 /*
817 * There's no requirement for the control list to be in any
818 * particular order, so don't assume the order.
819 */
820 for (i = 0; i < ARRAY_SIZE(ctl); i++)
821 ctl[i] = NULL;
822
823 list_for_each_entry(walkctl, &dsp->ctl_list, list) {
824 if (walkctl->offset == 0)
825 ctl[0] = walkctl;
826 if (walkctl->offset == 5)
827 ctl[1] = walkctl;
828 if (walkctl->offset == 8)
829 ctl[2] = walkctl;
830 }
831
832 KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
833 KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
834 KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
835
836 /*
837 * The data should have been populated into the control cache
838 * so should be readable through the control.
839 */
840 KUNIT_EXPECT_EQ(test,
841 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
842 0);
843 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
844
845 KUNIT_EXPECT_EQ(test,
846 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
847 0);
848 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
849
850 KUNIT_EXPECT_EQ(test,
851 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback,
852 def.length_bytes),
853 0);
854 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
855 }
856
857 /*
858 * Read from a cached control before the firmware is started.
859 * Should return the data in the cache.
860 */
cs_dsp_ctl_cache_read_not_started(struct kunit * test)861 static void cs_dsp_ctl_cache_read_not_started(struct kunit *test)
862 {
863 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
864 struct cs_dsp_test *priv = test->priv;
865 struct cs_dsp_test_local *local = priv->local;
866 struct cs_dsp *dsp = priv->dsp;
867 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
868 int alg_idx = _find_alg_entry(test, param->alg_id);
869 unsigned int reg, alg_base_words;
870 struct cs_dsp_coeff_ctl *ctl;
871 struct firmware *wmfw;
872 u32 *reg_vals, *readback;
873
874 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
875 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
876
877 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
878 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
879
880 /* Create some DSP data to be read into the control cache */
881 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
882 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
883 reg += (alg_base_words + param->offs_words) *
884 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
885 get_random_bytes(reg_vals, param->len_bytes);
886 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
887
888 /* Create control pointing to this data */
889 def.flags = param->flags;
890 def.mem_type = param->mem_type;
891 def.offset_dsp_words = param->offs_words;
892 def.length_bytes = param->len_bytes;
893
894 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
895 cs_dsp_ctl_cache_test_algs[alg_idx].id,
896 "dummyalg", NULL);
897 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
898 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
899
900 /* Power-up DSP but don't start firmware */
901 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
902 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
903
904 /* Drop expected writes and the regmap cache should be clean */
905 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
906 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
907 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
908
909 /* Control should readback the data from the control cache */
910 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
911 KUNIT_ASSERT_NOT_NULL(test, ctl);
912 KUNIT_EXPECT_EQ(test,
913 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
914 0);
915 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
916 }
917
918 /*
919 * Read from a cached control after the firmware has been stopped.
920 * Should return the data in the cache.
921 */
cs_dsp_ctl_cache_read_stopped(struct kunit * test)922 static void cs_dsp_ctl_cache_read_stopped(struct kunit *test)
923 {
924 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
925 struct cs_dsp_test *priv = test->priv;
926 struct cs_dsp_test_local *local = priv->local;
927 struct cs_dsp *dsp = priv->dsp;
928 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
929 int alg_idx = _find_alg_entry(test, param->alg_id);
930 unsigned int reg, alg_base_words;
931 struct cs_dsp_coeff_ctl *ctl;
932 struct firmware *wmfw;
933 u32 *reg_vals, *readback;
934
935 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
936 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
937
938 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
939 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
940
941 /* Create some DSP data to be read into the control cache */
942 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
943 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
944 reg += (alg_base_words + param->offs_words) *
945 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
946 get_random_bytes(reg_vals, param->len_bytes);
947 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
948
949 /* Create control pointing to this data */
950 def.flags = param->flags;
951 def.mem_type = param->mem_type;
952 def.offset_dsp_words = param->offs_words;
953 def.length_bytes = param->len_bytes;
954
955 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
956 cs_dsp_ctl_cache_test_algs[alg_idx].id,
957 "dummyalg", NULL);
958 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
959 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
960
961 /* Power-up DSP */
962 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
963 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
964
965 /* Start and stop the firmware */
966 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
967 cs_dsp_stop(dsp);
968
969 /* Drop expected writes and the regmap cache should be clean */
970 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
971 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
972 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
973
974 /* Control should readback the data from the control cache */
975 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
976 KUNIT_ASSERT_NOT_NULL(test, ctl);
977 KUNIT_EXPECT_EQ(test,
978 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
979 0);
980 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
981 }
982
983 /*
984 * Read from a cached control after the DSP has been powered-up and
985 * then powered-down without running.
986 * Should return the data in the cache.
987 */
cs_dsp_ctl_cache_read_powered_down(struct kunit * test)988 static void cs_dsp_ctl_cache_read_powered_down(struct kunit *test)
989 {
990 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
991 struct cs_dsp_test *priv = test->priv;
992 struct cs_dsp_test_local *local = priv->local;
993 struct cs_dsp *dsp = priv->dsp;
994 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
995 int alg_idx = _find_alg_entry(test, param->alg_id);
996 unsigned int reg, alg_base_words;
997 struct cs_dsp_coeff_ctl *ctl;
998 struct firmware *wmfw;
999 u32 *reg_vals, *readback;
1000
1001 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1002 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1003
1004 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1005 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1006
1007 /* Create some DSP data to be read into the control cache */
1008 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1009 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1010 reg += (alg_base_words + param->offs_words) *
1011 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1012 get_random_bytes(reg_vals, param->len_bytes);
1013 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1014
1015 /* Create control pointing to this data */
1016 def.flags = param->flags;
1017 def.mem_type = param->mem_type;
1018 def.offset_dsp_words = param->offs_words;
1019 def.length_bytes = param->len_bytes;
1020
1021 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1022 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1023 "dummyalg", NULL);
1024 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1025 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1026
1027 /* Power-up DSP then power-down */
1028 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1029 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1030 cs_dsp_power_down(dsp);
1031
1032 /* Drop expected writes and the regmap cache should be clean */
1033 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1034 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1035 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1036
1037 /* Control should readback the data from the control cache */
1038 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1039 KUNIT_ASSERT_NOT_NULL(test, ctl);
1040 KUNIT_EXPECT_EQ(test,
1041 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1042 0);
1043 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1044 }
1045
1046 /*
1047 * Read from a cached control after the firmware has been run and
1048 * stopped, then the DSP has been powered-down.
1049 * Should return the data in the cache.
1050 */
cs_dsp_ctl_cache_read_stopped_powered_down(struct kunit * test)1051 static void cs_dsp_ctl_cache_read_stopped_powered_down(struct kunit *test)
1052 {
1053 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1054 struct cs_dsp_test *priv = test->priv;
1055 struct cs_dsp_test_local *local = priv->local;
1056 struct cs_dsp *dsp = priv->dsp;
1057 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1058 int alg_idx = _find_alg_entry(test, param->alg_id);
1059 unsigned int reg, alg_base_words;
1060 struct cs_dsp_coeff_ctl *ctl;
1061 struct firmware *wmfw;
1062 u32 *reg_vals, *readback;
1063
1064 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1065 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1066
1067 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1068 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1069
1070 /* Create some DSP data to be read into the control cache */
1071 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1072 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1073 reg += (alg_base_words + param->offs_words) *
1074 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1075 get_random_bytes(reg_vals, param->len_bytes);
1076 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1077
1078 /* Create control pointing to this data */
1079 def.flags = param->flags;
1080 def.mem_type = param->mem_type;
1081 def.offset_dsp_words = param->offs_words;
1082 def.length_bytes = param->len_bytes;
1083
1084 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1085 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1086 "dummyalg", NULL);
1087 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1088 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1089
1090 /* Power-up DSP */
1091 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1092 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1093
1094 /* Start and stop the firmware then power-down */
1095 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1096 cs_dsp_stop(dsp);
1097 cs_dsp_power_down(dsp);
1098
1099 /* Drop expected writes and the regmap cache should be clean */
1100 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1101 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1102 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1103
1104 /* Control should readback the data from the control cache */
1105 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1106 KUNIT_ASSERT_NOT_NULL(test, ctl);
1107 KUNIT_EXPECT_EQ(test,
1108 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1109 0);
1110 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1111 }
1112
1113 /*
1114 * Read from a cached control when a different firmware is currently
1115 * loaded into the DSP.
1116 * Should return the data in the cache.
1117 */
cs_dsp_ctl_cache_read_not_current_loaded_fw(struct kunit * test)1118 static void cs_dsp_ctl_cache_read_not_current_loaded_fw(struct kunit *test)
1119 {
1120 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1121 struct cs_dsp_test *priv = test->priv;
1122 struct cs_dsp_test_local *local = priv->local;
1123 struct cs_dsp *dsp = priv->dsp;
1124 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1125 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1126 int alg_idx = _find_alg_entry(test, param->alg_id);
1127 unsigned int reg, alg_base_words;
1128 struct cs_dsp_coeff_ctl *ctl;
1129 struct firmware *wmfw;
1130 u32 *reg_vals, *readback;
1131
1132 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1133 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1134
1135 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1136 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1137
1138 /* Create some DSP data to be read into the control cache */
1139 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1140 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1141 reg += (alg_base_words + param->offs_words) *
1142 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1143 get_random_bytes(reg_vals, param->len_bytes);
1144 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1145
1146 /* Create control pointing to this data */
1147 def.flags = param->flags;
1148 def.mem_type = param->mem_type;
1149 def.offset_dsp_words = param->offs_words;
1150 def.length_bytes = param->len_bytes;
1151
1152 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1153 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1154 "dummyalg", NULL);
1155 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1156 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1157
1158 /* Power-up DSP */
1159 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1160 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1161
1162 /* Power-down DSP then power-up with a different firmware */
1163 cs_dsp_power_down(dsp);
1164 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1165 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1166
1167 /* Drop expected writes and the regmap cache should be clean */
1168 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1169 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1170 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1171
1172 /* Control should readback the data from the control cache */
1173 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1174 KUNIT_ASSERT_NOT_NULL(test, ctl);
1175 KUNIT_EXPECT_EQ(test,
1176 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1177 0);
1178 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1179 }
1180
1181 /*
1182 * Read from a cached control when a different firmware is currently
1183 * running.
1184 * Should return the data in the cache.
1185 */
cs_dsp_ctl_cache_read_not_current_running_fw(struct kunit * test)1186 static void cs_dsp_ctl_cache_read_not_current_running_fw(struct kunit *test)
1187 {
1188 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1189 struct cs_dsp_test *priv = test->priv;
1190 struct cs_dsp_test_local *local = priv->local;
1191 struct cs_dsp *dsp = priv->dsp;
1192 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1193 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1194 int alg_idx = _find_alg_entry(test, param->alg_id);
1195 unsigned int reg, alg_base_words;
1196 struct cs_dsp_coeff_ctl *ctl;
1197 struct firmware *wmfw;
1198 u32 *reg_vals, *readback;
1199
1200 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1201 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1202
1203 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1204 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1205
1206 /* Create some DSP data to be read into the control cache */
1207 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1208 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1209 reg += (alg_base_words + param->offs_words) *
1210 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1211 get_random_bytes(reg_vals, param->len_bytes);
1212 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1213
1214 /* Create control pointing to this data */
1215 def.flags = param->flags;
1216 def.mem_type = param->mem_type;
1217 def.offset_dsp_words = param->offs_words;
1218 def.length_bytes = param->len_bytes;
1219
1220 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1221 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1222 "dummyalg", NULL);
1223 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1224 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1225
1226 /* Power-up DSP then power-down */
1227 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1228 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1229 cs_dsp_power_down(dsp);
1230
1231 /* Power-up with a different firmware and run it */
1232 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1233 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1234 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1235 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1236
1237 /* Drop expected writes and the regmap cache should be clean */
1238 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1239 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1240 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1241
1242 /* Control should readback the data from the control cache */
1243 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1244 KUNIT_ASSERT_NOT_NULL(test, ctl);
1245 KUNIT_EXPECT_EQ(test,
1246 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1247 0);
1248 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1249 }
1250
1251 /*
1252 * Read from a cached control with non-zero flags while the firmware is
1253 * running.
1254 * Should return the data in the cache, not from the registers.
1255 */
cs_dsp_ctl_cache_read_running(struct kunit * test)1256 static void cs_dsp_ctl_cache_read_running(struct kunit *test)
1257 {
1258 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1259 struct cs_dsp_test *priv = test->priv;
1260 struct cs_dsp_test_local *local = priv->local;
1261 struct cs_dsp *dsp = priv->dsp;
1262 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1263 int alg_idx = _find_alg_entry(test, param->alg_id);
1264 unsigned int reg, alg_base_words;
1265 struct cs_dsp_coeff_ctl *ctl;
1266 struct firmware *wmfw;
1267 u32 *init_reg_vals, *new_reg_vals, *readback;
1268
1269 init_reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1270 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_reg_vals);
1271
1272 new_reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1273 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_reg_vals);
1274
1275 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1276 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1277
1278 /* Create data in the registers backing the control */
1279 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1280 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1281 reg += (alg_base_words + param->offs_words) *
1282 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1283 get_random_bytes(init_reg_vals, param->len_bytes);
1284 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1285
1286 /* Create control pointing to this data */
1287 def.flags = param->flags;
1288 def.mem_type = param->mem_type;
1289 def.offset_dsp_words = param->offs_words;
1290 def.length_bytes = param->len_bytes;
1291
1292 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1293 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1294 "dummyalg", NULL);
1295 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1296 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1297
1298 /* Power-up DSP */
1299 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1300 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1301
1302 /* Start the firmware running */
1303 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1304 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1305
1306 /*
1307 * Change the values in the registers backing the control then drop
1308 * them from the regmap cache. This allows checking that the control
1309 * read is returning values from the control cache and not accessing
1310 * the registers.
1311 */
1312 KUNIT_ASSERT_EQ(test,
1313 regmap_raw_write(dsp->regmap, reg, new_reg_vals, param->len_bytes),
1314 0);
1315 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1316
1317 /* Control should readback the origin data from its cache */
1318 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1319 KUNIT_ASSERT_NOT_NULL(test, ctl);
1320 KUNIT_EXPECT_EQ(test,
1321 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1322 0);
1323 KUNIT_EXPECT_MEMEQ(test, readback, init_reg_vals, param->len_bytes);
1324
1325 /* Stop and power-down the DSP */
1326 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1327 cs_dsp_power_down(dsp);
1328
1329 /* Control should readback from the cache */
1330 KUNIT_EXPECT_EQ(test,
1331 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1332 0);
1333 KUNIT_EXPECT_MEMEQ(test, readback, init_reg_vals, param->len_bytes);
1334 }
1335
1336 /*
1337 * Read from a cached control with flags == 0 while the firmware is
1338 * running.
1339 * Should behave as volatile and read from the registers.
1340 * (This is for backwards compatibility with old firmware versions)
1341 */
cs_dsp_ctl_cache_read_running_zero_flags(struct kunit * test)1342 static void cs_dsp_ctl_cache_read_running_zero_flags(struct kunit *test)
1343 {
1344 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1345 struct cs_dsp_test *priv = test->priv;
1346 struct cs_dsp_test_local *local = priv->local;
1347 struct cs_dsp *dsp = priv->dsp;
1348 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1349 int alg_idx = _find_alg_entry(test, param->alg_id);
1350 unsigned int reg, alg_base_words;
1351 struct cs_dsp_coeff_ctl *ctl;
1352 struct firmware *wmfw;
1353 u32 *init_reg_vals, *new_reg_vals, *readback;
1354
1355 init_reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1356 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_reg_vals);
1357
1358 new_reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1359 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_reg_vals);
1360
1361 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1362 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1363
1364 /* Zero-fill the registers backing the control */
1365 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1366 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1367 reg += (alg_base_words + param->offs_words) *
1368 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1369 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1370
1371 /* Create control pointing to this data */
1372 def.flags = 0;
1373 def.mem_type = param->mem_type;
1374 def.offset_dsp_words = param->offs_words;
1375 def.length_bytes = param->len_bytes;
1376
1377 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1378 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1379 "dummyalg", NULL);
1380 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1381 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1382
1383 /* Power-up DSP */
1384 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1385 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1386
1387 /* Start the firmware running */
1388 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1389 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1390
1391 /* Change the values in the registers backing the control */
1392 get_random_bytes(new_reg_vals, param->len_bytes);
1393 regmap_raw_write(dsp->regmap, reg, new_reg_vals, param->len_bytes);
1394
1395 /* Control should readback the new data from the registers */
1396 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1397 KUNIT_ASSERT_NOT_NULL(test, ctl);
1398 KUNIT_EXPECT_EQ(test,
1399 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1400 0);
1401 KUNIT_EXPECT_MEMEQ(test, readback, new_reg_vals, param->len_bytes);
1402
1403 /* Stop and power-down the DSP */
1404 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1405 cs_dsp_power_down(dsp);
1406
1407 /* Change the values in the registers backing the control */
1408 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1409
1410 /* Control should readback from the cache */
1411 KUNIT_EXPECT_EQ(test,
1412 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1413 0);
1414 KUNIT_EXPECT_MEMEQ(test, readback, new_reg_vals, param->len_bytes);
1415 }
1416
1417 /*
1418 * Write to a cached control while the firmware is running.
1419 * This should be a writethrough operation, writing to the cache and
1420 * the registers.
1421 */
cs_dsp_ctl_cache_writethrough(struct kunit * test)1422 static void cs_dsp_ctl_cache_writethrough(struct kunit *test)
1423 {
1424 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1425 struct cs_dsp_test *priv = test->priv;
1426 struct cs_dsp_test_local *local = priv->local;
1427 struct cs_dsp *dsp = priv->dsp;
1428 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1429 int alg_idx = _find_alg_entry(test, param->alg_id);
1430 unsigned int reg, alg_base_words;
1431 struct cs_dsp_coeff_ctl *ctl;
1432 struct firmware *wmfw;
1433 u32 *reg_vals, *readback;
1434
1435 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1436 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1437
1438 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1439 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1440
1441 /* Create some DSP data to be read into the control cache */
1442 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1443 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1444 reg += (alg_base_words + param->offs_words) *
1445 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1446 memset(reg_vals, 0, param->len_bytes);
1447 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1448
1449 /* Create control pointing to this data */
1450 def.flags = param->flags;
1451 def.mem_type = param->mem_type;
1452 def.offset_dsp_words = param->offs_words;
1453 def.length_bytes = param->len_bytes;
1454
1455 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1456 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1457 "dummyalg", NULL);
1458 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1459 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1460
1461 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1462 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1463
1464 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1465 KUNIT_ASSERT_NOT_NULL(test, ctl);
1466
1467 /* Start the firmware and add an action to stop it during cleanup */
1468 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1469 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1470
1471 /* Write new data to the control, it should be written to the registers */
1472 get_random_bytes(reg_vals, param->len_bytes);
1473 KUNIT_EXPECT_EQ(test,
1474 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1475 1);
1476 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1477 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1478 }
1479
1480 /*
1481 * Write unchanged data to a cached control while the firmware is running.
1482 * The control write should return 0 to indicate that the content
1483 * didn't change.
1484 */
cs_dsp_ctl_cache_writethrough_unchanged(struct kunit * test)1485 static void cs_dsp_ctl_cache_writethrough_unchanged(struct kunit *test)
1486 {
1487 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1488 struct cs_dsp_test *priv = test->priv;
1489 struct cs_dsp_test_local *local = priv->local;
1490 struct cs_dsp *dsp = priv->dsp;
1491 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1492 int alg_idx = _find_alg_entry(test, param->alg_id);
1493 unsigned int reg, alg_base_words;
1494 struct cs_dsp_coeff_ctl *ctl;
1495 struct firmware *wmfw;
1496 u32 *reg_vals, *readback;
1497
1498 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1499 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1500
1501 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1502 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1503
1504 /* Create some DSP data to be read into the control cache */
1505 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1506 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1507 reg += (alg_base_words + param->offs_words) *
1508 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1509 get_random_bytes(reg_vals, param->len_bytes);
1510 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1511
1512 /* Create control pointing to this data */
1513 def.flags = param->flags;
1514 def.mem_type = param->mem_type;
1515 def.offset_dsp_words = param->offs_words;
1516 def.length_bytes = param->len_bytes;
1517
1518 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1519 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1520 "dummyalg", NULL);
1521 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1522 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1523
1524 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1525 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1526
1527 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1528 KUNIT_ASSERT_NOT_NULL(test, ctl);
1529
1530 /* Start the firmware and add an action to stop it during cleanup */
1531 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1532 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1533
1534 /*
1535 * If the control is write-only the cache will have been zero-initialized
1536 * so the first write will always indicate a change.
1537 */
1538 if (def.flags && !(def.flags & WMFW_CTL_FLAG_READABLE)) {
1539 KUNIT_EXPECT_EQ(test,
1540 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1541 param->len_bytes),
1542 1);
1543 }
1544
1545 /*
1546 * Write the same data to the control, cs_dsp_coeff_lock_and_write_ctrl()
1547 * should return 0 to indicate the content didn't change.
1548 */
1549 KUNIT_EXPECT_EQ(test,
1550 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1551 0);
1552 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1553 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1554 }
1555
1556 /*
1557 * Write unchanged data to a cached control while the firmware is not started.
1558 * The control write should return 0 to indicate that the cache content
1559 * didn't change.
1560 */
cs_dsp_ctl_cache_write_unchanged_not_started(struct kunit * test)1561 static void cs_dsp_ctl_cache_write_unchanged_not_started(struct kunit *test)
1562 {
1563 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1564 struct cs_dsp_test *priv = test->priv;
1565 struct cs_dsp_test_local *local = priv->local;
1566 struct cs_dsp *dsp = priv->dsp;
1567 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1568 int alg_idx = _find_alg_entry(test, param->alg_id);
1569 unsigned int reg, alg_base_words;
1570 struct cs_dsp_coeff_ctl *ctl;
1571 struct firmware *wmfw;
1572 u32 *reg_vals, *readback;
1573
1574 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1575 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1576
1577 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1578 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1579
1580 /* Create some DSP data to be read into the control cache */
1581 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1582 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1583 reg += (alg_base_words + param->offs_words) *
1584 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1585 get_random_bytes(reg_vals, param->len_bytes);
1586 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1587
1588 /* Create control pointing to this data */
1589 def.flags = param->flags;
1590 def.mem_type = param->mem_type;
1591 def.offset_dsp_words = param->offs_words;
1592 def.length_bytes = param->len_bytes;
1593
1594 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1595 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1596 "dummyalg", NULL);
1597 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1598 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1599
1600 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1601 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1602
1603 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1604 KUNIT_ASSERT_NOT_NULL(test, ctl);
1605
1606 /*
1607 * If the control is write-only the cache will have been zero-initialized
1608 * so the first write will always indicate a change.
1609 */
1610 if (def.flags && !(def.flags & WMFW_CTL_FLAG_READABLE)) {
1611 KUNIT_EXPECT_EQ(test,
1612 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1613 param->len_bytes),
1614 1);
1615 }
1616
1617 /*
1618 * Write the same data to the control, cs_dsp_coeff_lock_and_write_ctrl()
1619 * should return 0 to indicate the content didn't change.
1620 */
1621 KUNIT_EXPECT_EQ(test,
1622 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1623 0);
1624 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1625 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1626 }
1627
1628 /*
1629 * Write to a cached control while the firmware is loaded but not
1630 * started.
1631 * This should write to the cache only.
1632 */
cs_dsp_ctl_cache_write_not_started(struct kunit * test)1633 static void cs_dsp_ctl_cache_write_not_started(struct kunit *test)
1634 {
1635 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1636 struct cs_dsp_test *priv = test->priv;
1637 struct cs_dsp_test_local *local = priv->local;
1638 struct cs_dsp *dsp = priv->dsp;
1639 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1640 int alg_idx = _find_alg_entry(test, param->alg_id);
1641 unsigned int reg, alg_base_words;
1642 struct cs_dsp_coeff_ctl *ctl;
1643 struct firmware *wmfw;
1644 u32 *reg_vals, *readback;
1645
1646 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1647 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1648
1649 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1650 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1651
1652 /* Create some DSP data to be read into the control cache */
1653 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1654 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1655 reg += (alg_base_words + param->offs_words) *
1656 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1657 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1658
1659 /* Create control pointing to this data */
1660 def.flags = param->flags;
1661 def.mem_type = param->mem_type;
1662 def.offset_dsp_words = param->offs_words;
1663 def.length_bytes = param->len_bytes;
1664
1665 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1666 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1667 "dummyalg", NULL);
1668 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1669 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1670
1671 /* Power-up DSP but don't start firmware */
1672 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1673 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1674
1675 /* Drop expected writes and the regmap cache should be clean */
1676 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1677 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1678 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1679
1680 /* Write new data to the control, it should not be written to the registers */
1681 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1682 KUNIT_ASSERT_NOT_NULL(test, ctl);
1683
1684 get_random_bytes(reg_vals, param->len_bytes);
1685 KUNIT_EXPECT_EQ(test,
1686 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1687 1);
1688
1689 /* Registers should not have been written so regmap cache should still be clean */
1690 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1691
1692 /* Control should readback the new data from the control cache */
1693 KUNIT_EXPECT_EQ(test,
1694 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1695 0);
1696 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1697 }
1698
1699 /*
1700 * Write to a cached control after the firmware has been loaded,
1701 * started and stopped.
1702 * This should write to the cache only.
1703 */
cs_dsp_ctl_cache_write_stopped(struct kunit * test)1704 static void cs_dsp_ctl_cache_write_stopped(struct kunit *test)
1705 {
1706 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1707 struct cs_dsp_test *priv = test->priv;
1708 struct cs_dsp_test_local *local = priv->local;
1709 struct cs_dsp *dsp = priv->dsp;
1710 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1711 int alg_idx = _find_alg_entry(test, param->alg_id);
1712 unsigned int reg, alg_base_words;
1713 struct cs_dsp_coeff_ctl *ctl;
1714 struct firmware *wmfw;
1715 u32 *reg_vals, *readback;
1716
1717 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1718 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1719
1720 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1721 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1722
1723 /* Create some DSP data to be read into the control cache */
1724 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1725 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1726 reg += (alg_base_words + param->offs_words) *
1727 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1728 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1729
1730 /* Create control pointing to this data */
1731 def.flags = param->flags;
1732 def.mem_type = param->mem_type;
1733 def.offset_dsp_words = param->offs_words;
1734 def.length_bytes = param->len_bytes;
1735
1736 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1737 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1738 "dummyalg", NULL);
1739 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1740 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1741
1742 /* Power-up DSP */
1743 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1744 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1745
1746 /* Start and stop the firmware */
1747 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1748 cs_dsp_stop(dsp);
1749
1750 /* Drop expected writes and the regmap cache should be clean */
1751 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1752 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1753 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1754
1755 /* Write new data to the control, it should not be written to the registers */
1756 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1757 KUNIT_ASSERT_NOT_NULL(test, ctl);
1758
1759 get_random_bytes(reg_vals, param->len_bytes);
1760 KUNIT_EXPECT_EQ(test,
1761 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1762 1);
1763
1764 /* Registers should not have been written so regmap cache should still be clean */
1765 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1766
1767 /* Control should readback the new data from the control cache */
1768 KUNIT_EXPECT_EQ(test,
1769 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1770 0);
1771 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1772 }
1773
1774 /*
1775 * Write to a cached control after the firmware has been loaded,
1776 * then the DSP powered-down.
1777 * This should write to the cache only.
1778 */
cs_dsp_ctl_cache_write_powered_down(struct kunit * test)1779 static void cs_dsp_ctl_cache_write_powered_down(struct kunit *test)
1780 {
1781 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1782 struct cs_dsp_test *priv = test->priv;
1783 struct cs_dsp_test_local *local = priv->local;
1784 struct cs_dsp *dsp = priv->dsp;
1785 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1786 int alg_idx = _find_alg_entry(test, param->alg_id);
1787 unsigned int reg, alg_base_words;
1788 struct cs_dsp_coeff_ctl *ctl;
1789 struct firmware *wmfw;
1790 u32 *reg_vals, *readback;
1791
1792 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1793 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1794
1795 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1796 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1797
1798 /* Create some DSP data to be read into the control cache */
1799 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1800 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1801 reg += (alg_base_words + param->offs_words) *
1802 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1803 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1804
1805 /* Create control pointing to this data */
1806 def.flags = param->flags;
1807 def.mem_type = param->mem_type;
1808 def.offset_dsp_words = param->offs_words;
1809 def.length_bytes = param->len_bytes;
1810
1811 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1812 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1813 "dummyalg", NULL);
1814 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1815 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1816
1817 /* Power-up DSP then power-down */
1818 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1819 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1820 cs_dsp_power_down(dsp);
1821
1822 /* Drop expected writes and the regmap cache should be clean */
1823 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1824 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1825 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1826
1827 /* Write new data to the control, it should not be written to the registers */
1828 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1829 KUNIT_ASSERT_NOT_NULL(test, ctl);
1830
1831 get_random_bytes(reg_vals, param->len_bytes);
1832 KUNIT_EXPECT_EQ(test,
1833 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1834 1);
1835
1836 /* Registers should not have been written so regmap cache should still be clean */
1837 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1838
1839 /* Control should readback the new data from the control cache */
1840 KUNIT_EXPECT_EQ(test,
1841 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1842 0);
1843 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1844 }
1845
1846 /*
1847 * Write to a cached control after the firmware has been loaded,
1848 * started, stopped, and then the DSP powered-down.
1849 * This should write to the cache only.
1850 */
cs_dsp_ctl_cache_write_stopped_powered_down(struct kunit * test)1851 static void cs_dsp_ctl_cache_write_stopped_powered_down(struct kunit *test)
1852 {
1853 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1854 struct cs_dsp_test *priv = test->priv;
1855 struct cs_dsp_test_local *local = priv->local;
1856 struct cs_dsp *dsp = priv->dsp;
1857 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1858 int alg_idx = _find_alg_entry(test, param->alg_id);
1859 unsigned int reg, alg_base_words;
1860 struct cs_dsp_coeff_ctl *ctl;
1861 struct firmware *wmfw;
1862 u32 *reg_vals, *readback;
1863
1864 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1865 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1866
1867 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1868 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1869
1870 /* Create some DSP data to be read into the control cache */
1871 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1872 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1873 reg += (alg_base_words + param->offs_words) *
1874 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1875 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1876
1877 /* Create control pointing to this data */
1878 def.flags = param->flags;
1879 def.mem_type = param->mem_type;
1880 def.offset_dsp_words = param->offs_words;
1881 def.length_bytes = param->len_bytes;
1882
1883 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1884 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1885 "dummyalg", NULL);
1886 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1887 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1888
1889 /* Power-up DSP */
1890 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1891 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1892
1893 /* Start and stop the firmware then power-down */
1894 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1895 cs_dsp_stop(dsp);
1896 cs_dsp_power_down(dsp);
1897
1898 /* Drop expected writes and the regmap cache should be clean */
1899 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1900 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1901 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1902
1903 /* Write new data to the control, it should not be written to the registers */
1904 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1905 KUNIT_ASSERT_NOT_NULL(test, ctl);
1906
1907 get_random_bytes(reg_vals, param->len_bytes);
1908 KUNIT_EXPECT_EQ(test,
1909 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1910 1);
1911
1912 /* Registers should not have been written so regmap cache should still be clean */
1913 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1914
1915 /* Control should readback the new data from the control cache */
1916 KUNIT_EXPECT_EQ(test,
1917 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1918 0);
1919 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1920 }
1921
1922 /*
1923 * Write to a cached control that is not in the currently loaded firmware.
1924 * This should write to the cache only.
1925 */
cs_dsp_ctl_cache_write_not_current_loaded_fw(struct kunit * test)1926 static void cs_dsp_ctl_cache_write_not_current_loaded_fw(struct kunit *test)
1927 {
1928 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1929 struct cs_dsp_test *priv = test->priv;
1930 struct cs_dsp_test_local *local = priv->local;
1931 struct cs_dsp *dsp = priv->dsp;
1932 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1933 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1934 int alg_idx = _find_alg_entry(test, param->alg_id);
1935 unsigned int reg, alg_base_words;
1936 struct cs_dsp_coeff_ctl *ctl;
1937 struct firmware *wmfw;
1938 u32 *reg_vals, *readback;
1939
1940 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1941 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1942
1943 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1944 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1945
1946 /* Create some DSP data to be read into the control cache */
1947 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1948 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1949 reg += (alg_base_words + param->offs_words) *
1950 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1951 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1952
1953 /* Create control pointing to this data */
1954 def.flags = param->flags;
1955 def.mem_type = param->mem_type;
1956 def.offset_dsp_words = param->offs_words;
1957 def.length_bytes = param->len_bytes;
1958
1959 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1960 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1961 "dummyalg", NULL);
1962 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1963 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1964
1965 /* Power-up DSP */
1966 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1967 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1968
1969 /* Get the control */
1970 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1971 KUNIT_ASSERT_NOT_NULL(test, ctl);
1972
1973 /* Power-down DSP then power-up with a different firmware */
1974 cs_dsp_power_down(dsp);
1975 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1976 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1977
1978 /* Control from unloaded firmware should be disabled */
1979 KUNIT_EXPECT_FALSE(test, ctl->enabled);
1980
1981 /* Drop expected writes and the regmap cache should be clean */
1982 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1983 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1984 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1985
1986 /*
1987 * It should be possible to write new data to the control from
1988 * the first firmware. But this should not be written to the
1989 * registers.
1990 */
1991 get_random_bytes(reg_vals, param->len_bytes);
1992 KUNIT_EXPECT_EQ(test,
1993 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1994 1);
1995
1996 /* Registers should not have been written so regmap cache should still be clean */
1997 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1998
1999 /* Control should readback the new data from the control cache */
2000 KUNIT_EXPECT_EQ(test,
2001 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2002 0);
2003 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2004 }
2005
2006 /*
2007 * Write to a cached control that is not in the currently running firmware.
2008 * This should write to the cache only.
2009 */
cs_dsp_ctl_cache_write_not_current_running_fw(struct kunit * test)2010 static void cs_dsp_ctl_cache_write_not_current_running_fw(struct kunit *test)
2011 {
2012 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2013 struct cs_dsp_test *priv = test->priv;
2014 struct cs_dsp_test_local *local = priv->local;
2015 struct cs_dsp *dsp = priv->dsp;
2016 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2017 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2018 int alg_idx = _find_alg_entry(test, param->alg_id);
2019 unsigned int reg, alg_base_words;
2020 struct cs_dsp_coeff_ctl *ctl;
2021 struct firmware *wmfw;
2022 u32 *reg_vals, *readback;
2023
2024 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2025 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2026
2027 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2028 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2029
2030 /* Create some DSP data to be read into the control cache */
2031 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2032 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2033 reg += (alg_base_words + param->offs_words) *
2034 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2035 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2036
2037 /* Create control pointing to this data */
2038 def.flags = param->flags;
2039 def.mem_type = param->mem_type;
2040 def.offset_dsp_words = param->offs_words;
2041 def.length_bytes = param->len_bytes;
2042
2043 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2044 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2045 "dummyalg", NULL);
2046 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2047 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2048
2049 /* Power-up DSP then power-down */
2050 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2051 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2052 cs_dsp_power_down(dsp);
2053
2054 /* Get the control */
2055 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2056 KUNIT_ASSERT_NOT_NULL(test, ctl);
2057
2058 /* Power-up with a different firmware and run it */
2059 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2060 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2061 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2062 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2063
2064 /* Control from unloaded firmware should be disabled */
2065 KUNIT_EXPECT_FALSE(test, ctl->enabled);
2066
2067 /* Drop expected writes and the regmap cache should be clean */
2068 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
2069 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
2070 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2071
2072 /*
2073 * It should be possible to write new data to the control from
2074 * the first firmware. But this should not be written to the
2075 * registers.
2076 */
2077 get_random_bytes(reg_vals, param->len_bytes);
2078 KUNIT_EXPECT_EQ(test,
2079 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2080 1);
2081
2082 /* Registers should not have been written so regmap cache should still be clean */
2083 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2084
2085 /* Control should readback the new data from the control cache */
2086 KUNIT_EXPECT_EQ(test,
2087 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2088 0);
2089 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2090 }
2091
2092 /*
2093 * Write to a cached control before running the firmware.
2094 * The value written to the cache should be synced out to the registers
2095 * backing the control when the firmware is run.
2096 */
cs_dsp_ctl_cache_sync_write_before_run(struct kunit * test)2097 static void cs_dsp_ctl_cache_sync_write_before_run(struct kunit *test)
2098 {
2099 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2100 struct cs_dsp_test *priv = test->priv;
2101 struct cs_dsp_test_local *local = priv->local;
2102 struct cs_dsp *dsp = priv->dsp;
2103 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2104 int alg_idx = _find_alg_entry(test, param->alg_id);
2105 unsigned int reg, alg_base_words;
2106 struct cs_dsp_coeff_ctl *ctl;
2107 struct firmware *wmfw;
2108 u32 *reg_vals, *readback;
2109
2110 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2111 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2112
2113 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2114 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2115
2116 /* Create some DSP data to be read into the control cache */
2117 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2118 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2119 reg += (alg_base_words + param->offs_words) *
2120 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2121 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2122
2123 /* Create control pointing to this data */
2124 def.flags = param->flags;
2125 def.mem_type = param->mem_type;
2126 def.offset_dsp_words = param->offs_words;
2127 def.length_bytes = param->len_bytes;
2128
2129 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2130 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2131 "dummyalg", NULL);
2132 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2133 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2134
2135 /* Power-up DSP but don't start firmware */
2136 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2137 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2138
2139 /* Write new data to the control, it should not be written to the registers */
2140 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2141 KUNIT_ASSERT_NOT_NULL(test, ctl);
2142
2143 get_random_bytes(reg_vals, param->len_bytes);
2144 KUNIT_EXPECT_EQ(test,
2145 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2146 1);
2147
2148 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2149 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2150
2151 /* Start the firmware and the cached data should be written to registers */
2152 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2153 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2154
2155 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2156 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2157
2158 /* Control should readback the new data from the control cache */
2159 KUNIT_EXPECT_EQ(test,
2160 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2161 0);
2162 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2163 }
2164
2165 /*
2166 * Write to a cached control while the firmware is running.
2167 * The value written should be synced out to the registers
2168 * backing the control when the firmware is next run.
2169 */
cs_dsp_ctl_cache_sync_write_while_running(struct kunit * test)2170 static void cs_dsp_ctl_cache_sync_write_while_running(struct kunit *test)
2171 {
2172 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2173 struct cs_dsp_test *priv = test->priv;
2174 struct cs_dsp_test_local *local = priv->local;
2175 struct cs_dsp *dsp = priv->dsp;
2176 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2177 int alg_idx = _find_alg_entry(test, param->alg_id);
2178 unsigned int reg, alg_base_words;
2179 struct cs_dsp_coeff_ctl *ctl;
2180 struct firmware *wmfw;
2181 u32 *init_vals, *ctl_vals, *readback;
2182
2183 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2184 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2185
2186 ctl_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2187 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2188
2189 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2190 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2191
2192 /* Zero-fill the registers backing the control */
2193 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2194 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2195 reg += (alg_base_words + param->offs_words) *
2196 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2197 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2198
2199 /* Create control pointing to this data */
2200 def.flags = param->flags;
2201 def.mem_type = param->mem_type;
2202 def.offset_dsp_words = param->offs_words;
2203 def.length_bytes = param->len_bytes;
2204
2205 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2206 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2207 "dummyalg", NULL);
2208 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2209 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2210
2211 /* Power-up DSP and start firmware */
2212 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2213 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2214 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2215 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2216
2217 /* Write new data to the control */
2218 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2219 KUNIT_ASSERT_NOT_NULL(test, ctl);
2220
2221 get_random_bytes(ctl_vals, param->len_bytes);
2222 KUNIT_EXPECT_EQ(test,
2223 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2224 1);
2225
2226 /* Stop firmware and zero the registers backing the control */
2227 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2228 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2229 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2230 KUNIT_EXPECT_MEMEQ(test, readback, init_vals, param->len_bytes);
2231
2232 /* Start the firmware and the cached data should be written to registers */
2233 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2234 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2235
2236 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2237 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2238
2239 /* Control should readback the new data from the control cache */
2240 KUNIT_EXPECT_EQ(test,
2241 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2242 0);
2243 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2244 }
2245
2246 /*
2247 * Write to a cached control after stopping the firmware.
2248 * The value written to the cache should be synced out to the registers
2249 * backing the control when the firmware is next run.
2250 */
cs_dsp_ctl_cache_sync_write_after_stop(struct kunit * test)2251 static void cs_dsp_ctl_cache_sync_write_after_stop(struct kunit *test)
2252 {
2253 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2254 struct cs_dsp_test *priv = test->priv;
2255 struct cs_dsp_test_local *local = priv->local;
2256 struct cs_dsp *dsp = priv->dsp;
2257 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2258 int alg_idx = _find_alg_entry(test, param->alg_id);
2259 unsigned int reg, alg_base_words;
2260 struct cs_dsp_coeff_ctl *ctl;
2261 struct firmware *wmfw;
2262 u32 *reg_vals, *readback;
2263
2264 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2265 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2266
2267 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2268 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2269
2270 /* Create some DSP data to be read into the control cache */
2271 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2272 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2273 reg += (alg_base_words + param->offs_words) *
2274 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2275 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2276
2277 /* Create control pointing to this data */
2278 def.flags = param->flags;
2279 def.mem_type = param->mem_type;
2280 def.offset_dsp_words = param->offs_words;
2281 def.length_bytes = param->len_bytes;
2282
2283 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2284 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2285 "dummyalg", NULL);
2286 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2287 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2288
2289 /* Power-up DSP but don't start firmware */
2290 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2291 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2292
2293 /* Start and stop the firmware */
2294 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2295 cs_dsp_stop(dsp);
2296
2297 /* Write new data to the control, it should not be written to the registers */
2298 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2299 KUNIT_ASSERT_NOT_NULL(test, ctl);
2300
2301 get_random_bytes(reg_vals, param->len_bytes);
2302 KUNIT_EXPECT_EQ(test,
2303 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2304 1);
2305
2306 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2307 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2308
2309 /* Start the firmware and the cached data should be written to registers */
2310 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2311 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2312
2313 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2314 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2315
2316 /* Control should readback the new data from the control cache */
2317 KUNIT_EXPECT_EQ(test,
2318 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2319 0);
2320 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2321 }
2322
2323 /*
2324 * Write to a cached control that is not in the currently loaded firmware.
2325 * The value written to the cache should be synced out to the registers
2326 * backing the control the next time the firmware containing the
2327 * control is run.
2328 */
cs_dsp_ctl_cache_sync_write_not_current_fw(struct kunit * test)2329 static void cs_dsp_ctl_cache_sync_write_not_current_fw(struct kunit *test)
2330 {
2331 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2332 struct cs_dsp_test *priv = test->priv;
2333 struct cs_dsp_test_local *local = priv->local;
2334 struct cs_dsp *dsp = priv->dsp;
2335 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2336 int alg_idx = _find_alg_entry(test, param->alg_id);
2337 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2338 unsigned int reg, alg_base_words;
2339 struct cs_dsp_coeff_ctl *ctl;
2340 struct firmware *wmfw;
2341 u32 *reg_vals, *readback;
2342
2343 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2344 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2345
2346 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2347 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2348
2349 /* Create some DSP data to be read into the control cache */
2350 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2351 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2352 reg += (alg_base_words + param->offs_words) *
2353 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2354 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2355
2356 /* Create control pointing to this data */
2357 def.flags = param->flags;
2358 def.mem_type = param->mem_type;
2359 def.offset_dsp_words = param->offs_words;
2360 def.length_bytes = param->len_bytes;
2361
2362 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2363 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2364 "dummyalg", NULL);
2365 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2366 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2367
2368 /* Power-up DSP but don't start firmware */
2369 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2370 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2371
2372 /* Get the control */
2373 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2374 KUNIT_ASSERT_NOT_NULL(test, ctl);
2375
2376 /* Power-down DSP then power-up with a different firmware */
2377 cs_dsp_power_down(dsp);
2378 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2379 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2380
2381 /* Write new data to the control, it should not be written to the registers */
2382 get_random_bytes(reg_vals, param->len_bytes);
2383 KUNIT_EXPECT_EQ(test,
2384 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2385 1);
2386
2387 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2388 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2389
2390 /* Power-down DSP then power-up with the original firmware */
2391 cs_dsp_power_down(dsp);
2392 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2393 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2394
2395 /* Start the firmware and the cached data should be written to registers */
2396 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2397 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2398
2399 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2400 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2401
2402 /* Control should readback the new data from the control cache */
2403 KUNIT_EXPECT_EQ(test,
2404 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2405 0);
2406 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2407 }
2408
2409 /*
2410 * The value in the control cache should be synced out to the registers
2411 * backing the control every time the firmware containing the control
2412 * is run.
2413 */
cs_dsp_ctl_cache_sync_reapply_every_run(struct kunit * test)2414 static void cs_dsp_ctl_cache_sync_reapply_every_run(struct kunit *test)
2415 {
2416 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2417 struct cs_dsp_test *priv = test->priv;
2418 struct cs_dsp_test_local *local = priv->local;
2419 struct cs_dsp *dsp = priv->dsp;
2420 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2421 int alg_idx = _find_alg_entry(test, param->alg_id);
2422 unsigned int reg, alg_base_words;
2423 struct cs_dsp_coeff_ctl *ctl;
2424 struct firmware *wmfw;
2425 u32 *init_vals, *readback, *ctl_vals;
2426
2427 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2428 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2429
2430 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2431 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2432
2433 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2434 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2435
2436 /* Zero-fill the registers backing the control */
2437 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2438 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2439 reg += (alg_base_words + param->offs_words) *
2440 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2441 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2442
2443 /* Create control pointing to this data */
2444 def.flags = param->flags;
2445 def.mem_type = param->mem_type;
2446 def.offset_dsp_words = param->offs_words;
2447 def.length_bytes = param->len_bytes;
2448
2449 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2450 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2451 "dummyalg", NULL);
2452 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2453 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2454
2455 /* Power-up DSP but don't start firmware */
2456 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2457 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2458
2459 /* Write new data to the control */
2460 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2461 KUNIT_ASSERT_NOT_NULL(test, ctl);
2462
2463 get_random_bytes(ctl_vals, param->len_bytes);
2464 KUNIT_EXPECT_EQ(test,
2465 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2466 1);
2467
2468 /* Start the firmware and the cached data should be written to registers */
2469 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2470 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2471 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2472 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2473
2474 /* Stop the firmware and reset the registers */
2475 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2476 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2477
2478 /* Start the firmware again and the cached data should be written to registers */
2479 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2480 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2481 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2482 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2483
2484 /* Control should readback the new data from the control cache */
2485 KUNIT_EXPECT_EQ(test,
2486 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2487 0);
2488 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2489 }
2490
2491 /*
2492 * The value in the control cache should be retained if the same
2493 * firmware is downloaded again. It should be synced out to the
2494 * registers backing the control after the firmware containing the
2495 * control is downloaded again and run.
2496 */
cs_dsp_ctl_cache_sync_reapply_after_fw_reload(struct kunit * test)2497 static void cs_dsp_ctl_cache_sync_reapply_after_fw_reload(struct kunit *test)
2498 {
2499 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2500 struct cs_dsp_test *priv = test->priv;
2501 struct cs_dsp_test_local *local = priv->local;
2502 struct cs_dsp *dsp = priv->dsp;
2503 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2504 int alg_idx = _find_alg_entry(test, param->alg_id);
2505 unsigned int reg, alg_base_words;
2506 struct cs_dsp_coeff_ctl *ctl;
2507 struct firmware *wmfw;
2508 u32 *init_vals, *readback, *ctl_vals;
2509
2510 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2511 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2512
2513 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2514 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2515
2516 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2517 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2518
2519 /* Zero-fill the registers backing the control */
2520 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2521 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2522 reg += (alg_base_words + param->offs_words) *
2523 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2524 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2525
2526 /* Create control pointing to this data */
2527 def.flags = param->flags;
2528 def.mem_type = param->mem_type;
2529 def.offset_dsp_words = param->offs_words;
2530 def.length_bytes = param->len_bytes;
2531
2532 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2533 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2534 "dummyalg", NULL);
2535 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2536 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2537
2538 /* Power-up DSP but don't start firmware */
2539 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2540 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2541
2542 /* Write new data to the control */
2543 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2544 KUNIT_ASSERT_NOT_NULL(test, ctl);
2545
2546 get_random_bytes(ctl_vals, param->len_bytes);
2547 KUNIT_EXPECT_EQ(test,
2548 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2549 1);
2550
2551 /* Start the firmware and the cached data should be written to registers */
2552 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2553 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2554 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2555 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2556
2557 /* Stop the firmware and power-down the DSP */
2558 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2559 cs_dsp_power_down(dsp);
2560
2561 /* Reset the registers */
2562 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2563
2564 /* Download the firmware again, the cache content should not change */
2565 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2566
2567 /* Start the firmware and the cached data should be written to registers */
2568 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2569 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2570 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2571 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2572
2573 /* Control should readback the new data from the control cache */
2574 KUNIT_EXPECT_EQ(test,
2575 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2576 0);
2577 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2578 }
2579
2580 /*
2581 * The value in the control cache should be retained after a different
2582 * firmware is downloaded.
2583 * When the firmware containing the control is downloaded and run
2584 * the value in the control cache should be synced out to the registers
2585 * backing the control.
2586 */
cs_dsp_ctl_cache_sync_reapply_after_fw_swap(struct kunit * test)2587 static void cs_dsp_ctl_cache_sync_reapply_after_fw_swap(struct kunit *test)
2588 {
2589 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2590 struct cs_dsp_test *priv = test->priv;
2591 struct cs_dsp_test_local *local = priv->local;
2592 struct cs_dsp *dsp = priv->dsp;
2593 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2594 int alg_idx = _find_alg_entry(test, param->alg_id);
2595 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2596 unsigned int reg, alg_base_words;
2597 struct cs_dsp_coeff_ctl *ctl;
2598 struct firmware *wmfw;
2599 u32 *init_vals, *readback, *ctl_vals;
2600
2601 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2602 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2603
2604 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2605 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2606
2607 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2608 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2609
2610 /* Zero-fill the registers backing the control */
2611 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2612 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2613 reg += (alg_base_words + param->offs_words) *
2614 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2615 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2616
2617 /* Create control pointing to this data */
2618 def.flags = param->flags;
2619 def.mem_type = param->mem_type;
2620 def.offset_dsp_words = param->offs_words;
2621 def.length_bytes = param->len_bytes;
2622
2623 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2624 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2625 "dummyalg", NULL);
2626 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2627 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2628
2629 /* Power-up DSP but don't start firmware */
2630 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2631 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2632
2633 /* Write new data to the control */
2634 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2635 KUNIT_ASSERT_NOT_NULL(test, ctl);
2636
2637 get_random_bytes(ctl_vals, param->len_bytes);
2638 KUNIT_EXPECT_EQ(test,
2639 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2640 1);
2641
2642 /* Start the firmware and the cached data should be written to registers */
2643 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2644 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2645 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2646 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2647
2648 /* Stop the firmware and power-down the DSP */
2649 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2650 cs_dsp_power_down(dsp);
2651
2652 /* Reset the registers */
2653 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2654
2655 /* Download and run a different firmware */
2656 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2657 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2658 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2659 cs_dsp_power_down(dsp);
2660
2661 /* Reset the registers */
2662 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2663
2664 /* Download the original firmware again */
2665 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2666 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2667 KUNIT_EXPECT_TRUE(test, ctl->set);
2668
2669 /* Start the firmware and the cached data should be written to registers */
2670 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2671 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2672 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2673 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2674
2675 /* Control should readback the new data from the control cache */
2676 KUNIT_EXPECT_EQ(test,
2677 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2678 0);
2679 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2680 }
2681
cs_dsp_ctl_cache_test_common_init(struct kunit * test,struct cs_dsp * dsp,int wmfw_version)2682 static int cs_dsp_ctl_cache_test_common_init(struct kunit *test, struct cs_dsp *dsp,
2683 int wmfw_version)
2684 {
2685 struct cs_dsp_test *priv;
2686 struct cs_dsp_test_local *local;
2687 struct device *test_dev;
2688 int ret;
2689
2690 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
2691 if (!priv)
2692 return -ENOMEM;
2693
2694 local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
2695 if (!local)
2696 return -ENOMEM;
2697
2698 priv->test = test;
2699 priv->dsp = dsp;
2700 test->priv = priv;
2701 priv->local = local;
2702 priv->local->wmfw_version = wmfw_version;
2703
2704 /* Create dummy struct device */
2705 test_dev = kunit_device_register(test, "cs_dsp_test_drv");
2706 if (IS_ERR(test_dev))
2707 return PTR_ERR(test_dev);
2708
2709 dsp->dev = get_device(test_dev);
2710 if (!dsp->dev)
2711 return -ENODEV;
2712
2713 ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
2714 if (ret)
2715 return ret;
2716
2717 dev_set_drvdata(dsp->dev, priv);
2718
2719 /* Allocate regmap */
2720 ret = cs_dsp_mock_regmap_init(priv);
2721 if (ret)
2722 return ret;
2723
2724 /*
2725 * There must always be a XM header with at least 1 algorithm, so create
2726 * a dummy one that tests can use and extract it to a data blob.
2727 */
2728 local->xm_header = cs_dsp_create_mock_xm_header(priv,
2729 cs_dsp_ctl_cache_test_algs,
2730 ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
2731 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
2732
2733 /* Create wmfw builder */
2734 local->wmfw_builder = _create_dummy_wmfw(test);
2735
2736 /* Init cs_dsp */
2737 dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
2738 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
2739
2740 switch (dsp->type) {
2741 case WMFW_ADSP2:
2742 ret = cs_dsp_adsp2_init(dsp);
2743 break;
2744 case WMFW_HALO:
2745 ret = cs_dsp_halo_init(dsp);
2746 break;
2747 default:
2748 KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
2749 return -EINVAL;
2750 }
2751
2752 if (ret)
2753 return ret;
2754
2755 /* Automatically call cs_dsp_remove() when test case ends */
2756 return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
2757 }
2758
cs_dsp_ctl_cache_test_halo_init(struct kunit * test)2759 static int cs_dsp_ctl_cache_test_halo_init(struct kunit *test)
2760 {
2761 struct cs_dsp *dsp;
2762
2763 /* Fill in cs_dsp and initialize */
2764 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2765 if (!dsp)
2766 return -ENOMEM;
2767
2768 dsp->num = 1;
2769 dsp->type = WMFW_HALO;
2770 dsp->mem = cs_dsp_mock_halo_dsp1_regions;
2771 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
2772 dsp->base = cs_dsp_mock_halo_core_base;
2773 dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
2774
2775 return cs_dsp_ctl_cache_test_common_init(test, dsp, 3);
2776 }
2777
cs_dsp_ctl_cache_test_adsp2_32bit_init(struct kunit * test,int wmfw_ver)2778 static int cs_dsp_ctl_cache_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
2779 {
2780 struct cs_dsp *dsp;
2781
2782 /* Fill in cs_dsp and initialize */
2783 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2784 if (!dsp)
2785 return -ENOMEM;
2786
2787 dsp->num = 1;
2788 dsp->type = WMFW_ADSP2;
2789 dsp->rev = 1;
2790 dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
2791 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
2792 dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
2793
2794 return cs_dsp_ctl_cache_test_common_init(test, dsp, wmfw_ver);
2795 }
2796
cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init(struct kunit * test)2797 static int cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init(struct kunit *test)
2798 {
2799 return cs_dsp_ctl_cache_test_adsp2_32bit_init(test, 1);
2800 }
2801
cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init(struct kunit * test)2802 static int cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init(struct kunit *test)
2803 {
2804 return cs_dsp_ctl_cache_test_adsp2_32bit_init(test, 2);
2805 }
2806
cs_dsp_ctl_cache_test_adsp2_16bit_init(struct kunit * test,int wmfw_ver)2807 static int cs_dsp_ctl_cache_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
2808 {
2809 struct cs_dsp *dsp;
2810
2811 /* Fill in cs_dsp and initialize */
2812 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2813 if (!dsp)
2814 return -ENOMEM;
2815
2816 dsp->num = 1;
2817 dsp->type = WMFW_ADSP2;
2818 dsp->rev = 0;
2819 dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
2820 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
2821 dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
2822
2823 return cs_dsp_ctl_cache_test_common_init(test, dsp, wmfw_ver);
2824 }
2825
cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init(struct kunit * test)2826 static int cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init(struct kunit *test)
2827 {
2828 return cs_dsp_ctl_cache_test_adsp2_16bit_init(test, 1);
2829 }
2830
cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init(struct kunit * test)2831 static int cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init(struct kunit *test)
2832 {
2833 return cs_dsp_ctl_cache_test_adsp2_16bit_init(test, 2);
2834 }
2835
cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_cache_test_param * param,char * desc)2836 static void cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_cache_test_param *param,
2837 char *desc)
2838 {
2839 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg:%#x %s@%u len:%u flags:%#x",
2840 param->alg_id, cs_dsp_mem_region_name(param->mem_type),
2841 param->offs_words, param->len_bytes, param->flags);
2842 }
2843
2844 /* All parameters populated, with various lengths */
2845 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_len_cases[] = {
2846 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2847 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 8 },
2848 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 12 },
2849 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 16 },
2850 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 48 },
2851 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 100 },
2852 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512 },
2853 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 1000 },
2854 };
2855 KUNIT_ARRAY_PARAM(all_pop_varying_len, all_pop_varying_len_cases,
2856 cs_dsp_ctl_all_param_desc);
2857
2858 /* All parameters populated, with various offsets */
2859 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_offset_cases[] = {
2860 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 0, .len_bytes = 4 },
2861 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2862 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 2, .len_bytes = 4 },
2863 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 3, .len_bytes = 4 },
2864 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 8, .len_bytes = 4 },
2865 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 10, .len_bytes = 4 },
2866 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 128, .len_bytes = 4 },
2867 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 180, .len_bytes = 4 },
2868 };
2869 KUNIT_ARRAY_PARAM(all_pop_varying_offset, all_pop_varying_offset_cases,
2870 cs_dsp_ctl_all_param_desc);
2871
2872 /* All parameters populated, with various X and Y memory regions */
2873 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_xy_cases[] = {
2874 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_XM, .offs_words = 1, .len_bytes = 4 },
2875 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2876 };
2877 KUNIT_ARRAY_PARAM(all_pop_varying_xy, all_pop_varying_xy_cases,
2878 cs_dsp_ctl_all_param_desc);
2879
2880 /* All parameters populated, using ZM */
2881 static const struct cs_dsp_ctl_cache_test_param all_pop_z_cases[] = {
2882 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_ZM, .offs_words = 1, .len_bytes = 4 },
2883 };
2884 KUNIT_ARRAY_PARAM(all_pop_z, all_pop_z_cases, cs_dsp_ctl_all_param_desc);
2885
2886 /* All parameters populated, with various algorithm ids */
2887 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_alg_cases[] = {
2888 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2889 { .alg_id = 0xb, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2890 { .alg_id = 0x9f1234, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2891 { .alg_id = 0xff00ff, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2892 };
2893 KUNIT_ARRAY_PARAM(all_pop_varying_alg, all_pop_varying_alg_cases,
2894 cs_dsp_ctl_all_param_desc);
2895
2896 /*
2897 * All parameters populated, with all combinations of flags for a
2898 * non-volatile readable control
2899 */
2900 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_readable_flags_cases[] = {
2901 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2902 .flags = 0
2903 },
2904 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2905 .flags = WMFW_CTL_FLAG_READABLE,
2906 },
2907 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2908 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2909 },
2910 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2911 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2912 },
2913 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2914 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2915 },
2916 };
2917 KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_flags,
2918 all_pop_nonvol_readable_flags_cases,
2919 cs_dsp_ctl_all_param_desc);
2920
2921 /*
2922 * All parameters populated, with all combinations of flags for a
2923 * non-volatile readable control, except flags==0
2924 */
2925 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_readable_nonzero_flags_cases[] = {
2926 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2927 .flags = WMFW_CTL_FLAG_READABLE,
2928 },
2929 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2930 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2931 },
2932 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2933 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2934 },
2935 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2936 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2937 },
2938 };
2939 KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_nonzero_flags,
2940 all_pop_nonvol_readable_nonzero_flags_cases,
2941 cs_dsp_ctl_all_param_desc);
2942
2943 /*
2944 * All parameters populated, with all combinations of flags for a
2945 * non-volatile writeable control
2946 */
2947 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_writeable_flags_cases[] = {
2948 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2949 .flags = 0
2950 },
2951 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2952 .flags = WMFW_CTL_FLAG_WRITEABLE,
2953 },
2954 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2955 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2956 },
2957 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2958 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2959 },
2960 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2961 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2962 },
2963 };
2964 KUNIT_ARRAY_PARAM(all_pop_nonvol_writeable_flags,
2965 all_pop_nonvol_writeable_flags_cases,
2966 cs_dsp_ctl_all_param_desc);
2967
2968 /*
2969 * All parameters populated, with all combinations of flags for a
2970 * non-volatile write-only control of varying lengths
2971 */
2972 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_write_only_length_cases[] = {
2973 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2974 .flags = WMFW_CTL_FLAG_WRITEABLE,
2975 },
2976 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512,
2977 .flags = WMFW_CTL_FLAG_WRITEABLE,
2978 },
2979 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2980 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2981 },
2982 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512,
2983 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2984 },
2985 };
2986 KUNIT_ARRAY_PARAM(all_pop_nonvol_write_only_length,
2987 all_pop_nonvol_write_only_length_cases,
2988 cs_dsp_ctl_all_param_desc);
2989
2990 static struct kunit_case cs_dsp_ctl_cache_test_cases_v1[] = {
2991 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
2992 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
2993 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
2994 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_z_gen_params),
2995 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
2996 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
2997
2998 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
2999 all_pop_nonvol_write_only_length_gen_params),
3000
3001 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3002 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3003 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3004 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3005
3006 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3007 all_pop_nonvol_readable_flags_gen_params),
3008 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3009 all_pop_nonvol_readable_flags_gen_params),
3010 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3011 all_pop_nonvol_readable_flags_gen_params),
3012 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3013 all_pop_nonvol_readable_flags_gen_params),
3014 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3015 all_pop_nonvol_readable_flags_gen_params),
3016 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3017 all_pop_nonvol_readable_flags_gen_params),
3018 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3019 all_pop_nonvol_readable_nonzero_flags_gen_params),
3020 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running_zero_flags,
3021 all_pop_varying_len_gen_params),
3022
3023 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3024 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3025 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3026 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_z_gen_params),
3027 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3028 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3029
3030 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3031 all_pop_varying_len_gen_params),
3032 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3033 all_pop_varying_offset_gen_params),
3034 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3035 all_pop_varying_xy_gen_params),
3036 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3037 all_pop_z_gen_params),
3038 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3039 all_pop_varying_alg_gen_params),
3040 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3041 all_pop_nonvol_writeable_flags_gen_params),
3042
3043 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3044 all_pop_nonvol_writeable_flags_gen_params),
3045 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3046 all_pop_nonvol_writeable_flags_gen_params),
3047 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3048 all_pop_nonvol_writeable_flags_gen_params),
3049 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3050 all_pop_nonvol_writeable_flags_gen_params),
3051 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3052 all_pop_nonvol_writeable_flags_gen_params),
3053 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3054 all_pop_nonvol_writeable_flags_gen_params),
3055 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3056 all_pop_nonvol_writeable_flags_gen_params),
3057
3058 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3059 all_pop_nonvol_writeable_flags_gen_params),
3060 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3061 all_pop_nonvol_writeable_flags_gen_params),
3062 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3063 all_pop_nonvol_writeable_flags_gen_params),
3064 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3065 all_pop_nonvol_writeable_flags_gen_params),
3066 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3067 all_pop_nonvol_writeable_flags_gen_params),
3068 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3069 all_pop_nonvol_writeable_flags_gen_params),
3070 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3071 all_pop_nonvol_writeable_flags_gen_params),
3072
3073 { } /* terminator */
3074 };
3075
3076 static struct kunit_case cs_dsp_ctl_cache_test_cases_v2[] = {
3077 KUNIT_CASE(cs_dsp_ctl_v2_cache_alloc),
3078
3079 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
3080 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
3081 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
3082 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_z_gen_params),
3083 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
3084 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
3085
3086 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
3087 all_pop_nonvol_write_only_length_gen_params),
3088
3089 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3090 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3091 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3092 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3093 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_offsets),
3094
3095 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3096 all_pop_nonvol_readable_flags_gen_params),
3097 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3098 all_pop_nonvol_readable_flags_gen_params),
3099 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3100 all_pop_nonvol_readable_flags_gen_params),
3101 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3102 all_pop_nonvol_readable_flags_gen_params),
3103 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3104 all_pop_nonvol_readable_flags_gen_params),
3105 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3106 all_pop_nonvol_readable_flags_gen_params),
3107 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3108 all_pop_nonvol_readable_nonzero_flags_gen_params),
3109 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running_zero_flags,
3110 all_pop_varying_len_gen_params),
3111
3112 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3113 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3114 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3115 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_z_gen_params),
3116 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3117 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3118
3119 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3120 all_pop_varying_len_gen_params),
3121 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3122 all_pop_varying_offset_gen_params),
3123 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3124 all_pop_varying_xy_gen_params),
3125 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3126 all_pop_z_gen_params),
3127 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3128 all_pop_varying_alg_gen_params),
3129 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3130 all_pop_nonvol_writeable_flags_gen_params),
3131
3132 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3133 all_pop_nonvol_writeable_flags_gen_params),
3134 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3135 all_pop_nonvol_writeable_flags_gen_params),
3136 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3137 all_pop_nonvol_writeable_flags_gen_params),
3138 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3139 all_pop_nonvol_writeable_flags_gen_params),
3140 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3141 all_pop_nonvol_writeable_flags_gen_params),
3142 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3143 all_pop_nonvol_writeable_flags_gen_params),
3144 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3145 all_pop_nonvol_writeable_flags_gen_params),
3146
3147 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3148 all_pop_nonvol_writeable_flags_gen_params),
3149 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3150 all_pop_nonvol_writeable_flags_gen_params),
3151 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3152 all_pop_nonvol_writeable_flags_gen_params),
3153 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3154 all_pop_nonvol_writeable_flags_gen_params),
3155 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3156 all_pop_nonvol_writeable_flags_gen_params),
3157 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3158 all_pop_nonvol_writeable_flags_gen_params),
3159 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3160 all_pop_nonvol_writeable_flags_gen_params),
3161
3162 { } /* terminator */
3163 };
3164
3165 static struct kunit_case cs_dsp_ctl_cache_test_cases_v3[] = {
3166 KUNIT_CASE(cs_dsp_ctl_v2_cache_alloc),
3167
3168 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
3169 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
3170 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
3171 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
3172 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
3173
3174 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
3175 all_pop_nonvol_write_only_length_gen_params),
3176
3177 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3178 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3179 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3180 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3181 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_offsets),
3182
3183 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3184 all_pop_nonvol_readable_flags_gen_params),
3185 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3186 all_pop_nonvol_readable_flags_gen_params),
3187 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3188 all_pop_nonvol_readable_flags_gen_params),
3189 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3190 all_pop_nonvol_readable_flags_gen_params),
3191 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3192 all_pop_nonvol_readable_flags_gen_params),
3193 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3194 all_pop_nonvol_readable_flags_gen_params),
3195 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3196 all_pop_nonvol_readable_nonzero_flags_gen_params),
3197
3198 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3199 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3200 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3201 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3202 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3203
3204 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3205 all_pop_varying_len_gen_params),
3206 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3207 all_pop_varying_offset_gen_params),
3208 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3209 all_pop_varying_xy_gen_params),
3210 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3211 all_pop_varying_alg_gen_params),
3212 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3213 all_pop_nonvol_writeable_flags_gen_params),
3214
3215 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3216 all_pop_nonvol_writeable_flags_gen_params),
3217 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3218 all_pop_nonvol_writeable_flags_gen_params),
3219 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3220 all_pop_nonvol_writeable_flags_gen_params),
3221 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3222 all_pop_nonvol_writeable_flags_gen_params),
3223 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3224 all_pop_nonvol_writeable_flags_gen_params),
3225 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3226 all_pop_nonvol_writeable_flags_gen_params),
3227 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3228 all_pop_nonvol_writeable_flags_gen_params),
3229
3230 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3231 all_pop_nonvol_writeable_flags_gen_params),
3232 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3233 all_pop_nonvol_writeable_flags_gen_params),
3234 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3235 all_pop_nonvol_writeable_flags_gen_params),
3236 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3237 all_pop_nonvol_writeable_flags_gen_params),
3238 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3239 all_pop_nonvol_writeable_flags_gen_params),
3240 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3241 all_pop_nonvol_writeable_flags_gen_params),
3242 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3243 all_pop_nonvol_writeable_flags_gen_params),
3244
3245 { } /* terminator */
3246 };
3247
3248 static struct kunit_suite cs_dsp_ctl_cache_test_halo = {
3249 .name = "cs_dsp_ctl_cache_wmfwV3_halo",
3250 .init = cs_dsp_ctl_cache_test_halo_init,
3251 .test_cases = cs_dsp_ctl_cache_test_cases_v3,
3252 };
3253
3254 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1 = {
3255 .name = "cs_dsp_ctl_cache_wmfwV1_adsp2_32bit",
3256 .init = cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init,
3257 .test_cases = cs_dsp_ctl_cache_test_cases_v1,
3258 };
3259
3260 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2 = {
3261 .name = "cs_dsp_ctl_cache_wmfwV2_adsp2_32bit",
3262 .init = cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init,
3263 .test_cases = cs_dsp_ctl_cache_test_cases_v2,
3264 };
3265
3266 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1 = {
3267 .name = "cs_dsp_ctl_cache_wmfwV1_adsp2_16bit",
3268 .init = cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init,
3269 .test_cases = cs_dsp_ctl_cache_test_cases_v1,
3270 };
3271
3272 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2 = {
3273 .name = "cs_dsp_ctl_cache_wmfwV2_adsp2_16bit",
3274 .init = cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init,
3275 .test_cases = cs_dsp_ctl_cache_test_cases_v2,
3276 };
3277
3278 kunit_test_suites(&cs_dsp_ctl_cache_test_halo,
3279 &cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1,
3280 &cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2,
3281 &cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1,
3282 &cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2);
3283