1 // SPDX-License-Identifier: GPL-2.0-only
3 // KUnit test for the Cirrus common amplifier library.
5 // Copyright (C) 2024 Cirrus Logic, Inc. and
6 // Cirrus Logic International Semiconductor Ltd.
8 #include <kunit/test.h>
9 #include <kunit/static_stub.h>
10 #include <linux/firmware/cirrus/cs_dsp.h>
11 #include <linux/firmware/cirrus/wmfw.h>
12 #include <linux/gpio/driver.h>
13 #include <linux/list.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/random.h>
17 #include <sound/cs-amp-lib.h>
19 struct cs_amp_lib_test_priv
{
20 struct platform_device amp_pdev
;
22 struct cirrus_amp_efi_data
*cal_blob
;
23 struct list_head ctl_write_list
;
26 struct cs_amp_lib_test_ctl_write_entry
{
27 struct list_head list
;
32 struct cs_amp_lib_test_param
{
37 static void cs_amp_lib_test_init_dummy_cal_blob(struct kunit
*test
, int num_amps
)
39 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
40 unsigned int blob_size
;
43 blob_size
= offsetof(struct cirrus_amp_efi_data
, data
) +
44 sizeof(struct cirrus_amp_cal_data
) * num_amps
;
46 priv
->cal_blob
= kunit_kzalloc(test
, blob_size
, GFP_KERNEL
);
47 KUNIT_ASSERT_NOT_NULL(test
, priv
->cal_blob
);
49 priv
->cal_blob
->size
= blob_size
;
50 priv
->cal_blob
->count
= num_amps
;
52 get_random_bytes(priv
->cal_blob
->data
, sizeof(struct cirrus_amp_cal_data
) * num_amps
);
54 /* Ensure all timestamps are non-zero to mark the entry valid. */
55 for (i
= 0; i
< num_amps
; i
++)
56 priv
->cal_blob
->data
[i
].calTime
[0] |= 1;
58 /* Ensure that all UIDs are non-zero and unique. */
59 for (i
= 0; i
< num_amps
; i
++)
60 *(u8
*)&priv
->cal_blob
->data
[i
].calTarget
[0] = i
+ 1;
63 static u64
cs_amp_lib_test_get_target_uid(struct kunit
*test
)
65 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
66 const struct cs_amp_lib_test_param
*param
= test
->param_value
;
69 uid
= priv
->cal_blob
->data
[param
->amp_index
].calTarget
[1];
71 uid
|= priv
->cal_blob
->data
[param
->amp_index
].calTarget
[0];
76 /* Redirected get_efi_variable to simulate that the file is too short */
77 static efi_status_t
cs_amp_lib_test_get_efi_variable_nohead(efi_char16_t
*name
,
83 *size
= offsetof(struct cirrus_amp_efi_data
, data
) - 1;
84 return EFI_BUFFER_TOO_SMALL
;
90 /* Should return -EOVERFLOW if the header is larger than the EFI data */
91 static void cs_amp_lib_test_cal_data_too_short_test(struct kunit
*test
)
93 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
94 struct cirrus_amp_cal_data result_data
;
97 /* Redirect calls to get EFI data */
98 kunit_activate_static_stub(test
,
99 cs_amp_test_hooks
->get_efi_variable
,
100 cs_amp_lib_test_get_efi_variable_nohead
);
102 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, 0, 0, &result_data
);
103 KUNIT_EXPECT_EQ(test
, ret
, -EOVERFLOW
);
105 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
108 /* Redirected get_efi_variable to simulate that the count is larger than the file */
109 static efi_status_t
cs_amp_lib_test_get_efi_variable_bad_count(efi_char16_t
*name
,
114 struct kunit
*test
= kunit_get_current_test();
115 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
119 * Return a size that is shorter than required for the
120 * declared number of entries.
122 *size
= priv
->cal_blob
->size
- 1;
123 return EFI_BUFFER_TOO_SMALL
;
126 memcpy(buf
, priv
->cal_blob
, priv
->cal_blob
->size
- 1);
131 /* Should return -EOVERFLOW if the entry count is larger than the EFI data */
132 static void cs_amp_lib_test_cal_count_too_big_test(struct kunit
*test
)
134 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
135 struct cirrus_amp_cal_data result_data
;
138 cs_amp_lib_test_init_dummy_cal_blob(test
, 8);
140 /* Redirect calls to get EFI data */
141 kunit_activate_static_stub(test
,
142 cs_amp_test_hooks
->get_efi_variable
,
143 cs_amp_lib_test_get_efi_variable_bad_count
);
145 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, 0, 0, &result_data
);
146 KUNIT_EXPECT_EQ(test
, ret
, -EOVERFLOW
);
148 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
151 /* Redirected get_efi_variable to simulate that the variable not found */
152 static efi_status_t
cs_amp_lib_test_get_efi_variable_none(efi_char16_t
*name
,
157 return EFI_NOT_FOUND
;
160 /* If EFI doesn't contain a cal data variable the result should be -ENOENT */
161 static void cs_amp_lib_test_no_cal_data_test(struct kunit
*test
)
163 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
164 struct cirrus_amp_cal_data result_data
;
167 /* Redirect calls to get EFI data */
168 kunit_activate_static_stub(test
,
169 cs_amp_test_hooks
->get_efi_variable
,
170 cs_amp_lib_test_get_efi_variable_none
);
172 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, 0, 0, &result_data
);
173 KUNIT_EXPECT_EQ(test
, ret
, -ENOENT
);
175 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
178 /* Redirected get_efi_variable to simulate reading a cal data blob */
179 static efi_status_t
cs_amp_lib_test_get_efi_variable(efi_char16_t
*name
,
184 static const efi_char16_t expected_name
[] = L
"CirrusSmartAmpCalibrationData";
185 static const efi_guid_t expected_guid
=
186 EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3);
187 struct kunit
*test
= kunit_get_current_test();
188 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
190 KUNIT_EXPECT_NOT_ERR_OR_NULL(test
, name
);
191 KUNIT_EXPECT_NOT_ERR_OR_NULL(test
, guid
);
192 KUNIT_EXPECT_NOT_ERR_OR_NULL(test
, size
);
194 KUNIT_EXPECT_MEMEQ(test
, name
, expected_name
, sizeof(expected_name
));
195 KUNIT_EXPECT_MEMEQ(test
, guid
, &expected_guid
, sizeof(expected_guid
));
198 *size
= priv
->cal_blob
->size
;
199 return EFI_BUFFER_TOO_SMALL
;
202 KUNIT_ASSERT_GE_MSG(test
, ksize(buf
), priv
->cal_blob
->size
, "Buffer to small");
204 memcpy(buf
, priv
->cal_blob
, priv
->cal_blob
->size
);
209 /* Get cal data block for a given amp, matched by target UID. */
210 static void cs_amp_lib_test_get_efi_cal_by_uid_test(struct kunit
*test
)
212 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
213 const struct cs_amp_lib_test_param
*param
= test
->param_value
;
214 struct cirrus_amp_cal_data result_data
;
218 cs_amp_lib_test_init_dummy_cal_blob(test
, param
->num_amps
);
220 /* Redirect calls to get EFI data */
221 kunit_activate_static_stub(test
,
222 cs_amp_test_hooks
->get_efi_variable
,
223 cs_amp_lib_test_get_efi_variable
);
225 target_uid
= cs_amp_lib_test_get_target_uid(test
);
226 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, target_uid
, -1, &result_data
);
227 KUNIT_EXPECT_EQ(test
, ret
, 0);
229 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
231 KUNIT_EXPECT_EQ(test
, result_data
.calTarget
[0], target_uid
& 0xFFFFFFFFULL
);
232 KUNIT_EXPECT_EQ(test
, result_data
.calTarget
[1], target_uid
>> 32);
233 KUNIT_EXPECT_EQ(test
, result_data
.calTime
[0],
234 priv
->cal_blob
->data
[param
->amp_index
].calTime
[0]);
235 KUNIT_EXPECT_EQ(test
, result_data
.calTime
[1],
236 priv
->cal_blob
->data
[param
->amp_index
].calTime
[1]);
237 KUNIT_EXPECT_EQ(test
, result_data
.calAmbient
,
238 priv
->cal_blob
->data
[param
->amp_index
].calAmbient
);
239 KUNIT_EXPECT_EQ(test
, result_data
.calStatus
,
240 priv
->cal_blob
->data
[param
->amp_index
].calStatus
);
241 KUNIT_EXPECT_EQ(test
, result_data
.calR
,
242 priv
->cal_blob
->data
[param
->amp_index
].calR
);
245 /* Get cal data block for a given amp index without checking target UID. */
246 static void cs_amp_lib_test_get_efi_cal_by_index_unchecked_test(struct kunit
*test
)
248 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
249 const struct cs_amp_lib_test_param
*param
= test
->param_value
;
250 struct cirrus_amp_cal_data result_data
;
253 cs_amp_lib_test_init_dummy_cal_blob(test
, param
->num_amps
);
255 /* Redirect calls to get EFI data */
256 kunit_activate_static_stub(test
,
257 cs_amp_test_hooks
->get_efi_variable
,
258 cs_amp_lib_test_get_efi_variable
);
260 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, 0,
261 param
->amp_index
, &result_data
);
262 KUNIT_EXPECT_EQ(test
, ret
, 0);
264 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
266 KUNIT_EXPECT_EQ(test
, result_data
.calTime
[0],
267 priv
->cal_blob
->data
[param
->amp_index
].calTime
[0]);
268 KUNIT_EXPECT_EQ(test
, result_data
.calTime
[1],
269 priv
->cal_blob
->data
[param
->amp_index
].calTime
[1]);
270 KUNIT_EXPECT_EQ(test
, result_data
.calAmbient
,
271 priv
->cal_blob
->data
[param
->amp_index
].calAmbient
);
272 KUNIT_EXPECT_EQ(test
, result_data
.calStatus
,
273 priv
->cal_blob
->data
[param
->amp_index
].calStatus
);
274 KUNIT_EXPECT_EQ(test
, result_data
.calR
,
275 priv
->cal_blob
->data
[param
->amp_index
].calR
);
278 /* Get cal data block for a given amp index with checked target UID. */
279 static void cs_amp_lib_test_get_efi_cal_by_index_checked_test(struct kunit
*test
)
281 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
282 const struct cs_amp_lib_test_param
*param
= test
->param_value
;
283 struct cirrus_amp_cal_data result_data
;
287 cs_amp_lib_test_init_dummy_cal_blob(test
, param
->num_amps
);
289 /* Redirect calls to get EFI data */
290 kunit_activate_static_stub(test
,
291 cs_amp_test_hooks
->get_efi_variable
,
292 cs_amp_lib_test_get_efi_variable
);
294 target_uid
= cs_amp_lib_test_get_target_uid(test
);
295 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, target_uid
,
296 param
->amp_index
, &result_data
);
297 KUNIT_EXPECT_EQ(test
, ret
, 0);
299 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
301 KUNIT_EXPECT_EQ(test
, result_data
.calTime
[0],
302 priv
->cal_blob
->data
[param
->amp_index
].calTime
[0]);
303 KUNIT_EXPECT_EQ(test
, result_data
.calTime
[1],
304 priv
->cal_blob
->data
[param
->amp_index
].calTime
[1]);
305 KUNIT_EXPECT_EQ(test
, result_data
.calAmbient
,
306 priv
->cal_blob
->data
[param
->amp_index
].calAmbient
);
307 KUNIT_EXPECT_EQ(test
, result_data
.calStatus
,
308 priv
->cal_blob
->data
[param
->amp_index
].calStatus
);
309 KUNIT_EXPECT_EQ(test
, result_data
.calR
,
310 priv
->cal_blob
->data
[param
->amp_index
].calR
);
314 * Get cal data block for a given amp index with checked target UID.
315 * The UID does not match so the result should be -ENOENT.
317 static void cs_amp_lib_test_get_efi_cal_by_index_uid_mismatch_test(struct kunit
*test
)
319 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
320 const struct cs_amp_lib_test_param
*param
= test
->param_value
;
321 struct cirrus_amp_cal_data result_data
;
325 cs_amp_lib_test_init_dummy_cal_blob(test
, param
->num_amps
);
327 /* Redirect calls to get EFI data */
328 kunit_activate_static_stub(test
,
329 cs_amp_test_hooks
->get_efi_variable
,
330 cs_amp_lib_test_get_efi_variable
);
332 /* Get a target UID that won't match the entry */
333 target_uid
= ~cs_amp_lib_test_get_target_uid(test
);
334 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, target_uid
,
335 param
->amp_index
, &result_data
);
336 KUNIT_EXPECT_EQ(test
, ret
, -ENOENT
);
338 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
342 * Get cal data block for a given amp, where the cal data does not
343 * specify calTarget so the lookup falls back to using the index
345 static void cs_amp_lib_test_get_efi_cal_by_index_fallback_test(struct kunit
*test
)
347 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
348 const struct cs_amp_lib_test_param
*param
= test
->param_value
;
349 struct cirrus_amp_cal_data result_data
;
350 static const u64 bad_target_uid
= 0xBADCA100BABABABAULL
;
353 cs_amp_lib_test_init_dummy_cal_blob(test
, param
->num_amps
);
355 /* Make all the target values zero so they are ignored */
356 for (i
= 0; i
< priv
->cal_blob
->count
; ++i
) {
357 priv
->cal_blob
->data
[i
].calTarget
[0] = 0;
358 priv
->cal_blob
->data
[i
].calTarget
[1] = 0;
361 /* Redirect calls to get EFI data */
362 kunit_activate_static_stub(test
,
363 cs_amp_test_hooks
->get_efi_variable
,
364 cs_amp_lib_test_get_efi_variable
);
366 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, bad_target_uid
,
367 param
->amp_index
, &result_data
);
368 KUNIT_EXPECT_EQ(test
, ret
, 0);
370 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
372 KUNIT_EXPECT_EQ(test
, result_data
.calTime
[0],
373 priv
->cal_blob
->data
[param
->amp_index
].calTime
[0]);
374 KUNIT_EXPECT_EQ(test
, result_data
.calTime
[1],
375 priv
->cal_blob
->data
[param
->amp_index
].calTime
[1]);
376 KUNIT_EXPECT_EQ(test
, result_data
.calAmbient
,
377 priv
->cal_blob
->data
[param
->amp_index
].calAmbient
);
378 KUNIT_EXPECT_EQ(test
, result_data
.calStatus
,
379 priv
->cal_blob
->data
[param
->amp_index
].calStatus
);
380 KUNIT_EXPECT_EQ(test
, result_data
.calR
,
381 priv
->cal_blob
->data
[param
->amp_index
].calR
);
385 * If the target UID isn't present in the cal data, and there isn't an
386 * index to fall back do, the result should be -ENOENT.
388 static void cs_amp_lib_test_get_efi_cal_uid_not_found_noindex_test(struct kunit
*test
)
390 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
391 struct cirrus_amp_cal_data result_data
;
392 static const u64 bad_target_uid
= 0xBADCA100BABABABAULL
;
395 cs_amp_lib_test_init_dummy_cal_blob(test
, 8);
397 /* Make all the target values != bad_target_uid */
398 for (i
= 0; i
< priv
->cal_blob
->count
; ++i
) {
399 priv
->cal_blob
->data
[i
].calTarget
[0] &= ~(bad_target_uid
& 0xFFFFFFFFULL
);
400 priv
->cal_blob
->data
[i
].calTarget
[1] &= ~(bad_target_uid
>> 32);
403 /* Redirect calls to get EFI data */
404 kunit_activate_static_stub(test
,
405 cs_amp_test_hooks
->get_efi_variable
,
406 cs_amp_lib_test_get_efi_variable
);
408 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, bad_target_uid
, -1,
410 KUNIT_EXPECT_EQ(test
, ret
, -ENOENT
);
412 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
416 * If the target UID isn't present in the cal data, and the index is
417 * out of range, the result should be -ENOENT.
419 static void cs_amp_lib_test_get_efi_cal_uid_not_found_index_not_found_test(struct kunit
*test
)
421 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
422 struct cirrus_amp_cal_data result_data
;
423 static const u64 bad_target_uid
= 0xBADCA100BABABABAULL
;
426 cs_amp_lib_test_init_dummy_cal_blob(test
, 8);
428 /* Make all the target values != bad_target_uid */
429 for (i
= 0; i
< priv
->cal_blob
->count
; ++i
) {
430 priv
->cal_blob
->data
[i
].calTarget
[0] &= ~(bad_target_uid
& 0xFFFFFFFFULL
);
431 priv
->cal_blob
->data
[i
].calTarget
[1] &= ~(bad_target_uid
>> 32);
434 /* Redirect calls to get EFI data */
435 kunit_activate_static_stub(test
,
436 cs_amp_test_hooks
->get_efi_variable
,
437 cs_amp_lib_test_get_efi_variable
);
439 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, bad_target_uid
, 99,
441 KUNIT_EXPECT_EQ(test
, ret
, -ENOENT
);
443 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
447 * If the target UID isn't given, and the index is out of range, the
448 * result should be -ENOENT.
450 static void cs_amp_lib_test_get_efi_cal_no_uid_index_not_found_test(struct kunit
*test
)
452 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
453 struct cirrus_amp_cal_data result_data
;
456 cs_amp_lib_test_init_dummy_cal_blob(test
, 8);
458 /* Redirect calls to get EFI data */
459 kunit_activate_static_stub(test
,
460 cs_amp_test_hooks
->get_efi_variable
,
461 cs_amp_lib_test_get_efi_variable
);
463 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, 0, 99, &result_data
);
464 KUNIT_EXPECT_EQ(test
, ret
, -ENOENT
);
466 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
469 /* If neither the target UID or the index is given the result should be -ENOENT. */
470 static void cs_amp_lib_test_get_efi_cal_no_uid_no_index_test(struct kunit
*test
)
472 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
473 struct cirrus_amp_cal_data result_data
;
476 cs_amp_lib_test_init_dummy_cal_blob(test
, 8);
478 /* Redirect calls to get EFI data */
479 kunit_activate_static_stub(test
,
480 cs_amp_test_hooks
->get_efi_variable
,
481 cs_amp_lib_test_get_efi_variable
);
483 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, 0, -1, &result_data
);
484 KUNIT_EXPECT_EQ(test
, ret
, -ENOENT
);
486 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
490 * If the UID is passed as 0 this must not match an entry with an
491 * unpopulated calTarget
493 static void cs_amp_lib_test_get_efi_cal_zero_not_matched_test(struct kunit
*test
)
495 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
496 struct cirrus_amp_cal_data result_data
;
499 cs_amp_lib_test_init_dummy_cal_blob(test
, 8);
501 /* Make all the target values zero so they are ignored */
502 for (i
= 0; i
< priv
->cal_blob
->count
; ++i
) {
503 priv
->cal_blob
->data
[i
].calTarget
[0] = 0;
504 priv
->cal_blob
->data
[i
].calTarget
[1] = 0;
507 /* Redirect calls to get EFI data */
508 kunit_activate_static_stub(test
,
509 cs_amp_test_hooks
->get_efi_variable
,
510 cs_amp_lib_test_get_efi_variable
);
512 ret
= cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
, 0, -1, &result_data
);
513 KUNIT_EXPECT_EQ(test
, ret
, -ENOENT
);
515 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
519 * If an entry has a timestamp of 0 it should be ignored even if it has
520 * a matching target UID.
522 static void cs_amp_lib_test_get_efi_cal_empty_entry_test(struct kunit
*test
)
524 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
525 struct cirrus_amp_cal_data result_data
;
528 cs_amp_lib_test_init_dummy_cal_blob(test
, 8);
530 /* Mark the 3rd entry invalid by zeroing calTime */
531 priv
->cal_blob
->data
[2].calTime
[0] = 0;
532 priv
->cal_blob
->data
[2].calTime
[1] = 0;
534 /* Get the UID value of the 3rd entry */
535 uid
= priv
->cal_blob
->data
[2].calTarget
[1];
537 uid
|= priv
->cal_blob
->data
[2].calTarget
[0];
539 /* Redirect calls to get EFI data */
540 kunit_activate_static_stub(test
,
541 cs_amp_test_hooks
->get_efi_variable
,
542 cs_amp_lib_test_get_efi_variable
);
544 /* Lookup by UID should not find it */
545 KUNIT_EXPECT_EQ(test
,
546 cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
,
551 /* Get by index should ignore it */
552 KUNIT_EXPECT_EQ(test
,
553 cs_amp_get_efi_calibration_data(&priv
->amp_pdev
.dev
,
558 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->get_efi_variable
);
561 static const struct cirrus_amp_cal_controls cs_amp_lib_test_calibration_controls
= {
563 .mem_region
= WMFW_ADSP2_YM
,
564 .ambient
= "CAL_AMBIENT",
566 .status
= "CAL_STATUS",
567 .checksum
= "CAL_CHECKSUM",
570 static int cs_amp_lib_test_write_cal_coeff(struct cs_dsp
*dsp
,
571 const struct cirrus_amp_cal_controls
*controls
,
572 const char *ctl_name
, u32 val
)
574 struct kunit
*test
= kunit_get_current_test();
575 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
576 struct cs_amp_lib_test_ctl_write_entry
*entry
;
578 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, ctl_name
);
579 KUNIT_EXPECT_PTR_EQ(test
, controls
, &cs_amp_lib_test_calibration_controls
);
581 entry
= kunit_kzalloc(test
, sizeof(*entry
), GFP_KERNEL
);
582 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, entry
);
584 INIT_LIST_HEAD(&entry
->list
);
585 strscpy(entry
->name
, ctl_name
, sizeof(entry
->name
));
588 list_add_tail(&entry
->list
, &priv
->ctl_write_list
);
593 static void cs_amp_lib_test_write_cal_data_test(struct kunit
*test
)
595 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
596 struct cs_amp_lib_test_ctl_write_entry
*entry
;
597 struct cirrus_amp_cal_data data
;
601 dsp
= kunit_kzalloc(test
, sizeof(*dsp
), GFP_KERNEL
);
602 KUNIT_ASSERT_NOT_ERR_OR_NULL(test
, dsp
);
603 dsp
->dev
= &priv
->amp_pdev
.dev
;
605 get_random_bytes(&data
, sizeof(data
));
607 /* Redirect calls to write firmware controls */
608 kunit_activate_static_stub(test
,
609 cs_amp_test_hooks
->write_cal_coeff
,
610 cs_amp_lib_test_write_cal_coeff
);
612 ret
= cs_amp_write_cal_coeffs(dsp
, &cs_amp_lib_test_calibration_controls
, &data
);
613 KUNIT_EXPECT_EQ(test
, ret
, 0);
615 kunit_deactivate_static_stub(test
, cs_amp_test_hooks
->write_cal_coeff
);
617 KUNIT_EXPECT_EQ(test
, list_count_nodes(&priv
->ctl_write_list
), 4);
619 /* Checksum control must be written last */
620 entry
= list_last_entry(&priv
->ctl_write_list
, typeof(*entry
), list
);
621 KUNIT_EXPECT_STREQ(test
, entry
->name
, cs_amp_lib_test_calibration_controls
.checksum
);
622 KUNIT_EXPECT_EQ(test
, entry
->value
, data
.calR
+ 1);
623 list_del(&entry
->list
);
625 entry
= list_first_entry(&priv
->ctl_write_list
, typeof(*entry
), list
);
626 KUNIT_EXPECT_STREQ(test
, entry
->name
, cs_amp_lib_test_calibration_controls
.ambient
);
627 KUNIT_EXPECT_EQ(test
, entry
->value
, data
.calAmbient
);
628 list_del(&entry
->list
);
630 entry
= list_first_entry(&priv
->ctl_write_list
, typeof(*entry
), list
);
631 KUNIT_EXPECT_STREQ(test
, entry
->name
, cs_amp_lib_test_calibration_controls
.calr
);
632 KUNIT_EXPECT_EQ(test
, entry
->value
, data
.calR
);
633 list_del(&entry
->list
);
635 entry
= list_first_entry(&priv
->ctl_write_list
, typeof(*entry
), list
);
636 KUNIT_EXPECT_STREQ(test
, entry
->name
, cs_amp_lib_test_calibration_controls
.status
);
637 KUNIT_EXPECT_EQ(test
, entry
->value
, data
.calStatus
);
640 static void cs_amp_lib_test_dev_release(struct device
*dev
)
644 static int cs_amp_lib_test_case_init(struct kunit
*test
)
646 struct cs_amp_lib_test_priv
*priv
;
649 KUNIT_ASSERT_NOT_NULL(test
, cs_amp_test_hooks
);
651 priv
= kunit_kzalloc(test
, sizeof(*priv
), GFP_KERNEL
);
656 INIT_LIST_HEAD(&priv
->ctl_write_list
);
658 /* Create dummy amp driver dev */
659 priv
->amp_pdev
.name
= "cs_amp_lib_test_drv";
660 priv
->amp_pdev
.id
= -1;
661 priv
->amp_pdev
.dev
.release
= cs_amp_lib_test_dev_release
;
662 ret
= platform_device_register(&priv
->amp_pdev
);
663 KUNIT_ASSERT_GE_MSG(test
, ret
, 0, "Failed to register amp platform device\n");
668 static void cs_amp_lib_test_case_exit(struct kunit
*test
)
670 struct cs_amp_lib_test_priv
*priv
= test
->priv
;
672 if (priv
->amp_pdev
.name
)
673 platform_device_unregister(&priv
->amp_pdev
);
676 static const struct cs_amp_lib_test_param cs_amp_lib_test_get_cal_param_cases
[] = {
677 { .num_amps
= 2, .amp_index
= 0 },
678 { .num_amps
= 2, .amp_index
= 1 },
680 { .num_amps
= 3, .amp_index
= 0 },
681 { .num_amps
= 3, .amp_index
= 1 },
682 { .num_amps
= 3, .amp_index
= 2 },
684 { .num_amps
= 4, .amp_index
= 0 },
685 { .num_amps
= 4, .amp_index
= 1 },
686 { .num_amps
= 4, .amp_index
= 2 },
687 { .num_amps
= 4, .amp_index
= 3 },
689 { .num_amps
= 5, .amp_index
= 0 },
690 { .num_amps
= 5, .amp_index
= 1 },
691 { .num_amps
= 5, .amp_index
= 2 },
692 { .num_amps
= 5, .amp_index
= 3 },
693 { .num_amps
= 5, .amp_index
= 4 },
695 { .num_amps
= 6, .amp_index
= 0 },
696 { .num_amps
= 6, .amp_index
= 1 },
697 { .num_amps
= 6, .amp_index
= 2 },
698 { .num_amps
= 6, .amp_index
= 3 },
699 { .num_amps
= 6, .amp_index
= 4 },
700 { .num_amps
= 6, .amp_index
= 5 },
702 { .num_amps
= 8, .amp_index
= 0 },
703 { .num_amps
= 8, .amp_index
= 1 },
704 { .num_amps
= 8, .amp_index
= 2 },
705 { .num_amps
= 8, .amp_index
= 3 },
706 { .num_amps
= 8, .amp_index
= 4 },
707 { .num_amps
= 8, .amp_index
= 5 },
708 { .num_amps
= 8, .amp_index
= 6 },
709 { .num_amps
= 8, .amp_index
= 7 },
712 static void cs_amp_lib_test_get_cal_param_desc(const struct cs_amp_lib_test_param
*param
,
715 snprintf(desc
, KUNIT_PARAM_DESC_SIZE
, "num_amps:%d amp_index:%d",
716 param
->num_amps
, param
->amp_index
);
719 KUNIT_ARRAY_PARAM(cs_amp_lib_test_get_cal
, cs_amp_lib_test_get_cal_param_cases
,
720 cs_amp_lib_test_get_cal_param_desc
);
722 static struct kunit_case cs_amp_lib_test_cases
[] = {
723 /* Tests for getting calibration data from EFI */
724 KUNIT_CASE(cs_amp_lib_test_cal_data_too_short_test
),
725 KUNIT_CASE(cs_amp_lib_test_cal_count_too_big_test
),
726 KUNIT_CASE(cs_amp_lib_test_no_cal_data_test
),
727 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_uid_not_found_noindex_test
),
728 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_uid_not_found_index_not_found_test
),
729 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_index_not_found_test
),
730 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_no_index_test
),
731 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_zero_not_matched_test
),
732 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_uid_test
,
733 cs_amp_lib_test_get_cal_gen_params
),
734 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_unchecked_test
,
735 cs_amp_lib_test_get_cal_gen_params
),
736 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_checked_test
,
737 cs_amp_lib_test_get_cal_gen_params
),
738 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_uid_mismatch_test
,
739 cs_amp_lib_test_get_cal_gen_params
),
740 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_fallback_test
,
741 cs_amp_lib_test_get_cal_gen_params
),
742 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_empty_entry_test
),
744 /* Tests for writing calibration data */
745 KUNIT_CASE(cs_amp_lib_test_write_cal_data_test
),
750 static struct kunit_suite cs_amp_lib_test_suite
= {
751 .name
= "snd-soc-cs-amp-lib-test",
752 .init
= cs_amp_lib_test_case_init
,
753 .exit
= cs_amp_lib_test_case_exit
,
754 .test_cases
= cs_amp_lib_test_cases
,
757 kunit_test_suite(cs_amp_lib_test_suite
);
759 MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
760 MODULE_DESCRIPTION("KUnit test for Cirrus Logic amplifier library");
761 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
762 MODULE_LICENSE("GPL");