]> Git Repo - linux.git/blob - drivers/firmware/cirrus/test/cs_dsp_mock_bin.c
Linux 6.14-rc3
[linux.git] / drivers / firmware / cirrus / test / cs_dsp_mock_bin.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
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:             Offset.
60  * @payload_data:       Pointer to buffer containing the payload data.
61  * @payload_len_bytes:  Length of payload data in bytes.
62  */
63 void 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 }
89 EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_raw_block, "FW_CS_DSP_KUNIT_TEST_UTILS");
90
91 static 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                 info_len = round_up(info_len, 4);
100                 tmp = kunit_kzalloc(builder->test_priv->test, info_len, GFP_KERNEL);
101                 KUNIT_ASSERT_NOT_ERR_OR_NULL(builder->test_priv->test, tmp);
102                 memcpy(tmp, info, info_len);
103                 info = tmp;
104         }
105
106         cs_dsp_mock_bin_add_raw_block(builder, 0, 0, WMFW_INFO_TEXT, 0, info, info_len);
107         kunit_kfree(builder->test_priv->test, tmp);
108 }
109
110 /**
111  * cs_dsp_mock_bin_add_info() - Add an info block to the bin file.
112  *
113  * @builder:    Pointer to struct cs_dsp_mock_bin_builder.
114  * @info:       Pointer to info string to be copied into the file.
115  *
116  * The string will be padded to a length that is a multiple of 4 bytes.
117  */
118 void cs_dsp_mock_bin_add_info(struct cs_dsp_mock_bin_builder *builder,
119                               const char *info)
120 {
121         cs_dsp_mock_bin_add_name_or_info(builder, info, WMFW_INFO_TEXT);
122 }
123 EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_info, "FW_CS_DSP_KUNIT_TEST_UTILS");
124
125 /**
126  * cs_dsp_mock_bin_add_name() - Add a name block to the bin file.
127  *
128  * @builder:    Pointer to struct cs_dsp_mock_bin_builder.
129  * @name:       Pointer to name string to be copied into the file.
130  */
131 void cs_dsp_mock_bin_add_name(struct cs_dsp_mock_bin_builder *builder,
132                               const char *name)
133 {
134         cs_dsp_mock_bin_add_name_or_info(builder, name, WMFW_NAME_TEXT);
135 }
136 EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_name, "FW_CS_DSP_KUNIT_TEST_UTILS");
137
138 /**
139  * cs_dsp_mock_bin_add_patch() - Add a patch data block to the bin file.
140  *
141  * @builder:            Pointer to struct cs_dsp_mock_bin_builder.
142  * @alg_id:             Algorithm ID for the patch.
143  * @alg_ver:            Algorithm version for the patch.
144  * @mem_region:         Memory region for the patch.
145  * @reg_addr_offset:    Offset to start of data in register addresses.
146  * @payload_data:       Pointer to buffer containing the payload data.
147  * @payload_len_bytes:  Length of payload data in bytes.
148  */
149 void cs_dsp_mock_bin_add_patch(struct cs_dsp_mock_bin_builder *builder,
150                                unsigned int alg_id, unsigned int alg_ver,
151                                int mem_region, unsigned int reg_addr_offset,
152                                const void *payload_data, size_t payload_len_bytes)
153 {
154         /* Payload length must be a multiple of 4 */
155         KUNIT_ASSERT_EQ(builder->test_priv->test, payload_len_bytes % 4, 0);
156
157         cs_dsp_mock_bin_add_raw_block(builder, alg_id, alg_ver,
158                                       mem_region, reg_addr_offset,
159                                       payload_data, payload_len_bytes);
160 }
161 EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_add_patch, "FW_CS_DSP_KUNIT_TEST_UTILS");
162
163 /**
164  * cs_dsp_mock_bin_init() - Initialize a struct cs_dsp_mock_bin_builder.
165  *
166  * @priv:               Pointer to struct cs_dsp_test.
167  * @format_version:     Required bin format version.
168  * @fw_version:         Firmware version to put in bin file.
169  *
170  * Return: Pointer to created struct cs_dsp_mock_bin_builder.
171  */
172 struct cs_dsp_mock_bin_builder *cs_dsp_mock_bin_init(struct cs_dsp_test *priv,
173                                                      int format_version,
174                                                      unsigned int fw_version)
175 {
176         struct cs_dsp_mock_bin_builder *builder;
177         struct wmfw_coeff_hdr *hdr;
178
179         builder = kunit_kzalloc(priv->test, sizeof(*builder), GFP_KERNEL);
180         KUNIT_ASSERT_NOT_ERR_OR_NULL(priv->test, builder);
181         builder->test_priv = priv;
182
183         builder->buf = vmalloc(CS_DSP_MOCK_BIN_BUF_SIZE);
184         KUNIT_ASSERT_NOT_NULL(priv->test, builder->buf);
185         kunit_add_action_or_reset(priv->test, vfree_action_wrapper, builder->buf);
186
187         /* Create header */
188         hdr = builder->buf;
189         memcpy(hdr->magic, "WMDR", sizeof(hdr->magic));
190         hdr->len = cpu_to_le32(offsetof(struct wmfw_coeff_hdr, data));
191         hdr->ver = cpu_to_le32(fw_version | (format_version << 24));
192         hdr->core_ver = cpu_to_le32(((u32)priv->dsp->type << 24) | priv->dsp->rev);
193
194         builder->write_p = hdr->data;
195         builder->bytes_used = offsetof(struct wmfw_coeff_hdr, data);
196
197         return builder;
198 }
199 EXPORT_SYMBOL_NS_GPL(cs_dsp_mock_bin_init, "FW_CS_DSP_KUNIT_TEST_UTILS");
This page took 0.036542 seconds and 4 git commands to generate.