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