File Index
Files and directories
Sign in
FILE

cs_dsp_mock_bin.c

File preview with syntax highlighting.

linux-6.19.14/drivers/firmware/cirrus/test/cs_dsp_mock_bin.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2//
  3// bin file builder for cs_dsp KUnit tests.
  4//
  5// Copyright (C) 2024 Cirrus Logic, Inc. and
  6//                    Cirrus Logic International Semiconductor Ltd.
  7
  8#include <kunit/resource.h>
  9#include <kunit/test.h>
 10#include <linux/firmware/cirrus/cs_dsp.h>
 11#include <linux/firmware/cirrus/cs_dsp_test_utils.h>
 12#include <linux/firmware/cirrus/wmfw.h>
 13#include <linux/firmware.h>
 14#include <linux/math.h>
 15#include <linux/overflow.h>
 16#include <linux/string.h>
 17#include <linux/vmalloc.h>
 18
 19/* Buffer large enough for bin file content */
 20#define CS_DSP_MOCK_BIN_BUF_SIZE	32768
 21
 22KUNIT_DEFINE_ACTION_WRAPPER(vfree_action_wrapper, vfree, void *)
 23
 24struct cs_dsp_mock_bin_builder {
 25	struct cs_dsp_test *test_priv;
 26	void *buf;
 27	void *write_p;
 28	size_t bytes_used;
 29};
 30
 31/**
 32 * cs_dsp_mock_bin_get_firmware() - Get struct firmware wrapper for data.
 33 *
 34 * @builder:	Pointer to struct cs_dsp_mock_bin_builder.
 35 *
 36 * Return: Pointer to a struct firmware wrapper for the data.
 37 */
 38struct firmware *cs_dsp_mock_bin_get_firmware(struct cs_dsp_mock_bin_builder *builder)
 39{
 40	struct firmware *fw;
 41
 42	fw = kunit_kzalloc(builder->test_priv->test, sizeof(*fw), GFP_KERNEL);
 43	KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, fw);
 44
 45	fw->data = builder->buf;
 46	fw->size = builder->bytes_used;
 47
 48	return fw;
 49}
 50EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_get_firmware, "FW_CS_DSP_KUNIT_TEST_UTILS");
 51
 52/**
 53 * cs_dsp_mock_bin_add_raw_block() - Add a data block to the bin file.
 54 *
 55 * @builder:		Pointer to struct cs_dsp_mock_bin_builder.
 56 * @alg_id:		Algorithm ID.
 57 * @alg_ver:		Algorithm version.
 58 * @type:		Type of the block.
 59 * @offset:		Offset.
 60 * @payload_data:	Pointer to buffer containing the payload data.
 61 * @payload_len_bytes:	Length of payload data in bytes.
 62 */
 63void cs_dsp_mock_bin_add_raw_block(struct cs_dsp_mock_bin_builder *builder,
 64				   unsigned int alg_id, unsigned int alg_ver,
 65				   int type, unsigned int offset,
 66				   const void *payload_data, size_t payload_len_bytes)
 67{
 68	struct wmfw_coeff_item *item;
 69	size_t bytes_needed = struct_size_t(struct wmfw_coeff_item, data, payload_len_bytes);
 70
 71	KUNIT_ASSERT_TRUE(builder->test_priv->test,
 72			  (builder->write_p + bytes_needed) <
 73			  (builder->buf + CS_DSP_MOCK_BIN_BUF_SIZE));
 74
 75	item = builder->write_p;
 76
 77	item->offset = cpu_to_le16(offset);
 78	item->type = cpu_to_le16(type);
 79	item->id = cpu_to_le32(alg_id);
 80	item->ver = cpu_to_le32(alg_ver << 8);
 81	item->len = cpu_to_le32(payload_len_bytes);
 82
 83	if (payload_len_bytes)
 84		memcpy(item->data, payload_data, payload_len_bytes);
 85
 86	builder->write_p += bytes_needed;
 87	builder->bytes_used += bytes_needed;
 88}
 89EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_raw_block, "FW_CS_DSP_KUNIT_TEST_UTILS");
 90
 91static void cs_dsp_mock_bin_add_name_or_info(struct cs_dsp_mock_bin_builder *builder,
 92					     const char *info, int type)
 93{
 94	size_t info_len = strlen(info);
 95	char *tmp = NULL;
 96
 97	if (info_len % 4) {
 98		/* Create a padded string with length a multiple of 4 */
 99		size_t copy_len = info_len;
100		info_len = round_up(info_len, 4);
101		tmp = kunit_kzalloc(builder->test_priv->test, info_len, GFP_KERNEL);
102		KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, tmp);
103		memcpy(tmp, info, copy_len);
104		info = tmp;
105	}
106
107	cs_dsp_mock_bin_add_raw_block(builder, 0, 0, WMFW_INFO_TEXT, 0, info, info_len);
108	kunit_kfree(builder->test_priv->test, tmp);
109}
110
111/**
112 * cs_dsp_mock_bin_add_info() - Add an info block to the bin file.
113 *
114 * @builder:	Pointer to struct cs_dsp_mock_bin_builder.
115 * @info:	Pointer to info string to be copied into the file.
116 *
117 * The string will be padded to a length that is a multiple of 4 bytes.
118 */
119void cs_dsp_mock_bin_add_info(struct cs_dsp_mock_bin_builder *builder,
120			      const char *info)
121{
122	cs_dsp_mock_bin_add_name_or_info(builder, info, WMFW_INFO_TEXT);
123}
124EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_info, "FW_CS_DSP_KUNIT_TEST_UTILS");
125
126/**
127 * cs_dsp_mock_bin_add_name() - Add a name block to the bin file.
128 *
129 * @builder:	Pointer to struct cs_dsp_mock_bin_builder.
130 * @name:	Pointer to name string to be copied into the file.
131 */
132void cs_dsp_mock_bin_add_name(struct cs_dsp_mock_bin_builder *builder,
133			      const char *name)
134{
135	cs_dsp_mock_bin_add_name_or_info(builder, name, WMFW_NAME_TEXT);
136}
137EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_name, "FW_CS_DSP_KUNIT_TEST_UTILS");
138
139/**
140 * cs_dsp_mock_bin_add_patch() - Add a patch data block to the bin file.
141 *
142 * @builder:		Pointer to struct cs_dsp_mock_bin_builder.
143 * @alg_id:		Algorithm ID for the patch.
144 * @alg_ver:		Algorithm version for the patch.
145 * @mem_region:		Memory region for the patch.
146 * @reg_addr_offset:	Offset to start of data in register addresses.
147 * @payload_data:	Pointer to buffer containing the payload data.
148 * @payload_len_bytes:	Length of payload data in bytes.
149 */
150void cs_dsp_mock_bin_add_patch(struct cs_dsp_mock_bin_builder *builder,
151			       unsigned int alg_id, unsigned int alg_ver,
152			       int mem_region, unsigned int reg_addr_offset,
153			       const void *payload_data, size_t payload_len_bytes)
154{
155	/* Payload length must be a multiple of 4 */
156	KUNIT_ASSERT_EQ(builder->test_priv->test, payload_len_bytes % 4, 0);
157
158	cs_dsp_mock_bin_add_raw_block(builder, alg_id, alg_ver,
159				      mem_region, reg_addr_offset,
160				      payload_data, payload_len_bytes);
161}
162EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_patch, "FW_CS_DSP_KUNIT_TEST_UTILS");
163
164/**
165 * cs_dsp_mock_bin_init() - Initialize a struct cs_dsp_mock_bin_builder.
166 *
167 * @priv:		Pointer to struct cs_dsp_test.
168 * @format_version:	Required bin format version.
169 * @fw_version:		Firmware version to put in bin file.
170 *
171 * Return: Pointer to created struct cs_dsp_mock_bin_builder.
172 */
173struct cs_dsp_mock_bin_builder *cs_dsp_mock_bin_init(struct cs_dsp_test *priv,
174						     int format_version,
175						     unsigned int fw_version)
176{
177	struct cs_dsp_mock_bin_builder *builder;
178	struct wmfw_coeff_hdr *hdr;
179
180	KUNIT_ASSERT_LE(priv->test, format_version, 0xff);
181	KUNIT_ASSERT_LE(priv->test, fw_version, 0xffffff);
182
183	builder = kunit_kzalloc(priv->test, sizeof(*builder), GFP_KERNEL);
184	KUNIT_ASSERT_NOT_ERR_OR_NULL(priv->test, builder);
185	builder->test_priv = priv;
186
187	builder->buf = vmalloc(CS_DSP_MOCK_BIN_BUF_SIZE);
188	KUNIT_ASSERT_NOT_NULL(priv->test, builder->buf);
189	kunit_add_action_or_reset(priv->test, vfree_action_wrapper, builder->buf);
190
191	/* Create header */
192	hdr = builder->buf;
193	memcpy(hdr->magic, "WMDR", sizeof(hdr->magic));
194	hdr->len = cpu_to_le32(offsetof(struct wmfw_coeff_hdr, data));
195	hdr->ver = cpu_to_le32(fw_version | (format_version << 24));
196	hdr->core_ver = cpu_to_le32(((u32)priv->dsp->type << 24) | priv->dsp->rev);
197
198	builder->write_p = hdr->data;
199	builder->bytes_used = offsetof(struct wmfw_coeff_hdr, data);
200
201	return builder;
202}
203EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_init, "FW_CS_DSP_KUNIT_TEST_UTILS");
~/ Read-only file preview.