763 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// KUnit test for the Cirrus common amplifier library.4//5// Copyright (C) 2024 Cirrus Logic, Inc. and6// 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 19struct 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 26struct cs_amp_lib_test_ctl_write_entry {27 struct list_head list;28 unsigned int value;29 char name[16];30};31 32struct cs_amp_lib_test_param {33 int num_amps;34 int amp_index;35};36 37static 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 int i;42 43 blob_size = offsetof(struct cirrus_amp_efi_data, data) +44 sizeof(struct cirrus_amp_cal_data) * num_amps;45 46 priv->cal_blob = kunit_kzalloc(test, blob_size, GFP_KERNEL);47 KUNIT_ASSERT_NOT_NULL(test, priv->cal_blob);48 49 priv->cal_blob->size = blob_size;50 priv->cal_blob->count = num_amps;51 52 get_random_bytes(priv->cal_blob->data, sizeof(struct cirrus_amp_cal_data) * num_amps);53 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;57 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;61}62 63static u64 cs_amp_lib_test_get_target_uid(struct kunit *test)64{65 struct cs_amp_lib_test_priv *priv = test->priv;66 const struct cs_amp_lib_test_param *param = test->param_value;67 u64 uid;68 69 uid = priv->cal_blob->data[param->amp_index].calTarget[1];70 uid <<= 32;71 uid |= priv->cal_blob->data[param->amp_index].calTarget[0];72 73 return uid;74}75 76/* Redirected get_efi_variable to simulate that the file is too short */77static efi_status_t cs_amp_lib_test_get_efi_variable_nohead(efi_char16_t *name,78 efi_guid_t *guid,79 unsigned long *size,80 void *buf)81{82 if (!buf) {83 *size = offsetof(struct cirrus_amp_efi_data, data) - 1;84 return EFI_BUFFER_TOO_SMALL;85 }86 87 return EFI_NOT_FOUND;88}89 90/* Should return -EOVERFLOW if the header is larger than the EFI data */91static void cs_amp_lib_test_cal_data_too_short_test(struct kunit *test)92{93 struct cs_amp_lib_test_priv *priv = test->priv;94 struct cirrus_amp_cal_data result_data;95 int ret;96 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);101 102 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 0, &result_data);103 KUNIT_EXPECT_EQ(test, ret, -EOVERFLOW);104 105 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);106}107 108/* Redirected get_efi_variable to simulate that the count is larger than the file */109static efi_status_t cs_amp_lib_test_get_efi_variable_bad_count(efi_char16_t *name,110 efi_guid_t *guid,111 unsigned long *size,112 void *buf)113{114 struct kunit *test = kunit_get_current_test();115 struct cs_amp_lib_test_priv *priv = test->priv;116 117 if (!buf) {118 /*119 * Return a size that is shorter than required for the120 * declared number of entries.121 */122 *size = priv->cal_blob->size - 1;123 return EFI_BUFFER_TOO_SMALL;124 }125 126 memcpy(buf, priv->cal_blob, priv->cal_blob->size - 1);127 128 return EFI_SUCCESS;129}130 131/* Should return -EOVERFLOW if the entry count is larger than the EFI data */132static void cs_amp_lib_test_cal_count_too_big_test(struct kunit *test)133{134 struct cs_amp_lib_test_priv *priv = test->priv;135 struct cirrus_amp_cal_data result_data;136 int ret;137 138 cs_amp_lib_test_init_dummy_cal_blob(test, 8);139 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);144 145 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 0, &result_data);146 KUNIT_EXPECT_EQ(test, ret, -EOVERFLOW);147 148 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);149}150 151/* Redirected get_efi_variable to simulate that the variable not found */152static efi_status_t cs_amp_lib_test_get_efi_variable_none(efi_char16_t *name,153 efi_guid_t *guid,154 unsigned long *size,155 void *buf)156{157 return EFI_NOT_FOUND;158}159 160/* If EFI doesn't contain a cal data variable the result should be -ENOENT */161static void cs_amp_lib_test_no_cal_data_test(struct kunit *test)162{163 struct cs_amp_lib_test_priv *priv = test->priv;164 struct cirrus_amp_cal_data result_data;165 int ret;166 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);171 172 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 0, &result_data);173 KUNIT_EXPECT_EQ(test, ret, -ENOENT);174 175 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);176}177 178/* Redirected get_efi_variable to simulate reading a cal data blob */179static efi_status_t cs_amp_lib_test_get_efi_variable(efi_char16_t *name,180 efi_guid_t *guid,181 unsigned long *size,182 void *buf)183{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;189 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);193 194 KUNIT_EXPECT_MEMEQ(test, name, expected_name, sizeof(expected_name));195 KUNIT_EXPECT_MEMEQ(test, guid, &expected_guid, sizeof(expected_guid));196 197 if (!buf) {198 *size = priv->cal_blob->size;199 return EFI_BUFFER_TOO_SMALL;200 }201 202 KUNIT_ASSERT_GE_MSG(test, ksize(buf), priv->cal_blob->size, "Buffer to small");203 204 memcpy(buf, priv->cal_blob, priv->cal_blob->size);205 206 return EFI_SUCCESS;207}208 209/* Get cal data block for a given amp, matched by target UID. */210static void cs_amp_lib_test_get_efi_cal_by_uid_test(struct kunit *test)211{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;215 u64 target_uid;216 int ret;217 218 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps);219 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);224 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);228 229 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);230 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);243}244 245/* Get cal data block for a given amp index without checking target UID. */246static void cs_amp_lib_test_get_efi_cal_by_index_unchecked_test(struct kunit *test)247{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;251 int ret;252 253 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps);254 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);259 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);263 264 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);265 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);276}277 278/* Get cal data block for a given amp index with checked target UID. */279static void cs_amp_lib_test_get_efi_cal_by_index_checked_test(struct kunit *test)280{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;284 u64 target_uid;285 int ret;286 287 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps);288 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);293 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);298 299 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);300 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);311}312 313/*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.316 */317static void cs_amp_lib_test_get_efi_cal_by_index_uid_mismatch_test(struct kunit *test)318{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;322 u64 target_uid;323 int ret;324 325 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps);326 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);331 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);337 338 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);339}340 341/*342 * Get cal data block for a given amp, where the cal data does not343 * specify calTarget so the lookup falls back to using the index344 */345static void cs_amp_lib_test_get_efi_cal_by_index_fallback_test(struct kunit *test)346{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;351 int i, ret;352 353 cs_amp_lib_test_init_dummy_cal_blob(test, param->num_amps);354 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;359 }360 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);365 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);369 370 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);371 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);382}383 384/*385 * If the target UID isn't present in the cal data, and there isn't an386 * index to fall back do, the result should be -ENOENT.387 */388static void cs_amp_lib_test_get_efi_cal_uid_not_found_noindex_test(struct kunit *test)389{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;393 int i, ret;394 395 cs_amp_lib_test_init_dummy_cal_blob(test, 8);396 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);401 }402 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);407 408 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, bad_target_uid, -1,409 &result_data);410 KUNIT_EXPECT_EQ(test, ret, -ENOENT);411 412 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);413}414 415/*416 * If the target UID isn't present in the cal data, and the index is417 * out of range, the result should be -ENOENT.418 */419static void cs_amp_lib_test_get_efi_cal_uid_not_found_index_not_found_test(struct kunit *test)420{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;424 int i, ret;425 426 cs_amp_lib_test_init_dummy_cal_blob(test, 8);427 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);432 }433 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);438 439 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, bad_target_uid, 99,440 &result_data);441 KUNIT_EXPECT_EQ(test, ret, -ENOENT);442 443 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);444}445 446/*447 * If the target UID isn't given, and the index is out of range, the448 * result should be -ENOENT.449 */450static void cs_amp_lib_test_get_efi_cal_no_uid_index_not_found_test(struct kunit *test)451{452 struct cs_amp_lib_test_priv *priv = test->priv;453 struct cirrus_amp_cal_data result_data;454 int ret;455 456 cs_amp_lib_test_init_dummy_cal_blob(test, 8);457 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);462 463 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, 99, &result_data);464 KUNIT_EXPECT_EQ(test, ret, -ENOENT);465 466 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);467}468 469/* If neither the target UID or the index is given the result should be -ENOENT. */470static void cs_amp_lib_test_get_efi_cal_no_uid_no_index_test(struct kunit *test)471{472 struct cs_amp_lib_test_priv *priv = test->priv;473 struct cirrus_amp_cal_data result_data;474 int ret;475 476 cs_amp_lib_test_init_dummy_cal_blob(test, 8);477 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);482 483 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, -1, &result_data);484 KUNIT_EXPECT_EQ(test, ret, -ENOENT);485 486 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);487}488 489/*490 * If the UID is passed as 0 this must not match an entry with an491 * unpopulated calTarget492 */493static void cs_amp_lib_test_get_efi_cal_zero_not_matched_test(struct kunit *test)494{495 struct cs_amp_lib_test_priv *priv = test->priv;496 struct cirrus_amp_cal_data result_data;497 int i, ret;498 499 cs_amp_lib_test_init_dummy_cal_blob(test, 8);500 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;505 }506 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);511 512 ret = cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev, 0, -1, &result_data);513 KUNIT_EXPECT_EQ(test, ret, -ENOENT);514 515 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);516}517 518/*519 * If an entry has a timestamp of 0 it should be ignored even if it has520 * a matching target UID.521 */522static void cs_amp_lib_test_get_efi_cal_empty_entry_test(struct kunit *test)523{524 struct cs_amp_lib_test_priv *priv = test->priv;525 struct cirrus_amp_cal_data result_data;526 u64 uid;527 528 cs_amp_lib_test_init_dummy_cal_blob(test, 8);529 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;533 534 /* Get the UID value of the 3rd entry */535 uid = priv->cal_blob->data[2].calTarget[1];536 uid <<= 32;537 uid |= priv->cal_blob->data[2].calTarget[0];538 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);543 544 /* Lookup by UID should not find it */545 KUNIT_EXPECT_EQ(test,546 cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev,547 uid, -1,548 &result_data),549 -ENOENT);550 551 /* Get by index should ignore it */552 KUNIT_EXPECT_EQ(test,553 cs_amp_get_efi_calibration_data(&priv->amp_pdev.dev,554 0, 2,555 &result_data),556 -ENOENT);557 558 kunit_deactivate_static_stub(test, cs_amp_test_hooks->get_efi_variable);559}560 561static const struct cirrus_amp_cal_controls cs_amp_lib_test_calibration_controls = {562 .alg_id = 0x9f210,563 .mem_region = WMFW_ADSP2_YM,564 .ambient = "CAL_AMBIENT",565 .calr = "CAL_R",566 .status = "CAL_STATUS",567 .checksum = "CAL_CHECKSUM",568};569 570static 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)573{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;577 578 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_name);579 KUNIT_EXPECT_PTR_EQ(test, controls, &cs_amp_lib_test_calibration_controls);580 581 entry = kunit_kzalloc(test, sizeof(*entry), GFP_KERNEL);582 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, entry);583 584 INIT_LIST_HEAD(&entry->list);585 strscpy(entry->name, ctl_name, sizeof(entry->name));586 entry->value = val;587 588 list_add_tail(&entry->list, &priv->ctl_write_list);589 590 return 0;591}592 593static void cs_amp_lib_test_write_cal_data_test(struct kunit *test)594{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;598 struct cs_dsp *dsp;599 int ret;600 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;604 605 get_random_bytes(&data, sizeof(data));606 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);611 612 ret = cs_amp_write_cal_coeffs(dsp, &cs_amp_lib_test_calibration_controls, &data);613 KUNIT_EXPECT_EQ(test, ret, 0);614 615 kunit_deactivate_static_stub(test, cs_amp_test_hooks->write_cal_coeff);616 617 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->ctl_write_list), 4);618 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);624 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);629 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);634 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);638}639 640static void cs_amp_lib_test_dev_release(struct device *dev)641{642}643 644static int cs_amp_lib_test_case_init(struct kunit *test)645{646 struct cs_amp_lib_test_priv *priv;647 int ret;648 649 KUNIT_ASSERT_NOT_NULL(test, cs_amp_test_hooks);650 651 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);652 if (!priv)653 return -ENOMEM;654 655 test->priv = priv;656 INIT_LIST_HEAD(&priv->ctl_write_list);657 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");664 665 return 0;666}667 668static void cs_amp_lib_test_case_exit(struct kunit *test)669{670 struct cs_amp_lib_test_priv *priv = test->priv;671 672 if (priv->amp_pdev.name)673 platform_device_unregister(&priv->amp_pdev);674}675 676static 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 },679 680 { .num_amps = 3, .amp_index = 0 },681 { .num_amps = 3, .amp_index = 1 },682 { .num_amps = 3, .amp_index = 2 },683 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 },688 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 },694 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 },701 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 },710};711 712static void cs_amp_lib_test_get_cal_param_desc(const struct cs_amp_lib_test_param *param,713 char *desc)714{715 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "num_amps:%d amp_index:%d",716 param->num_amps, param->amp_index);717}718 719KUNIT_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);721 722static 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),743 744 /* Tests for writing calibration data */745 KUNIT_CASE(cs_amp_lib_test_write_cal_data_test),746 747 { } /* terminator */748};749 750static 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,755};756 757kunit_test_suite(cs_amp_lib_test_suite);758 759MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);760MODULE_DESCRIPTION("KUnit test for Cirrus Logic amplifier library");761MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");762MODULE_LICENSE("GPL");763