1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // KUnit test for the Cirrus common amplifier library. 4 // 5 // Copyright (C) 2024 Cirrus Logic, Inc. and 6 // Cirrus Logic International Semiconductor Ltd. 7 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> 18 19 struct cs_amp_lib_test_priv { 20 struct platform_device amp_pdev; 21 22 struct cirrus_amp_efi_data *cal_blob; 23 struct list_head ctl_write_list; 24 }; 25 26 struct cs_amp_lib_test_ctl_write_entry { 27 struct list_head list; 28 unsigned int value; 29 char name[16]; 30 }; 31 32 struct cs_amp_lib_test_param { 33 int num_amps; 34 int amp_index; 35 }; 36 37 static void cs_amp_lib_test_init_dummy_cal_blob(struct kunit *test, int num_amps) 38 { 39 struct cs_amp_lib_test_priv *priv = test->priv; 40 unsigned int blob_size; 41 42 blob_size = offsetof(struct cirrus_amp_efi_data, data) + 43 sizeof(struct cirrus_amp_cal_data) * num_amps; 44 45 priv->cal_blob = kunit_kzalloc(test, blob_size, GFP_KERNEL); 46 KUNIT_ASSERT_NOT_NULL(test, priv->cal_blob); 47 48 priv->cal_blob->size = blob_size; 49 priv->cal_blob->count = num_amps; 50 51 get_random_bytes(priv->cal_blob->data, sizeof(struct cirrus_amp_cal_data) * num_amps); 52 } 53 54 static u64 cs_amp_lib_test_get_target_uid(struct kunit *test) 55 { 56 struct cs_amp_lib_test_priv *priv = test->priv; 57 const struct cs_amp_lib_test_param *param = test->param_value; 58 u64 uid; 59 60 uid = priv->cal_blob->data[param->amp_index].calTarget[1]; 61 uid <<= 32; 62 uid |= priv->cal_blob->data[param->amp_index].calTarget[0]; 63 64 return uid; 65 } 66 67 /* Redirected get_efi_variable to simulate that the file is too short */ 68 static efi_status_t cs_amp_lib_test_get_efi_variable_nohead(efi_char16_t *name, 69 efi_guid_t *guid, 70 unsigned long *size, 71 void *buf) 72 { 73 if (!buf) { 74 *size = offsetof(struct cirrus_amp_efi_data, data) - 1; 75 return EFI_BUFFER_TOO_SMALL; 76 } 77 78 return EFI_NOT_FOUND; 79 } 80 81 /* Should return -EOVERFLOW if the header is larger than the EFI data */ 82 static void cs_amp_lib_test_cal_data_too_short_test(struct kunit *test) 83 { 84 struct cs_amp_lib_test_priv *priv = test->priv; 85 struct cirrus_amp_cal_data result_data; 86 int ret; 87 88 /* Redirect calls to get EFI data */ 89 kunit_activate_static_stub(test, 90 cs_amp_test_hooks->get_efi_variable, 91 cs_amp_lib_test_get_efi_variable_nohead); 92 93 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 0, &result_data); 94 KUNIT_EXPECT_EQ(test, ret, -EOVERFLOW); 95 96 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 97 } 98 99 /* Redirected get_efi_variable to simulate that the count is larger than the file */ 100 static efi_status_t cs_amp_lib_test_get_efi_variable_bad_count(efi_char16_t *name, 101 efi_guid_t *guid, 102 unsigned long *size, 103 void *buf) 104 { 105 struct kunit *test = kunit_get_current_test(); 106 struct cs_amp_lib_test_priv *priv = test->priv; 107 108 if (!buf) { 109 /* 110 * Return a size that is shorter than required for the 111 * declared number of entries. 112 */ 113 *size = priv->cal_blob->size - 1; 114 return EFI_BUFFER_TOO_SMALL; 115 } 116 117 memcpy(buf, priv->cal_blob, priv->cal_blob->size - 1); 118 119 return EFI_SUCCESS; 120 } 121 122 /* Should return -EOVERFLOW if the entry count is larger than the EFI data */ 123 static void cs_amp_lib_test_cal_count_too_big_test(struct kunit *test) 124 { 125 struct cs_amp_lib_test_priv *priv = test->priv; 126 struct cirrus_amp_cal_data result_data; 127 int ret; 128 129 cs_amp_lib_test_init_dummy_cal_blob(test, 8); 130 131 /* Redirect calls to get EFI data */ 132 kunit_activate_static_stub(test, 133 cs_amp_test_hooks->get_efi_variable, 134 cs_amp_lib_test_get_efi_variable_bad_count); 135 136 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 0, &result_data); 137 KUNIT_EXPECT_EQ(test, ret, -EOVERFLOW); 138 139 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 140 } 141 142 /* Redirected get_efi_variable to simulate that the variable not found */ 143 static efi_status_t cs_amp_lib_test_get_efi_variable_none(efi_char16_t *name, 144 efi_guid_t *guid, 145 unsigned long *size, 146 void *buf) 147 { 148 return EFI_NOT_FOUND; 149 } 150 151 /* If EFI doesn't contain a cal data variable the result should be -ENOENT */ 152 static void cs_amp_lib_test_no_cal_data_test(struct kunit *test) 153 { 154 struct cs_amp_lib_test_priv *priv = test->priv; 155 struct cirrus_amp_cal_data result_data; 156 int ret; 157 158 /* Redirect calls to get EFI data */ 159 kunit_activate_static_stub(test, 160 cs_amp_test_hooks->get_efi_variable, 161 cs_amp_lib_test_get_efi_variable_none); 162 163 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 0, &result_data); 164 KUNIT_EXPECT_EQ(test, ret, -ENOENT); 165 166 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 167 } 168 169 /* Redirected get_efi_variable to simulate reading a cal data blob */ 170 static efi_status_t cs_amp_lib_test_get_efi_variable(efi_char16_t *name, 171 efi_guid_t *guid, 172 unsigned long *size, 173 void *buf) 174 { 175 static const efi_char16_t expected_name[] = L"CirrusSmartAmpCalibrationData"; 176 static const efi_guid_t expected_guid = 177 EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3); 178 struct kunit *test = kunit_get_current_test(); 179 struct cs_amp_lib_test_priv *priv = test->priv; 180 181 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, name); 182 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, guid); 183 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, size); 184 185 KUNIT_EXPECT_MEMEQ(test, name, expected_name, sizeof(expected_name)); 186 KUNIT_EXPECT_MEMEQ(test, guid, &expected_guid, sizeof(expected_guid)); 187 188 if (!buf) { 189 *size = priv->cal_blob->size; 190 return EFI_BUFFER_TOO_SMALL; 191 } 192 193 KUNIT_ASSERT_GE_MSG(test, ksize(buf), priv->cal_blob->size, "Buffer to small"); 194 195 memcpy(buf, priv->cal_blob, priv->cal_blob->size); 196 197 return EFI_SUCCESS; 198 } 199 200 /* Get cal data block for a given amp, matched by target UID. */ 201 static void cs_amp_lib_test_get_efi_cal_by_uid_test(struct kunit *test) 202 { 203 struct cs_amp_lib_test_priv *priv = test->priv; 204 const struct cs_amp_lib_test_param *param = test->param_value; 205 struct cirrus_amp_cal_data result_data; 206 u64 target_uid; 207 int ret; 208 209 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps); 210 211 /* Redirect calls to get EFI data */ 212 kunit_activate_static_stub(test, 213 cs_amp_test_hooks->get_efi_variable, 214 cs_amp_lib_test_get_efi_variable); 215 216 target_uid = cs_amp_lib_test_get_target_uid(test); 217 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, target_uid, -1, &result_data); 218 KUNIT_EXPECT_EQ(test, ret, 0); 219 220 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 221 222 KUNIT_EXPECT_EQ(test, result_data.calTarget[0], target_uid & 0xFFFFFFFFULL); 223 KUNIT_EXPECT_EQ(test, result_data.calTarget[1], target_uid >> 32); 224 KUNIT_EXPECT_EQ(test, result_data.calTime[0], 225 priv->cal_blob->data[param->amp_index].calTime[0]); 226 KUNIT_EXPECT_EQ(test, result_data.calTime[1], 227 priv->cal_blob->data[param->amp_index].calTime[1]); 228 KUNIT_EXPECT_EQ(test, result_data.calAmbient, 229 priv->cal_blob->data[param->amp_index].calAmbient); 230 KUNIT_EXPECT_EQ(test, result_data.calStatus, 231 priv->cal_blob->data[param->amp_index].calStatus); 232 KUNIT_EXPECT_EQ(test, result_data.calR, 233 priv->cal_blob->data[param->amp_index].calR); 234 } 235 236 /* Get cal data block for a given amp index without checking target UID. */ 237 static void cs_amp_lib_test_get_efi_cal_by_index_unchecked_test(struct kunit *test) 238 { 239 struct cs_amp_lib_test_priv *priv = test->priv; 240 const struct cs_amp_lib_test_param *param = test->param_value; 241 struct cirrus_amp_cal_data result_data; 242 int ret; 243 244 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps); 245 246 /* Redirect calls to get EFI data */ 247 kunit_activate_static_stub(test, 248 cs_amp_test_hooks->get_efi_variable, 249 cs_amp_lib_test_get_efi_variable); 250 251 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 252 param->amp_index, &result_data); 253 KUNIT_EXPECT_EQ(test, ret, 0); 254 255 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 256 257 KUNIT_EXPECT_EQ(test, result_data.calTime[0], 258 priv->cal_blob->data[param->amp_index].calTime[0]); 259 KUNIT_EXPECT_EQ(test, result_data.calTime[1], 260 priv->cal_blob->data[param->amp_index].calTime[1]); 261 KUNIT_EXPECT_EQ(test, result_data.calAmbient, 262 priv->cal_blob->data[param->amp_index].calAmbient); 263 KUNIT_EXPECT_EQ(test, result_data.calStatus, 264 priv->cal_blob->data[param->amp_index].calStatus); 265 KUNIT_EXPECT_EQ(test, result_data.calR, 266 priv->cal_blob->data[param->amp_index].calR); 267 } 268 269 /* Get cal data block for a given amp index with checked target UID. */ 270 static void cs_amp_lib_test_get_efi_cal_by_index_checked_test(struct kunit *test) 271 { 272 struct cs_amp_lib_test_priv *priv = test->priv; 273 const struct cs_amp_lib_test_param *param = test->param_value; 274 struct cirrus_amp_cal_data result_data; 275 u64 target_uid; 276 int ret; 277 278 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps); 279 280 /* Redirect calls to get EFI data */ 281 kunit_activate_static_stub(test, 282 cs_amp_test_hooks->get_efi_variable, 283 cs_amp_lib_test_get_efi_variable); 284 285 target_uid = cs_amp_lib_test_get_target_uid(test); 286 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, target_uid, 287 param->amp_index, &result_data); 288 KUNIT_EXPECT_EQ(test, ret, 0); 289 290 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 291 292 KUNIT_EXPECT_EQ(test, result_data.calTime[0], 293 priv->cal_blob->data[param->amp_index].calTime[0]); 294 KUNIT_EXPECT_EQ(test, result_data.calTime[1], 295 priv->cal_blob->data[param->amp_index].calTime[1]); 296 KUNIT_EXPECT_EQ(test, result_data.calAmbient, 297 priv->cal_blob->data[param->amp_index].calAmbient); 298 KUNIT_EXPECT_EQ(test, result_data.calStatus, 299 priv->cal_blob->data[param->amp_index].calStatus); 300 KUNIT_EXPECT_EQ(test, result_data.calR, 301 priv->cal_blob->data[param->amp_index].calR); 302 } 303 304 /* 305 * Get cal data block for a given amp index with checked target UID. 306 * The UID does not match so the result should be -ENOENT. 307 */ 308 static void cs_amp_lib_test_get_efi_cal_by_index_uid_mismatch_test(struct kunit *test) 309 { 310 struct cs_amp_lib_test_priv *priv = test->priv; 311 const struct cs_amp_lib_test_param *param = test->param_value; 312 struct cirrus_amp_cal_data result_data; 313 u64 target_uid; 314 int ret; 315 316 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps); 317 318 /* Redirect calls to get EFI data */ 319 kunit_activate_static_stub(test, 320 cs_amp_test_hooks->get_efi_variable, 321 cs_amp_lib_test_get_efi_variable); 322 323 /* Get a target UID that won't match the entry */ 324 target_uid = ~cs_amp_lib_test_get_target_uid(test); 325 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, target_uid, 326 param->amp_index, &result_data); 327 KUNIT_EXPECT_EQ(test, ret, -ENOENT); 328 329 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 330 } 331 332 /* 333 * Get cal data block for a given amp, where the cal data does not 334 * specify calTarget so the lookup falls back to using the index 335 */ 336 static void cs_amp_lib_test_get_efi_cal_by_index_fallback_test(struct kunit *test) 337 { 338 struct cs_amp_lib_test_priv *priv = test->priv; 339 const struct cs_amp_lib_test_param *param = test->param_value; 340 struct cirrus_amp_cal_data result_data; 341 static const u64 bad_target_uid = 0xBADCA100BABABABAULL; 342 int i, ret; 343 344 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps); 345 346 /* Make all the target values zero so they are ignored */ 347 for (i = 0; i < priv->cal_blob->count; ++i) { 348 priv->cal_blob->data[i].calTarget[0] = 0; 349 priv->cal_blob->data[i].calTarget[1] = 0; 350 } 351 352 /* Redirect calls to get EFI data */ 353 kunit_activate_static_stub(test, 354 cs_amp_test_hooks->get_efi_variable, 355 cs_amp_lib_test_get_efi_variable); 356 357 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, bad_target_uid, 358 param->amp_index, &result_data); 359 KUNIT_EXPECT_EQ(test, ret, 0); 360 361 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 362 363 KUNIT_EXPECT_EQ(test, result_data.calTime[0], 364 priv->cal_blob->data[param->amp_index].calTime[0]); 365 KUNIT_EXPECT_EQ(test, result_data.calTime[1], 366 priv->cal_blob->data[param->amp_index].calTime[1]); 367 KUNIT_EXPECT_EQ(test, result_data.calAmbient, 368 priv->cal_blob->data[param->amp_index].calAmbient); 369 KUNIT_EXPECT_EQ(test, result_data.calStatus, 370 priv->cal_blob->data[param->amp_index].calStatus); 371 KUNIT_EXPECT_EQ(test, result_data.calR, 372 priv->cal_blob->data[param->amp_index].calR); 373 } 374 375 /* 376 * If the target UID isn't present in the cal data, and there isn't an 377 * index to fall back do, the result should be -ENOENT. 378 */ 379 static void cs_amp_lib_test_get_efi_cal_uid_not_found_noindex_test(struct kunit *test) 380 { 381 struct cs_amp_lib_test_priv *priv = test->priv; 382 struct cirrus_amp_cal_data result_data; 383 static const u64 bad_target_uid = 0xBADCA100BABABABAULL; 384 int i, ret; 385 386 cs_amp_lib_test_init_dummy_cal_blob(test, 8); 387 388 /* Make all the target values != bad_target_uid */ 389 for (i = 0; i < priv->cal_blob->count; ++i) { 390 priv->cal_blob->data[i].calTarget[0] &= ~(bad_target_uid & 0xFFFFFFFFULL); 391 priv->cal_blob->data[i].calTarget[1] &= ~(bad_target_uid >> 32); 392 } 393 394 /* Redirect calls to get EFI data */ 395 kunit_activate_static_stub(test, 396 cs_amp_test_hooks->get_efi_variable, 397 cs_amp_lib_test_get_efi_variable); 398 399 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, bad_target_uid, -1, 400 &result_data); 401 KUNIT_EXPECT_EQ(test, ret, -ENOENT); 402 403 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 404 } 405 406 /* 407 * If the target UID isn't present in the cal data, and the index is 408 * out of range, the result should be -ENOENT. 409 */ 410 static void cs_amp_lib_test_get_efi_cal_uid_not_found_index_not_found_test(struct kunit *test) 411 { 412 struct cs_amp_lib_test_priv *priv = test->priv; 413 struct cirrus_amp_cal_data result_data; 414 static const u64 bad_target_uid = 0xBADCA100BABABABAULL; 415 int i, ret; 416 417 cs_amp_lib_test_init_dummy_cal_blob(test, 8); 418 419 /* Make all the target values != bad_target_uid */ 420 for (i = 0; i < priv->cal_blob->count; ++i) { 421 priv->cal_blob->data[i].calTarget[0] &= ~(bad_target_uid & 0xFFFFFFFFULL); 422 priv->cal_blob->data[i].calTarget[1] &= ~(bad_target_uid >> 32); 423 } 424 425 /* Redirect calls to get EFI data */ 426 kunit_activate_static_stub(test, 427 cs_amp_test_hooks->get_efi_variable, 428 cs_amp_lib_test_get_efi_variable); 429 430 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, bad_target_uid, 99, 431 &result_data); 432 KUNIT_EXPECT_EQ(test, ret, -ENOENT); 433 434 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 435 } 436 437 /* 438 * If the target UID isn't given, and the index is out of range, the 439 * result should be -ENOENT. 440 */ 441 static void cs_amp_lib_test_get_efi_cal_no_uid_index_not_found_test(struct kunit *test) 442 { 443 struct cs_amp_lib_test_priv *priv = test->priv; 444 struct cirrus_amp_cal_data result_data; 445 int ret; 446 447 cs_amp_lib_test_init_dummy_cal_blob(test, 8); 448 449 /* Redirect calls to get EFI data */ 450 kunit_activate_static_stub(test, 451 cs_amp_test_hooks->get_efi_variable, 452 cs_amp_lib_test_get_efi_variable); 453 454 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 99, &result_data); 455 KUNIT_EXPECT_EQ(test, ret, -ENOENT); 456 457 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 458 } 459 460 /* If neither the target UID or the index is given the result should be -ENOENT. */ 461 static void cs_amp_lib_test_get_efi_cal_no_uid_no_index_test(struct kunit *test) 462 { 463 struct cs_amp_lib_test_priv *priv = test->priv; 464 struct cirrus_amp_cal_data result_data; 465 int ret; 466 467 cs_amp_lib_test_init_dummy_cal_blob(test, 8); 468 469 /* Redirect calls to get EFI data */ 470 kunit_activate_static_stub(test, 471 cs_amp_test_hooks->get_efi_variable, 472 cs_amp_lib_test_get_efi_variable); 473 474 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, -1, &result_data); 475 KUNIT_EXPECT_EQ(test, ret, -ENOENT); 476 477 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 478 } 479 480 /* 481 * If the UID is passed as 0 this must not match an entry with an 482 * unpopulated calTarget 483 */ 484 static void cs_amp_lib_test_get_efi_cal_zero_not_matched_test(struct kunit *test) 485 { 486 struct cs_amp_lib_test_priv *priv = test->priv; 487 struct cirrus_amp_cal_data result_data; 488 int i, ret; 489 490 cs_amp_lib_test_init_dummy_cal_blob(test, 8); 491 492 /* Make all the target values zero so they are ignored */ 493 for (i = 0; i < priv->cal_blob->count; ++i) { 494 priv->cal_blob->data[i].calTarget[0] = 0; 495 priv->cal_blob->data[i].calTarget[1] = 0; 496 } 497 498 /* Redirect calls to get EFI data */ 499 kunit_activate_static_stub(test, 500 cs_amp_test_hooks->get_efi_variable, 501 cs_amp_lib_test_get_efi_variable); 502 503 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, -1, &result_data); 504 KUNIT_EXPECT_EQ(test, ret, -ENOENT); 505 506 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable); 507 } 508 509 static const struct cirrus_amp_cal_controls cs_amp_lib_test_calibration_controls = { 510 .alg_id = 0x9f210, 511 .mem_region = WMFW_ADSP2_YM, 512 .ambient = "CAL_AMBIENT", 513 .calr = "CAL_R", 514 .status = "CAL_STATUS", 515 .checksum = "CAL_CHECKSUM", 516 }; 517 518 static int cs_amp_lib_test_write_cal_coeff(struct cs_dsp *dsp, 519 const struct cirrus_amp_cal_controls *controls, 520 const char *ctl_name, u32 val) 521 { 522 struct kunit *test = kunit_get_current_test(); 523 struct cs_amp_lib_test_priv *priv = test->priv; 524 struct cs_amp_lib_test_ctl_write_entry *entry; 525 526 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_name); 527 KUNIT_EXPECT_PTR_EQ(test, controls, &cs_amp_lib_test_calibration_controls); 528 529 entry = kunit_kzalloc(test, sizeof(*entry), GFP_KERNEL); 530 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, entry); 531 532 INIT_LIST_HEAD(&entry->list); 533 strscpy(entry->name, ctl_name, sizeof(entry->name)); 534 entry->value = val; 535 536 list_add_tail(&entry->list, &priv->ctl_write_list); 537 538 return 0; 539 } 540 541 static void cs_amp_lib_test_write_cal_data_test(struct kunit *test) 542 { 543 struct cs_amp_lib_test_priv *priv = test->priv; 544 struct cs_amp_lib_test_ctl_write_entry *entry; 545 struct cirrus_amp_cal_data data; 546 struct cs_dsp *dsp; 547 int ret; 548 549 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); 550 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp); 551 dsp->dev = &priv->amp_pdev.dev; 552 553 get_random_bytes(&data, sizeof(data)); 554 555 /* Redirect calls to write firmware controls */ 556 kunit_activate_static_stub(test, 557 cs_amp_test_hooks->write_cal_coeff, 558 cs_amp_lib_test_write_cal_coeff); 559 560 ret = cs_amp_write_cal_coeffs(dsp, &cs_amp_lib_test_calibration_controls, &data); 561 KUNIT_EXPECT_EQ(test, ret, 0); 562 563 kunit_deactivate_static_stub(test, cs_amp_test_hooks->write_cal_coeff); 564 565 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->ctl_write_list), 4); 566 567 /* Checksum control must be written last */ 568 entry = list_last_entry(&priv->ctl_write_list, typeof(*entry), list); 569 KUNIT_EXPECT_STREQ(test, entry->name, cs_amp_lib_test_calibration_controls.checksum); 570 KUNIT_EXPECT_EQ(test, entry->value, data.calR + 1); 571 list_del(&entry->list); 572 573 entry = list_first_entry(&priv->ctl_write_list, typeof(*entry), list); 574 KUNIT_EXPECT_STREQ(test, entry->name, cs_amp_lib_test_calibration_controls.ambient); 575 KUNIT_EXPECT_EQ(test, entry->value, data.calAmbient); 576 list_del(&entry->list); 577 578 entry = list_first_entry(&priv->ctl_write_list, typeof(*entry), list); 579 KUNIT_EXPECT_STREQ(test, entry->name, cs_amp_lib_test_calibration_controls.calr); 580 KUNIT_EXPECT_EQ(test, entry->value, data.calR); 581 list_del(&entry->list); 582 583 entry = list_first_entry(&priv->ctl_write_list, typeof(*entry), list); 584 KUNIT_EXPECT_STREQ(test, entry->name, cs_amp_lib_test_calibration_controls.status); 585 KUNIT_EXPECT_EQ(test, entry->value, data.calStatus); 586 } 587 588 static void cs_amp_lib_test_dev_release(struct device *dev) 589 { 590 } 591 592 static int cs_amp_lib_test_case_init(struct kunit *test) 593 { 594 struct cs_amp_lib_test_priv *priv; 595 int ret; 596 597 KUNIT_ASSERT_NOT_NULL(test, cs_amp_test_hooks); 598 599 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 600 if (!priv) 601 return -ENOMEM; 602 603 test->priv = priv; 604 INIT_LIST_HEAD(&priv->ctl_write_list); 605 606 /* Create dummy amp driver dev */ 607 priv->amp_pdev.name = "cs_amp_lib_test_drv"; 608 priv->amp_pdev.id = -1; 609 priv->amp_pdev.dev.release = cs_amp_lib_test_dev_release; 610 ret = platform_device_register(&priv->amp_pdev); 611 KUNIT_ASSERT_GE_MSG(test, ret, 0, "Failed to register amp platform device\n"); 612 613 return 0; 614 } 615 616 static void cs_amp_lib_test_case_exit(struct kunit *test) 617 { 618 struct cs_amp_lib_test_priv *priv = test->priv; 619 620 if (priv->amp_pdev.name) 621 platform_device_unregister(&priv->amp_pdev); 622 } 623 624 static const struct cs_amp_lib_test_param cs_amp_lib_test_get_cal_param_cases[] = { 625 { .num_amps = 2, .amp_index = 0 }, 626 { .num_amps = 2, .amp_index = 1 }, 627 628 { .num_amps = 3, .amp_index = 0 }, 629 { .num_amps = 3, .amp_index = 1 }, 630 { .num_amps = 3, .amp_index = 2 }, 631 632 { .num_amps = 4, .amp_index = 0 }, 633 { .num_amps = 4, .amp_index = 1 }, 634 { .num_amps = 4, .amp_index = 2 }, 635 { .num_amps = 4, .amp_index = 3 }, 636 637 { .num_amps = 5, .amp_index = 0 }, 638 { .num_amps = 5, .amp_index = 1 }, 639 { .num_amps = 5, .amp_index = 2 }, 640 { .num_amps = 5, .amp_index = 3 }, 641 { .num_amps = 5, .amp_index = 4 }, 642 643 { .num_amps = 6, .amp_index = 0 }, 644 { .num_amps = 6, .amp_index = 1 }, 645 { .num_amps = 6, .amp_index = 2 }, 646 { .num_amps = 6, .amp_index = 3 }, 647 { .num_amps = 6, .amp_index = 4 }, 648 { .num_amps = 6, .amp_index = 5 }, 649 650 { .num_amps = 8, .amp_index = 0 }, 651 { .num_amps = 8, .amp_index = 1 }, 652 { .num_amps = 8, .amp_index = 2 }, 653 { .num_amps = 8, .amp_index = 3 }, 654 { .num_amps = 8, .amp_index = 4 }, 655 { .num_amps = 8, .amp_index = 5 }, 656 { .num_amps = 8, .amp_index = 6 }, 657 { .num_amps = 8, .amp_index = 7 }, 658 }; 659 660 static void cs_amp_lib_test_get_cal_param_desc(const struct cs_amp_lib_test_param *param, 661 char *desc) 662 { 663 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "num_amps:%d amp_index:%d", 664 param->num_amps, param->amp_index); 665 } 666 667 KUNIT_ARRAY_PARAM(cs_amp_lib_test_get_cal, cs_amp_lib_test_get_cal_param_cases, 668 cs_amp_lib_test_get_cal_param_desc); 669 670 static struct kunit_case cs_amp_lib_test_cases[] = { 671 /* Tests for getting calibration data from EFI */ 672 KUNIT_CASE(cs_amp_lib_test_cal_data_too_short_test), 673 KUNIT_CASE(cs_amp_lib_test_cal_count_too_big_test), 674 KUNIT_CASE(cs_amp_lib_test_no_cal_data_test), 675 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_uid_not_found_noindex_test), 676 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_uid_not_found_index_not_found_test), 677 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_index_not_found_test), 678 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_no_uid_no_index_test), 679 KUNIT_CASE(cs_amp_lib_test_get_efi_cal_zero_not_matched_test), 680 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_uid_test, 681 cs_amp_lib_test_get_cal_gen_params), 682 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_unchecked_test, 683 cs_amp_lib_test_get_cal_gen_params), 684 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_checked_test, 685 cs_amp_lib_test_get_cal_gen_params), 686 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_uid_mismatch_test, 687 cs_amp_lib_test_get_cal_gen_params), 688 KUNIT_CASE_PARAM(cs_amp_lib_test_get_efi_cal_by_index_fallback_test, 689 cs_amp_lib_test_get_cal_gen_params), 690 691 /* Tests for writing calibration data */ 692 KUNIT_CASE(cs_amp_lib_test_write_cal_data_test), 693 694 { } /* terminator */ 695 }; 696 697 static struct kunit_suite cs_amp_lib_test_suite = { 698 .name = "snd-soc-cs-amp-lib-test", 699 .init = cs_amp_lib_test_case_init, 700 .exit = cs_amp_lib_test_case_exit, 701 .test_cases = cs_amp_lib_test_cases, 702 }; 703 704 kunit_test_suite(cs_amp_lib_test_suite); 705 706 MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB); 707 MODULE_DESCRIPTION("KUnit test for Cirrus Logic amplifier library"); 708 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 709 MODULE_LICENSE("GPL"); 710