xref: /linux/drivers/firmware/cirrus/test/cs_dsp_mock_bin.c (revision a9e6060bb2a6cae6d43a98ec0794844ad01273d3)
17c052c66SRichard Fitzgerald // SPDX-License-Identifier: GPL-2.0-only
27c052c66SRichard Fitzgerald //
37c052c66SRichard Fitzgerald // bin file builder for cs_dsp KUnit tests.
47c052c66SRichard Fitzgerald //
57c052c66SRichard Fitzgerald // Copyright (C) 2024 Cirrus Logic, Inc. and
67c052c66SRichard Fitzgerald //                    Cirrus Logic International Semiconductor Ltd.
77c052c66SRichard Fitzgerald 
87c052c66SRichard Fitzgerald #include <kunit/resource.h>
97c052c66SRichard Fitzgerald #include <kunit/test.h>
107c052c66SRichard Fitzgerald #include <linux/firmware/cirrus/cs_dsp.h>
117c052c66SRichard Fitzgerald #include <linux/firmware/cirrus/cs_dsp_test_utils.h>
127c052c66SRichard Fitzgerald #include <linux/firmware/cirrus/wmfw.h>
137c052c66SRichard Fitzgerald #include <linux/firmware.h>
147c052c66SRichard Fitzgerald #include <linux/math.h>
157c052c66SRichard Fitzgerald #include <linux/overflow.h>
167c052c66SRichard Fitzgerald #include <linux/string.h>
177c052c66SRichard Fitzgerald #include <linux/vmalloc.h>
187c052c66SRichard Fitzgerald 
197c052c66SRichard Fitzgerald /* Buffer large enough for bin file content */
207c052c66SRichard Fitzgerald #define CS_DSP_MOCK_BIN_BUF_SIZE	32768
217c052c66SRichard Fitzgerald 
227c052c66SRichard Fitzgerald KUNIT_DEFINE_ACTION_WRAPPER(vfree_action_wrapper, vfree, void *)
237c052c66SRichard Fitzgerald 
247c052c66SRichard Fitzgerald struct cs_dsp_mock_bin_builder {
257c052c66SRichard Fitzgerald 	struct cs_dsp_test *test_priv;
267c052c66SRichard Fitzgerald 	void *buf;
277c052c66SRichard Fitzgerald 	void *write_p;
287c052c66SRichard Fitzgerald 	size_t bytes_used;
297c052c66SRichard Fitzgerald };
307c052c66SRichard Fitzgerald 
317c052c66SRichard Fitzgerald /**
327c052c66SRichard Fitzgerald  * cs_dsp_mock_bin_get_firmware() - Get struct firmware wrapper for data.
337c052c66SRichard Fitzgerald  *
347c052c66SRichard Fitzgerald  * @builder:	Pointer to struct cs_dsp_mock_bin_builder.
357c052c66SRichard Fitzgerald  *
367c052c66SRichard Fitzgerald  * Return: Pointer to a struct firmware wrapper for the data.
377c052c66SRichard Fitzgerald  */
cs_dsp_mock_bin_get_firmware(struct cs_dsp_mock_bin_builder * builder)387c052c66SRichard Fitzgerald struct firmware *cs_dsp_mock_bin_get_firmware(struct cs_dsp_mock_bin_builder *builder)
397c052c66SRichard Fitzgerald {
407c052c66SRichard Fitzgerald 	struct firmware *fw;
417c052c66SRichard Fitzgerald 
427c052c66SRichard Fitzgerald 	fw = kunit_kzalloc(builder->test_priv->test, sizeof(*fw), GFP_KERNEL);
437c052c66SRichard Fitzgerald 	KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, fw);
447c052c66SRichard Fitzgerald 
457c052c66SRichard Fitzgerald 	fw->data = builder->buf;
467c052c66SRichard Fitzgerald 	fw->size = builder->bytes_used;
477c052c66SRichard Fitzgerald 
487c052c66SRichard Fitzgerald 	return fw;
497c052c66SRichard Fitzgerald }
507c052c66SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_get_firmware, "FW_CS_DSP_KUNIT_TEST_UTILS");
517c052c66SRichard Fitzgerald 
527c052c66SRichard Fitzgerald /**
537c052c66SRichard Fitzgerald  * cs_dsp_mock_bin_add_raw_block() - Add a data block to the bin file.
547c052c66SRichard Fitzgerald  *
557c052c66SRichard Fitzgerald  * @builder:		Pointer to struct cs_dsp_mock_bin_builder.
56539a3f0cSRichard Fitzgerald  * @alg_id:		Algorithm ID.
577c052c66SRichard Fitzgerald  * @alg_ver:		Algorithm version.
587c052c66SRichard Fitzgerald  * @type:		Type of the block.
597c052c66SRichard Fitzgerald  * @offset:		Offset.
607c052c66SRichard Fitzgerald  * @payload_data:	Pointer to buffer containing the payload data.
617c052c66SRichard Fitzgerald  * @payload_len_bytes:	Length of payload data in bytes.
627c052c66SRichard Fitzgerald  */
cs_dsp_mock_bin_add_raw_block(struct cs_dsp_mock_bin_builder * builder,unsigned int alg_id,unsigned int alg_ver,int type,unsigned int offset,const void * payload_data,size_t payload_len_bytes)637c052c66SRichard Fitzgerald void cs_dsp_mock_bin_add_raw_block(struct cs_dsp_mock_bin_builder *builder,
647c052c66SRichard Fitzgerald 				   unsigned int alg_id, unsigned int alg_ver,
657c052c66SRichard Fitzgerald 				   int type, unsigned int offset,
667c052c66SRichard Fitzgerald 				   const void *payload_data, size_t payload_len_bytes)
677c052c66SRichard Fitzgerald {
687c052c66SRichard Fitzgerald 	struct wmfw_coeff_item *item;
697c052c66SRichard Fitzgerald 	size_t bytes_needed = struct_size_t(struct wmfw_coeff_item, data, payload_len_bytes);
707c052c66SRichard Fitzgerald 
717c052c66SRichard Fitzgerald 	KUNIT_ASSERT_TRUE(builder->test_priv->test,
727c052c66SRichard Fitzgerald 			  (builder->write_p + bytes_needed) <
737c052c66SRichard Fitzgerald 			  (builder->buf + CS_DSP_MOCK_BIN_BUF_SIZE));
747c052c66SRichard Fitzgerald 
757c052c66SRichard Fitzgerald 	item = builder->write_p;
767c052c66SRichard Fitzgerald 
777c052c66SRichard Fitzgerald 	item->offset = cpu_to_le16(offset);
787c052c66SRichard Fitzgerald 	item->type = cpu_to_le16(type);
797c052c66SRichard Fitzgerald 	item->id = cpu_to_le32(alg_id);
807c052c66SRichard Fitzgerald 	item->ver = cpu_to_le32(alg_ver << 8);
817c052c66SRichard Fitzgerald 	item->len = cpu_to_le32(payload_len_bytes);
827c052c66SRichard Fitzgerald 
837c052c66SRichard Fitzgerald 	if (payload_len_bytes)
847c052c66SRichard Fitzgerald 		memcpy(item->data, payload_data, payload_len_bytes);
857c052c66SRichard Fitzgerald 
867c052c66SRichard Fitzgerald 	builder->write_p += bytes_needed;
877c052c66SRichard Fitzgerald 	builder->bytes_used += bytes_needed;
887c052c66SRichard Fitzgerald }
897c052c66SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_raw_block, "FW_CS_DSP_KUNIT_TEST_UTILS");
907c052c66SRichard Fitzgerald 
cs_dsp_mock_bin_add_name_or_info(struct cs_dsp_mock_bin_builder * builder,const char * info,int type)917c052c66SRichard Fitzgerald static void cs_dsp_mock_bin_add_name_or_info(struct cs_dsp_mock_bin_builder *builder,
927c052c66SRichard Fitzgerald 					     const char *info, int type)
937c052c66SRichard Fitzgerald {
947c052c66SRichard Fitzgerald 	size_t info_len = strlen(info);
957c052c66SRichard Fitzgerald 	char *tmp = NULL;
967c052c66SRichard Fitzgerald 
977c052c66SRichard Fitzgerald 	if (info_len % 4) {
987c052c66SRichard Fitzgerald 		/* Create a padded string with length a multiple of 4 */
99*fe644621SJaroslav Kysela 		size_t copy_len = info_len;
1007c052c66SRichard Fitzgerald 		info_len = round_up(info_len, 4);
1017c052c66SRichard Fitzgerald 		tmp = kunit_kzalloc(builder->test_priv->test, info_len, GFP_KERNEL);
1027c052c66SRichard Fitzgerald 		KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, tmp);
103*fe644621SJaroslav Kysela 		memcpy(tmp, info, copy_len);
1047c052c66SRichard Fitzgerald 		info = tmp;
1057c052c66SRichard Fitzgerald 	}
1067c052c66SRichard Fitzgerald 
1077c052c66SRichard Fitzgerald 	cs_dsp_mock_bin_add_raw_block(builder, 0, 0, WMFW_INFO_TEXT, 0, info, info_len);
1087c052c66SRichard Fitzgerald 	kunit_kfree(builder->test_priv->test, tmp);
1097c052c66SRichard Fitzgerald }
1107c052c66SRichard Fitzgerald 
1117c052c66SRichard Fitzgerald /**
1127c052c66SRichard Fitzgerald  * cs_dsp_mock_bin_add_info() - Add an info block to the bin file.
1137c052c66SRichard Fitzgerald  *
1147c052c66SRichard Fitzgerald  * @builder:	Pointer to struct cs_dsp_mock_bin_builder.
1157c052c66SRichard Fitzgerald  * @info:	Pointer to info string to be copied into the file.
1167c052c66SRichard Fitzgerald  *
1177c052c66SRichard Fitzgerald  * The string will be padded to a length that is a multiple of 4 bytes.
1187c052c66SRichard Fitzgerald  */
cs_dsp_mock_bin_add_info(struct cs_dsp_mock_bin_builder * builder,const char * info)1197c052c66SRichard Fitzgerald void cs_dsp_mock_bin_add_info(struct cs_dsp_mock_bin_builder *builder,
1207c052c66SRichard Fitzgerald 			      const char *info)
1217c052c66SRichard Fitzgerald {
1227c052c66SRichard Fitzgerald 	cs_dsp_mock_bin_add_name_or_info(builder, info, WMFW_INFO_TEXT);
1237c052c66SRichard Fitzgerald }
1247c052c66SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_info, "FW_CS_DSP_KUNIT_TEST_UTILS");
1257c052c66SRichard Fitzgerald 
1267c052c66SRichard Fitzgerald /**
1277c052c66SRichard Fitzgerald  * cs_dsp_mock_bin_add_name() - Add a name block to the bin file.
1287c052c66SRichard Fitzgerald  *
1297c052c66SRichard Fitzgerald  * @builder:	Pointer to struct cs_dsp_mock_bin_builder.
1307c052c66SRichard Fitzgerald  * @name:	Pointer to name string to be copied into the file.
1317c052c66SRichard Fitzgerald  */
cs_dsp_mock_bin_add_name(struct cs_dsp_mock_bin_builder * builder,const char * name)1327c052c66SRichard Fitzgerald void cs_dsp_mock_bin_add_name(struct cs_dsp_mock_bin_builder *builder,
1337c052c66SRichard Fitzgerald 			      const char *name)
1347c052c66SRichard Fitzgerald {
1357c052c66SRichard Fitzgerald 	cs_dsp_mock_bin_add_name_or_info(builder, name, WMFW_NAME_TEXT);
1367c052c66SRichard Fitzgerald }
1377c052c66SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_name, "FW_CS_DSP_KUNIT_TEST_UTILS");
1387c052c66SRichard Fitzgerald 
1397c052c66SRichard Fitzgerald /**
1407c052c66SRichard Fitzgerald  * cs_dsp_mock_bin_add_patch() - Add a patch data block to the bin file.
1417c052c66SRichard Fitzgerald  *
1427c052c66SRichard Fitzgerald  * @builder:		Pointer to struct cs_dsp_mock_bin_builder.
143539a3f0cSRichard Fitzgerald  * @alg_id:		Algorithm ID for the patch.
1447c052c66SRichard Fitzgerald  * @alg_ver:		Algorithm version for the patch.
1457c052c66SRichard Fitzgerald  * @mem_region:		Memory region for the patch.
1467c052c66SRichard Fitzgerald  * @reg_addr_offset:	Offset to start of data in register addresses.
1477c052c66SRichard Fitzgerald  * @payload_data:	Pointer to buffer containing the payload data.
1487c052c66SRichard Fitzgerald  * @payload_len_bytes:	Length of payload data in bytes.
1497c052c66SRichard Fitzgerald  */
cs_dsp_mock_bin_add_patch(struct cs_dsp_mock_bin_builder * builder,unsigned int alg_id,unsigned int alg_ver,int mem_region,unsigned int reg_addr_offset,const void * payload_data,size_t payload_len_bytes)1507c052c66SRichard Fitzgerald void cs_dsp_mock_bin_add_patch(struct cs_dsp_mock_bin_builder *builder,
1517c052c66SRichard Fitzgerald 			       unsigned int alg_id, unsigned int alg_ver,
1527c052c66SRichard Fitzgerald 			       int mem_region, unsigned int reg_addr_offset,
1537c052c66SRichard Fitzgerald 			       const void *payload_data, size_t payload_len_bytes)
1547c052c66SRichard Fitzgerald {
1557c052c66SRichard Fitzgerald 	/* Payload length must be a multiple of 4 */
1567c052c66SRichard Fitzgerald 	KUNIT_ASSERT_EQ(builder->test_priv->test, payload_len_bytes % 4, 0);
1577c052c66SRichard Fitzgerald 
1587c052c66SRichard Fitzgerald 	cs_dsp_mock_bin_add_raw_block(builder, alg_id, alg_ver,
1597c052c66SRichard Fitzgerald 				      mem_region, reg_addr_offset,
1607c052c66SRichard Fitzgerald 				      payload_data, payload_len_bytes);
1617c052c66SRichard Fitzgerald }
1627c052c66SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_patch, "FW_CS_DSP_KUNIT_TEST_UTILS");
1637c052c66SRichard Fitzgerald 
1647c052c66SRichard Fitzgerald /**
1657c052c66SRichard Fitzgerald  * cs_dsp_mock_bin_init() - Initialize a struct cs_dsp_mock_bin_builder.
1667c052c66SRichard Fitzgerald  *
1677c052c66SRichard Fitzgerald  * @priv:		Pointer to struct cs_dsp_test.
1687c052c66SRichard Fitzgerald  * @format_version:	Required bin format version.
1697c052c66SRichard Fitzgerald  * @fw_version:		Firmware version to put in bin file.
1707c052c66SRichard Fitzgerald  *
1717c052c66SRichard Fitzgerald  * Return: Pointer to created struct cs_dsp_mock_bin_builder.
1727c052c66SRichard Fitzgerald  */
cs_dsp_mock_bin_init(struct cs_dsp_test * priv,int format_version,unsigned int fw_version)1737c052c66SRichard Fitzgerald struct cs_dsp_mock_bin_builder *cs_dsp_mock_bin_init(struct cs_dsp_test *priv,
1747c052c66SRichard Fitzgerald 						     int format_version,
1757c052c66SRichard Fitzgerald 						     unsigned int fw_version)
1767c052c66SRichard Fitzgerald {
1777c052c66SRichard Fitzgerald 	struct cs_dsp_mock_bin_builder *builder;
1787c052c66SRichard Fitzgerald 	struct wmfw_coeff_hdr *hdr;
1797c052c66SRichard Fitzgerald 
1804308487bSRichard Fitzgerald 	KUNIT_ASSERT_LE(priv->test, format_version, 0xff);
1814308487bSRichard Fitzgerald 	KUNIT_ASSERT_LE(priv->test, fw_version, 0xffffff);
1824308487bSRichard Fitzgerald 
1837c052c66SRichard Fitzgerald 	builder = kunit_kzalloc(priv->test, sizeof(*builder), GFP_KERNEL);
1847c052c66SRichard Fitzgerald 	KUNIT_ASSERT_NOT_ERR_OR_NULL(priv->test, builder);
1857c052c66SRichard Fitzgerald 	builder->test_priv = priv;
1867c052c66SRichard Fitzgerald 
1877c052c66SRichard Fitzgerald 	builder->buf = vmalloc(CS_DSP_MOCK_BIN_BUF_SIZE);
1887c052c66SRichard Fitzgerald 	KUNIT_ASSERT_NOT_NULL(priv->test, builder->buf);
1897c052c66SRichard Fitzgerald 	kunit_add_action_or_reset(priv->test, vfree_action_wrapper, builder->buf);
1907c052c66SRichard Fitzgerald 
1917c052c66SRichard Fitzgerald 	/* Create header */
1927c052c66SRichard Fitzgerald 	hdr = builder->buf;
1937c052c66SRichard Fitzgerald 	memcpy(hdr->magic, "WMDR", sizeof(hdr->magic));
1947c052c66SRichard Fitzgerald 	hdr->len = cpu_to_le32(offsetof(struct wmfw_coeff_hdr, data));
1957c052c66SRichard Fitzgerald 	hdr->ver = cpu_to_le32(fw_version | (format_version << 24));
1967c052c66SRichard Fitzgerald 	hdr->core_ver = cpu_to_le32(((u32)priv->dsp->type << 24) | priv->dsp->rev);
1977c052c66SRichard Fitzgerald 
1987c052c66SRichard Fitzgerald 	builder->write_p = hdr->data;
1997c052c66SRichard Fitzgerald 	builder->bytes_used = offsetof(struct wmfw_coeff_hdr, data);
2007c052c66SRichard Fitzgerald 
2017c052c66SRichard Fitzgerald 	return builder;
2027c052c66SRichard Fitzgerald }
2037c052c66SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_init, "FW_CS_DSP_KUNIT_TEST_UTILS");
204