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
9 #include <kunit/device.h>
10 #include <kunit/resource.h>
11 #include <kunit/test.h>
12 #include <kunit/test-bug.h>
13 #include <linux/build_bug.h>
14 #include <linux/firmware/cirrus/cs_dsp.h>
15 #include <linux/firmware/cirrus/cs_dsp_test_utils.h>
16 #include <linux/firmware/cirrus/wmfw.h>
17 #include <linux/random.h>
18 #include <linux/regmap.h>
19 #include <linux/string.h>
20 #include <linux/vmalloc.h>
21
22 #define ADSP2_LOCK_REGION_CTRL 0x7A
23 #define ADSP2_WDT_TIMEOUT_STS_MASK 0x2000
24
25 KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *)
26 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *)
27
28 struct cs_dsp_test_local {
29 struct cs_dsp_mock_wmfw_builder *wmfw_builder;
30
31 int num_control_add;
32 int num_control_remove;
33 int num_pre_run;
34 int num_post_run;
35 int num_pre_stop;
36 int num_post_stop;
37 int num_watchdog_expired;
38
39 struct cs_dsp_coeff_ctl *passed_ctl[16];
40 struct cs_dsp *passed_dsp;
41 };
42
43 struct cs_dsp_callbacks_test_param {
44 const struct cs_dsp_client_ops *ops;
45 const char *case_name;
46 };
47
48 static const struct cs_dsp_mock_alg_def cs_dsp_callbacks_test_mock_algs[] = {
49 {
50 .id = 0xfafa,
51 .ver = 0x100000,
52 .xm_size_words = 164,
53 .ym_size_words = 164,
54 .zm_size_words = 164,
55 },
56 };
57
58 static const struct cs_dsp_mock_coeff_def mock_coeff_template = {
59 .shortname = "Dummy Coeff",
60 .type = WMFW_CTL_TYPE_BYTES,
61 .mem_type = WMFW_ADSP2_YM,
62 .flags = WMFW_CTL_FLAG_VOLATILE,
63 .length_bytes = 4,
64 };
65
cs_dsp_test_control_add_callback(struct cs_dsp_coeff_ctl * ctl)66 static int cs_dsp_test_control_add_callback(struct cs_dsp_coeff_ctl *ctl)
67 {
68 struct kunit *test = kunit_get_current_test();
69 struct cs_dsp_test *priv = test->priv;
70 struct cs_dsp_test_local *local = priv->local;
71
72 local->passed_ctl[local->num_control_add] = ctl;
73 local->num_control_add++;
74
75 return 0;
76 }
77
cs_dsp_test_control_remove_callback(struct cs_dsp_coeff_ctl * ctl)78 static void cs_dsp_test_control_remove_callback(struct cs_dsp_coeff_ctl *ctl)
79 {
80 struct kunit *test = kunit_get_current_test();
81 struct cs_dsp_test *priv = test->priv;
82 struct cs_dsp_test_local *local = priv->local;
83
84 local->passed_ctl[local->num_control_remove] = ctl;
85 local->num_control_remove++;
86 }
87
cs_dsp_test_pre_run_callback(struct cs_dsp * dsp)88 static int cs_dsp_test_pre_run_callback(struct cs_dsp *dsp)
89 {
90 struct kunit *test = kunit_get_current_test();
91 struct cs_dsp_test *priv = test->priv;
92 struct cs_dsp_test_local *local = priv->local;
93
94 local->passed_dsp = dsp;
95 local->num_pre_run++;
96
97 return 0;
98 }
99
cs_dsp_test_post_run_callback(struct cs_dsp * dsp)100 static int cs_dsp_test_post_run_callback(struct cs_dsp *dsp)
101 {
102 struct kunit *test = kunit_get_current_test();
103 struct cs_dsp_test *priv = test->priv;
104 struct cs_dsp_test_local *local = priv->local;
105
106 local->passed_dsp = dsp;
107 local->num_post_run++;
108
109 return 0;
110 }
111
cs_dsp_test_pre_stop_callback(struct cs_dsp * dsp)112 static void cs_dsp_test_pre_stop_callback(struct cs_dsp *dsp)
113 {
114 struct kunit *test = kunit_get_current_test();
115 struct cs_dsp_test *priv = test->priv;
116 struct cs_dsp_test_local *local = priv->local;
117
118 local->passed_dsp = dsp;
119 local->num_pre_stop++;
120 }
121
cs_dsp_test_post_stop_callback(struct cs_dsp * dsp)122 static void cs_dsp_test_post_stop_callback(struct cs_dsp *dsp)
123 {
124 struct kunit *test = kunit_get_current_test();
125 struct cs_dsp_test *priv = test->priv;
126 struct cs_dsp_test_local *local = priv->local;
127
128 local->passed_dsp = dsp;
129 local->num_post_stop++;
130 }
131
cs_dsp_test_watchdog_expired_callback(struct cs_dsp * dsp)132 static void cs_dsp_test_watchdog_expired_callback(struct cs_dsp *dsp)
133 {
134 struct kunit *test = kunit_get_current_test();
135 struct cs_dsp_test *priv = test->priv;
136 struct cs_dsp_test_local *local = priv->local;
137
138 local->passed_dsp = dsp;
139 local->num_watchdog_expired++;
140 }
141
142 static const struct cs_dsp_client_ops cs_dsp_callback_test_client_ops = {
143 .control_add = cs_dsp_test_control_add_callback,
144 .control_remove = cs_dsp_test_control_remove_callback,
145 .pre_run = cs_dsp_test_pre_run_callback,
146 .post_run = cs_dsp_test_post_run_callback,
147 .pre_stop = cs_dsp_test_pre_stop_callback,
148 .post_stop = cs_dsp_test_post_stop_callback,
149 .watchdog_expired = cs_dsp_test_watchdog_expired_callback,
150 };
151
152 static const struct cs_dsp_client_ops cs_dsp_callback_test_empty_client_ops = {
153 /* No entries */
154 };
155
cs_dsp_test_run_stop_callbacks(struct kunit * test)156 static void cs_dsp_test_run_stop_callbacks(struct kunit *test)
157 {
158 struct cs_dsp_test *priv = test->priv;
159 struct cs_dsp_test_local *local = priv->local;
160 struct firmware *wmfw;
161
162 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
163
164 KUNIT_EXPECT_EQ(test,
165 cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
166 0);
167
168 KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
169 KUNIT_EXPECT_EQ(test, local->num_pre_run, 1);
170 KUNIT_EXPECT_EQ(test, local->num_post_run, 1);
171 KUNIT_EXPECT_EQ(test, local->num_pre_stop, 0);
172 KUNIT_EXPECT_EQ(test, local->num_post_stop, 0);
173 KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
174 local->passed_dsp = NULL;
175
176 cs_dsp_stop(priv->dsp);
177 KUNIT_EXPECT_EQ(test, local->num_pre_run, 1);
178 KUNIT_EXPECT_EQ(test, local->num_post_run, 1);
179 KUNIT_EXPECT_EQ(test, local->num_pre_stop, 1);
180 KUNIT_EXPECT_EQ(test, local->num_post_stop, 1);
181 KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
182 local->passed_dsp = NULL;
183
184 KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
185 KUNIT_EXPECT_EQ(test, local->num_pre_run, 2);
186 KUNIT_EXPECT_EQ(test, local->num_post_run, 2);
187 KUNIT_EXPECT_EQ(test, local->num_pre_stop, 1);
188 KUNIT_EXPECT_EQ(test, local->num_post_stop, 1);
189 KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
190 local->passed_dsp = NULL;
191
192 cs_dsp_stop(priv->dsp);
193 KUNIT_EXPECT_EQ(test, local->num_pre_run, 2);
194 KUNIT_EXPECT_EQ(test, local->num_post_run, 2);
195 KUNIT_EXPECT_EQ(test, local->num_pre_stop, 2);
196 KUNIT_EXPECT_EQ(test, local->num_post_stop, 2);
197 KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
198 local->passed_dsp = NULL;
199 }
200
cs_dsp_test_ctl_v1_callbacks(struct kunit * test)201 static void cs_dsp_test_ctl_v1_callbacks(struct kunit *test)
202 {
203 struct cs_dsp_test *priv = test->priv;
204 struct cs_dsp_test_local *local = priv->local;
205 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
206 struct cs_dsp_coeff_ctl *ctl;
207 struct firmware *wmfw;
208 int i;
209
210 /* Add a control for each memory */
211 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
212 cs_dsp_callbacks_test_mock_algs[0].id,
213 "dummyalg", NULL);
214 def.shortname = "zm";
215 def.mem_type = WMFW_ADSP2_ZM;
216 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
217
218 def.shortname = "ym";
219 def.mem_type = WMFW_ADSP2_YM;
220 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
221
222 def.shortname = "xm";
223 def.mem_type = WMFW_ADSP2_XM;
224 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
225
226 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
227
228 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
229 KUNIT_EXPECT_EQ(test,
230 cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
231 0);
232
233 /* There should have been an add callback for each control */
234 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 3);
235 KUNIT_EXPECT_EQ(test, local->num_control_add, 3);
236 KUNIT_EXPECT_EQ(test, local->num_control_remove, 0);
237
238 i = 0;
239 list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list)
240 KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl);
241
242 /*
243 * Call cs_dsp_remove() and there should be a remove callback
244 * for each control
245 */
246 memset(local->passed_ctl, 0, sizeof(local->passed_ctl));
247 cs_dsp_remove(priv->dsp);
248
249 /* Prevent double cleanup */
250 kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp);
251
252 KUNIT_EXPECT_EQ(test, local->num_control_add, 3);
253 KUNIT_EXPECT_EQ(test, local->num_control_remove, 3);
254
255 i = 0;
256 list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list)
257 KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl);
258 }
259
cs_dsp_test_ctl_v2_callbacks(struct kunit * test)260 static void cs_dsp_test_ctl_v2_callbacks(struct kunit *test)
261 {
262 struct cs_dsp_test *priv = test->priv;
263 struct cs_dsp_test_local *local = priv->local;
264 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
265 struct cs_dsp_coeff_ctl *ctl;
266 struct firmware *wmfw;
267 char name[2] = { };
268 int i;
269
270 /* Add some controls */
271 def.shortname = name;
272 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
273 cs_dsp_callbacks_test_mock_algs[0].id,
274 "dummyalg", NULL);
275 for (i = 0; i < ARRAY_SIZE(local->passed_ctl); ++i) {
276 name[0] = 'A' + i;
277 def.offset_dsp_words = i;
278 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
279 }
280 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
281
282 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
283 KUNIT_EXPECT_EQ(test,
284 cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
285 0);
286
287 /* There should have been an add callback for each control */
288 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list),
289 ARRAY_SIZE(local->passed_ctl));
290 KUNIT_EXPECT_EQ(test, local->num_control_add, ARRAY_SIZE(local->passed_ctl));
291 KUNIT_EXPECT_EQ(test, local->num_control_remove, 0);
292
293 i = 0;
294 list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list)
295 KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl);
296
297 /*
298 * Call cs_dsp_remove() and there should be a remove callback
299 * for each control
300 */
301 memset(local->passed_ctl, 0, sizeof(local->passed_ctl));
302 cs_dsp_remove(priv->dsp);
303
304 /* Prevent double cleanup */
305 kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp);
306
307 KUNIT_EXPECT_EQ(test, local->num_control_add, ARRAY_SIZE(local->passed_ctl));
308 KUNIT_EXPECT_EQ(test, local->num_control_remove, ARRAY_SIZE(local->passed_ctl));
309
310 i = 0;
311 list_for_each_entry_reverse(ctl, &priv->dsp->ctl_list, list)
312 KUNIT_EXPECT_PTR_EQ(test, local->passed_ctl[i++], ctl);
313 }
314
cs_dsp_test_no_callbacks(struct kunit * test)315 static void cs_dsp_test_no_callbacks(struct kunit *test)
316 {
317 struct cs_dsp_test *priv = test->priv;
318 struct cs_dsp_test_local *local = priv->local;
319 struct cs_dsp_mock_coeff_def def = mock_coeff_template;
320 struct firmware *wmfw;
321
322 /* Add a controls */
323 def.shortname = "A";
324 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder,
325 cs_dsp_callbacks_test_mock_algs[0].id,
326 "dummyalg", NULL);
327 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def);
328 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder);
329
330 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
331
332 /* Run a sequence of ops that would invoke callbacks */
333 KUNIT_EXPECT_EQ(test,
334 cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
335 0);
336 KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
337 cs_dsp_stop(priv->dsp);
338 cs_dsp_remove(priv->dsp);
339
340 /* Prevent double cleanup */
341 kunit_remove_action(priv->test, _cs_dsp_remove_wrapper, priv->dsp);
342
343 /* Something went very wrong if any of our callbacks were called */
344 KUNIT_EXPECT_EQ(test, local->num_control_add, 0);
345 KUNIT_EXPECT_EQ(test, local->num_control_remove, 0);
346 KUNIT_EXPECT_EQ(test, local->num_pre_run, 0);
347 KUNIT_EXPECT_EQ(test, local->num_post_run, 0);
348 KUNIT_EXPECT_EQ(test, local->num_pre_stop, 0);
349 KUNIT_EXPECT_EQ(test, local->num_post_stop, 0);
350 }
351
cs_dsp_test_adsp2v2_watchdog_callback(struct kunit * test)352 static void cs_dsp_test_adsp2v2_watchdog_callback(struct kunit *test)
353 {
354 struct cs_dsp_test *priv = test->priv;
355 struct cs_dsp_test_local *local = priv->local;
356 struct firmware *wmfw;
357
358 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
359
360 KUNIT_EXPECT_EQ(test,
361 cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
362 0);
363
364 KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
365
366 /* Set the watchdog timeout bit */
367 regmap_write(priv->dsp->regmap, priv->dsp->base + ADSP2_LOCK_REGION_CTRL,
368 ADSP2_WDT_TIMEOUT_STS_MASK);
369
370 /* Notify an interrupt and the watchdog callback should be called */
371 cs_dsp_adsp2_bus_error(priv->dsp);
372 KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 1);
373 KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
374 }
375
cs_dsp_test_adsp2v2_watchdog_no_callbacks(struct kunit * test)376 static void cs_dsp_test_adsp2v2_watchdog_no_callbacks(struct kunit *test)
377 {
378 struct cs_dsp_test *priv = test->priv;
379 struct cs_dsp_test_local *local = priv->local;
380 struct firmware *wmfw;
381
382 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
383 KUNIT_EXPECT_EQ(test,
384 cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
385 0);
386 KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
387
388 /* Set the watchdog timeout bit */
389 regmap_write(priv->dsp->regmap, priv->dsp->base + ADSP2_LOCK_REGION_CTRL,
390 ADSP2_WDT_TIMEOUT_STS_MASK);
391
392 /* Notify an interrupt, which will look for a watchdog callback */
393 cs_dsp_adsp2_bus_error(priv->dsp);
394 KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 0);
395 }
396
cs_dsp_test_halo_watchdog_callback(struct kunit * test)397 static void cs_dsp_test_halo_watchdog_callback(struct kunit *test)
398 {
399 struct cs_dsp_test *priv = test->priv;
400 struct cs_dsp_test_local *local = priv->local;
401 struct firmware *wmfw;
402
403 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
404
405 KUNIT_EXPECT_EQ(test,
406 cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
407 0);
408
409 KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
410
411 /* Notify an interrupt and the watchdog callback should be called */
412 cs_dsp_halo_wdt_expire(priv->dsp);
413 KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 1);
414 KUNIT_EXPECT_PTR_EQ(test, local->passed_dsp, priv->dsp);
415 }
416
cs_dsp_test_halo_watchdog_no_callbacks(struct kunit * test)417 static void cs_dsp_test_halo_watchdog_no_callbacks(struct kunit *test)
418 {
419 struct cs_dsp_test *priv = test->priv;
420 struct cs_dsp_test_local *local = priv->local;
421 struct firmware *wmfw;
422
423 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
424 KUNIT_EXPECT_EQ(test,
425 cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
426 0);
427 KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
428
429 /* Notify an interrupt, which will look for a watchdog callback */
430 cs_dsp_halo_wdt_expire(priv->dsp);
431 KUNIT_EXPECT_EQ(test, local->num_watchdog_expired, 0);
432 }
433
cs_dsp_callbacks_test_common_init(struct kunit * test,struct cs_dsp * dsp,int wmfw_version)434 static int cs_dsp_callbacks_test_common_init(struct kunit *test, struct cs_dsp *dsp,
435 int wmfw_version)
436 {
437 const struct cs_dsp_callbacks_test_param *param = test->param_value;
438 struct cs_dsp_test *priv;
439 struct cs_dsp_test_local *local;
440 struct device *test_dev;
441 struct cs_dsp_mock_xm_header *xm_header;
442 int ret;
443
444 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
445 if (!priv)
446 return -ENOMEM;
447
448 local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
449 if (!local)
450 return -ENOMEM;
451
452 priv->test = test;
453 priv->dsp = dsp;
454 test->priv = priv;
455 priv->local = local;
456
457 /* Create dummy struct device */
458 test_dev = kunit_device_register(test, "cs_dsp_test_drv");
459 if (IS_ERR(test_dev))
460 return PTR_ERR(test_dev);
461
462 dsp->dev = get_device(test_dev);
463 if (!dsp->dev)
464 return -ENODEV;
465
466 ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
467 if (ret)
468 return ret;
469
470 dev_set_drvdata(dsp->dev, priv);
471
472 /* Allocate regmap */
473 ret = cs_dsp_mock_regmap_init(priv);
474 if (ret)
475 return ret;
476
477 /*
478 * There must always be a XM header with at least 1 algorithm,
479 * so create a dummy one and pre-populate XM so the wmfw doesn't
480 * have to contain an XM blob.
481 */
482 xm_header = cs_dsp_create_mock_xm_header(priv,
483 cs_dsp_callbacks_test_mock_algs,
484 ARRAY_SIZE(cs_dsp_callbacks_test_mock_algs));
485 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xm_header);
486 cs_dsp_mock_xm_header_write_to_regmap(xm_header);
487
488 local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, wmfw_version);
489 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->wmfw_builder);
490
491 /* Add dummy XM header payload to wmfw */
492 cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder,
493 WMFW_ADSP2_XM, 0,
494 xm_header->blob_data,
495 xm_header->blob_size_bytes);
496
497 /* Init cs_dsp */
498 dsp->client_ops = param->ops;
499
500 switch (dsp->type) {
501 case WMFW_ADSP2:
502 ret = cs_dsp_adsp2_init(dsp);
503 break;
504 case WMFW_HALO:
505 ret = cs_dsp_halo_init(dsp);
506 break;
507 default:
508 KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
509 return -EINVAL;
510 }
511
512 if (ret)
513 return ret;
514
515 /* Automatically call cs_dsp_remove() when test case ends */
516 return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
517 }
518
cs_dsp_callbacks_test_halo_init(struct kunit * test)519 static int cs_dsp_callbacks_test_halo_init(struct kunit *test)
520 {
521 struct cs_dsp *dsp;
522
523 /* Fill in cs_dsp and initialize */
524 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
525 if (!dsp)
526 return -ENOMEM;
527
528 dsp->num = 1;
529 dsp->type = WMFW_HALO;
530 dsp->mem = cs_dsp_mock_halo_dsp1_regions;
531 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
532 dsp->base = cs_dsp_mock_halo_core_base;
533 dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
534
535 return cs_dsp_callbacks_test_common_init(test, dsp, 3);
536 }
537
cs_dsp_callbacks_test_adsp2_32bit_init(struct kunit * test,int rev)538 static int cs_dsp_callbacks_test_adsp2_32bit_init(struct kunit *test, int rev)
539 {
540 struct cs_dsp *dsp;
541
542 /* Fill in cs_dsp and initialize */
543 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
544 if (!dsp)
545 return -ENOMEM;
546
547 dsp->num = 1;
548 dsp->type = WMFW_ADSP2;
549 dsp->rev = rev;
550 dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
551 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
552 dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
553
554 return cs_dsp_callbacks_test_common_init(test, dsp, 2);
555 }
556
cs_dsp_callbacks_test_adsp2v2_32bit_init(struct kunit * test)557 static int cs_dsp_callbacks_test_adsp2v2_32bit_init(struct kunit *test)
558 {
559 return cs_dsp_callbacks_test_adsp2_32bit_init(test, 2);
560 }
561
cs_dsp_callbacks_test_adsp2v1_32bit_init(struct kunit * test)562 static int cs_dsp_callbacks_test_adsp2v1_32bit_init(struct kunit *test)
563 {
564 return cs_dsp_callbacks_test_adsp2_32bit_init(test, 1);
565 }
566
cs_dsp_callbacks_test_adsp2_16bit_init(struct kunit * test)567 static int cs_dsp_callbacks_test_adsp2_16bit_init(struct kunit *test)
568 {
569 struct cs_dsp *dsp;
570
571 /* Fill in cs_dsp and initialize */
572 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
573 if (!dsp)
574 return -ENOMEM;
575
576 dsp->num = 1;
577 dsp->type = WMFW_ADSP2;
578 dsp->rev = 0;
579 dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
580 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
581 dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
582
583 return cs_dsp_callbacks_test_common_init(test, dsp, 1);
584 }
585
cs_dsp_callbacks_param_desc(const struct cs_dsp_callbacks_test_param * param,char * desc)586 static void cs_dsp_callbacks_param_desc(const struct cs_dsp_callbacks_test_param *param,
587 char *desc)
588 {
589 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", param->case_name);
590 }
591
592 /* Parameterize on different client callback ops tables */
593 static const struct cs_dsp_callbacks_test_param cs_dsp_callbacks_ops_cases[] = {
594 { .ops = &cs_dsp_callback_test_client_ops, .case_name = "all ops" },
595 };
596
597 KUNIT_ARRAY_PARAM(cs_dsp_callbacks_ops,
598 cs_dsp_callbacks_ops_cases,
599 cs_dsp_callbacks_param_desc);
600
601 static const struct cs_dsp_callbacks_test_param cs_dsp_no_callbacks_cases[] = {
602 { .ops = &cs_dsp_callback_test_empty_client_ops, .case_name = "empty ops" },
603 };
604
605 KUNIT_ARRAY_PARAM(cs_dsp_no_callbacks,
606 cs_dsp_no_callbacks_cases,
607 cs_dsp_callbacks_param_desc);
608
609 static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv1_test_cases[] = {
610 KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
611 KUNIT_CASE_PARAM(cs_dsp_test_ctl_v1_callbacks, cs_dsp_callbacks_ops_gen_params),
612 KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
613
614 { } /* terminator */
615 };
616
617 static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv2_test_cases[] = {
618 KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
619 KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params),
620 KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
621
622 { } /* terminator */
623 };
624
625 static struct kunit_case cs_dsp_callbacks_halo_test_cases[] = {
626 KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
627 KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params),
628 KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
629
630 { } /* terminator */
631 };
632
633 static struct kunit_case cs_dsp_watchdog_adsp2v2_test_cases[] = {
634 KUNIT_CASE_PARAM(cs_dsp_test_adsp2v2_watchdog_callback, cs_dsp_callbacks_ops_gen_params),
635 KUNIT_CASE_PARAM(cs_dsp_test_adsp2v2_watchdog_no_callbacks, cs_dsp_no_callbacks_gen_params),
636
637 { } /* terminator */
638 };
639
640 static struct kunit_case cs_dsp_watchdog_halo_test_cases[] = {
641 KUNIT_CASE_PARAM(cs_dsp_test_halo_watchdog_callback, cs_dsp_callbacks_ops_gen_params),
642 KUNIT_CASE_PARAM(cs_dsp_test_halo_watchdog_no_callbacks, cs_dsp_no_callbacks_gen_params),
643
644 { } /* terminator */
645 };
646
647 static struct kunit_suite cs_dsp_callbacks_test_halo = {
648 .name = "cs_dsp_callbacks_halo",
649 .init = cs_dsp_callbacks_test_halo_init,
650 .test_cases = cs_dsp_callbacks_halo_test_cases,
651 };
652
653 static struct kunit_suite cs_dsp_callbacks_test_adsp2v2_32bit = {
654 .name = "cs_dsp_callbacks_adsp2v2_32bit_wmfwv2",
655 .init = cs_dsp_callbacks_test_adsp2v2_32bit_init,
656 .test_cases = cs_dsp_callbacks_adsp2_wmfwv2_test_cases,
657 };
658
659 static struct kunit_suite cs_dsp_callbacks_test_adsp2v1_32bit = {
660 .name = "cs_dsp_callbacks_adsp2v1_32bit_wmfwv2",
661 .init = cs_dsp_callbacks_test_adsp2v1_32bit_init,
662 .test_cases = cs_dsp_callbacks_adsp2_wmfwv2_test_cases,
663 };
664
665 static struct kunit_suite cs_dsp_callbacks_test_adsp2_16bit = {
666 .name = "cs_dsp_callbacks_adsp2_16bit_wmfwv1",
667 .init = cs_dsp_callbacks_test_adsp2_16bit_init,
668 .test_cases = cs_dsp_callbacks_adsp2_wmfwv1_test_cases,
669 };
670
671 static struct kunit_suite cs_dsp_watchdog_test_adsp2v2_32bit = {
672 .name = "cs_dsp_watchdog_adsp2v2_32bit",
673 .init = cs_dsp_callbacks_test_adsp2v2_32bit_init,
674 .test_cases = cs_dsp_watchdog_adsp2v2_test_cases,
675 };
676
677 static struct kunit_suite cs_dsp_watchdog_test_halo_32bit = {
678 .name = "cs_dsp_watchdog_halo",
679 .init = cs_dsp_callbacks_test_halo_init,
680 .test_cases = cs_dsp_watchdog_halo_test_cases,
681 };
682
683 kunit_test_suites(&cs_dsp_callbacks_test_halo,
684 &cs_dsp_callbacks_test_adsp2v2_32bit,
685 &cs_dsp_callbacks_test_adsp2v1_32bit,
686 &cs_dsp_callbacks_test_adsp2_16bit,
687 &cs_dsp_watchdog_test_adsp2v2_32bit,
688 &cs_dsp_watchdog_test_halo_32bit);
689