Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/cirrus/test/cs_dsp_mock_bin.c
53055 views
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
22
KUNIT_DEFINE_ACTION_WRAPPER(vfree_action_wrapper, vfree, void *)
23
24
struct 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
*/
38
struct 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
}
50
EXPORT_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: 16-bit offset.
60
* @offset32: 32-bit offset (sample rate on V1 and V2 file formats).
61
* @payload_data: Pointer to buffer containing the payload data.
62
* @payload_len_bytes: Length of payload data in bytes.
63
*/
64
void cs_dsp_mock_bin_add_raw_block(struct cs_dsp_mock_bin_builder *builder,
65
unsigned int alg_id, unsigned int alg_ver,
66
int type, u16 offset, u32 offset32,
67
const void *payload_data, size_t payload_len_bytes)
68
{
69
struct wmfw_coeff_item *item;
70
size_t bytes_needed = struct_size_t(struct wmfw_coeff_item, data, payload_len_bytes);
71
72
KUNIT_ASSERT_TRUE(builder->test_priv->test,
73
(builder->write_p + bytes_needed) <
74
(builder->buf + CS_DSP_MOCK_BIN_BUF_SIZE));
75
76
item = builder->write_p;
77
78
item->offset = cpu_to_le16(offset);
79
item->offset32 = cpu_to_le32(offset32);
80
item->type = cpu_to_le16(type);
81
item->id = cpu_to_le32(alg_id);
82
item->ver = cpu_to_le32(alg_ver << 8);
83
item->len = cpu_to_le32(payload_len_bytes);
84
85
if (payload_len_bytes)
86
memcpy(item->data, payload_data, payload_len_bytes);
87
88
builder->write_p += bytes_needed;
89
builder->bytes_used += bytes_needed;
90
}
91
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_raw_block, "FW_CS_DSP_KUNIT_TEST_UTILS");
92
93
static void cs_dsp_mock_bin_add_name_or_info(struct cs_dsp_mock_bin_builder *builder,
94
const char *info, int type)
95
{
96
size_t info_len = strlen(info);
97
char *tmp = NULL;
98
99
if (info_len % 4) {
100
/* Create a padded string with length a multiple of 4 */
101
size_t copy_len = info_len;
102
info_len = round_up(info_len, 4);
103
tmp = kunit_kzalloc(builder->test_priv->test, info_len, GFP_KERNEL);
104
KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, tmp);
105
memcpy(tmp, info, copy_len);
106
info = tmp;
107
}
108
109
cs_dsp_mock_bin_add_raw_block(builder, 0, 0, WMFW_INFO_TEXT, 0, 0, info, info_len);
110
kunit_kfree(builder->test_priv->test, tmp);
111
}
112
113
/**
114
* cs_dsp_mock_bin_add_info() - Add an info block to the bin file.
115
*
116
* @builder: Pointer to struct cs_dsp_mock_bin_builder.
117
* @info: Pointer to info string to be copied into the file.
118
*
119
* The string will be padded to a length that is a multiple of 4 bytes.
120
*/
121
void cs_dsp_mock_bin_add_info(struct cs_dsp_mock_bin_builder *builder,
122
const char *info)
123
{
124
cs_dsp_mock_bin_add_name_or_info(builder, info, WMFW_INFO_TEXT);
125
}
126
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_info, "FW_CS_DSP_KUNIT_TEST_UTILS");
127
128
/**
129
* cs_dsp_mock_bin_add_name() - Add a name block to the bin file.
130
*
131
* @builder: Pointer to struct cs_dsp_mock_bin_builder.
132
* @name: Pointer to name string to be copied into the file.
133
*/
134
void cs_dsp_mock_bin_add_name(struct cs_dsp_mock_bin_builder *builder,
135
const char *name)
136
{
137
cs_dsp_mock_bin_add_name_or_info(builder, name, WMFW_NAME_TEXT);
138
}
139
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_name, "FW_CS_DSP_KUNIT_TEST_UTILS");
140
141
/**
142
* cs_dsp_mock_bin_add_patch() - Add a patch data block to the bin file.
143
*
144
* @builder: Pointer to struct cs_dsp_mock_bin_builder.
145
* @alg_id: Algorithm ID for the patch.
146
* @alg_ver: Algorithm version for the patch.
147
* @mem_region: Memory region for the patch.
148
* @reg_addr_offset: Offset to start of data in register addresses.
149
* @payload_data: Pointer to buffer containing the payload data.
150
* @payload_len_bytes: Length of payload data in bytes.
151
*/
152
void cs_dsp_mock_bin_add_patch(struct cs_dsp_mock_bin_builder *builder,
153
unsigned int alg_id, unsigned int alg_ver,
154
int mem_region, unsigned int reg_addr_offset,
155
const void *payload_data, size_t payload_len_bytes)
156
{
157
/* Payload length must be a multiple of 4 */
158
KUNIT_ASSERT_EQ(builder->test_priv->test, payload_len_bytes % 4, 0);
159
160
cs_dsp_mock_bin_add_raw_block(builder, alg_id, alg_ver,
161
mem_region, (u16)reg_addr_offset, 0,
162
payload_data, payload_len_bytes);
163
}
164
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_patch, "FW_CS_DSP_KUNIT_TEST_UTILS");
165
166
/**
167
* cs_dsp_mock_bin_add_patch_off32() - Add a patch data block with 32-bit offset.
168
*
169
* @builder: Pointer to struct cs_dsp_mock_bin_builder.
170
* @alg_id: Algorithm ID for the patch.
171
* @alg_ver: Algorithm version for the patch.
172
* @mem_region: Memory region for the patch.
173
* @reg_addr_offset: Offset to start of data in register addresses.
174
* @payload_data: Pointer to buffer containing the payload data.
175
* @payload_len_bytes: Length of payload data in bytes.
176
*/
177
void cs_dsp_mock_bin_add_patch_off32(struct cs_dsp_mock_bin_builder *builder,
178
unsigned int alg_id, unsigned int alg_ver,
179
int mem_region, unsigned int reg_addr_offset,
180
const void *payload_data, size_t payload_len_bytes)
181
{
182
/* Payload length must be a multiple of 4 */
183
KUNIT_ASSERT_EQ(builder->test_priv->test, payload_len_bytes % 4, 0);
184
185
/* Mark the block as using the 32-bit offset */
186
mem_region |= 0xf400;
187
188
cs_dsp_mock_bin_add_raw_block(builder, alg_id, alg_ver,
189
mem_region, 0, reg_addr_offset,
190
payload_data, payload_len_bytes);
191
}
192
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_patch_off32, "FW_CS_DSP_KUNIT_TEST_UTILS");
193
194
/**
195
* cs_dsp_mock_bin_init() - Initialize a struct cs_dsp_mock_bin_builder.
196
*
197
* @priv: Pointer to struct cs_dsp_test.
198
* @format_version: Required bin format version.
199
* @fw_version: Firmware version to put in bin file.
200
*
201
* Return: Pointer to created struct cs_dsp_mock_bin_builder.
202
*/
203
struct cs_dsp_mock_bin_builder *cs_dsp_mock_bin_init(struct cs_dsp_test *priv,
204
int format_version,
205
unsigned int fw_version)
206
{
207
struct cs_dsp_mock_bin_builder *builder;
208
struct wmfw_coeff_hdr *hdr;
209
210
KUNIT_ASSERT_LE(priv->test, format_version, 0xff);
211
KUNIT_ASSERT_LE(priv->test, fw_version, 0xffffff);
212
213
builder = kunit_kzalloc(priv->test, sizeof(*builder), GFP_KERNEL);
214
KUNIT_ASSERT_NOT_ERR_OR_NULL(priv->test, builder);
215
builder->test_priv = priv;
216
217
builder->buf = vmalloc(CS_DSP_MOCK_BIN_BUF_SIZE);
218
KUNIT_ASSERT_NOT_NULL(priv->test, builder->buf);
219
kunit_add_action_or_reset(priv->test, vfree_action_wrapper, builder->buf);
220
221
/* Create header */
222
hdr = builder->buf;
223
memcpy(hdr->magic, "WMDR", sizeof(hdr->magic));
224
hdr->len = cpu_to_le32(offsetof(struct wmfw_coeff_hdr, data));
225
hdr->ver = cpu_to_le32(fw_version | (format_version << 24));
226
hdr->core_ver = cpu_to_le32(((u32)priv->dsp->type << 24) | priv->dsp->rev);
227
228
builder->write_p = hdr->data;
229
builder->bytes_used = offsetof(struct wmfw_coeff_hdr, data);
230
231
return builder;
232
}
233
EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_init, "FW_CS_DSP_KUNIT_TEST_UTILS");
234
235