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.offset_dsp_words = 0;
780 def.shortname = "CtlA";
781 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
782
783 def.offset_dsp_words = 5;
784 def.shortname = "CtlB";
785 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
786
787 def.offset_dsp_words = 8;
788 def.shortname = "CtlC";
789 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
790
791 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
792
793 /* Create random content in the registers backing each control */
794 alg_base_words = _get_alg_mem_base_words(test, 0, def.mem_type);
795 alg_base_reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type);
796 alg_base_reg += alg_base_words * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
797
798 reg = alg_base_reg;
799 regmap_raw_write(dsp->regmap, reg, reg_vals[0], def.length_bytes);
800 reg = alg_base_reg + (5 * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv));
801 regmap_raw_write(dsp->regmap, reg, reg_vals[1], def.length_bytes);
802 reg = alg_base_reg + (8 * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv));
803 regmap_raw_write(dsp->regmap, reg, reg_vals[2], def.length_bytes);
804
805 /* Download, run, stop and power-down the firmware */
806 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
807 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
808 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
809 cs_dsp_stop(dsp);
810 cs_dsp_power_down(dsp);
811
812 /* There should now be 3 controls */
813 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3);
814
815 /*
816 * There's no requirement for the control list to be in any
817 * particular order, so don't assume the order.
818 */
819 for (i = 0; i < ARRAY_SIZE(ctl); i++)
820 ctl[i] = NULL;
821
822 list_for_each_entry(walkctl, &dsp->ctl_list, list) {
823 if (walkctl->offset == 0)
824 ctl[0] = walkctl;
825 if (walkctl->offset == 5)
826 ctl[1] = walkctl;
827 if (walkctl->offset == 8)
828 ctl[2] = walkctl;
829 }
830
831 KUNIT_ASSERT_NOT_NULL(test, ctl[0]);
832 KUNIT_ASSERT_NOT_NULL(test, ctl[1]);
833 KUNIT_ASSERT_NOT_NULL(test, ctl[2]);
834
835 /*
836 * The data should have been populated into the control cache
837 * so should be readable through the control.
838 */
839 KUNIT_EXPECT_EQ(test,
840 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes),
841 0);
842 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes);
843
844 KUNIT_EXPECT_EQ(test,
845 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes),
846 0);
847 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes);
848
849 KUNIT_EXPECT_EQ(test,
850 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback,
851 def.length_bytes),
852 0);
853 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes);
854 }
855
856 /*
857 * Read from a cached control before the firmware is started.
858 * Should return the data in the cache.
859 */
cs_dsp_ctl_cache_read_not_started(struct kunit * test)860 static void cs_dsp_ctl_cache_read_not_started(struct kunit *test)
861 {
862 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
863 struct cs_dsp_test *priv = test->priv;
864 struct cs_dsp_test_local *local = priv->local;
865 struct cs_dsp *dsp = priv->dsp;
866 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
867 int alg_idx = _find_alg_entry(test, param->alg_id);
868 unsigned int reg, alg_base_words;
869 struct cs_dsp_coeff_ctl *ctl;
870 struct firmware *wmfw;
871 u32 *reg_vals, *readback;
872
873 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
874 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
875
876 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
877 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
878
879 /* Create some DSP data to be read into the control cache */
880 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
881 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
882 reg += (alg_base_words + param->offs_words) *
883 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
884 get_random_bytes(reg_vals, param->len_bytes);
885 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
886
887 /* Create control pointing to this data */
888 def.flags = param->flags;
889 def.mem_type = param->mem_type;
890 def.offset_dsp_words = param->offs_words;
891 def.length_bytes = param->len_bytes;
892
893 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
894 cs_dsp_ctl_cache_test_algs[alg_idx].id,
895 "dummyalg", NULL);
896 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
897 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
898
899 /* Power-up DSP but don't start firmware */
900 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
901 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
902
903 /* Drop expected writes and the regmap cache should be clean */
904 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
905 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
906 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
907
908 /* Control should readback the data from the control cache */
909 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
910 KUNIT_ASSERT_NOT_NULL(test, ctl);
911 KUNIT_EXPECT_EQ(test,
912 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
913 0);
914 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
915 }
916
917 /*
918 * Read from a cached control after the firmware has been stopped.
919 * Should return the data in the cache.
920 */
cs_dsp_ctl_cache_read_stopped(struct kunit * test)921 static void cs_dsp_ctl_cache_read_stopped(struct kunit *test)
922 {
923 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
924 struct cs_dsp_test *priv = test->priv;
925 struct cs_dsp_test_local *local = priv->local;
926 struct cs_dsp *dsp = priv->dsp;
927 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
928 int alg_idx = _find_alg_entry(test, param->alg_id);
929 unsigned int reg, alg_base_words;
930 struct cs_dsp_coeff_ctl *ctl;
931 struct firmware *wmfw;
932 u32 *reg_vals, *readback;
933
934 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
935 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
936
937 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
938 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
939
940 /* Create some DSP data to be read into the control cache */
941 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
942 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
943 reg += (alg_base_words + param->offs_words) *
944 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
945 get_random_bytes(reg_vals, param->len_bytes);
946 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
947
948 /* Create control pointing to this data */
949 def.flags = param->flags;
950 def.mem_type = param->mem_type;
951 def.offset_dsp_words = param->offs_words;
952 def.length_bytes = param->len_bytes;
953
954 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
955 cs_dsp_ctl_cache_test_algs[alg_idx].id,
956 "dummyalg", NULL);
957 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
958 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
959
960 /* Power-up DSP */
961 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
962 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
963
964 /* Start and stop the firmware */
965 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
966 cs_dsp_stop(dsp);
967
968 /* Drop expected writes and the regmap cache should be clean */
969 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
970 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
971 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
972
973 /* Control should readback the data from the control cache */
974 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
975 KUNIT_ASSERT_NOT_NULL(test, ctl);
976 KUNIT_EXPECT_EQ(test,
977 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
978 0);
979 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
980 }
981
982 /*
983 * Read from a cached control after the DSP has been powered-up and
984 * then powered-down without running.
985 * Should return the data in the cache.
986 */
cs_dsp_ctl_cache_read_powered_down(struct kunit * test)987 static void cs_dsp_ctl_cache_read_powered_down(struct kunit *test)
988 {
989 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
990 struct cs_dsp_test *priv = test->priv;
991 struct cs_dsp_test_local *local = priv->local;
992 struct cs_dsp *dsp = priv->dsp;
993 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
994 int alg_idx = _find_alg_entry(test, param->alg_id);
995 unsigned int reg, alg_base_words;
996 struct cs_dsp_coeff_ctl *ctl;
997 struct firmware *wmfw;
998 u32 *reg_vals, *readback;
999
1000 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1001 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1002
1003 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1004 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1005
1006 /* Create some DSP data to be read into the control cache */
1007 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1008 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1009 reg += (alg_base_words + param->offs_words) *
1010 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1011 get_random_bytes(reg_vals, param->len_bytes);
1012 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1013
1014 /* Create control pointing to this data */
1015 def.flags = param->flags;
1016 def.mem_type = param->mem_type;
1017 def.offset_dsp_words = param->offs_words;
1018 def.length_bytes = param->len_bytes;
1019
1020 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1021 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1022 "dummyalg", NULL);
1023 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1024 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1025
1026 /* Power-up DSP then power-down */
1027 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1028 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1029 cs_dsp_power_down(dsp);
1030
1031 /* Drop expected writes and the regmap cache should be clean */
1032 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1033 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1034 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1035
1036 /* Control should readback the data from the control cache */
1037 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1038 KUNIT_ASSERT_NOT_NULL(test, ctl);
1039 KUNIT_EXPECT_EQ(test,
1040 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1041 0);
1042 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1043 }
1044
1045 /*
1046 * Read from a cached control after the firmware has been run and
1047 * stopped, then the DSP has been powered-down.
1048 * Should return the data in the cache.
1049 */
cs_dsp_ctl_cache_read_stopped_powered_down(struct kunit * test)1050 static void cs_dsp_ctl_cache_read_stopped_powered_down(struct kunit *test)
1051 {
1052 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1053 struct cs_dsp_test *priv = test->priv;
1054 struct cs_dsp_test_local *local = priv->local;
1055 struct cs_dsp *dsp = priv->dsp;
1056 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1057 int alg_idx = _find_alg_entry(test, param->alg_id);
1058 unsigned int reg, alg_base_words;
1059 struct cs_dsp_coeff_ctl *ctl;
1060 struct firmware *wmfw;
1061 u32 *reg_vals, *readback;
1062
1063 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1064 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1065
1066 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1067 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1068
1069 /* Create some DSP data to be read into the control cache */
1070 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1071 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1072 reg += (alg_base_words + param->offs_words) *
1073 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1074 get_random_bytes(reg_vals, param->len_bytes);
1075 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1076
1077 /* Create control pointing to this data */
1078 def.flags = param->flags;
1079 def.mem_type = param->mem_type;
1080 def.offset_dsp_words = param->offs_words;
1081 def.length_bytes = param->len_bytes;
1082
1083 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1084 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1085 "dummyalg", NULL);
1086 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1087 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1088
1089 /* Power-up DSP */
1090 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1091 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1092
1093 /* Start and stop the firmware then power-down */
1094 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1095 cs_dsp_stop(dsp);
1096 cs_dsp_power_down(dsp);
1097
1098 /* Drop expected writes and the regmap cache should be clean */
1099 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1100 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1101 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1102
1103 /* Control should readback the data from the control cache */
1104 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1105 KUNIT_ASSERT_NOT_NULL(test, ctl);
1106 KUNIT_EXPECT_EQ(test,
1107 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1108 0);
1109 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1110 }
1111
1112 /*
1113 * Read from a cached control when a different firmware is currently
1114 * loaded into the DSP.
1115 * Should return the data in the cache.
1116 */
cs_dsp_ctl_cache_read_not_current_loaded_fw(struct kunit * test)1117 static void cs_dsp_ctl_cache_read_not_current_loaded_fw(struct kunit *test)
1118 {
1119 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1120 struct cs_dsp_test *priv = test->priv;
1121 struct cs_dsp_test_local *local = priv->local;
1122 struct cs_dsp *dsp = priv->dsp;
1123 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1124 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1125 int alg_idx = _find_alg_entry(test, param->alg_id);
1126 unsigned int reg, alg_base_words;
1127 struct cs_dsp_coeff_ctl *ctl;
1128 struct firmware *wmfw;
1129 u32 *reg_vals, *readback;
1130
1131 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1132 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1133
1134 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1135 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1136
1137 /* Create some DSP data to be read into the control cache */
1138 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1139 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1140 reg += (alg_base_words + param->offs_words) *
1141 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1142 get_random_bytes(reg_vals, param->len_bytes);
1143 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1144
1145 /* Create control pointing to this data */
1146 def.flags = param->flags;
1147 def.mem_type = param->mem_type;
1148 def.offset_dsp_words = param->offs_words;
1149 def.length_bytes = param->len_bytes;
1150
1151 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1152 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1153 "dummyalg", NULL);
1154 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1155 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1156
1157 /* Power-up DSP */
1158 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1159 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1160
1161 /* Power-down DSP then power-up with a different firmware */
1162 cs_dsp_power_down(dsp);
1163 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1164 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1165
1166 /* Drop expected writes and the regmap cache should be clean */
1167 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1168 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1169 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1170
1171 /* Control should readback the data from the control cache */
1172 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1173 KUNIT_ASSERT_NOT_NULL(test, ctl);
1174 KUNIT_EXPECT_EQ(test,
1175 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1176 0);
1177 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1178 }
1179
1180 /*
1181 * Read from a cached control when a different firmware is currently
1182 * running.
1183 * Should return the data in the cache.
1184 */
cs_dsp_ctl_cache_read_not_current_running_fw(struct kunit * test)1185 static void cs_dsp_ctl_cache_read_not_current_running_fw(struct kunit *test)
1186 {
1187 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1188 struct cs_dsp_test *priv = test->priv;
1189 struct cs_dsp_test_local *local = priv->local;
1190 struct cs_dsp *dsp = priv->dsp;
1191 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1192 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1193 int alg_idx = _find_alg_entry(test, param->alg_id);
1194 unsigned int reg, alg_base_words;
1195 struct cs_dsp_coeff_ctl *ctl;
1196 struct firmware *wmfw;
1197 u32 *reg_vals, *readback;
1198
1199 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1200 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1201
1202 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1203 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1204
1205 /* Create some DSP data to be read into the control cache */
1206 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1207 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1208 reg += (alg_base_words + param->offs_words) *
1209 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1210 get_random_bytes(reg_vals, param->len_bytes);
1211 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1212
1213 /* Create control pointing to this data */
1214 def.flags = param->flags;
1215 def.mem_type = param->mem_type;
1216 def.offset_dsp_words = param->offs_words;
1217 def.length_bytes = param->len_bytes;
1218
1219 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1220 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1221 "dummyalg", NULL);
1222 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1223 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1224
1225 /* Power-up DSP then power-down */
1226 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1227 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1228 cs_dsp_power_down(dsp);
1229
1230 /* Power-up with a different firmware and run it */
1231 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1232 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1233 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1234 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1235
1236 /* Drop expected writes and the regmap cache should be clean */
1237 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1238 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1239 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1240
1241 /* Control should readback the data from the control cache */
1242 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1243 KUNIT_ASSERT_NOT_NULL(test, ctl);
1244 KUNIT_EXPECT_EQ(test,
1245 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1246 0);
1247 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1248 }
1249
1250 /*
1251 * Read from a cached control with non-zero flags while the firmware is
1252 * running.
1253 * Should return the data in the cache, not from the registers.
1254 */
cs_dsp_ctl_cache_read_running(struct kunit * test)1255 static void cs_dsp_ctl_cache_read_running(struct kunit *test)
1256 {
1257 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1258 struct cs_dsp_test *priv = test->priv;
1259 struct cs_dsp_test_local *local = priv->local;
1260 struct cs_dsp *dsp = priv->dsp;
1261 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1262 int alg_idx = _find_alg_entry(test, param->alg_id);
1263 unsigned int reg, alg_base_words;
1264 struct cs_dsp_coeff_ctl *ctl;
1265 struct firmware *wmfw;
1266 u32 *init_reg_vals, *new_reg_vals, *readback;
1267
1268 init_reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1269 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_reg_vals);
1270
1271 new_reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1272 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_reg_vals);
1273
1274 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1275 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1276
1277 /* Create data in the registers backing the control */
1278 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1279 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1280 reg += (alg_base_words + param->offs_words) *
1281 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1282 get_random_bytes(init_reg_vals, param->len_bytes);
1283 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1284
1285 /* Create control pointing to this data */
1286 def.flags = param->flags;
1287 def.mem_type = param->mem_type;
1288 def.offset_dsp_words = param->offs_words;
1289 def.length_bytes = param->len_bytes;
1290
1291 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1292 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1293 "dummyalg", NULL);
1294 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1295 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1296
1297 /* Power-up DSP */
1298 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1299 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1300
1301 /* Start the firmware running */
1302 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1303 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1304
1305 /*
1306 * Change the values in the registers backing the control then drop
1307 * them from the regmap cache. This allows checking that the control
1308 * read is returning values from the control cache and not accessing
1309 * the registers.
1310 */
1311 KUNIT_ASSERT_EQ(test,
1312 regmap_raw_write(dsp->regmap, reg, new_reg_vals, param->len_bytes),
1313 0);
1314 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1315
1316 /* Control should readback the origin data from its cache */
1317 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1318 KUNIT_ASSERT_NOT_NULL(test, ctl);
1319 KUNIT_EXPECT_EQ(test,
1320 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1321 0);
1322 KUNIT_EXPECT_MEMEQ(test, readback, init_reg_vals, param->len_bytes);
1323
1324 /* Stop and power-down the DSP */
1325 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1326 cs_dsp_power_down(dsp);
1327
1328 /* Control should readback from the cache */
1329 KUNIT_EXPECT_EQ(test,
1330 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1331 0);
1332 KUNIT_EXPECT_MEMEQ(test, readback, init_reg_vals, param->len_bytes);
1333 }
1334
1335 /*
1336 * Read from a cached control with flags == 0 while the firmware is
1337 * running.
1338 * Should behave as volatile and read from the registers.
1339 * (This is for backwards compatibility with old firmware versions)
1340 */
cs_dsp_ctl_cache_read_running_zero_flags(struct kunit * test)1341 static void cs_dsp_ctl_cache_read_running_zero_flags(struct kunit *test)
1342 {
1343 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1344 struct cs_dsp_test *priv = test->priv;
1345 struct cs_dsp_test_local *local = priv->local;
1346 struct cs_dsp *dsp = priv->dsp;
1347 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1348 int alg_idx = _find_alg_entry(test, param->alg_id);
1349 unsigned int reg, alg_base_words;
1350 struct cs_dsp_coeff_ctl *ctl;
1351 struct firmware *wmfw;
1352 u32 *init_reg_vals, *new_reg_vals, *readback;
1353
1354 init_reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1355 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_reg_vals);
1356
1357 new_reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1358 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_reg_vals);
1359
1360 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1361 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1362
1363 /* Zero-fill the registers backing the control */
1364 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1365 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1366 reg += (alg_base_words + param->offs_words) *
1367 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1368 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1369
1370 /* Create control pointing to this data */
1371 def.flags = 0;
1372 def.mem_type = param->mem_type;
1373 def.offset_dsp_words = param->offs_words;
1374 def.length_bytes = param->len_bytes;
1375
1376 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1377 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1378 "dummyalg", NULL);
1379 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1380 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1381
1382 /* Power-up DSP */
1383 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1384 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1385
1386 /* Start the firmware running */
1387 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1388 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1389
1390 /* Change the values in the registers backing the control */
1391 get_random_bytes(new_reg_vals, param->len_bytes);
1392 regmap_raw_write(dsp->regmap, reg, new_reg_vals, param->len_bytes);
1393
1394 /* Control should readback the new data from the registers */
1395 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1396 KUNIT_ASSERT_NOT_NULL(test, ctl);
1397 KUNIT_EXPECT_EQ(test,
1398 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1399 0);
1400 KUNIT_EXPECT_MEMEQ(test, readback, new_reg_vals, param->len_bytes);
1401
1402 /* Stop and power-down the DSP */
1403 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
1404 cs_dsp_power_down(dsp);
1405
1406 /* Change the values in the registers backing the control */
1407 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes);
1408
1409 /* Control should readback from the cache */
1410 KUNIT_EXPECT_EQ(test,
1411 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1412 0);
1413 KUNIT_EXPECT_MEMEQ(test, readback, new_reg_vals, param->len_bytes);
1414 }
1415
1416 /*
1417 * Write to a cached control while the firmware is running.
1418 * This should be a writethrough operation, writing to the cache and
1419 * the registers.
1420 */
cs_dsp_ctl_cache_writethrough(struct kunit * test)1421 static void cs_dsp_ctl_cache_writethrough(struct kunit *test)
1422 {
1423 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1424 struct cs_dsp_test *priv = test->priv;
1425 struct cs_dsp_test_local *local = priv->local;
1426 struct cs_dsp *dsp = priv->dsp;
1427 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1428 int alg_idx = _find_alg_entry(test, param->alg_id);
1429 unsigned int reg, alg_base_words;
1430 struct cs_dsp_coeff_ctl *ctl;
1431 struct firmware *wmfw;
1432 u32 *reg_vals, *readback;
1433
1434 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1435 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1436
1437 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1438 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1439
1440 /* Create some DSP data to be read into the control cache */
1441 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1442 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1443 reg += (alg_base_words + param->offs_words) *
1444 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1445 memset(reg_vals, 0, param->len_bytes);
1446 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1447
1448 /* Create control pointing to this data */
1449 def.flags = param->flags;
1450 def.mem_type = param->mem_type;
1451 def.offset_dsp_words = param->offs_words;
1452 def.length_bytes = param->len_bytes;
1453
1454 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1455 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1456 "dummyalg", NULL);
1457 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1458 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1459
1460 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1461 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1462
1463 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1464 KUNIT_ASSERT_NOT_NULL(test, ctl);
1465
1466 /* Start the firmware and add an action to stop it during cleanup */
1467 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1468 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1469
1470 /* Write new data to the control, it should be written to the registers */
1471 get_random_bytes(reg_vals, param->len_bytes);
1472 KUNIT_EXPECT_EQ(test,
1473 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1474 1);
1475 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1476 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1477 }
1478
1479 /*
1480 * Write unchanged data to a cached control while the firmware is running.
1481 * The control write should return 0 to indicate that the content
1482 * didn't change.
1483 */
cs_dsp_ctl_cache_writethrough_unchanged(struct kunit * test)1484 static void cs_dsp_ctl_cache_writethrough_unchanged(struct kunit *test)
1485 {
1486 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1487 struct cs_dsp_test *priv = test->priv;
1488 struct cs_dsp_test_local *local = priv->local;
1489 struct cs_dsp *dsp = priv->dsp;
1490 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1491 int alg_idx = _find_alg_entry(test, param->alg_id);
1492 unsigned int reg, alg_base_words;
1493 struct cs_dsp_coeff_ctl *ctl;
1494 struct firmware *wmfw;
1495 u32 *reg_vals, *readback;
1496
1497 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1498 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1499
1500 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1501 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1502
1503 /* Create some DSP data to be read into the control cache */
1504 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1505 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1506 reg += (alg_base_words + param->offs_words) *
1507 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1508 get_random_bytes(reg_vals, param->len_bytes);
1509 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1510
1511 /* Create control pointing to this data */
1512 def.flags = param->flags;
1513 def.mem_type = param->mem_type;
1514 def.offset_dsp_words = param->offs_words;
1515 def.length_bytes = param->len_bytes;
1516
1517 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1518 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1519 "dummyalg", NULL);
1520 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1521 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1522
1523 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1524 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1525
1526 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1527 KUNIT_ASSERT_NOT_NULL(test, ctl);
1528
1529 /* Start the firmware and add an action to stop it during cleanup */
1530 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1531 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
1532
1533 /*
1534 * If the control is write-only the cache will have been zero-initialized
1535 * so the first write will always indicate a change.
1536 */
1537 if (def.flags && !(def.flags & WMFW_CTL_FLAG_READABLE)) {
1538 KUNIT_EXPECT_EQ(test,
1539 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1540 param->len_bytes),
1541 1);
1542 }
1543
1544 /*
1545 * Write the same data to the control, cs_dsp_coeff_lock_and_write_ctrl()
1546 * should return 0 to indicate the content didn't change.
1547 */
1548 KUNIT_EXPECT_EQ(test,
1549 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1550 0);
1551 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1552 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1553 }
1554
1555 /*
1556 * Write unchanged data to a cached control while the firmware is not started.
1557 * The control write should return 0 to indicate that the cache content
1558 * didn't change.
1559 */
cs_dsp_ctl_cache_write_unchanged_not_started(struct kunit * test)1560 static void cs_dsp_ctl_cache_write_unchanged_not_started(struct kunit *test)
1561 {
1562 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1563 struct cs_dsp_test *priv = test->priv;
1564 struct cs_dsp_test_local *local = priv->local;
1565 struct cs_dsp *dsp = priv->dsp;
1566 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1567 int alg_idx = _find_alg_entry(test, param->alg_id);
1568 unsigned int reg, alg_base_words;
1569 struct cs_dsp_coeff_ctl *ctl;
1570 struct firmware *wmfw;
1571 u32 *reg_vals, *readback;
1572
1573 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
1574 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1575
1576 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1577 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1578
1579 /* Create some DSP data to be read into the control cache */
1580 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1581 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1582 reg += (alg_base_words + param->offs_words) *
1583 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1584 get_random_bytes(reg_vals, param->len_bytes);
1585 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1586
1587 /* Create control pointing to this data */
1588 def.flags = param->flags;
1589 def.mem_type = param->mem_type;
1590 def.offset_dsp_words = param->offs_words;
1591 def.length_bytes = param->len_bytes;
1592
1593 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1594 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1595 "dummyalg", NULL);
1596 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1597 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1598
1599 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1600 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1601
1602 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1603 KUNIT_ASSERT_NOT_NULL(test, ctl);
1604
1605 /*
1606 * If the control is write-only the cache will have been zero-initialized
1607 * so the first write will always indicate a change.
1608 */
1609 if (def.flags && !(def.flags & WMFW_CTL_FLAG_READABLE)) {
1610 KUNIT_EXPECT_EQ(test,
1611 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals,
1612 param->len_bytes),
1613 1);
1614 }
1615
1616 /*
1617 * Write the same data to the control, cs_dsp_coeff_lock_and_write_ctrl()
1618 * should return 0 to indicate the content didn't change.
1619 */
1620 KUNIT_EXPECT_EQ(test,
1621 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1622 0);
1623 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
1624 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1625 }
1626
1627 /*
1628 * Write to a cached control while the firmware is loaded but not
1629 * started.
1630 * This should write to the cache only.
1631 */
cs_dsp_ctl_cache_write_not_started(struct kunit * test)1632 static void cs_dsp_ctl_cache_write_not_started(struct kunit *test)
1633 {
1634 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1635 struct cs_dsp_test *priv = test->priv;
1636 struct cs_dsp_test_local *local = priv->local;
1637 struct cs_dsp *dsp = priv->dsp;
1638 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1639 int alg_idx = _find_alg_entry(test, param->alg_id);
1640 unsigned int reg, alg_base_words;
1641 struct cs_dsp_coeff_ctl *ctl;
1642 struct firmware *wmfw;
1643 u32 *reg_vals, *readback;
1644
1645 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1646 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1647
1648 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1649 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1650
1651 /* Create some DSP data to be read into the control cache */
1652 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1653 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1654 reg += (alg_base_words + param->offs_words) *
1655 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1656 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1657
1658 /* Create control pointing to this data */
1659 def.flags = param->flags;
1660 def.mem_type = param->mem_type;
1661 def.offset_dsp_words = param->offs_words;
1662 def.length_bytes = param->len_bytes;
1663
1664 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1665 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1666 "dummyalg", NULL);
1667 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1668 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1669
1670 /* Power-up DSP but don't start firmware */
1671 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1672 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1673
1674 /* Drop expected writes and the regmap cache should be clean */
1675 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1676 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1677 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1678
1679 /* Write new data to the control, it should not be written to the registers */
1680 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1681 KUNIT_ASSERT_NOT_NULL(test, ctl);
1682
1683 get_random_bytes(reg_vals, param->len_bytes);
1684 KUNIT_EXPECT_EQ(test,
1685 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1686 1);
1687
1688 /* Registers should not have been written so regmap cache should still be clean */
1689 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1690
1691 /* Control should readback the new data from the control cache */
1692 KUNIT_EXPECT_EQ(test,
1693 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1694 0);
1695 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1696 }
1697
1698 /*
1699 * Write to a cached control after the firmware has been loaded,
1700 * started and stopped.
1701 * This should write to the cache only.
1702 */
cs_dsp_ctl_cache_write_stopped(struct kunit * test)1703 static void cs_dsp_ctl_cache_write_stopped(struct kunit *test)
1704 {
1705 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1706 struct cs_dsp_test *priv = test->priv;
1707 struct cs_dsp_test_local *local = priv->local;
1708 struct cs_dsp *dsp = priv->dsp;
1709 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1710 int alg_idx = _find_alg_entry(test, param->alg_id);
1711 unsigned int reg, alg_base_words;
1712 struct cs_dsp_coeff_ctl *ctl;
1713 struct firmware *wmfw;
1714 u32 *reg_vals, *readback;
1715
1716 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1717 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1718
1719 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1720 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1721
1722 /* Create some DSP data to be read into the control cache */
1723 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1724 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1725 reg += (alg_base_words + param->offs_words) *
1726 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1727 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1728
1729 /* Create control pointing to this data */
1730 def.flags = param->flags;
1731 def.mem_type = param->mem_type;
1732 def.offset_dsp_words = param->offs_words;
1733 def.length_bytes = param->len_bytes;
1734
1735 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1736 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1737 "dummyalg", NULL);
1738 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1739 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1740
1741 /* Power-up DSP */
1742 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1743 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1744
1745 /* Start and stop the firmware */
1746 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1747 cs_dsp_stop(dsp);
1748
1749 /* Drop expected writes and the regmap cache should be clean */
1750 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1751 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1752 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1753
1754 /* Write new data to the control, it should not be written to the registers */
1755 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1756 KUNIT_ASSERT_NOT_NULL(test, ctl);
1757
1758 get_random_bytes(reg_vals, param->len_bytes);
1759 KUNIT_EXPECT_EQ(test,
1760 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1761 1);
1762
1763 /* Registers should not have been written so regmap cache should still be clean */
1764 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1765
1766 /* Control should readback the new data from the control cache */
1767 KUNIT_EXPECT_EQ(test,
1768 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1769 0);
1770 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1771 }
1772
1773 /*
1774 * Write to a cached control after the firmware has been loaded,
1775 * then the DSP powered-down.
1776 * This should write to the cache only.
1777 */
cs_dsp_ctl_cache_write_powered_down(struct kunit * test)1778 static void cs_dsp_ctl_cache_write_powered_down(struct kunit *test)
1779 {
1780 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1781 struct cs_dsp_test *priv = test->priv;
1782 struct cs_dsp_test_local *local = priv->local;
1783 struct cs_dsp *dsp = priv->dsp;
1784 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1785 int alg_idx = _find_alg_entry(test, param->alg_id);
1786 unsigned int reg, alg_base_words;
1787 struct cs_dsp_coeff_ctl *ctl;
1788 struct firmware *wmfw;
1789 u32 *reg_vals, *readback;
1790
1791 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1792 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1793
1794 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1795 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1796
1797 /* Create some DSP data to be read into the control cache */
1798 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1799 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1800 reg += (alg_base_words + param->offs_words) *
1801 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1802 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1803
1804 /* Create control pointing to this data */
1805 def.flags = param->flags;
1806 def.mem_type = param->mem_type;
1807 def.offset_dsp_words = param->offs_words;
1808 def.length_bytes = param->len_bytes;
1809
1810 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1811 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1812 "dummyalg", NULL);
1813 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1814 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1815
1816 /* Power-up DSP then power-down */
1817 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1818 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1819 cs_dsp_power_down(dsp);
1820
1821 /* Drop expected writes and the regmap cache should be clean */
1822 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1823 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1824 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1825
1826 /* Write new data to the control, it should not be written to the registers */
1827 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1828 KUNIT_ASSERT_NOT_NULL(test, ctl);
1829
1830 get_random_bytes(reg_vals, param->len_bytes);
1831 KUNIT_EXPECT_EQ(test,
1832 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1833 1);
1834
1835 /* Registers should not have been written so regmap cache should still be clean */
1836 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1837
1838 /* Control should readback the new data from the control cache */
1839 KUNIT_EXPECT_EQ(test,
1840 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1841 0);
1842 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1843 }
1844
1845 /*
1846 * Write to a cached control after the firmware has been loaded,
1847 * started, stopped, and then the DSP powered-down.
1848 * This should write to the cache only.
1849 */
cs_dsp_ctl_cache_write_stopped_powered_down(struct kunit * test)1850 static void cs_dsp_ctl_cache_write_stopped_powered_down(struct kunit *test)
1851 {
1852 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1853 struct cs_dsp_test *priv = test->priv;
1854 struct cs_dsp_test_local *local = priv->local;
1855 struct cs_dsp *dsp = priv->dsp;
1856 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1857 int alg_idx = _find_alg_entry(test, param->alg_id);
1858 unsigned int reg, alg_base_words;
1859 struct cs_dsp_coeff_ctl *ctl;
1860 struct firmware *wmfw;
1861 u32 *reg_vals, *readback;
1862
1863 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1864 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1865
1866 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1867 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1868
1869 /* Create some DSP data to be read into the control cache */
1870 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1871 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1872 reg += (alg_base_words + param->offs_words) *
1873 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1874 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1875
1876 /* Create control pointing to this data */
1877 def.flags = param->flags;
1878 def.mem_type = param->mem_type;
1879 def.offset_dsp_words = param->offs_words;
1880 def.length_bytes = param->len_bytes;
1881
1882 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1883 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1884 "dummyalg", NULL);
1885 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1886 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1887
1888 /* Power-up DSP */
1889 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1890 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1891
1892 /* Start and stop the firmware then power-down */
1893 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
1894 cs_dsp_stop(dsp);
1895 cs_dsp_power_down(dsp);
1896
1897 /* Drop expected writes and the regmap cache should be clean */
1898 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1899 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1900 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1901
1902 /* Write new data to the control, it should not be written to the registers */
1903 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1904 KUNIT_ASSERT_NOT_NULL(test, ctl);
1905
1906 get_random_bytes(reg_vals, param->len_bytes);
1907 KUNIT_EXPECT_EQ(test,
1908 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1909 1);
1910
1911 /* Registers should not have been written so regmap cache should still be clean */
1912 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1913
1914 /* Control should readback the new data from the control cache */
1915 KUNIT_EXPECT_EQ(test,
1916 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
1917 0);
1918 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
1919 }
1920
1921 /*
1922 * Write to a cached control that is not in the currently loaded firmware.
1923 * This should write to the cache only.
1924 */
cs_dsp_ctl_cache_write_not_current_loaded_fw(struct kunit * test)1925 static void cs_dsp_ctl_cache_write_not_current_loaded_fw(struct kunit *test)
1926 {
1927 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
1928 struct cs_dsp_test *priv = test->priv;
1929 struct cs_dsp_test_local *local = priv->local;
1930 struct cs_dsp *dsp = priv->dsp;
1931 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
1932 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
1933 int alg_idx = _find_alg_entry(test, param->alg_id);
1934 unsigned int reg, alg_base_words;
1935 struct cs_dsp_coeff_ctl *ctl;
1936 struct firmware *wmfw;
1937 u32 *reg_vals, *readback;
1938
1939 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1940 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
1941
1942 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
1943 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
1944
1945 /* Create some DSP data to be read into the control cache */
1946 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
1947 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
1948 reg += (alg_base_words + param->offs_words) *
1949 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
1950 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
1951
1952 /* Create control pointing to this data */
1953 def.flags = param->flags;
1954 def.mem_type = param->mem_type;
1955 def.offset_dsp_words = param->offs_words;
1956 def.length_bytes = param->len_bytes;
1957
1958 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
1959 cs_dsp_ctl_cache_test_algs[alg_idx].id,
1960 "dummyalg", NULL);
1961 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
1962 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
1963
1964 /* Power-up DSP */
1965 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
1966 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
1967
1968 /* Get the control */
1969 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
1970 KUNIT_ASSERT_NOT_NULL(test, ctl);
1971
1972 /* Power-down DSP then power-up with a different firmware */
1973 cs_dsp_power_down(dsp);
1974 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
1975 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
1976
1977 /* Control from unloaded firmware should be disabled */
1978 KUNIT_EXPECT_FALSE(test, ctl->enabled);
1979
1980 /* Drop expected writes and the regmap cache should be clean */
1981 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1982 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
1983 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1984
1985 /*
1986 * It should be possible to write new data to the control from
1987 * the first firmware. But this should not be written to the
1988 * registers.
1989 */
1990 get_random_bytes(reg_vals, param->len_bytes);
1991 KUNIT_EXPECT_EQ(test,
1992 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
1993 1);
1994
1995 /* Registers should not have been written so regmap cache should still be clean */
1996 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1997
1998 /* Control should readback the new data from the control cache */
1999 KUNIT_EXPECT_EQ(test,
2000 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2001 0);
2002 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2003 }
2004
2005 /*
2006 * Write to a cached control that is not in the currently running firmware.
2007 * This should write to the cache only.
2008 */
cs_dsp_ctl_cache_write_not_current_running_fw(struct kunit * test)2009 static void cs_dsp_ctl_cache_write_not_current_running_fw(struct kunit *test)
2010 {
2011 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2012 struct cs_dsp_test *priv = test->priv;
2013 struct cs_dsp_test_local *local = priv->local;
2014 struct cs_dsp *dsp = priv->dsp;
2015 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2016 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2017 int alg_idx = _find_alg_entry(test, param->alg_id);
2018 unsigned int reg, alg_base_words;
2019 struct cs_dsp_coeff_ctl *ctl;
2020 struct firmware *wmfw;
2021 u32 *reg_vals, *readback;
2022
2023 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2024 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2025
2026 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2027 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2028
2029 /* Create some DSP data to be read into the control cache */
2030 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2031 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2032 reg += (alg_base_words + param->offs_words) *
2033 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2034 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2035
2036 /* Create control pointing to this data */
2037 def.flags = param->flags;
2038 def.mem_type = param->mem_type;
2039 def.offset_dsp_words = param->offs_words;
2040 def.length_bytes = param->len_bytes;
2041
2042 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2043 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2044 "dummyalg", NULL);
2045 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2046 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2047
2048 /* Power-up DSP then power-down */
2049 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2050 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2051 cs_dsp_power_down(dsp);
2052
2053 /* Get the control */
2054 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2055 KUNIT_ASSERT_NOT_NULL(test, ctl);
2056
2057 /* Power-up with a different firmware and run it */
2058 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2059 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2060 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2061 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2062
2063 /* Control from unloaded firmware should be disabled */
2064 KUNIT_EXPECT_FALSE(test, ctl->enabled);
2065
2066 /* Drop expected writes and the regmap cache should be clean */
2067 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
2068 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes);
2069 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2070
2071 /*
2072 * It should be possible to write new data to the control from
2073 * the first firmware. But this should not be written to the
2074 * registers.
2075 */
2076 get_random_bytes(reg_vals, param->len_bytes);
2077 KUNIT_EXPECT_EQ(test,
2078 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2079 1);
2080
2081 /* Registers should not have been written so regmap cache should still be clean */
2082 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2083
2084 /* Control should readback the new data from the control cache */
2085 KUNIT_EXPECT_EQ(test,
2086 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2087 0);
2088 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2089 }
2090
2091 /*
2092 * Write to a cached control before running the firmware.
2093 * The value written to the cache should be synced out to the registers
2094 * backing the control when the firmware is run.
2095 */
cs_dsp_ctl_cache_sync_write_before_run(struct kunit * test)2096 static void cs_dsp_ctl_cache_sync_write_before_run(struct kunit *test)
2097 {
2098 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2099 struct cs_dsp_test *priv = test->priv;
2100 struct cs_dsp_test_local *local = priv->local;
2101 struct cs_dsp *dsp = priv->dsp;
2102 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2103 int alg_idx = _find_alg_entry(test, param->alg_id);
2104 unsigned int reg, alg_base_words;
2105 struct cs_dsp_coeff_ctl *ctl;
2106 struct firmware *wmfw;
2107 u32 *reg_vals, *readback;
2108
2109 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2110 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2111
2112 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2113 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2114
2115 /* Create some DSP data to be read into the control cache */
2116 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2117 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2118 reg += (alg_base_words + param->offs_words) *
2119 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2120 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2121
2122 /* Create control pointing to this data */
2123 def.flags = param->flags;
2124 def.mem_type = param->mem_type;
2125 def.offset_dsp_words = param->offs_words;
2126 def.length_bytes = param->len_bytes;
2127
2128 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2129 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2130 "dummyalg", NULL);
2131 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2132 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2133
2134 /* Power-up DSP but don't start firmware */
2135 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2136 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2137
2138 /* Write new data to the control, it should not be written to the registers */
2139 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2140 KUNIT_ASSERT_NOT_NULL(test, ctl);
2141
2142 get_random_bytes(reg_vals, param->len_bytes);
2143 KUNIT_EXPECT_EQ(test,
2144 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2145 1);
2146
2147 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2148 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2149
2150 /* Start the firmware and the cached data should be written to registers */
2151 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2152 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2153
2154 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2155 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2156
2157 /* Control should readback the new data from the control cache */
2158 KUNIT_EXPECT_EQ(test,
2159 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2160 0);
2161 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2162 }
2163
2164 /*
2165 * Write to a cached control while the firmware is running.
2166 * The value written should be synced out to the registers
2167 * backing the control when the firmware is next run.
2168 */
cs_dsp_ctl_cache_sync_write_while_running(struct kunit * test)2169 static void cs_dsp_ctl_cache_sync_write_while_running(struct kunit *test)
2170 {
2171 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2172 struct cs_dsp_test *priv = test->priv;
2173 struct cs_dsp_test_local *local = priv->local;
2174 struct cs_dsp *dsp = priv->dsp;
2175 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2176 int alg_idx = _find_alg_entry(test, param->alg_id);
2177 unsigned int reg, alg_base_words;
2178 struct cs_dsp_coeff_ctl *ctl;
2179 struct firmware *wmfw;
2180 u32 *init_vals, *ctl_vals, *readback;
2181
2182 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2183 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2184
2185 ctl_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2186 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2187
2188 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2189 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2190
2191 /* Zero-fill the registers backing the control */
2192 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2193 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2194 reg += (alg_base_words + param->offs_words) *
2195 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2196 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2197
2198 /* Create control pointing to this data */
2199 def.flags = param->flags;
2200 def.mem_type = param->mem_type;
2201 def.offset_dsp_words = param->offs_words;
2202 def.length_bytes = param->len_bytes;
2203
2204 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2205 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2206 "dummyalg", NULL);
2207 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2208 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2209
2210 /* Power-up DSP and start firmware */
2211 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2212 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2213 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2214 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2215
2216 /* Write new data to the control */
2217 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2218 KUNIT_ASSERT_NOT_NULL(test, ctl);
2219
2220 get_random_bytes(ctl_vals, param->len_bytes);
2221 KUNIT_EXPECT_EQ(test,
2222 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2223 1);
2224
2225 /* Stop firmware and zero the registers backing the control */
2226 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2227 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2228 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2229 KUNIT_EXPECT_MEMEQ(test, readback, init_vals, param->len_bytes);
2230
2231 /* Start the firmware and the cached data should be written to registers */
2232 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2233 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2234
2235 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2236 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2237
2238 /* Control should readback the new data from the control cache */
2239 KUNIT_EXPECT_EQ(test,
2240 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2241 0);
2242 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2243 }
2244
2245 /*
2246 * Write to a cached control after stopping the firmware.
2247 * The value written to the cache should be synced out to the registers
2248 * backing the control when the firmware is next run.
2249 */
cs_dsp_ctl_cache_sync_write_after_stop(struct kunit * test)2250 static void cs_dsp_ctl_cache_sync_write_after_stop(struct kunit *test)
2251 {
2252 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2253 struct cs_dsp_test *priv = test->priv;
2254 struct cs_dsp_test_local *local = priv->local;
2255 struct cs_dsp *dsp = priv->dsp;
2256 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2257 int alg_idx = _find_alg_entry(test, param->alg_id);
2258 unsigned int reg, alg_base_words;
2259 struct cs_dsp_coeff_ctl *ctl;
2260 struct firmware *wmfw;
2261 u32 *reg_vals, *readback;
2262
2263 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2264 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2265
2266 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2267 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2268
2269 /* Create some DSP data to be read into the control cache */
2270 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2271 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2272 reg += (alg_base_words + param->offs_words) *
2273 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2274 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2275
2276 /* Create control pointing to this data */
2277 def.flags = param->flags;
2278 def.mem_type = param->mem_type;
2279 def.offset_dsp_words = param->offs_words;
2280 def.length_bytes = param->len_bytes;
2281
2282 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2283 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2284 "dummyalg", NULL);
2285 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2286 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2287
2288 /* Power-up DSP but don't start firmware */
2289 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2290 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2291
2292 /* Start and stop the firmware */
2293 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2294 cs_dsp_stop(dsp);
2295
2296 /* Write new data to the control, it should not be written to the registers */
2297 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2298 KUNIT_ASSERT_NOT_NULL(test, ctl);
2299
2300 get_random_bytes(reg_vals, param->len_bytes);
2301 KUNIT_EXPECT_EQ(test,
2302 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2303 1);
2304
2305 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2306 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2307
2308 /* Start the firmware and the cached data should be written to registers */
2309 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2310 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2311
2312 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2313 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2314
2315 /* Control should readback the new data from the control cache */
2316 KUNIT_EXPECT_EQ(test,
2317 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2318 0);
2319 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2320 }
2321
2322 /*
2323 * Write to a cached control that is not in the currently loaded firmware.
2324 * The value written to the cache should be synced out to the registers
2325 * backing the control the next time the firmware containing the
2326 * control is run.
2327 */
cs_dsp_ctl_cache_sync_write_not_current_fw(struct kunit * test)2328 static void cs_dsp_ctl_cache_sync_write_not_current_fw(struct kunit *test)
2329 {
2330 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2331 struct cs_dsp_test *priv = test->priv;
2332 struct cs_dsp_test_local *local = priv->local;
2333 struct cs_dsp *dsp = priv->dsp;
2334 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2335 int alg_idx = _find_alg_entry(test, param->alg_id);
2336 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2337 unsigned int reg, alg_base_words;
2338 struct cs_dsp_coeff_ctl *ctl;
2339 struct firmware *wmfw;
2340 u32 *reg_vals, *readback;
2341
2342 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2343 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals);
2344
2345 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2346 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2347
2348 /* Create some DSP data to be read into the control cache */
2349 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2350 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2351 reg += (alg_base_words + param->offs_words) *
2352 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2353 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes);
2354
2355 /* Create control pointing to this data */
2356 def.flags = param->flags;
2357 def.mem_type = param->mem_type;
2358 def.offset_dsp_words = param->offs_words;
2359 def.length_bytes = param->len_bytes;
2360
2361 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2362 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2363 "dummyalg", NULL);
2364 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2365 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2366
2367 /* Power-up DSP but don't start firmware */
2368 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2369 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2370
2371 /* Get the control */
2372 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2373 KUNIT_ASSERT_NOT_NULL(test, ctl);
2374
2375 /* Power-down DSP then power-up with a different firmware */
2376 cs_dsp_power_down(dsp);
2377 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2378 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2379
2380 /* Write new data to the control, it should not be written to the registers */
2381 get_random_bytes(reg_vals, param->len_bytes);
2382 KUNIT_EXPECT_EQ(test,
2383 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes),
2384 1);
2385
2386 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2387 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes);
2388
2389 /* Power-down DSP then power-up with the original firmware */
2390 cs_dsp_power_down(dsp);
2391 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2392 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2393
2394 /* Start the firmware and the cached data should be written to registers */
2395 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2396 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2397
2398 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2399 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2400
2401 /* Control should readback the new data from the control cache */
2402 KUNIT_EXPECT_EQ(test,
2403 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2404 0);
2405 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes);
2406 }
2407
2408 /*
2409 * The value in the control cache should be synced out to the registers
2410 * backing the control every time the firmware containing the control
2411 * is run.
2412 */
cs_dsp_ctl_cache_sync_reapply_every_run(struct kunit * test)2413 static void cs_dsp_ctl_cache_sync_reapply_every_run(struct kunit *test)
2414 {
2415 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2416 struct cs_dsp_test *priv = test->priv;
2417 struct cs_dsp_test_local *local = priv->local;
2418 struct cs_dsp *dsp = priv->dsp;
2419 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2420 int alg_idx = _find_alg_entry(test, param->alg_id);
2421 unsigned int reg, alg_base_words;
2422 struct cs_dsp_coeff_ctl *ctl;
2423 struct firmware *wmfw;
2424 u32 *init_vals, *readback, *ctl_vals;
2425
2426 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2427 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2428
2429 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2430 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2431
2432 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2433 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2434
2435 /* Zero-fill the registers backing the control */
2436 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2437 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2438 reg += (alg_base_words + param->offs_words) *
2439 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2440 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2441
2442 /* Create control pointing to this data */
2443 def.flags = param->flags;
2444 def.mem_type = param->mem_type;
2445 def.offset_dsp_words = param->offs_words;
2446 def.length_bytes = param->len_bytes;
2447
2448 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2449 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2450 "dummyalg", NULL);
2451 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2452 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2453
2454 /* Power-up DSP but don't start firmware */
2455 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2456 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2457
2458 /* Write new data to the control */
2459 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2460 KUNIT_ASSERT_NOT_NULL(test, ctl);
2461
2462 get_random_bytes(ctl_vals, param->len_bytes);
2463 KUNIT_EXPECT_EQ(test,
2464 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2465 1);
2466
2467 /* Start the firmware and the cached data should be written to registers */
2468 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2469 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2470 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2471 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2472
2473 /* Stop the firmware and reset the registers */
2474 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2475 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2476
2477 /* Start the firmware again and the cached data should be written to registers */
2478 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2479 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2480 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2481 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2482
2483 /* Control should readback the new data from the control cache */
2484 KUNIT_EXPECT_EQ(test,
2485 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2486 0);
2487 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2488 }
2489
2490 /*
2491 * The value in the control cache should be retained if the same
2492 * firmware is downloaded again. It should be synced out to the
2493 * registers backing the control after the firmware containing the
2494 * control is downloaded again and run.
2495 */
cs_dsp_ctl_cache_sync_reapply_after_fw_reload(struct kunit * test)2496 static void cs_dsp_ctl_cache_sync_reapply_after_fw_reload(struct kunit *test)
2497 {
2498 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2499 struct cs_dsp_test *priv = test->priv;
2500 struct cs_dsp_test_local *local = priv->local;
2501 struct cs_dsp *dsp = priv->dsp;
2502 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2503 int alg_idx = _find_alg_entry(test, param->alg_id);
2504 unsigned int reg, alg_base_words;
2505 struct cs_dsp_coeff_ctl *ctl;
2506 struct firmware *wmfw;
2507 u32 *init_vals, *readback, *ctl_vals;
2508
2509 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2510 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2511
2512 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2513 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2514
2515 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2516 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2517
2518 /* Zero-fill the registers backing the control */
2519 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2520 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2521 reg += (alg_base_words + param->offs_words) *
2522 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2523 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2524
2525 /* Create control pointing to this data */
2526 def.flags = param->flags;
2527 def.mem_type = param->mem_type;
2528 def.offset_dsp_words = param->offs_words;
2529 def.length_bytes = param->len_bytes;
2530
2531 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2532 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2533 "dummyalg", NULL);
2534 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2535 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2536
2537 /* Power-up DSP but don't start firmware */
2538 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2539 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2540
2541 /* Write new data to the control */
2542 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2543 KUNIT_ASSERT_NOT_NULL(test, ctl);
2544
2545 get_random_bytes(ctl_vals, param->len_bytes);
2546 KUNIT_EXPECT_EQ(test,
2547 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2548 1);
2549
2550 /* Start the firmware and the cached data should be written to registers */
2551 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2552 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2553 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2554 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2555
2556 /* Stop the firmware and power-down the DSP */
2557 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2558 cs_dsp_power_down(dsp);
2559
2560 /* Reset the registers */
2561 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2562
2563 /* Download the firmware again, the cache content should not change */
2564 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2565
2566 /* Start the firmware and the cached data should be written to registers */
2567 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2568 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2569 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2570 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2571
2572 /* Control should readback the new data from the control cache */
2573 KUNIT_EXPECT_EQ(test,
2574 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2575 0);
2576 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2577 }
2578
2579 /*
2580 * The value in the control cache should be retained after a different
2581 * firmware is downloaded.
2582 * When the firmware containing the control is downloaded and run
2583 * the value in the control cache should be synced out to the registers
2584 * backing the control.
2585 */
cs_dsp_ctl_cache_sync_reapply_after_fw_swap(struct kunit * test)2586 static void cs_dsp_ctl_cache_sync_reapply_after_fw_swap(struct kunit *test)
2587 {
2588 const struct cs_dsp_ctl_cache_test_param *param = test->param_value;
2589 struct cs_dsp_test *priv = test->priv;
2590 struct cs_dsp_test_local *local = priv->local;
2591 struct cs_dsp *dsp = priv->dsp;
2592 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
2593 int alg_idx = _find_alg_entry(test, param->alg_id);
2594 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test);
2595 unsigned int reg, alg_base_words;
2596 struct cs_dsp_coeff_ctl *ctl;
2597 struct firmware *wmfw;
2598 u32 *init_vals, *readback, *ctl_vals;
2599
2600 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2601 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals);
2602
2603 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL);
2604 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback);
2605
2606 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL);
2607 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals);
2608
2609 /* Zero-fill the registers backing the control */
2610 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type);
2611 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type);
2612 reg += (alg_base_words + param->offs_words) *
2613 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2614 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2615
2616 /* Create control pointing to this data */
2617 def.flags = param->flags;
2618 def.mem_type = param->mem_type;
2619 def.offset_dsp_words = param->offs_words;
2620 def.length_bytes = param->len_bytes;
2621
2622 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
2623 cs_dsp_ctl_cache_test_algs[alg_idx].id,
2624 "dummyalg", NULL);
2625 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
2626 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
2627
2628 /* Power-up DSP but don't start firmware */
2629 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2630 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2631
2632 /* Write new data to the control */
2633 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2634 KUNIT_ASSERT_NOT_NULL(test, ctl);
2635
2636 get_random_bytes(ctl_vals, param->len_bytes);
2637 KUNIT_EXPECT_EQ(test,
2638 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes),
2639 1);
2640
2641 /* Start the firmware and the cached data should be written to registers */
2642 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2643 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2644 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2645 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2646
2647 /* Stop the firmware and power-down the DSP */
2648 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp);
2649 cs_dsp_power_down(dsp);
2650
2651 /* Reset the registers */
2652 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2653
2654 /* Download and run a different firmware */
2655 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2);
2656 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0);
2657 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2658 cs_dsp_power_down(dsp);
2659
2660 /* Reset the registers */
2661 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes);
2662
2663 /* Download the original firmware again */
2664 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2665 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0);
2666 KUNIT_EXPECT_TRUE(test, ctl->set);
2667
2668 /* Start the firmware and the cached data should be written to registers */
2669 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0);
2670 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0);
2671 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0);
2672 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2673
2674 /* Control should readback the new data from the control cache */
2675 KUNIT_EXPECT_EQ(test,
2676 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes),
2677 0);
2678 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes);
2679 }
2680
cs_dsp_ctl_cache_test_common_init(struct kunit * test,struct cs_dsp * dsp,int wmfw_version)2681 static int cs_dsp_ctl_cache_test_common_init(struct kunit *test, struct cs_dsp *dsp,
2682 int wmfw_version)
2683 {
2684 struct cs_dsp_test *priv;
2685 struct cs_dsp_test_local *local;
2686 struct device *test_dev;
2687 int ret;
2688
2689 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
2690 if (!priv)
2691 return -ENOMEM;
2692
2693 local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
2694 if (!local)
2695 return -ENOMEM;
2696
2697 priv->test = test;
2698 priv->dsp = dsp;
2699 test->priv = priv;
2700 priv->local = local;
2701 priv->local->wmfw_version = wmfw_version;
2702
2703 /* Create dummy struct device */
2704 test_dev = kunit_device_register(test, "cs_dsp_test_drv");
2705 if (IS_ERR(test_dev))
2706 return PTR_ERR(test_dev);
2707
2708 dsp->dev = get_device(test_dev);
2709 if (!dsp->dev)
2710 return -ENODEV;
2711
2712 ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
2713 if (ret)
2714 return ret;
2715
2716 dev_set_drvdata(dsp->dev, priv);
2717
2718 /* Allocate regmap */
2719 ret = cs_dsp_mock_regmap_init(priv);
2720 if (ret)
2721 return ret;
2722
2723 /*
2724 * There must always be a XM header with at least 1 algorithm, so create
2725 * a dummy one that tests can use and extract it to a data blob.
2726 */
2727 local->xm_header = cs_dsp_create_mock_xm_header(priv,
2728 cs_dsp_ctl_cache_test_algs,
2729 ARRAY_SIZE(cs_dsp_ctl_cache_test_algs));
2730 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header);
2731
2732 /* Create wmfw builder */
2733 local->wmfw_builder = _create_dummy_wmfw(test);
2734
2735 /* Init cs_dsp */
2736 dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
2737 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
2738
2739 switch (dsp->type) {
2740 case WMFW_ADSP2:
2741 ret = cs_dsp_adsp2_init(dsp);
2742 break;
2743 case WMFW_HALO:
2744 ret = cs_dsp_halo_init(dsp);
2745 break;
2746 default:
2747 KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
2748 return -EINVAL;
2749 }
2750
2751 if (ret)
2752 return ret;
2753
2754 /* Automatically call cs_dsp_remove() when test case ends */
2755 return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
2756 }
2757
cs_dsp_ctl_cache_test_halo_init(struct kunit * test)2758 static int cs_dsp_ctl_cache_test_halo_init(struct kunit *test)
2759 {
2760 struct cs_dsp *dsp;
2761
2762 /* Fill in cs_dsp and initialize */
2763 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2764 if (!dsp)
2765 return -ENOMEM;
2766
2767 dsp->num = 1;
2768 dsp->type = WMFW_HALO;
2769 dsp->mem = cs_dsp_mock_halo_dsp1_regions;
2770 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
2771 dsp->base = cs_dsp_mock_halo_core_base;
2772 dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
2773
2774 return cs_dsp_ctl_cache_test_common_init(test, dsp, 3);
2775 }
2776
cs_dsp_ctl_cache_test_adsp2_32bit_init(struct kunit * test,int wmfw_ver)2777 static int cs_dsp_ctl_cache_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver)
2778 {
2779 struct cs_dsp *dsp;
2780
2781 /* Fill in cs_dsp and initialize */
2782 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2783 if (!dsp)
2784 return -ENOMEM;
2785
2786 dsp->num = 1;
2787 dsp->type = WMFW_ADSP2;
2788 dsp->rev = 1;
2789 dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
2790 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
2791 dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
2792
2793 return cs_dsp_ctl_cache_test_common_init(test, dsp, wmfw_ver);
2794 }
2795
cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init(struct kunit * test)2796 static int cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init(struct kunit *test)
2797 {
2798 return cs_dsp_ctl_cache_test_adsp2_32bit_init(test, 1);
2799 }
2800
cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init(struct kunit * test)2801 static int cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init(struct kunit *test)
2802 {
2803 return cs_dsp_ctl_cache_test_adsp2_32bit_init(test, 2);
2804 }
2805
cs_dsp_ctl_cache_test_adsp2_16bit_init(struct kunit * test,int wmfw_ver)2806 static int cs_dsp_ctl_cache_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver)
2807 {
2808 struct cs_dsp *dsp;
2809
2810 /* Fill in cs_dsp and initialize */
2811 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2812 if (!dsp)
2813 return -ENOMEM;
2814
2815 dsp->num = 1;
2816 dsp->type = WMFW_ADSP2;
2817 dsp->rev = 0;
2818 dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
2819 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
2820 dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
2821
2822 return cs_dsp_ctl_cache_test_common_init(test, dsp, wmfw_ver);
2823 }
2824
cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init(struct kunit * test)2825 static int cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init(struct kunit *test)
2826 {
2827 return cs_dsp_ctl_cache_test_adsp2_16bit_init(test, 1);
2828 }
2829
cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init(struct kunit * test)2830 static int cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init(struct kunit *test)
2831 {
2832 return cs_dsp_ctl_cache_test_adsp2_16bit_init(test, 2);
2833 }
2834
cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_cache_test_param * param,char * desc)2835 static void cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_cache_test_param *param,
2836 char *desc)
2837 {
2838 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg:%#x %s@%u len:%u flags:%#x",
2839 param->alg_id, cs_dsp_mem_region_name(param->mem_type),
2840 param->offs_words, param->len_bytes, param->flags);
2841 }
2842
2843 /* All parameters populated, with various lengths */
2844 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_len_cases[] = {
2845 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2846 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 8 },
2847 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 12 },
2848 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 16 },
2849 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 48 },
2850 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 100 },
2851 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512 },
2852 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 1000 },
2853 };
2854 KUNIT_ARRAY_PARAM(all_pop_varying_len, all_pop_varying_len_cases,
2855 cs_dsp_ctl_all_param_desc);
2856
2857 /* All parameters populated, with various offsets */
2858 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_offset_cases[] = {
2859 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 0, .len_bytes = 4 },
2860 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2861 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 2, .len_bytes = 4 },
2862 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 3, .len_bytes = 4 },
2863 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 8, .len_bytes = 4 },
2864 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 10, .len_bytes = 4 },
2865 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 128, .len_bytes = 4 },
2866 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 180, .len_bytes = 4 },
2867 };
2868 KUNIT_ARRAY_PARAM(all_pop_varying_offset, all_pop_varying_offset_cases,
2869 cs_dsp_ctl_all_param_desc);
2870
2871 /* All parameters populated, with various X and Y memory regions */
2872 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_xy_cases[] = {
2873 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_XM, .offs_words = 1, .len_bytes = 4 },
2874 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2875 };
2876 KUNIT_ARRAY_PARAM(all_pop_varying_xy, all_pop_varying_xy_cases,
2877 cs_dsp_ctl_all_param_desc);
2878
2879 /* All parameters populated, using ZM */
2880 static const struct cs_dsp_ctl_cache_test_param all_pop_z_cases[] = {
2881 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_ZM, .offs_words = 1, .len_bytes = 4 },
2882 };
2883 KUNIT_ARRAY_PARAM(all_pop_z, all_pop_z_cases, cs_dsp_ctl_all_param_desc);
2884
2885 /* All parameters populated, with various algorithm ids */
2886 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_alg_cases[] = {
2887 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2888 { .alg_id = 0xb, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2889 { .alg_id = 0x9f1234, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2890 { .alg_id = 0xff00ff, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 },
2891 };
2892 KUNIT_ARRAY_PARAM(all_pop_varying_alg, all_pop_varying_alg_cases,
2893 cs_dsp_ctl_all_param_desc);
2894
2895 /*
2896 * All parameters populated, with all combinations of flags for a
2897 * non-volatile readable control
2898 */
2899 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_readable_flags_cases[] = {
2900 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2901 .flags = 0
2902 },
2903 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2904 .flags = WMFW_CTL_FLAG_READABLE,
2905 },
2906 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2907 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2908 },
2909 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2910 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2911 },
2912 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2913 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2914 },
2915 };
2916 KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_flags,
2917 all_pop_nonvol_readable_flags_cases,
2918 cs_dsp_ctl_all_param_desc);
2919
2920 /*
2921 * All parameters populated, with all combinations of flags for a
2922 * non-volatile readable control, except flags==0
2923 */
2924 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_readable_nonzero_flags_cases[] = {
2925 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2926 .flags = WMFW_CTL_FLAG_READABLE,
2927 },
2928 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2929 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2930 },
2931 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2932 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE,
2933 },
2934 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2935 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2936 },
2937 };
2938 KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_nonzero_flags,
2939 all_pop_nonvol_readable_nonzero_flags_cases,
2940 cs_dsp_ctl_all_param_desc);
2941
2942 /*
2943 * All parameters populated, with all combinations of flags for a
2944 * non-volatile writeable control
2945 */
2946 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_writeable_flags_cases[] = {
2947 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2948 .flags = 0
2949 },
2950 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2951 .flags = WMFW_CTL_FLAG_WRITEABLE,
2952 },
2953 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2954 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2955 },
2956 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2957 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2958 },
2959 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2960 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE,
2961 },
2962 };
2963 KUNIT_ARRAY_PARAM(all_pop_nonvol_writeable_flags,
2964 all_pop_nonvol_writeable_flags_cases,
2965 cs_dsp_ctl_all_param_desc);
2966
2967 /*
2968 * All parameters populated, with all combinations of flags for a
2969 * non-volatile write-only control of varying lengths
2970 */
2971 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_write_only_length_cases[] = {
2972 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2973 .flags = WMFW_CTL_FLAG_WRITEABLE,
2974 },
2975 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512,
2976 .flags = WMFW_CTL_FLAG_WRITEABLE,
2977 },
2978 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4,
2979 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2980 },
2981 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512,
2982 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE,
2983 },
2984 };
2985 KUNIT_ARRAY_PARAM(all_pop_nonvol_write_only_length,
2986 all_pop_nonvol_write_only_length_cases,
2987 cs_dsp_ctl_all_param_desc);
2988
2989 static struct kunit_case cs_dsp_ctl_cache_test_cases_v1[] = {
2990 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
2991 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
2992 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
2993 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_z_gen_params),
2994 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
2995 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
2996
2997 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
2998 all_pop_nonvol_write_only_length_gen_params),
2999
3000 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3001 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3002 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3003 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3004
3005 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3006 all_pop_nonvol_readable_flags_gen_params),
3007 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3008 all_pop_nonvol_readable_flags_gen_params),
3009 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3010 all_pop_nonvol_readable_flags_gen_params),
3011 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3012 all_pop_nonvol_readable_flags_gen_params),
3013 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3014 all_pop_nonvol_readable_flags_gen_params),
3015 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3016 all_pop_nonvol_readable_flags_gen_params),
3017 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3018 all_pop_nonvol_readable_nonzero_flags_gen_params),
3019 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running_zero_flags,
3020 all_pop_varying_len_gen_params),
3021
3022 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3023 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3024 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3025 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_z_gen_params),
3026 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3027 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3028
3029 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3030 all_pop_varying_len_gen_params),
3031 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3032 all_pop_varying_offset_gen_params),
3033 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3034 all_pop_varying_xy_gen_params),
3035 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3036 all_pop_z_gen_params),
3037 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3038 all_pop_varying_alg_gen_params),
3039 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3040 all_pop_nonvol_writeable_flags_gen_params),
3041
3042 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3043 all_pop_nonvol_writeable_flags_gen_params),
3044 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3045 all_pop_nonvol_writeable_flags_gen_params),
3046 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3047 all_pop_nonvol_writeable_flags_gen_params),
3048 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3049 all_pop_nonvol_writeable_flags_gen_params),
3050 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3051 all_pop_nonvol_writeable_flags_gen_params),
3052 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3053 all_pop_nonvol_writeable_flags_gen_params),
3054 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3055 all_pop_nonvol_writeable_flags_gen_params),
3056
3057 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3058 all_pop_nonvol_writeable_flags_gen_params),
3059 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3060 all_pop_nonvol_writeable_flags_gen_params),
3061 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3062 all_pop_nonvol_writeable_flags_gen_params),
3063 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3064 all_pop_nonvol_writeable_flags_gen_params),
3065 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3066 all_pop_nonvol_writeable_flags_gen_params),
3067 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3068 all_pop_nonvol_writeable_flags_gen_params),
3069 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3070 all_pop_nonvol_writeable_flags_gen_params),
3071
3072 { } /* terminator */
3073 };
3074
3075 static struct kunit_case cs_dsp_ctl_cache_test_cases_v2[] = {
3076 KUNIT_CASE(cs_dsp_ctl_v2_cache_alloc),
3077
3078 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
3079 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
3080 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
3081 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_z_gen_params),
3082 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
3083 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
3084
3085 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
3086 all_pop_nonvol_write_only_length_gen_params),
3087
3088 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3089 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3090 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3091 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3092 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_offsets),
3093
3094 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3095 all_pop_nonvol_readable_flags_gen_params),
3096 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3097 all_pop_nonvol_readable_flags_gen_params),
3098 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3099 all_pop_nonvol_readable_flags_gen_params),
3100 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3101 all_pop_nonvol_readable_flags_gen_params),
3102 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3103 all_pop_nonvol_readable_flags_gen_params),
3104 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3105 all_pop_nonvol_readable_flags_gen_params),
3106 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3107 all_pop_nonvol_readable_nonzero_flags_gen_params),
3108 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running_zero_flags,
3109 all_pop_varying_len_gen_params),
3110
3111 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3112 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3113 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3114 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_z_gen_params),
3115 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3116 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3117
3118 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3119 all_pop_varying_len_gen_params),
3120 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3121 all_pop_varying_offset_gen_params),
3122 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3123 all_pop_varying_xy_gen_params),
3124 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3125 all_pop_z_gen_params),
3126 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3127 all_pop_varying_alg_gen_params),
3128 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3129 all_pop_nonvol_writeable_flags_gen_params),
3130
3131 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3132 all_pop_nonvol_writeable_flags_gen_params),
3133 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3134 all_pop_nonvol_writeable_flags_gen_params),
3135 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3136 all_pop_nonvol_writeable_flags_gen_params),
3137 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3138 all_pop_nonvol_writeable_flags_gen_params),
3139 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3140 all_pop_nonvol_writeable_flags_gen_params),
3141 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3142 all_pop_nonvol_writeable_flags_gen_params),
3143 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3144 all_pop_nonvol_writeable_flags_gen_params),
3145
3146 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3147 all_pop_nonvol_writeable_flags_gen_params),
3148 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3149 all_pop_nonvol_writeable_flags_gen_params),
3150 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3151 all_pop_nonvol_writeable_flags_gen_params),
3152 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3153 all_pop_nonvol_writeable_flags_gen_params),
3154 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3155 all_pop_nonvol_writeable_flags_gen_params),
3156 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3157 all_pop_nonvol_writeable_flags_gen_params),
3158 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3159 all_pop_nonvol_writeable_flags_gen_params),
3160
3161 { } /* terminator */
3162 };
3163
3164 static struct kunit_case cs_dsp_ctl_cache_test_cases_v3[] = {
3165 KUNIT_CASE(cs_dsp_ctl_v2_cache_alloc),
3166
3167 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params),
3168 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params),
3169 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params),
3170 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params),
3171 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params),
3172
3173 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only,
3174 all_pop_nonvol_write_only_length_gen_params),
3175
3176 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls),
3177 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls),
3178 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems),
3179 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs),
3180 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_offsets),
3181
3182 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started,
3183 all_pop_nonvol_readable_flags_gen_params),
3184 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped,
3185 all_pop_nonvol_readable_flags_gen_params),
3186 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down,
3187 all_pop_nonvol_readable_flags_gen_params),
3188 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down,
3189 all_pop_nonvol_readable_flags_gen_params),
3190 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw,
3191 all_pop_nonvol_readable_flags_gen_params),
3192 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw,
3193 all_pop_nonvol_readable_flags_gen_params),
3194 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running,
3195 all_pop_nonvol_readable_nonzero_flags_gen_params),
3196
3197 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params),
3198 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params),
3199 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params),
3200 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params),
3201 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params),
3202
3203 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3204 all_pop_varying_len_gen_params),
3205 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3206 all_pop_varying_offset_gen_params),
3207 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3208 all_pop_varying_xy_gen_params),
3209 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3210 all_pop_varying_alg_gen_params),
3211 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged,
3212 all_pop_nonvol_writeable_flags_gen_params),
3213
3214 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started,
3215 all_pop_nonvol_writeable_flags_gen_params),
3216 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started,
3217 all_pop_nonvol_writeable_flags_gen_params),
3218 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped,
3219 all_pop_nonvol_writeable_flags_gen_params),
3220 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down,
3221 all_pop_nonvol_writeable_flags_gen_params),
3222 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down,
3223 all_pop_nonvol_writeable_flags_gen_params),
3224 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw,
3225 all_pop_nonvol_writeable_flags_gen_params),
3226 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw,
3227 all_pop_nonvol_writeable_flags_gen_params),
3228
3229 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run,
3230 all_pop_nonvol_writeable_flags_gen_params),
3231 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running,
3232 all_pop_nonvol_writeable_flags_gen_params),
3233 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop,
3234 all_pop_nonvol_writeable_flags_gen_params),
3235 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw,
3236 all_pop_nonvol_writeable_flags_gen_params),
3237 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run,
3238 all_pop_nonvol_writeable_flags_gen_params),
3239 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload,
3240 all_pop_nonvol_writeable_flags_gen_params),
3241 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap,
3242 all_pop_nonvol_writeable_flags_gen_params),
3243
3244 { } /* terminator */
3245 };
3246
3247 static struct kunit_suite cs_dsp_ctl_cache_test_halo = {
3248 .name = "cs_dsp_ctl_cache_wmfwV3_halo",
3249 .init = cs_dsp_ctl_cache_test_halo_init,
3250 .test_cases = cs_dsp_ctl_cache_test_cases_v3,
3251 };
3252
3253 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1 = {
3254 .name = "cs_dsp_ctl_cache_wmfwV1_adsp2_32bit",
3255 .init = cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init,
3256 .test_cases = cs_dsp_ctl_cache_test_cases_v1,
3257 };
3258
3259 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2 = {
3260 .name = "cs_dsp_ctl_cache_wmfwV2_adsp2_32bit",
3261 .init = cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init,
3262 .test_cases = cs_dsp_ctl_cache_test_cases_v2,
3263 };
3264
3265 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1 = {
3266 .name = "cs_dsp_ctl_cache_wmfwV1_adsp2_16bit",
3267 .init = cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init,
3268 .test_cases = cs_dsp_ctl_cache_test_cases_v1,
3269 };
3270
3271 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2 = {
3272 .name = "cs_dsp_ctl_cache_wmfwV2_adsp2_16bit",
3273 .init = cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init,
3274 .test_cases = cs_dsp_ctl_cache_test_cases_v2,
3275 };
3276
3277 kunit_test_suites(&cs_dsp_ctl_cache_test_halo,
3278 &cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1,
3279 &cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2,
3280 &cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1,
3281 &cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2);
3282