brintos

brintos / linux-shallow public Read only

0
0
Text · 24.7 KiB · a6e8348 Raw
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