xref: /linux/drivers/firmware/cirrus/test/cs_dsp_test_bin.c (revision a8e7ef3cec99ba2487110e01d77a8a278593b3e9)
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // KUnit tests for cs_dsp.
4 //
5 // Copyright (C) 2024 Cirrus Logic, Inc. and
6 //                    Cirrus Logic International Semiconductor Ltd.
7 
8 #include <kunit/device.h>
9 #include <kunit/resource.h>
10 #include <kunit/static_stub.h>
11 #include <kunit/test.h>
12 #include <linux/build_bug.h>
13 #include <linux/firmware/cirrus/cs_dsp.h>
14 #include <linux/firmware/cirrus/cs_dsp_test_utils.h>
15 #include <linux/firmware/cirrus/wmfw.h>
16 #include <linux/firmware.h>
17 #include <linux/math.h>
18 #include <linux/random.h>
19 #include <linux/regmap.h>
20 
21 #include "../cs_dsp.h"
22 
23 /*
24  * Test method is:
25  *
26  * 1) Create a mock regmap in cache-only mode so that all writes will be cached.
27  * 2) Create a XM header with an algorithm list in the cached regmap.
28  * 3) Create dummy wmfw file to satisfy cs_dsp.
29  * 4) Create bin file content.
30  * 5) Call cs_dsp_power_up() with the bin file.
31  * 6) Readback the cached value of registers that should have been written and
32  *    check they have the correct value.
33  * 7) All the registers that are expected to have been written are dropped from
34  *    the cache (including the XM header). This should leave the cache clean.
35  * 8) If the cache is still dirty there have been unexpected writes.
36  *
37  * There are multiple different schemes used for addressing across
38  * ADSP2 and Halo Core DSPs:
39  *
40  *  dsp words:	The addressing scheme used by the DSP, pointers and lengths
41  *		in DSP memory use this. A memory region (XM, YM, ZM) is
42  *		also required to create a unique DSP memory address.
43  *  registers:	Addresses in the register map. Older ADSP2 devices have
44  *		16-bit registers with an address stride of 1. Newer ADSP2
45  *		devices have 32-bit registers with an address stride of 2.
46  *		Halo Core devices have 32-bit registers with a stride of 4.
47  *  unpacked:	Registers that have a 1:1 mapping to DSP words
48  *  packed:	Registers that pack multiple DSP words more efficiently into
49  *		multiple 32-bit registers. Because of this the relationship
50  *		between a packed _register_ address and the corresponding
51  *		_dsp word_ address is different from unpacked registers.
52  *		Packed registers can only be accessed as a group of
53  *		multiple registers, therefore can only read/write a group
54  *		of multiple DSP words.
55  *		Packed registers only exist on Halo Core DSPs.
56  *
57  * Addresses can also be relative to the start of an algorithm, and this
58  * can be expressed in dsp words, register addresses, or bytes.
59  */
60 
61 KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *)
62 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *)
63 
64 struct cs_dsp_test_local {
65 	struct cs_dsp_mock_bin_builder *bin_builder;
66 	struct cs_dsp_mock_wmfw_builder *wmfw_builder;
67 	struct firmware *wmfw;
68 };
69 
70 struct bin_test_param {
71 	const char *name;
72 	int mem_type;
73 	unsigned int offset_words;
74 	int alg_idx;
75 	void (*add_patch)(struct cs_dsp_mock_bin_builder *builder,
76 			  unsigned int alg_id, unsigned int alg_ver,
77 			  int mem_region, unsigned int reg_addr_offset,
78 			  const void *payload_data, size_t payload_len_bytes);
79 };
80 
81 static const struct cs_dsp_mock_alg_def bin_test_mock_algs[] = {
82 	{
83 		.id = 0xfafa,
84 		.ver = 0x100000,
85 		.xm_size_words = 164,
86 		.ym_size_words = 164,
87 		.zm_size_words = 164,
88 	},
89 	{
90 		.id = 0xfbfb,
91 		.ver = 0x100000,
92 		.xm_size_words = 99,
93 		.ym_size_words = 99,
94 		.zm_size_words = 99,
95 	},
96 	{
97 		.id = 0xc321,
98 		.ver = 0x100000,
99 		.xm_size_words = 120,
100 		.ym_size_words = 120,
101 		.zm_size_words = 120,
102 	},
103 	{
104 		.id = 0xb123,
105 		.ver = 0x100000,
106 		.xm_size_words = 96,
107 		.ym_size_words = 96,
108 		.zm_size_words = 96,
109 	},
110 };
111 
112 /*
113  * Convert number of DSP words to number of packed registers rounded
114  * down to the nearest register.
115  * There are 3 registers for every 4 packed words.
116  */
117 static unsigned int _num_words_to_num_packed_regs(unsigned int num_dsp_words)
118 {
119 	return (num_dsp_words * 3) / 4;
120 }
121 
122 /* bin file that patches a single DSP word */
123 static void bin_patch_one_word(struct kunit *test)
124 {
125 	struct cs_dsp_test *priv = test->priv;
126 	const struct bin_test_param *param = test->param_value;
127 	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
128 	u32 reg_val, payload_data;
129 	unsigned int alg_base_words, reg_addr;
130 	struct firmware *fw;
131 
132 	get_random_bytes(&payload_data, sizeof(payload_data));
133 
134 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
135 							bin_test_mock_algs[param->alg_idx].id,
136 							param->mem_type);
137 
138 	param->add_patch(priv->local->bin_builder,
139 			 bin_test_mock_algs[param->alg_idx].id,
140 			 bin_test_mock_algs[param->alg_idx].ver,
141 			 param->mem_type,
142 			 param->offset_words * reg_inc_per_word,
143 			 &payload_data, sizeof(payload_data));
144 
145 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
146 	KUNIT_ASSERT_EQ(test,
147 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
148 					fw, "mock_bin", "misc"),
149 			0);
150 
151 	/* Content of registers should match payload_data */
152 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
153 		   ((alg_base_words + param->offset_words) * reg_inc_per_word);
154 	reg_val = 0;
155 	KUNIT_EXPECT_EQ(test,
156 			regmap_raw_read(priv->dsp->regmap, reg_addr,
157 					&reg_val, sizeof(reg_val)),
158 			0);
159 	KUNIT_EXPECT_EQ(test, reg_val, payload_data);
160 
161 	/* Drop expected writes and the cache should then be clean */
162 	cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
163 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
164 
165 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
166 }
167 
168 /* bin file with a single payload that patches consecutive words */
169 static void bin_patch_one_multiword(struct kunit *test)
170 {
171 	struct cs_dsp_test *priv = test->priv;
172 	const struct bin_test_param *param = test->param_value;
173 	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
174 	u32 payload_data[16], readback[16];
175 	unsigned int alg_base_words, reg_addr;
176 	struct firmware *fw;
177 
178 	static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));
179 
180 	get_random_bytes(&payload_data, sizeof(payload_data));
181 	memset(readback, 0, sizeof(readback));
182 
183 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
184 							bin_test_mock_algs[param->alg_idx].id,
185 							param->mem_type);
186 
187 	param->add_patch(priv->local->bin_builder,
188 			 bin_test_mock_algs[param->alg_idx].id,
189 			 bin_test_mock_algs[param->alg_idx].ver,
190 			 param->mem_type,
191 			 param->offset_words * reg_inc_per_word,
192 			 payload_data, sizeof(payload_data));
193 
194 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
195 	KUNIT_ASSERT_EQ(test,
196 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
197 					fw, "mock_bin", "misc"),
198 			0);
199 
200 	/* Content of registers should match payload_data */
201 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
202 		   ((alg_base_words + param->offset_words) * reg_inc_per_word);
203 	KUNIT_EXPECT_EQ(test,
204 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
205 					sizeof(readback)),
206 			0);
207 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
208 
209 	/* Drop expected writes and the cache should then be clean */
210 	cs_dsp_mock_regmap_drop_range(priv, reg_addr,
211 				      reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
212 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
213 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
214 }
215 
216 /* bin file with a multiple one-word payloads that patch consecutive words */
217 static void bin_patch_multi_oneword(struct kunit *test)
218 {
219 	struct cs_dsp_test *priv = test->priv;
220 	const struct bin_test_param *param = test->param_value;
221 	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
222 	u32 payload_data[16], readback[16];
223 	unsigned int alg_base_words, reg_addr;
224 	struct firmware *fw;
225 	int i;
226 
227 	static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));
228 
229 	get_random_bytes(&payload_data, sizeof(payload_data));
230 	memset(readback, 0, sizeof(readback));
231 
232 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
233 							bin_test_mock_algs[param->alg_idx].id,
234 							param->mem_type);
235 
236 	/* Add one payload per word */
237 	for (i = 0; i < ARRAY_SIZE(payload_data); ++i) {
238 		param->add_patch(priv->local->bin_builder,
239 				 bin_test_mock_algs[param->alg_idx].id,
240 				 bin_test_mock_algs[param->alg_idx].ver,
241 				 param->mem_type,
242 				 (param->offset_words + i) * reg_inc_per_word,
243 				 &payload_data[i], sizeof(payload_data[i]));
244 	}
245 
246 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
247 	KUNIT_ASSERT_EQ(test,
248 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
249 					fw, "mock_bin", "misc"),
250 			 0);
251 
252 	/* Content of registers should match payload_data */
253 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
254 		   ((alg_base_words + param->offset_words) * reg_inc_per_word);
255 	KUNIT_EXPECT_EQ(test,
256 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
257 					sizeof(readback)),
258 			0);
259 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
260 
261 	/* Drop expected writes and the cache should then be clean */
262 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
263 	cs_dsp_mock_regmap_drop_range(priv, reg_addr,
264 				      reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
265 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
266 }
267 
268 /*
269  * bin file with a multiple one-word payloads that patch a block of consecutive
270  * words but the payloads are not in address order.
271  */
272 static void bin_patch_multi_oneword_unordered(struct kunit *test)
273 {
274 	struct cs_dsp_test *priv = test->priv;
275 	const struct bin_test_param *param = test->param_value;
276 	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
277 	u32 payload_data[16], readback[16];
278 	static const u8 word_order[] = { 10, 2, 12, 4, 0, 11, 6, 1, 3, 15, 5, 13, 8, 7, 9, 14 };
279 	unsigned int alg_base_words, reg_addr;
280 	struct firmware *fw;
281 	int i;
282 
283 	static_assert(ARRAY_SIZE(readback) == ARRAY_SIZE(payload_data));
284 	static_assert(ARRAY_SIZE(word_order) == ARRAY_SIZE(payload_data));
285 
286 	get_random_bytes(&payload_data, sizeof(payload_data));
287 	memset(readback, 0, sizeof(readback));
288 
289 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
290 							bin_test_mock_algs[param->alg_idx].id,
291 							param->mem_type);
292 
293 	/* Add one payload per word */
294 	for (i = 0; i < ARRAY_SIZE(word_order); ++i) {
295 		param->add_patch(priv->local->bin_builder,
296 				 bin_test_mock_algs[param->alg_idx].id,
297 				 bin_test_mock_algs[param->alg_idx].ver,
298 				 param->mem_type,
299 				 (param->offset_words + word_order[i]) *
300 				 reg_inc_per_word,
301 				 &payload_data[word_order[i]], sizeof(payload_data[0]));
302 	}
303 
304 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
305 	KUNIT_ASSERT_EQ(test,
306 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
307 					fw, "mock_bin", "misc"),
308 			0);
309 
310 	/* Content of registers should match payload_data */
311 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
312 		   ((alg_base_words + param->offset_words) * reg_inc_per_word);
313 	KUNIT_EXPECT_EQ(test,
314 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
315 					sizeof(readback)),
316 			0);
317 	KUNIT_EXPECT_MEMEQ(test, readback, payload_data, sizeof(payload_data));
318 
319 	/* Drop expected writes and the cache should then be clean */
320 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
321 	cs_dsp_mock_regmap_drop_range(priv, reg_addr,
322 				      reg_addr + (reg_inc_per_word * ARRAY_SIZE(payload_data)));
323 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
324 }
325 
326 /*
327  * bin file with a multiple one-word payloads. The payloads are not in address
328  * order and collectively do not patch a contiguous block of memory.
329  */
330 static void bin_patch_multi_oneword_sparse_unordered(struct kunit *test)
331 {
332 	struct cs_dsp_test *priv = test->priv;
333 	const struct bin_test_param *param = test->param_value;
334 	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
335 	static const u8 word_offsets[] = {
336 		11, 69, 59, 61, 32, 75, 4, 38, 70, 13, 79, 47, 46, 53, 18, 44,
337 		54, 35, 51, 21, 26, 45, 27, 41, 66, 2, 17, 56, 40, 9, 8, 20,
338 		29, 19, 63, 42, 12, 16, 43, 3, 5, 55, 52, 22
339 	};
340 	u32 payload_data[44];
341 	unsigned int alg_base_words, reg_addr;
342 	struct firmware *fw;
343 	u32 reg_val;
344 	int i;
345 
346 	static_assert(ARRAY_SIZE(word_offsets) == ARRAY_SIZE(payload_data));
347 
348 	get_random_bytes(&payload_data, sizeof(payload_data));
349 
350 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
351 							bin_test_mock_algs[param->alg_idx].id,
352 							param->mem_type);
353 
354 	/* Add one payload per word */
355 	for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
356 		param->add_patch(priv->local->bin_builder,
357 				 bin_test_mock_algs[param->alg_idx].id,
358 				 bin_test_mock_algs[param->alg_idx].ver,
359 				 param->mem_type,
360 				 word_offsets[i] * reg_inc_per_word,
361 				 &payload_data[i], sizeof(payload_data[i]));
362 	}
363 
364 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
365 	KUNIT_ASSERT_EQ(test,
366 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
367 					fw, "mock_bin", "misc"),
368 			0);
369 
370 	/* Content of registers should match payload_data */
371 	for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
372 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
373 			   ((alg_base_words + word_offsets[i]) * reg_inc_per_word);
374 		reg_val = 0;
375 		KUNIT_EXPECT_EQ(test,
376 				regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val,
377 						sizeof(reg_val)),
378 				0);
379 		KUNIT_EXPECT_MEMEQ(test, &reg_val, &payload_data[i], sizeof(reg_val));
380 
381 		/* Drop expected writes from the cache */
382 		cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
383 	}
384 
385 	/* Drop expected writes and the cache should then be clean */
386 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
387 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
388 }
389 
390 /*
391  * bin file that patches a single DSP word in each of the memory regions
392  * of one algorithm.
393  */
394 static void bin_patch_one_word_multiple_mems(struct kunit *test)
395 {
396 	struct cs_dsp_test *priv = test->priv;
397 	const struct bin_test_param *param = test->param_value;
398 	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
399 	unsigned int alg_xm_base_words, alg_ym_base_words, alg_zm_base_words;
400 	unsigned int reg_addr;
401 	u32 payload_data[3];
402 	struct firmware *fw;
403 	u32 reg_val;
404 
405 	get_random_bytes(&payload_data, sizeof(payload_data));
406 
407 	alg_xm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
408 							bin_test_mock_algs[param->alg_idx].id,
409 							WMFW_ADSP2_XM);
410 	alg_ym_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
411 							bin_test_mock_algs[param->alg_idx].id,
412 							WMFW_ADSP2_YM);
413 
414 	if (cs_dsp_mock_has_zm(priv)) {
415 		alg_zm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
416 							bin_test_mock_algs[param->alg_idx].id,
417 							WMFW_ADSP2_ZM);
418 	} else {
419 		alg_zm_base_words = 0;
420 	}
421 
422 	/* Add words to XM, YM and ZM */
423 	param->add_patch(priv->local->bin_builder,
424 			 bin_test_mock_algs[param->alg_idx].id,
425 			 bin_test_mock_algs[param->alg_idx].ver,
426 			 WMFW_ADSP2_XM,
427 			 param->offset_words * reg_inc_per_word,
428 			 &payload_data[0], sizeof(payload_data[0]));
429 
430 	param->add_patch(priv->local->bin_builder,
431 			 bin_test_mock_algs[param->alg_idx].id,
432 			 bin_test_mock_algs[param->alg_idx].ver,
433 			 WMFW_ADSP2_YM,
434 			 param->offset_words * reg_inc_per_word,
435 			 &payload_data[1], sizeof(payload_data[1]));
436 
437 	if (cs_dsp_mock_has_zm(priv)) {
438 		param->add_patch(priv->local->bin_builder,
439 				 bin_test_mock_algs[param->alg_idx].id,
440 				 bin_test_mock_algs[param->alg_idx].ver,
441 				 WMFW_ADSP2_ZM,
442 				 param->offset_words * reg_inc_per_word,
443 				 &payload_data[2], sizeof(payload_data[2]));
444 	}
445 
446 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
447 	KUNIT_ASSERT_EQ(test,
448 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
449 					fw, "mock_bin", "misc"),
450 			0);
451 
452 	/* Content of registers should match payload_data */
453 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM) +
454 		   ((alg_xm_base_words + param->offset_words) * reg_inc_per_word);
455 	reg_val = 0;
456 	KUNIT_EXPECT_EQ(test,
457 			regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val, sizeof(reg_val)),
458 			0);
459 	KUNIT_EXPECT_EQ(test, reg_val, payload_data[0]);
460 
461 	cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
462 
463 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM) +
464 		   ((alg_ym_base_words + param->offset_words) * reg_inc_per_word);
465 	reg_val = 0;
466 	KUNIT_EXPECT_EQ(test,
467 			regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val, sizeof(reg_val)),
468 			0);
469 	KUNIT_EXPECT_EQ(test, reg_val, payload_data[1]);
470 
471 	cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
472 
473 	if (cs_dsp_mock_has_zm(priv)) {
474 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_ZM) +
475 			   ((alg_zm_base_words + param->offset_words) * reg_inc_per_word);
476 		reg_val = 0;
477 		KUNIT_EXPECT_EQ(test,
478 				regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val,
479 						sizeof(reg_val)),
480 				0);
481 		KUNIT_EXPECT_EQ(test, reg_val, payload_data[2]);
482 
483 		/* Drop expected writes from the cache */
484 		cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
485 	}
486 
487 	/* Drop expected writes and the cache should then be clean */
488 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
489 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
490 }
491 
492 /*
493  * bin file that patches a single DSP word in multiple algorithms.
494  */
495 static void bin_patch_one_word_multiple_algs(struct kunit *test)
496 {
497 	struct cs_dsp_test *priv = test->priv;
498 	const struct bin_test_param *param = test->param_value;
499 	u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)];
500 	unsigned int alg_base_words;
501 	unsigned int reg_inc_per_word, reg_addr;
502 	struct firmware *fw;
503 	u32 reg_val;
504 	int i;
505 
506 	get_random_bytes(&payload_data, sizeof(payload_data));
507 
508 	/* Add one payload per algorithm */
509 	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
510 		reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
511 
512 		param->add_patch(priv->local->bin_builder,
513 				 bin_test_mock_algs[i].id,
514 				 bin_test_mock_algs[i].ver,
515 				 param->mem_type,
516 				 param->offset_words * reg_inc_per_word,
517 				 &payload_data[i], sizeof(payload_data[i]));
518 	}
519 
520 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
521 	KUNIT_ASSERT_EQ(test,
522 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
523 					fw, "mock_bin", "misc"),
524 			0);
525 
526 	/* Content of registers should match payload_data */
527 	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
528 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
529 								bin_test_mock_algs[i].id,
530 								param->mem_type);
531 		reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
532 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
533 			   ((alg_base_words + param->offset_words) * reg_inc_per_word);
534 		reg_val = 0;
535 		KUNIT_EXPECT_EQ(test,
536 				regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val,
537 						sizeof(reg_val)),
538 				0);
539 		KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);
540 
541 		/* Drop expected writes from the cache */
542 		cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
543 	}
544 
545 	/* Drop expected writes and the cache should then be clean */
546 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
547 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
548 }
549 
550 /*
551  * bin file that patches a single DSP word in multiple algorithms.
552  * The algorithms are not patched in the same order they appear in the XM header.
553  */
554 static void bin_patch_one_word_multiple_algs_unordered(struct kunit *test)
555 {
556 	struct cs_dsp_test *priv = test->priv;
557 	const struct bin_test_param *param = test->param_value;
558 	static const u8 alg_order[] = { 3, 0, 2, 1 };
559 	u32 payload_data[ARRAY_SIZE(bin_test_mock_algs)];
560 	unsigned int alg_base_words;
561 	unsigned int reg_inc_per_word, reg_addr;
562 	struct firmware *fw;
563 	u32 reg_val;
564 	int i, alg_idx;
565 
566 	static_assert(ARRAY_SIZE(alg_order) == ARRAY_SIZE(bin_test_mock_algs));
567 
568 	get_random_bytes(&payload_data, sizeof(payload_data));
569 
570 	/* Add one payload per algorithm */
571 	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
572 		alg_idx = alg_order[i];
573 		reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
574 
575 		param->add_patch(priv->local->bin_builder,
576 				 bin_test_mock_algs[alg_idx].id,
577 				 bin_test_mock_algs[alg_idx].ver,
578 				 param->mem_type,
579 				 param->offset_words * reg_inc_per_word,
580 				 &payload_data[i], sizeof(payload_data[i]));
581 	}
582 
583 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
584 	KUNIT_ASSERT_EQ(test,
585 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
586 					fw, "mock_bin", "misc"),
587 			0);
588 
589 	/* Content of registers should match payload_data */
590 	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
591 		alg_idx = alg_order[i];
592 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
593 								bin_test_mock_algs[alg_idx].id,
594 								param->mem_type);
595 		reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
596 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
597 			   ((alg_base_words + param->offset_words) * reg_inc_per_word);
598 		reg_val = 0;
599 		KUNIT_EXPECT_EQ(test,
600 				regmap_raw_read(priv->dsp->regmap, reg_addr, &reg_val,
601 						sizeof(reg_val)),
602 				0);
603 		KUNIT_EXPECT_EQ(test, reg_val, payload_data[i]);
604 
605 		/* Drop expected writes from the cache */
606 		cs_dsp_mock_regmap_drop_range(priv, reg_addr, reg_addr + reg_inc_per_word - 1);
607 	}
608 
609 	/* Drop expected writes and the cache should then be clean */
610 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
611 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
612 }
613 
614 /* bin file that patches a single packed block of DSP words */
615 static void bin_patch_1_packed(struct kunit *test)
616 {
617 	struct cs_dsp_test *priv = test->priv;
618 	const struct bin_test_param *param = test->param_value;
619 	u32 packed_payload[3], readback[3];
620 	unsigned int alg_base_words, patch_pos_words;
621 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
622 	unsigned int reg_addr;
623 	struct firmware *fw;
624 
625 	static_assert(sizeof(readback) == sizeof(packed_payload));
626 
627 	get_random_bytes(packed_payload, sizeof(packed_payload));
628 
629 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
630 							bin_test_mock_algs[param->alg_idx].id,
631 							param->mem_type);
632 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
633 
634 	/* Round patch start word up to a packed boundary */
635 	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
636 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
637 
638 	param->add_patch(priv->local->bin_builder,
639 			 bin_test_mock_algs[param->alg_idx].id,
640 			 bin_test_mock_algs[param->alg_idx].ver,
641 			 param->mem_type,
642 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
643 			 packed_payload, sizeof(packed_payload));
644 
645 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
646 	KUNIT_ASSERT_EQ(test,
647 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
648 					fw, "mock_bin", "misc"),
649 			0);
650 
651 	/* Content of registers should match payload_data */
652 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
653 		   (patch_pos_in_packed_regs * 4);
654 	memset(readback, 0, sizeof(readback));
655 	KUNIT_EXPECT_EQ(test,
656 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
657 					sizeof(readback)),
658 			0);
659 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));
660 
661 	/* Drop expected writes and the cache should then be clean */
662 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
663 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
664 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
665 }
666 
667 /*
668  * Patch data that is one word longer than a packed block using one
669  * packed block followed by one unpacked word.
670  */
671 static void bin_patch_1_packed_1_single_trailing(struct kunit *test)
672 {
673 	struct cs_dsp_test *priv = test->priv;
674 	const struct bin_test_param *param = test->param_value;
675 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
676 	u32 packed_payload[3], unpacked_payload[1], readback[3];
677 	unsigned int alg_base_words, patch_pos_words;
678 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
679 	unsigned int reg_addr;
680 	struct firmware *fw;
681 
682 	static_assert(sizeof(readback) == sizeof(packed_payload));
683 	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
684 
685 	get_random_bytes(packed_payload, sizeof(packed_payload));
686 	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
687 
688 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
689 							bin_test_mock_algs[param->alg_idx].id,
690 							param->mem_type);
691 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
692 
693 	/* Round patch start word up to a packed boundary */
694 	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
695 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
696 
697 	/* Patch packed block */
698 	param->add_patch(priv->local->bin_builder,
699 			 bin_test_mock_algs[param->alg_idx].id,
700 			 bin_test_mock_algs[param->alg_idx].ver,
701 			 param->mem_type,
702 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
703 			 &packed_payload, sizeof(packed_payload));
704 
705 	/* ... and the unpacked word following that */
706 	param->add_patch(priv->local->bin_builder,
707 			 bin_test_mock_algs[param->alg_idx].id,
708 			 bin_test_mock_algs[param->alg_idx].ver,
709 			 unpacked_mem_type,
710 			 ((patch_pos_words + 4) - alg_base_words) * 4,
711 			 unpacked_payload, sizeof(unpacked_payload));
712 
713 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
714 	KUNIT_ASSERT_EQ(test,
715 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
716 					fw, "mock_bin", "misc"),
717 			0);
718 
719 	/* Content of packed registers should match packed_payload */
720 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
721 		   (patch_pos_in_packed_regs * 4);
722 	memset(readback, 0, sizeof(readback));
723 	KUNIT_EXPECT_EQ(test,
724 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
725 			0);
726 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
727 
728 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
729 
730 	/* Content of unpacked registers should match unpacked_payload */
731 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
732 		   (patch_pos_words + 4) * 4;
733 	memset(readback, 0, sizeof(readback));
734 	KUNIT_EXPECT_EQ(test,
735 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
736 					sizeof(unpacked_payload)),
737 			0);
738 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
739 
740 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
741 
742 	/* Drop expected writes and the cache should then be clean */
743 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
744 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
745 }
746 
747 /*
748  * Patch data that is two words longer than a packed block using one
749  * packed block followed by two blocks of one unpacked word.
750  */
751 static void bin_patch_1_packed_2_single_trailing(struct kunit *test)
752 {
753 	struct cs_dsp_test *priv = test->priv;
754 	const struct bin_test_param *param = test->param_value;
755 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
756 	u32 packed_payload[3], unpacked_payloads[2], readback[3];
757 	unsigned int alg_base_words, patch_pos_words;
758 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
759 	unsigned int reg_addr;
760 	struct firmware *fw;
761 
762 	static_assert(sizeof(readback) == sizeof(packed_payload));
763 	static_assert(sizeof(readback) >= sizeof(unpacked_payloads));
764 
765 	get_random_bytes(packed_payload, sizeof(packed_payload));
766 	get_random_bytes(unpacked_payloads, sizeof(unpacked_payloads));
767 
768 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
769 							bin_test_mock_algs[param->alg_idx].id,
770 							param->mem_type);
771 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
772 
773 	/* Round patch start word up to a packed boundary */
774 	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
775 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
776 
777 	/* Patch packed block */
778 	param->add_patch(priv->local->bin_builder,
779 			 bin_test_mock_algs[param->alg_idx].id,
780 			 bin_test_mock_algs[param->alg_idx].ver,
781 			 param->mem_type,
782 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
783 			 &packed_payload, sizeof(packed_payload));
784 
785 	/* ... and the unpacked words following that */
786 	param->add_patch(priv->local->bin_builder,
787 			 bin_test_mock_algs[param->alg_idx].id,
788 			 bin_test_mock_algs[param->alg_idx].ver,
789 			 unpacked_mem_type,
790 			 ((patch_pos_words + 4) - alg_base_words) * 4,
791 			 &unpacked_payloads[0], sizeof(unpacked_payloads[0]));
792 
793 	param->add_patch(priv->local->bin_builder,
794 			 bin_test_mock_algs[param->alg_idx].id,
795 			 bin_test_mock_algs[param->alg_idx].ver,
796 			 unpacked_mem_type,
797 			 ((patch_pos_words + 5) - alg_base_words) * 4,
798 			 &unpacked_payloads[1], sizeof(unpacked_payloads[1]));
799 
800 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
801 	KUNIT_ASSERT_EQ(test,
802 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
803 					fw, "mock_bin", "misc"),
804 			0);
805 
806 	/* Content of packed registers should match packed_payload */
807 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
808 		   (patch_pos_in_packed_regs * 4);
809 	memset(readback, 0, sizeof(readback));
810 	KUNIT_EXPECT_EQ(test,
811 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
812 			0);
813 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
814 
815 	/* Drop expected writes from the cache */
816 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
817 
818 	/* Content of unpacked registers should match unpacked_payloads */
819 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
820 		   (patch_pos_words + 4) * 4;
821 	memset(readback, 0, sizeof(readback));
822 	KUNIT_EXPECT_EQ(test,
823 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
824 					sizeof(unpacked_payloads)),
825 			0);
826 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payloads, sizeof(unpacked_payloads));
827 
828 	/* Drop expected writes from the cache */
829 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));
830 
831 	/* Drop expected writes and the cache should then be clean */
832 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
833 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
834 }
835 
836 /*
837  * Patch data that is three words longer than a packed block using one
838  * packed block followed by three blocks of one unpacked word.
839  */
840 static void bin_patch_1_packed_3_single_trailing(struct kunit *test)
841 {
842 	struct cs_dsp_test *priv = test->priv;
843 	const struct bin_test_param *param = test->param_value;
844 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
845 	u32 packed_payload[3], unpacked_payloads[3], readback[3];
846 	unsigned int alg_base_words, patch_pos_words;
847 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
848 	unsigned int reg_addr;
849 	struct firmware *fw;
850 
851 	static_assert(sizeof(readback) == sizeof(packed_payload));
852 	static_assert(sizeof(readback) >= sizeof(unpacked_payloads));
853 
854 	get_random_bytes(packed_payload, sizeof(packed_payload));
855 	get_random_bytes(unpacked_payloads, sizeof(unpacked_payloads));
856 
857 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
858 							bin_test_mock_algs[param->alg_idx].id,
859 							param->mem_type);
860 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
861 
862 	/* Round patch start word up to a packed boundary */
863 	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
864 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
865 
866 	/* Patch packed block */
867 	param->add_patch(priv->local->bin_builder,
868 			 bin_test_mock_algs[param->alg_idx].id,
869 			 bin_test_mock_algs[param->alg_idx].ver,
870 			 param->mem_type,
871 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
872 			 &packed_payload, sizeof(packed_payload));
873 
874 	/* ... and the unpacked words following that */
875 	param->add_patch(priv->local->bin_builder,
876 			 bin_test_mock_algs[param->alg_idx].id,
877 			 bin_test_mock_algs[param->alg_idx].ver,
878 			 unpacked_mem_type,
879 			 ((patch_pos_words + 4) - alg_base_words) * 4,
880 			 &unpacked_payloads[0], sizeof(unpacked_payloads[0]));
881 
882 	param->add_patch(priv->local->bin_builder,
883 			 bin_test_mock_algs[param->alg_idx].id,
884 			 bin_test_mock_algs[param->alg_idx].ver,
885 			 unpacked_mem_type,
886 			 ((patch_pos_words + 5) - alg_base_words) * 4,
887 			 &unpacked_payloads[1], sizeof(unpacked_payloads[1]));
888 
889 	param->add_patch(priv->local->bin_builder,
890 			 bin_test_mock_algs[param->alg_idx].id,
891 			 bin_test_mock_algs[param->alg_idx].ver,
892 			 unpacked_mem_type,
893 			 ((patch_pos_words + 6) - alg_base_words) * 4,
894 			 &unpacked_payloads[2], sizeof(unpacked_payloads[2]));
895 
896 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
897 	KUNIT_ASSERT_EQ(test,
898 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
899 					fw, "mock_bin", "misc"),
900 			0);
901 
902 	/* Content of packed registers should match packed_payload */
903 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
904 		   (patch_pos_in_packed_regs * 4);
905 	memset(readback, 0, sizeof(readback));
906 	KUNIT_EXPECT_EQ(test,
907 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
908 			0);
909 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
910 
911 	/* Drop expected writes from the cache */
912 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
913 
914 	/* Content of unpacked registers should match unpacked_payloads */
915 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
916 		   (patch_pos_words + 4) * 4;
917 	memset(readback, 0, sizeof(readback));
918 	KUNIT_EXPECT_EQ(test,
919 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
920 					sizeof(unpacked_payloads)),
921 			0);
922 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payloads, sizeof(unpacked_payloads));
923 
924 	/* Drop expected writes from the cache */
925 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payloads));
926 
927 	/* Drop expected writes and the cache should then be clean */
928 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
929 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
930 }
931 
932 /*
933  * Patch data that is two words longer than a packed block using one
934  * packed block followed by a block of two unpacked words.
935  */
936 static void bin_patch_1_packed_2_trailing(struct kunit *test)
937 {
938 	struct cs_dsp_test *priv = test->priv;
939 	const struct bin_test_param *param = test->param_value;
940 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
941 	u32 packed_payload[3], unpacked_payload[2], readback[3];
942 	unsigned int alg_base_words, patch_pos_words;
943 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
944 	unsigned int reg_addr;
945 	struct firmware *fw;
946 
947 	static_assert(sizeof(readback) == sizeof(packed_payload));
948 	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
949 
950 	get_random_bytes(packed_payload, sizeof(packed_payload));
951 	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
952 
953 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
954 							bin_test_mock_algs[param->alg_idx].id,
955 							param->mem_type);
956 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
957 
958 	/* Round patch start word up to a packed boundary */
959 	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
960 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
961 
962 	/* Patch packed block */
963 	param->add_patch(priv->local->bin_builder,
964 			 bin_test_mock_algs[param->alg_idx].id,
965 			 bin_test_mock_algs[param->alg_idx].ver,
966 			 param->mem_type,
967 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
968 			 &packed_payload, sizeof(packed_payload));
969 
970 	/* ... and the unpacked words following that */
971 	param->add_patch(priv->local->bin_builder,
972 			 bin_test_mock_algs[param->alg_idx].id,
973 			 bin_test_mock_algs[param->alg_idx].ver,
974 			 unpacked_mem_type,
975 			 ((patch_pos_words + 4) - alg_base_words) * 4,
976 			 unpacked_payload, sizeof(unpacked_payload));
977 
978 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
979 	KUNIT_ASSERT_EQ(test,
980 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
981 					fw, "mock_bin", "misc"),
982 			0);
983 
984 	/* Content of packed registers should match packed_payload */
985 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
986 		   (patch_pos_in_packed_regs * 4);
987 	memset(readback, 0, sizeof(readback));
988 	KUNIT_EXPECT_EQ(test,
989 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
990 			0);
991 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
992 
993 	/* Drop expected writes from the cache */
994 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
995 
996 	/* Content of unpacked registers should match unpacked_payload */
997 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
998 		   (patch_pos_words + 4) * 4;
999 	memset(readback, 0, sizeof(readback));
1000 	KUNIT_EXPECT_EQ(test,
1001 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1002 					sizeof(unpacked_payload)),
1003 			0);
1004 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1005 
1006 	/* Drop expected writes from the cache */
1007 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1008 
1009 	/* Drop expected writes and the cache should then be clean */
1010 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1011 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1012 }
1013 
1014 /*
1015  * Patch data that is three words longer than a packed block using one
1016  * packed block followed by a block of three unpacked words.
1017  */
1018 static void bin_patch_1_packed_3_trailing(struct kunit *test)
1019 {
1020 	struct cs_dsp_test *priv = test->priv;
1021 	const struct bin_test_param *param = test->param_value;
1022 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1023 	u32 packed_payload[3], unpacked_payload[3], readback[3];
1024 	unsigned int alg_base_words, patch_pos_words;
1025 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1026 	unsigned int reg_addr;
1027 	struct firmware *fw;
1028 
1029 	static_assert(sizeof(readback) == sizeof(packed_payload));
1030 	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1031 
1032 	get_random_bytes(packed_payload, sizeof(packed_payload));
1033 	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1034 
1035 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1036 							bin_test_mock_algs[param->alg_idx].id,
1037 							param->mem_type);
1038 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1039 
1040 	/* Round patch start word up to a packed boundary */
1041 	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1042 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1043 
1044 	/* Patch packed block */
1045 	param->add_patch(priv->local->bin_builder,
1046 			 bin_test_mock_algs[param->alg_idx].id,
1047 			 bin_test_mock_algs[param->alg_idx].ver,
1048 			 param->mem_type,
1049 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1050 			 &packed_payload, sizeof(packed_payload));
1051 
1052 	/* ... and the unpacked words following that */
1053 	param->add_patch(priv->local->bin_builder,
1054 			 bin_test_mock_algs[param->alg_idx].id,
1055 			 bin_test_mock_algs[param->alg_idx].ver,
1056 			 unpacked_mem_type,
1057 			 ((patch_pos_words + 4) - alg_base_words) * 4,
1058 			 unpacked_payload, sizeof(unpacked_payload));
1059 
1060 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1061 	KUNIT_ASSERT_EQ(test,
1062 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1063 					fw, "mock_bin", "misc"),
1064 			0);
1065 
1066 	/* Content of packed registers should match packed_payload */
1067 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1068 		   (patch_pos_in_packed_regs * 4);
1069 	memset(readback, 0, sizeof(readback));
1070 	KUNIT_EXPECT_EQ(test,
1071 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1072 			0);
1073 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1074 
1075 	/* Drop expected writes from the cache */
1076 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1077 
1078 	/* Content of unpacked registers should match unpacked_payload */
1079 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1080 		   (patch_pos_words + 4) * 4;
1081 	memset(readback, 0, sizeof(readback));
1082 	KUNIT_EXPECT_EQ(test,
1083 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1084 					sizeof(unpacked_payload)),
1085 			0);
1086 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1087 
1088 	/* Drop expected writes from the cache */
1089 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1090 
1091 	/* Drop expected writes and the cache should then be clean */
1092 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1093 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1094 }
1095 
1096 /*
1097  * Patch data that starts one word before a packed boundary using one
1098  * unpacked word followed by one packed block.
1099  */
1100 static void bin_patch_1_single_leading_1_packed(struct kunit *test)
1101 {
1102 	struct cs_dsp_test *priv = test->priv;
1103 	const struct bin_test_param *param = test->param_value;
1104 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1105 	u32 packed_payload[3], unpacked_payload[1], readback[3];
1106 	unsigned int alg_base_words, packed_patch_pos_words;
1107 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1108 	unsigned int reg_addr;
1109 	struct firmware *fw;
1110 
1111 	static_assert(sizeof(readback) == sizeof(packed_payload));
1112 	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1113 
1114 	get_random_bytes(packed_payload, sizeof(packed_payload));
1115 	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1116 	memset(readback, 0, sizeof(readback));
1117 
1118 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1119 							bin_test_mock_algs[param->alg_idx].id,
1120 							param->mem_type);
1121 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1122 
1123 	/* Round packed start word up to a packed boundary and move to the next boundary */
1124 	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1125 
1126 	/* Patch the leading unpacked word */
1127 	param->add_patch(priv->local->bin_builder,
1128 			 bin_test_mock_algs[param->alg_idx].id,
1129 			 bin_test_mock_algs[param->alg_idx].ver,
1130 			 unpacked_mem_type,
1131 			 ((packed_patch_pos_words - 1) - alg_base_words) * 4,
1132 			 unpacked_payload, sizeof(unpacked_payload));
1133 	/* ... then the packed block */
1134 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1135 	param->add_patch(priv->local->bin_builder,
1136 			 bin_test_mock_algs[param->alg_idx].id,
1137 			 bin_test_mock_algs[param->alg_idx].ver,
1138 			 param->mem_type,
1139 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1140 			 &packed_payload, sizeof(packed_payload));
1141 
1142 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1143 	KUNIT_ASSERT_EQ(test,
1144 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1145 					fw, "mock_bin", "misc"),
1146 			0);
1147 
1148 	/* Content of packed registers should match packed_payload */
1149 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1150 		   (patch_pos_in_packed_regs * 4);
1151 	KUNIT_EXPECT_EQ(test,
1152 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1153 			0);
1154 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1155 
1156 	/* Drop expected writes from the cache */
1157 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1158 
1159 	/* Content of unpacked registers should match unpacked_payload */
1160 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1161 		   (packed_patch_pos_words - 1) * 4;
1162 	KUNIT_EXPECT_EQ(test,
1163 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1164 					sizeof(unpacked_payload)),
1165 			0);
1166 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1167 
1168 	/* Drop expected writes from the cache */
1169 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1170 
1171 	/* Drop expected writes and the cache should then be clean */
1172 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1173 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1174 }
1175 
1176 /*
1177  * Patch data that starts two words before a packed boundary using two
1178  * unpacked words followed by one packed block.
1179  */
1180 static void bin_patch_2_single_leading_1_packed(struct kunit *test)
1181 {
1182 	struct cs_dsp_test *priv = test->priv;
1183 	const struct bin_test_param *param = test->param_value;
1184 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1185 	u32 packed_payload[3], unpacked_payload[2], readback[3];
1186 	unsigned int alg_base_words, packed_patch_pos_words;
1187 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1188 	unsigned int reg_addr;
1189 	struct firmware *fw;
1190 
1191 	static_assert(sizeof(readback) == sizeof(packed_payload));
1192 	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1193 
1194 	get_random_bytes(packed_payload, sizeof(packed_payload));
1195 	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1196 
1197 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1198 							bin_test_mock_algs[param->alg_idx].id,
1199 							param->mem_type);
1200 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1201 
1202 	/* Round packed start word up to a packed boundary and move to the next boundary */
1203 	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1204 
1205 	/* Patch the leading unpacked words */
1206 	param->add_patch(priv->local->bin_builder,
1207 			 bin_test_mock_algs[param->alg_idx].id,
1208 			 bin_test_mock_algs[param->alg_idx].ver,
1209 			 unpacked_mem_type,
1210 			 ((packed_patch_pos_words - 2) - alg_base_words) * 4,
1211 			 &unpacked_payload[0], sizeof(unpacked_payload[0]));
1212 	param->add_patch(priv->local->bin_builder,
1213 			 bin_test_mock_algs[param->alg_idx].id,
1214 			 bin_test_mock_algs[param->alg_idx].ver,
1215 			 unpacked_mem_type,
1216 			 ((packed_patch_pos_words - 1) - alg_base_words) * 4,
1217 			 &unpacked_payload[1], sizeof(unpacked_payload[1]));
1218 	/* ... then the packed block */
1219 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1220 	param->add_patch(priv->local->bin_builder,
1221 			 bin_test_mock_algs[param->alg_idx].id,
1222 			 bin_test_mock_algs[param->alg_idx].ver,
1223 			 param->mem_type,
1224 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1225 			 &packed_payload, sizeof(packed_payload));
1226 
1227 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1228 	KUNIT_ASSERT_EQ(test,
1229 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1230 					fw, "mock_bin", "misc"),
1231 			0);
1232 
1233 	/* Content of packed registers should match packed_payload */
1234 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1235 		   (patch_pos_in_packed_regs * 4);
1236 	memset(readback, 0, sizeof(readback));
1237 	KUNIT_EXPECT_EQ(test,
1238 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1239 			0);
1240 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1241 
1242 	/* Drop expected writes from the cache */
1243 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1244 
1245 	/* Content of unpacked registers should match unpacked_payload */
1246 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1247 		   (packed_patch_pos_words - 2) * 4;
1248 	memset(readback, 0, sizeof(readback));
1249 	KUNIT_EXPECT_EQ(test,
1250 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1251 					sizeof(unpacked_payload)),
1252 			0);
1253 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1254 
1255 	/* Drop expected writes from the cache */
1256 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1257 
1258 	/* Drop expected writes and the cache should then be clean */
1259 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1260 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1261 }
1262 
1263 /*
1264  * Patch data that starts two words before a packed boundary using one
1265  * block of two unpacked words followed by one packed block.
1266  */
1267 static void bin_patch_2_leading_1_packed(struct kunit *test)
1268 {
1269 	struct cs_dsp_test *priv = test->priv;
1270 	const struct bin_test_param *param = test->param_value;
1271 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1272 	u32 packed_payload[3], unpacked_payload[2], readback[3];
1273 	unsigned int alg_base_words, packed_patch_pos_words;
1274 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1275 	unsigned int reg_addr;
1276 	struct firmware *fw;
1277 
1278 	static_assert(sizeof(readback) == sizeof(packed_payload));
1279 	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1280 
1281 	get_random_bytes(packed_payload, sizeof(packed_payload));
1282 	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1283 
1284 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1285 							bin_test_mock_algs[param->alg_idx].id,
1286 							param->mem_type);
1287 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1288 
1289 	/* Round packed start word up to a packed boundary and move to the next boundary */
1290 	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1291 
1292 	/* Patch the leading unpacked words */
1293 	param->add_patch(priv->local->bin_builder,
1294 			 bin_test_mock_algs[param->alg_idx].id,
1295 			 bin_test_mock_algs[param->alg_idx].ver,
1296 			 unpacked_mem_type,
1297 			 ((packed_patch_pos_words - 2) - alg_base_words) * 4,
1298 			 unpacked_payload, sizeof(unpacked_payload));
1299 	/* ... then the packed block */
1300 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1301 	param->add_patch(priv->local->bin_builder,
1302 			 bin_test_mock_algs[param->alg_idx].id,
1303 			 bin_test_mock_algs[param->alg_idx].ver,
1304 			 param->mem_type,
1305 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1306 			 &packed_payload, sizeof(packed_payload));
1307 
1308 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1309 	KUNIT_ASSERT_EQ(test,
1310 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1311 					fw, "mock_bin", "misc"),
1312 			0);
1313 
1314 	/* Content of packed registers should match packed_payload */
1315 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1316 		   (patch_pos_in_packed_regs * 4);
1317 	memset(readback, 0, sizeof(readback));
1318 	KUNIT_EXPECT_EQ(test,
1319 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1320 			0);
1321 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1322 
1323 	/* Drop expected writes from the cache */
1324 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1325 
1326 	/* Content of unpacked registers should match unpacked_payload */
1327 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1328 		   (packed_patch_pos_words - 2) * 4;
1329 	memset(readback, 0, sizeof(readback));
1330 	KUNIT_EXPECT_EQ(test,
1331 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1332 					sizeof(unpacked_payload)),
1333 			0);
1334 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1335 
1336 	/* Drop expected writes from the cache */
1337 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1338 
1339 	/* Drop expected writes and the cache should then be clean */
1340 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1341 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1342 }
1343 
1344 /*
1345  * Patch data that starts three words before a packed boundary using three
1346  * unpacked words followed by one packed block.
1347  */
1348 static void bin_patch_3_single_leading_1_packed(struct kunit *test)
1349 {
1350 	struct cs_dsp_test *priv = test->priv;
1351 	const struct bin_test_param *param = test->param_value;
1352 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1353 	u32 packed_payload[3], unpacked_payload[3], readback[3];
1354 	unsigned int alg_base_words, packed_patch_pos_words;
1355 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1356 	unsigned int reg_addr;
1357 	struct firmware *fw;
1358 
1359 	static_assert(sizeof(readback) == sizeof(packed_payload));
1360 	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1361 
1362 	get_random_bytes(packed_payload, sizeof(packed_payload));
1363 	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1364 
1365 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1366 							bin_test_mock_algs[param->alg_idx].id,
1367 							param->mem_type);
1368 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1369 
1370 	/* Round packed start word up to a packed boundary and move to the next boundary */
1371 	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1372 
1373 	/* Patch the leading unpacked words */
1374 	param->add_patch(priv->local->bin_builder,
1375 			 bin_test_mock_algs[param->alg_idx].id,
1376 			 bin_test_mock_algs[param->alg_idx].ver,
1377 			 unpacked_mem_type,
1378 			 ((packed_patch_pos_words - 3) - alg_base_words) * 4,
1379 			 &unpacked_payload[0], sizeof(unpacked_payload[0]));
1380 	param->add_patch(priv->local->bin_builder,
1381 			 bin_test_mock_algs[param->alg_idx].id,
1382 			 bin_test_mock_algs[param->alg_idx].ver,
1383 			 unpacked_mem_type,
1384 			 ((packed_patch_pos_words - 2) - alg_base_words) * 4,
1385 			 &unpacked_payload[1], sizeof(unpacked_payload[1]));
1386 	param->add_patch(priv->local->bin_builder,
1387 			 bin_test_mock_algs[param->alg_idx].id,
1388 			 bin_test_mock_algs[param->alg_idx].ver,
1389 			 unpacked_mem_type,
1390 			 ((packed_patch_pos_words - 1) - alg_base_words) * 4,
1391 			 &unpacked_payload[2], sizeof(unpacked_payload[2]));
1392 	/* ... then the packed block */
1393 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1394 	param->add_patch(priv->local->bin_builder,
1395 			 bin_test_mock_algs[param->alg_idx].id,
1396 			 bin_test_mock_algs[param->alg_idx].ver,
1397 			 param->mem_type,
1398 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1399 			 &packed_payload, sizeof(packed_payload));
1400 
1401 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1402 	KUNIT_ASSERT_EQ(test,
1403 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1404 					fw, "mock_bin", "misc"),
1405 			0);
1406 
1407 	/* Content of packed registers should match packed_payload */
1408 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1409 		   (patch_pos_in_packed_regs * 4);
1410 	memset(readback, 0, sizeof(readback));
1411 	KUNIT_EXPECT_EQ(test,
1412 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1413 			0);
1414 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1415 
1416 	/* Drop expected writes from the cache */
1417 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1418 
1419 	/* Content of unpacked registers should match unpacked_payload */
1420 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1421 		   (packed_patch_pos_words - 3) * 4;
1422 	memset(readback, 0, sizeof(readback));
1423 	KUNIT_EXPECT_EQ(test,
1424 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1425 					sizeof(unpacked_payload)),
1426 			0);
1427 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1428 
1429 	/* Drop expected writes from the cache */
1430 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1431 
1432 	/* Drop expected writes and the cache should then be clean */
1433 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1434 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1435 }
1436 
1437 /*
1438  * Patch data that starts three words before a packed boundary using one
1439  * block of three unpacked words followed by one packed block.
1440  */
1441 static void bin_patch_3_leading_1_packed(struct kunit *test)
1442 {
1443 	struct cs_dsp_test *priv = test->priv;
1444 	const struct bin_test_param *param = test->param_value;
1445 	unsigned int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1446 	u32 packed_payload[3], unpacked_payload[3], readback[3];
1447 	unsigned int alg_base_words, packed_patch_pos_words;
1448 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1449 	unsigned int reg_addr;
1450 	struct firmware *fw;
1451 
1452 	static_assert(sizeof(readback) == sizeof(packed_payload));
1453 	static_assert(sizeof(readback) >= sizeof(unpacked_payload));
1454 
1455 	get_random_bytes(packed_payload, sizeof(packed_payload));
1456 	get_random_bytes(unpacked_payload, sizeof(unpacked_payload));
1457 
1458 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1459 							bin_test_mock_algs[param->alg_idx].id,
1460 							param->mem_type);
1461 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1462 
1463 	/* Round packed start word up to a packed boundary and move to the next boundary */
1464 	packed_patch_pos_words = round_up(alg_base_words + param->offset_words, 4) + 4;
1465 
1466 	/* Patch the leading unpacked words */
1467 	param->add_patch(priv->local->bin_builder,
1468 			 bin_test_mock_algs[param->alg_idx].id,
1469 			 bin_test_mock_algs[param->alg_idx].ver,
1470 			 unpacked_mem_type,
1471 			 ((packed_patch_pos_words - 3) - alg_base_words) * 4,
1472 			 unpacked_payload, sizeof(unpacked_payload));
1473 	/* ... then the packed block */
1474 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(packed_patch_pos_words);
1475 	param->add_patch(priv->local->bin_builder,
1476 			 bin_test_mock_algs[param->alg_idx].id,
1477 			 bin_test_mock_algs[param->alg_idx].ver,
1478 			 param->mem_type,
1479 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1480 			 &packed_payload, sizeof(packed_payload));
1481 
1482 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1483 	KUNIT_ASSERT_EQ(test,
1484 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1485 					fw, "mock_bin", "misc"),
1486 			0);
1487 
1488 	/* Content of packed registers should match packed_payload */
1489 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1490 		   (patch_pos_in_packed_regs * 4);
1491 	memset(readback, 0, sizeof(readback));
1492 	KUNIT_EXPECT_EQ(test,
1493 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback, sizeof(readback)),
1494 			0);
1495 	KUNIT_EXPECT_MEMEQ(test, &readback, &packed_payload, sizeof(packed_payload));
1496 
1497 	/* Drop expected writes from the cache */
1498 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload));
1499 
1500 	/* Content of unpacked registers should match unpacked_payload */
1501 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
1502 		   (packed_patch_pos_words - 3) * 4;
1503 	memset(readback, 0, sizeof(readback));
1504 	KUNIT_EXPECT_EQ(test,
1505 			regmap_raw_read(priv->dsp->regmap, reg_addr, &readback,
1506 					sizeof(unpacked_payload)),
1507 			0);
1508 	KUNIT_EXPECT_MEMEQ(test, &readback, unpacked_payload, sizeof(unpacked_payload));
1509 
1510 	/* Drop expected writes from the cache */
1511 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(unpacked_payload));
1512 
1513 	/* Drop expected writes and the cache should then be clean */
1514 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1515 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1516 }
1517 
1518 /* bin file with a multiple payloads that each patch one packed block. */
1519 static void bin_patch_multi_onepacked(struct kunit *test)
1520 {
1521 	struct cs_dsp_test *priv = test->priv;
1522 	const struct bin_test_param *param = test->param_value;
1523 	u32 packed_payloads[8][3], readback[8][3];
1524 	unsigned int alg_base_words, patch_pos_words;
1525 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1526 	unsigned int payload_offset;
1527 	unsigned int reg_addr;
1528 	struct firmware *fw;
1529 	int i;
1530 
1531 	static_assert(sizeof(readback) == sizeof(packed_payloads));
1532 
1533 	get_random_bytes(packed_payloads, sizeof(packed_payloads));
1534 
1535 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1536 							bin_test_mock_algs[param->alg_idx].id,
1537 							param->mem_type);
1538 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1539 
1540 	/* Round patch start word up to a packed boundary */
1541 	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1542 
1543 	/* Add one payload per packed block */
1544 	for (i = 0; i < ARRAY_SIZE(packed_payloads); ++i) {
1545 		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words + (i * 4));
1546 		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1547 		param->add_patch(priv->local->bin_builder,
1548 				 bin_test_mock_algs[param->alg_idx].id,
1549 				 bin_test_mock_algs[param->alg_idx].ver,
1550 				 param->mem_type,
1551 				 payload_offset,
1552 				 &packed_payloads[i], sizeof(packed_payloads[i]));
1553 	}
1554 
1555 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1556 	KUNIT_ASSERT_EQ(test,
1557 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1558 					fw, "mock_bin", "misc"),
1559 			0);
1560 
1561 	/* Content of packed registers should match packed_payloads */
1562 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1563 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1564 		   (patch_pos_in_packed_regs * 4);
1565 	memset(readback, 0, sizeof(readback));
1566 	KUNIT_EXPECT_EQ(test,
1567 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
1568 			0);
1569 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));
1570 
1571 	/* Drop expected writes and the cache should then be clean */
1572 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1573 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));
1574 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1575 }
1576 
1577 /*
1578  * bin file with a multiple payloads that each patch one packed block.
1579  * The payloads are not in address order.
1580  */
1581 static void bin_patch_multi_onepacked_unordered(struct kunit *test)
1582 {
1583 	struct cs_dsp_test *priv = test->priv;
1584 	const struct bin_test_param *param = test->param_value;
1585 	static const u8 payload_order[] = { 4, 3, 6, 1, 0, 7, 5, 2 };
1586 	u32 packed_payloads[8][3], readback[8][3];
1587 	unsigned int alg_base_words, patch_pos_words;
1588 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1589 	unsigned int payload_offset;
1590 	unsigned int reg_addr;
1591 	struct firmware *fw;
1592 	int i;
1593 
1594 	static_assert(ARRAY_SIZE(payload_order) == ARRAY_SIZE(packed_payloads));
1595 	static_assert(sizeof(readback) == sizeof(packed_payloads));
1596 
1597 	get_random_bytes(packed_payloads, sizeof(packed_payloads));
1598 
1599 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1600 							bin_test_mock_algs[param->alg_idx].id,
1601 							param->mem_type);
1602 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1603 
1604 	/* Round patch start word up to a packed boundary */
1605 	patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1606 
1607 	/* Add one payload per packed block */
1608 	for (i = 0; i < ARRAY_SIZE(payload_order); ++i) {
1609 		patch_pos_in_packed_regs =
1610 			_num_words_to_num_packed_regs(patch_pos_words + (payload_order[i] * 4));
1611 		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1612 		param->add_patch(priv->local->bin_builder,
1613 				 bin_test_mock_algs[param->alg_idx].id,
1614 				 bin_test_mock_algs[param->alg_idx].ver,
1615 				 param->mem_type,
1616 				 payload_offset,
1617 				 &packed_payloads[payload_order[i]],
1618 				 sizeof(packed_payloads[0]));
1619 	}
1620 
1621 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1622 	KUNIT_ASSERT_EQ(test,
1623 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1624 					fw, "mock_bin", "misc"),
1625 			0);
1626 
1627 	/* Content in registers should match the order of data in packed_payloads */
1628 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1629 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1630 		   (patch_pos_in_packed_regs * 4);
1631 	memset(readback, 0, sizeof(readback));
1632 	KUNIT_EXPECT_EQ(test,
1633 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
1634 			0);
1635 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads, sizeof(packed_payloads));
1636 
1637 	/* Drop expected writes and the cache should then be clean */
1638 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1639 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads));
1640 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1641 }
1642 
1643 /*
1644  * bin file with a multiple payloads that each patch one packed block.
1645  * The payloads are not in address order. The patched memory is not contiguous.
1646  */
1647 static void bin_patch_multi_onepacked_sparse_unordered(struct kunit *test)
1648 {
1649 	struct cs_dsp_test *priv = test->priv;
1650 	const struct bin_test_param *param = test->param_value;
1651 	static const u8 word_offsets[] = { 60, 24, 76, 4, 40, 52, 48, 36, 12 };
1652 	u32 packed_payloads[9][3], readback[3];
1653 	unsigned int alg_base_words, alg_base_in_packed_regs;
1654 	unsigned int patch_pos_words, patch_pos_in_packed_regs, payload_offset;
1655 	unsigned int reg_addr;
1656 	struct firmware *fw;
1657 	int i;
1658 
1659 	static_assert(ARRAY_SIZE(word_offsets) == ARRAY_SIZE(packed_payloads));
1660 	static_assert(sizeof(readback) == sizeof(packed_payloads[0]));
1661 
1662 	get_random_bytes(packed_payloads, sizeof(packed_payloads));
1663 
1664 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1665 							bin_test_mock_algs[param->alg_idx].id,
1666 							param->mem_type);
1667 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1668 
1669 	/* Add one payload per packed block */
1670 	for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
1671 		/* Round patch start word up to a packed boundary */
1672 		patch_pos_words = round_up(alg_base_words + word_offsets[i], 4);
1673 		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1674 		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1675 		param->add_patch(priv->local->bin_builder,
1676 				 bin_test_mock_algs[param->alg_idx].id,
1677 				 bin_test_mock_algs[param->alg_idx].ver,
1678 				 param->mem_type,
1679 				 payload_offset,
1680 				 &packed_payloads[i],
1681 				 sizeof(packed_payloads[0]));
1682 	}
1683 
1684 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1685 	KUNIT_ASSERT_EQ(test,
1686 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1687 					fw, "mock_bin", "misc"),
1688 			0);
1689 
1690 	/* Content of packed registers should match packed_payloads */
1691 	for (i = 0; i < ARRAY_SIZE(word_offsets); ++i) {
1692 		patch_pos_words = round_up(alg_base_words + word_offsets[i], 4);
1693 		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1694 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1695 			   (patch_pos_in_packed_regs * 4);
1696 		memset(readback, 0, sizeof(readback));
1697 		KUNIT_EXPECT_EQ(test,
1698 				regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
1699 						sizeof(readback)),
1700 				0);
1701 		KUNIT_EXPECT_MEMEQ(test, readback, packed_payloads[i], sizeof(packed_payloads[i]));
1702 
1703 		/* Drop expected writes from the cache */
1704 		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payloads[i]));
1705 	}
1706 
1707 	/* Drop expected writes and the cache should then be clean */
1708 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1709 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1710 }
1711 
1712 /*
1713  * bin file that patches a single packed block in each of the memory regions
1714  * of one algorithm.
1715  */
1716 static void bin_patch_1_packed_multiple_mems(struct kunit *test)
1717 {
1718 	struct cs_dsp_test *priv = test->priv;
1719 	const struct bin_test_param *param = test->param_value;
1720 	u32 packed_xm_payload[3], packed_ym_payload[3], readback[3];
1721 	unsigned int alg_xm_base_words, alg_ym_base_words;
1722 	unsigned int xm_patch_pos_words, ym_patch_pos_words;
1723 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1724 	unsigned int reg_addr;
1725 	struct firmware *fw;
1726 
1727 	static_assert(sizeof(readback) == sizeof(packed_xm_payload));
1728 	static_assert(sizeof(readback) == sizeof(packed_ym_payload));
1729 
1730 	get_random_bytes(packed_xm_payload, sizeof(packed_xm_payload));
1731 	get_random_bytes(packed_ym_payload, sizeof(packed_ym_payload));
1732 
1733 	alg_xm_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1734 							bin_test_mock_algs[param->alg_idx].id,
1735 							WMFW_HALO_XM_PACKED);
1736 	alg_ym_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1737 							bin_test_mock_algs[param->alg_idx].id,
1738 							WMFW_HALO_YM_PACKED);
1739 
1740 	/* Round patch start word up to a packed boundary */
1741 	xm_patch_pos_words = round_up(alg_xm_base_words + param->offset_words, 4);
1742 	ym_patch_pos_words = round_up(alg_ym_base_words + param->offset_words, 4);
1743 
1744 	/* Add XM and YM patches */
1745 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_xm_base_words);
1746 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(xm_patch_pos_words);
1747 	param->add_patch(priv->local->bin_builder,
1748 			 bin_test_mock_algs[param->alg_idx].id,
1749 			 bin_test_mock_algs[param->alg_idx].ver,
1750 			 WMFW_HALO_XM_PACKED,
1751 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1752 			 packed_xm_payload, sizeof(packed_xm_payload));
1753 
1754 	alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_ym_base_words);
1755 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(ym_patch_pos_words);
1756 	param->add_patch(priv->local->bin_builder,
1757 			 bin_test_mock_algs[param->alg_idx].id,
1758 			 bin_test_mock_algs[param->alg_idx].ver,
1759 			 WMFW_HALO_YM_PACKED,
1760 			 (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4,
1761 			 packed_ym_payload, sizeof(packed_ym_payload));
1762 
1763 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1764 	KUNIT_ASSERT_EQ(test,
1765 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1766 					fw, "mock_bin", "misc"),
1767 			0);
1768 
1769 	/* Content of packed XM registers should match packed_xm_payload */
1770 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(xm_patch_pos_words);
1771 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_XM_PACKED) +
1772 		   (patch_pos_in_packed_regs * 4);
1773 	memset(readback, 0, sizeof(readback));
1774 	KUNIT_EXPECT_EQ(test,
1775 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
1776 			0);
1777 	KUNIT_EXPECT_MEMEQ(test, readback, packed_xm_payload, sizeof(packed_xm_payload));
1778 
1779 	/* Drop expected writes from the cache */
1780 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_xm_payload));
1781 
1782 	/* Content of packed YM registers should match packed_ym_payload */
1783 	patch_pos_in_packed_regs = _num_words_to_num_packed_regs(ym_patch_pos_words);
1784 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_HALO_YM_PACKED) +
1785 		   (patch_pos_in_packed_regs * 4);
1786 	memset(readback, 0, sizeof(readback));
1787 	KUNIT_EXPECT_EQ(test,
1788 			regmap_raw_read(priv->dsp->regmap, reg_addr, readback, sizeof(readback)),
1789 			0);
1790 	KUNIT_EXPECT_MEMEQ(test, readback, packed_ym_payload, sizeof(packed_ym_payload));
1791 
1792 	/* Drop expected writes from the cache */
1793 	cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_ym_payload));
1794 
1795 	/* Drop expected writes and the cache should then be clean */
1796 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1797 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1798 }
1799 
1800 /*
1801  * bin file that patches a single packed block in multiple algorithms.
1802  */
1803 static void bin_patch_1_packed_multiple_algs(struct kunit *test)
1804 {
1805 	struct cs_dsp_test *priv = test->priv;
1806 	const struct bin_test_param *param = test->param_value;
1807 	u32 packed_payload[ARRAY_SIZE(bin_test_mock_algs)][3];
1808 	u32 readback[ARRAY_SIZE(bin_test_mock_algs)][3];
1809 	unsigned int alg_base_words, patch_pos_words;
1810 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1811 	unsigned int reg_addr, payload_offset;
1812 	struct firmware *fw;
1813 	int i;
1814 
1815 	static_assert(sizeof(readback) == sizeof(packed_payload));
1816 
1817 	get_random_bytes(packed_payload, sizeof(packed_payload));
1818 
1819 	/* For each algorithm patch one DSP word to a value from packed_payload */
1820 	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
1821 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1822 								bin_test_mock_algs[i].id,
1823 								param->mem_type);
1824 		alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1825 
1826 		/* Round patch start word up to a packed boundary */
1827 		patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1828 		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1829 
1830 		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1831 		param->add_patch(priv->local->bin_builder,
1832 				 bin_test_mock_algs[i].id,
1833 				 bin_test_mock_algs[i].ver,
1834 				 param->mem_type,
1835 				 payload_offset,
1836 				 packed_payload[i], sizeof(packed_payload[i]));
1837 	}
1838 
1839 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1840 	KUNIT_ASSERT_EQ(test,
1841 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1842 					fw, "mock_bin", "misc"),
1843 			0);
1844 
1845 	memset(readback, 0, sizeof(readback));
1846 
1847 	/*
1848 	 * Readback the registers that should have been written. Place
1849 	 * the values into the expected location in readback[] so that
1850 	 * the content of readback[] should match packed_payload[]
1851 	 */
1852 	for (i = 0; i < ARRAY_SIZE(bin_test_mock_algs); ++i) {
1853 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1854 								bin_test_mock_algs[i].id,
1855 								param->mem_type);
1856 		alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1857 
1858 		patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1859 		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1860 
1861 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1862 			   (patch_pos_in_packed_regs * 4);
1863 		KUNIT_EXPECT_EQ(test,
1864 				regmap_raw_read(priv->dsp->regmap, reg_addr,
1865 						readback[i], sizeof(readback[i])),
1866 				0);
1867 
1868 		/* Drop expected writes from the cache */
1869 		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload[i]));
1870 	}
1871 
1872 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));
1873 
1874 	/* Drop expected writes and the cache should then be clean */
1875 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1876 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1877 }
1878 
1879 /*
1880  * bin file that patches a single packed block in multiple algorithms.
1881  * The algorithms are not patched in the same order they appear in the XM header.
1882  */
1883 static void bin_patch_1_packed_multiple_algs_unordered(struct kunit *test)
1884 {
1885 	struct cs_dsp_test *priv = test->priv;
1886 	const struct bin_test_param *param = test->param_value;
1887 	static const u8 alg_order[] = { 3, 0, 2, 1 };
1888 	u32 packed_payload[ARRAY_SIZE(bin_test_mock_algs)][3];
1889 	u32 readback[ARRAY_SIZE(bin_test_mock_algs)][3];
1890 	unsigned int alg_base_words, patch_pos_words;
1891 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1892 	unsigned int reg_addr, payload_offset;
1893 	struct firmware *fw;
1894 	int i, alg_idx;
1895 
1896 	static_assert(ARRAY_SIZE(alg_order) == ARRAY_SIZE(bin_test_mock_algs));
1897 	static_assert(sizeof(readback) == sizeof(packed_payload));
1898 
1899 	get_random_bytes(packed_payload, sizeof(packed_payload));
1900 
1901 	/*
1902 	 * For each algorithm index in alg_order[] patch one DSP word in
1903 	 * that algorithm to a value from packed_payload.
1904 	 */
1905 	for (i = 0; i < ARRAY_SIZE(alg_order); ++i) {
1906 		alg_idx = alg_order[i];
1907 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1908 								bin_test_mock_algs[alg_idx].id,
1909 								param->mem_type);
1910 		alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
1911 
1912 		/* Round patch start word up to a packed boundary */
1913 		patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1914 		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1915 
1916 		payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
1917 		param->add_patch(priv->local->bin_builder,
1918 				 bin_test_mock_algs[alg_idx].id,
1919 				 bin_test_mock_algs[alg_idx].ver,
1920 				 param->mem_type,
1921 				 payload_offset,
1922 				 packed_payload[i], sizeof(packed_payload[i]));
1923 	}
1924 
1925 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
1926 	KUNIT_ASSERT_EQ(test,
1927 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
1928 					fw, "mock_bin", "misc"),
1929 			0);
1930 
1931 	memset(readback, 0, sizeof(readback));
1932 
1933 	/*
1934 	 * Readback the registers that should have been written. Place
1935 	 * the values into the expected location in readback[] so that
1936 	 * the content of readback[] should match packed_payload[]
1937 	 */
1938 	for (i = 0; i < ARRAY_SIZE(alg_order); ++i) {
1939 		alg_idx = alg_order[i];
1940 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
1941 								bin_test_mock_algs[alg_idx].id,
1942 								param->mem_type);
1943 
1944 		patch_pos_words = round_up(alg_base_words + param->offset_words, 4);
1945 		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
1946 
1947 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
1948 			   (patch_pos_in_packed_regs * 4);
1949 		KUNIT_EXPECT_EQ(test,
1950 				regmap_raw_read(priv->dsp->regmap, reg_addr,
1951 						readback[i], sizeof(readback[i])),
1952 				0);
1953 
1954 		/* Drop expected writes from the cache */
1955 		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(packed_payload[i]));
1956 	}
1957 
1958 	KUNIT_EXPECT_MEMEQ(test, readback, packed_payload, sizeof(packed_payload));
1959 
1960 	/* Drop expected writes and the cache should then be clean */
1961 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
1962 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
1963 }
1964 
1965 /*
1966  * bin file that contains a mix of packed and unpacked words.
1967  * payloads are in random offset order. Offsets that are on a packed boundary
1968  * are written as a packed block. Offsets that are not on a packed boundary
1969  * are written as a single unpacked word.
1970  */
1971 static void bin_patch_mixed_packed_unpacked_random(struct kunit *test)
1972 {
1973 	struct cs_dsp_test *priv = test->priv;
1974 	const struct bin_test_param *param = test->param_value;
1975 	static const u8 offset_words[] = {
1976 		58, 68, 50, 10, 44, 17, 74, 36,  8,  7, 49, 11, 78, 57, 65, 2,
1977 		48, 38, 22, 70, 77, 21, 61, 56, 75, 34, 27,  3, 31, 20,	43, 63,
1978 		 5, 30, 32, 25, 33, 79, 29,  0,	37, 60, 69, 52, 13, 12, 24, 26,
1979 		 4, 51, 76, 72, 16,  6, 39, 62, 15, 41, 28, 73, 53, 40, 45, 54,
1980 		14, 55, 46, 66, 64, 59, 23,  9, 67, 47, 19, 71, 35, 18, 42,  1,
1981 	};
1982 	struct {
1983 		u32 packed[80][3];
1984 		u32 unpacked[80];
1985 	} *payload;
1986 	u32 readback[3];
1987 	unsigned int alg_base_words, patch_pos_words;
1988 	unsigned int alg_base_in_packed_regs, patch_pos_in_packed_regs;
1989 	unsigned int reg_addr, payload_offset;
1990 	int unpacked_mem_type = cs_dsp_mock_packed_to_unpacked_mem_type(param->mem_type);
1991 	struct firmware *fw;
1992 	int i;
1993 
1994 	payload = kunit_kmalloc(test, sizeof(*payload), GFP_KERNEL);
1995 	KUNIT_ASSERT_NOT_NULL(test, payload);
1996 
1997 	get_random_bytes(payload->packed, sizeof(payload->packed));
1998 	get_random_bytes(payload->unpacked, sizeof(payload->unpacked));
1999 
2000 	/* Create a patch entry for every offset in offset_words[] */
2001 	for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {
2002 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
2003 								bin_test_mock_algs[0].id,
2004 								param->mem_type);
2005 		/*
2006 		 * If the offset is on a packed boundary use a packed payload else
2007 		 * use an unpacked word
2008 		 */
2009 		patch_pos_words = alg_base_words + offset_words[i];
2010 		if ((patch_pos_words % 4) == 0) {
2011 			alg_base_in_packed_regs = _num_words_to_num_packed_regs(alg_base_words);
2012 			patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
2013 			payload_offset = (patch_pos_in_packed_regs - alg_base_in_packed_regs) * 4;
2014 			param->add_patch(priv->local->bin_builder,
2015 					 bin_test_mock_algs[0].id,
2016 					 bin_test_mock_algs[0].ver,
2017 					 param->mem_type,
2018 					 payload_offset,
2019 					 payload->packed[i],
2020 					 sizeof(payload->packed[i]));
2021 		} else {
2022 			payload_offset = offset_words[i] * 4;
2023 			param->add_patch(priv->local->bin_builder,
2024 					 bin_test_mock_algs[0].id,
2025 					 bin_test_mock_algs[0].ver,
2026 					 unpacked_mem_type,
2027 					 payload_offset,
2028 					 &payload->unpacked[i],
2029 					 sizeof(payload->unpacked[i]));
2030 		}
2031 	}
2032 
2033 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
2034 	KUNIT_ASSERT_EQ(test,
2035 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
2036 					fw, "mock_bin", "misc"),
2037 			0);
2038 
2039 	/*
2040 	 * Readback the packed registers that should have been written.
2041 	 * Place the values into the expected location in readback[] so
2042 	 * that the content of readback[] should match payload->packed[]
2043 	 */
2044 	for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {
2045 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
2046 								bin_test_mock_algs[0].id,
2047 								param->mem_type);
2048 		patch_pos_words = alg_base_words + offset_words[i];
2049 
2050 		/* Skip if the offset is not on a packed boundary */
2051 		if ((patch_pos_words % 4) != 0)
2052 			continue;
2053 
2054 		patch_pos_in_packed_regs = _num_words_to_num_packed_regs(patch_pos_words);
2055 
2056 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type) +
2057 			   (patch_pos_in_packed_regs * 4);
2058 
2059 		memset(readback, 0, sizeof(readback));
2060 		KUNIT_EXPECT_EQ(test,
2061 				regmap_raw_read(priv->dsp->regmap, reg_addr, readback,
2062 						sizeof(readback)),
2063 				0);
2064 		KUNIT_EXPECT_MEMEQ(test, readback, payload->packed[i], sizeof(payload->packed[i]));
2065 
2066 		/* Drop expected writes from the cache */
2067 		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(payload->packed[i]));
2068 	}
2069 
2070 	/*
2071 	 * Readback the unpacked registers that should have been written.
2072 	 * Place the values into the expected location in readback[] so
2073 	 * that the content of readback[] should match payload->unpacked[]
2074 	 */
2075 	for (i = 0; i < ARRAY_SIZE(offset_words); ++i) {
2076 		alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
2077 								bin_test_mock_algs[0].id,
2078 								unpacked_mem_type);
2079 
2080 		patch_pos_words = alg_base_words + offset_words[i];
2081 
2082 		/* Skip if the offset is on a packed boundary */
2083 		if ((patch_pos_words % 4) == 0)
2084 			continue;
2085 
2086 		reg_addr = cs_dsp_mock_base_addr_for_mem(priv, unpacked_mem_type) +
2087 			   ((patch_pos_words) * 4);
2088 
2089 		readback[0] = 0;
2090 		KUNIT_EXPECT_EQ(test,
2091 				regmap_raw_read(priv->dsp->regmap, reg_addr,
2092 						&readback[0], sizeof(readback[0])),
2093 				0);
2094 		KUNIT_EXPECT_EQ(test, readback[0], payload->unpacked[i]);
2095 
2096 		/* Drop expected writes from the cache */
2097 		cs_dsp_mock_regmap_drop_bytes(priv, reg_addr, sizeof(payload->unpacked[i]));
2098 	}
2099 
2100 	/* Drop expected writes and the cache should then be clean */
2101 	cs_dsp_mock_xm_header_drop_from_regmap_cache(priv);
2102 	KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true));
2103 }
2104 
2105 /* Bin file with name and multiple info blocks */
2106 static void bin_patch_name_and_info(struct kunit *test)
2107 {
2108 	struct cs_dsp_test *priv = test->priv;
2109 	unsigned int reg_inc_per_word = cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv);
2110 	u32 reg_val, payload_data;
2111 	char *infobuf;
2112 	unsigned int alg_base_words, reg_addr;
2113 	struct firmware *fw;
2114 
2115 	get_random_bytes(&payload_data, sizeof(payload_data));
2116 
2117 	alg_base_words = cs_dsp_mock_xm_header_get_alg_base_in_words(priv,
2118 							bin_test_mock_algs[0].id,
2119 							WMFW_ADSP2_YM);
2120 
2121 	/* Add a name block and info block */
2122 	cs_dsp_mock_bin_add_name(priv->local->bin_builder, "The name");
2123 	cs_dsp_mock_bin_add_info(priv->local->bin_builder, "Some info");
2124 
2125 	/* Add a big block of info */
2126 	infobuf = kunit_kzalloc(test, 512, GFP_KERNEL);
2127 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, infobuf);
2128 
2129 	for (; strlcat(infobuf, "Waffle{Blah}\n", 512) < 512; )
2130 		;
2131 
2132 	cs_dsp_mock_bin_add_info(priv->local->bin_builder, infobuf);
2133 
2134 	/* Add a patch */
2135 	cs_dsp_mock_bin_add_patch(priv->local->bin_builder,
2136 				  bin_test_mock_algs[0].id,
2137 				  bin_test_mock_algs[0].ver,
2138 				  WMFW_ADSP2_YM,
2139 				  0,
2140 				  &payload_data, sizeof(payload_data));
2141 
2142 	fw = cs_dsp_mock_bin_get_firmware(priv->local->bin_builder);
2143 	KUNIT_ASSERT_EQ(test,
2144 			cs_dsp_power_up(priv->dsp, priv->local->wmfw, "mock_wmfw",
2145 					fw, "mock_bin", "misc"),
2146 			0);
2147 
2148 	/* Content of registers should match payload_data */
2149 	reg_addr = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM);
2150 	reg_addr += alg_base_words * reg_inc_per_word;
2151 	reg_val = 0;
2152 	KUNIT_EXPECT_EQ(test,
2153 			regmap_raw_read(priv->dsp->regmap, reg_addr,
2154 					&reg_val, sizeof(reg_val)),
2155 			0);
2156 	KUNIT_EXPECT_EQ(test, reg_val, payload_data);
2157 }
2158 
2159 static bool cs_dsp_bin_test_can_emit_message_hook(void)
2160 {
2161 #if defined(DEBUG)
2162 	return true;
2163 #else
2164 	return false;
2165 #endif
2166 }
2167 
2168 static int cs_dsp_bin_test_common_init(struct kunit *test, struct cs_dsp *dsp,
2169 					int wmdr_ver)
2170 {
2171 	struct cs_dsp_test *priv;
2172 	struct cs_dsp_mock_xm_header *xm_hdr;
2173 	struct device *test_dev;
2174 	int ret;
2175 
2176 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
2177 	if (!priv)
2178 		return -ENOMEM;
2179 
2180 	priv->local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL);
2181 	if (!priv->local)
2182 		return -ENOMEM;
2183 
2184 	priv->test = test;
2185 	priv->dsp = dsp;
2186 	test->priv = priv;
2187 
2188 	/* Create dummy struct device */
2189 	test_dev = kunit_device_register(test, "cs_dsp_test_drv");
2190 	if (IS_ERR(test_dev))
2191 		return PTR_ERR(test_dev);
2192 
2193 	dsp->dev = get_device(test_dev);
2194 	if (!dsp->dev)
2195 		return -ENODEV;
2196 
2197 	ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev);
2198 	if (ret)
2199 		return ret;
2200 
2201 	dev_set_drvdata(dsp->dev, priv);
2202 
2203 	/* Allocate regmap */
2204 	ret = cs_dsp_mock_regmap_init(priv);
2205 	if (ret)
2206 		return ret;
2207 
2208 	/* Create an XM header */
2209 	xm_hdr = cs_dsp_create_mock_xm_header(priv,
2210 					      bin_test_mock_algs,
2211 					      ARRAY_SIZE(bin_test_mock_algs));
2212 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xm_hdr);
2213 	ret = cs_dsp_mock_xm_header_write_to_regmap(xm_hdr);
2214 	KUNIT_ASSERT_EQ(test, ret, 0);
2215 
2216 	priv->local->bin_builder =
2217 		cs_dsp_mock_bin_init(priv, wmdr_ver,
2218 				     cs_dsp_mock_xm_header_get_fw_version(xm_hdr));
2219 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->local->bin_builder);
2220 
2221 	/* We must provide a dummy wmfw to load */
2222 	priv->local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, -1);
2223 	priv->local->wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder);
2224 
2225 	dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL);
2226 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops);
2227 
2228 	switch (dsp->type) {
2229 	case WMFW_ADSP2:
2230 		ret = cs_dsp_adsp2_init(dsp);
2231 		break;
2232 	case WMFW_HALO:
2233 		ret = cs_dsp_halo_init(dsp);
2234 		break;
2235 	default:
2236 		KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type);
2237 		return -EINVAL;
2238 	}
2239 
2240 	if (ret)
2241 		return ret;
2242 
2243 	/* Automatically call cs_dsp_remove() when test case ends */
2244 	ret = kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp);
2245 	if (ret)
2246 		return ret;
2247 
2248 	/*
2249 	 * The large number of test cases will cause an unusually large amount
2250 	 * of dev_info() messages from cs_dsp, so suppress these.
2251 	 */
2252 	kunit_activate_static_stub(test, cs_dsp_can_emit_message,
2253 				   cs_dsp_bin_test_can_emit_message_hook);
2254 
2255 	return 0;
2256 }
2257 
2258 static int cs_dsp_bin_test_halo_init_common(struct kunit *test, int wmdr_ver)
2259 {
2260 	struct cs_dsp *dsp;
2261 
2262 	/* Fill in cs_dsp and initialize */
2263 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2264 	if (!dsp)
2265 		return -ENOMEM;
2266 
2267 	dsp->num = 1;
2268 	dsp->type = WMFW_HALO;
2269 	dsp->mem = cs_dsp_mock_halo_dsp1_regions;
2270 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes);
2271 	dsp->base = cs_dsp_mock_halo_core_base;
2272 	dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base;
2273 
2274 	return cs_dsp_bin_test_common_init(test, dsp, wmdr_ver);
2275 }
2276 
2277 static int cs_dsp_bin_test_halo_init(struct kunit *test)
2278 {
2279 	return cs_dsp_bin_test_halo_init_common(test, 1);
2280 }
2281 
2282 static int cs_dsp_bin_test_halo_wmdr3_init(struct kunit *test)
2283 {
2284 	return cs_dsp_bin_test_halo_init_common(test, 3);
2285 }
2286 
2287 static int cs_dsp_bin_test_adsp2_32bit_init(struct kunit *test)
2288 {
2289 	struct cs_dsp *dsp;
2290 
2291 	/* Fill in cs_dsp and initialize */
2292 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2293 	if (!dsp)
2294 		return -ENOMEM;
2295 
2296 	dsp->num = 1;
2297 	dsp->type = WMFW_ADSP2;
2298 	dsp->rev = 1;
2299 	dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions;
2300 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes);
2301 	dsp->base = cs_dsp_mock_adsp2_32bit_sysbase;
2302 
2303 	return cs_dsp_bin_test_common_init(test, dsp, 1);
2304 }
2305 
2306 static int cs_dsp_bin_test_adsp2_16bit_init(struct kunit *test)
2307 {
2308 	struct cs_dsp *dsp;
2309 
2310 	/* Fill in cs_dsp and initialize */
2311 	dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL);
2312 	if (!dsp)
2313 		return -ENOMEM;
2314 
2315 	dsp->num = 1;
2316 	dsp->type = WMFW_ADSP2;
2317 	dsp->rev = 0;
2318 	dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions;
2319 	dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes);
2320 	dsp->base = cs_dsp_mock_adsp2_16bit_sysbase;
2321 
2322 	return cs_dsp_bin_test_common_init(test, dsp, 1);
2323 }
2324 
2325 #define WMDR_PATCH_SHORT .add_patch = cs_dsp_mock_bin_add_patch
2326 #define WMDR_PATCH_LONG .add_patch = cs_dsp_mock_bin_add_patch_off32
2327 
2328 /* Parameterize on choice of XM or YM with a range of word offsets */
2329 static const struct bin_test_param x_or_y_and_offset_param_cases[] = {
2330 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0,  WMDR_PATCH_SHORT },
2331 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 1,  WMDR_PATCH_SHORT },
2332 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 2,  WMDR_PATCH_SHORT },
2333 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 3,  WMDR_PATCH_SHORT },
2334 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 4,  WMDR_PATCH_SHORT },
2335 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 23, WMDR_PATCH_SHORT },
2336 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 22, WMDR_PATCH_SHORT },
2337 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 21, WMDR_PATCH_SHORT },
2338 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 20, WMDR_PATCH_SHORT },
2339 
2340 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0,  WMDR_PATCH_SHORT },
2341 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 1,  WMDR_PATCH_SHORT },
2342 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 2,  WMDR_PATCH_SHORT },
2343 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 3,  WMDR_PATCH_SHORT },
2344 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 4,  WMDR_PATCH_SHORT },
2345 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 23, WMDR_PATCH_SHORT },
2346 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 22, WMDR_PATCH_SHORT },
2347 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 21, WMDR_PATCH_SHORT },
2348 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 20, WMDR_PATCH_SHORT },
2349 };
2350 
2351 static const struct bin_test_param x_or_y_and_long_offset_param_cases[] = {
2352 	/* Offset < 0xffff in long-offset block type */
2353 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0,  WMDR_PATCH_LONG },
2354 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 1,  WMDR_PATCH_LONG },
2355 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 2,  WMDR_PATCH_LONG },
2356 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 3,  WMDR_PATCH_LONG },
2357 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 4,  WMDR_PATCH_LONG },
2358 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 23, WMDR_PATCH_LONG },
2359 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 22, WMDR_PATCH_LONG },
2360 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 21, WMDR_PATCH_LONG },
2361 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 20, WMDR_PATCH_LONG },
2362 
2363 	/* Offset < 0xffff in long-offset block type */
2364 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0,  WMDR_PATCH_LONG },
2365 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 1,  WMDR_PATCH_LONG },
2366 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 2,  WMDR_PATCH_LONG },
2367 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 3,  WMDR_PATCH_LONG },
2368 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 4,  WMDR_PATCH_LONG },
2369 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 23, WMDR_PATCH_LONG },
2370 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 22, WMDR_PATCH_LONG },
2371 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 21, WMDR_PATCH_LONG },
2372 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 20, WMDR_PATCH_LONG },
2373 
2374 	/* Offset > 0xffff in long-offset block type */
2375 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10000, WMDR_PATCH_LONG },
2376 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10001, WMDR_PATCH_LONG },
2377 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10002, WMDR_PATCH_LONG },
2378 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10003, WMDR_PATCH_LONG },
2379 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x10004, WMDR_PATCH_LONG },
2380 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x2f003, WMDR_PATCH_LONG },
2381 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x2f002, WMDR_PATCH_LONG },
2382 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x2f001, WMDR_PATCH_LONG },
2383 	{ .mem_type = WMFW_ADSP2_XM, .offset_words = 0x2f000, WMDR_PATCH_LONG },
2384 
2385 	/* Offset > 0xffff in long-offset block type */
2386 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10000, WMDR_PATCH_LONG },
2387 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10001, WMDR_PATCH_LONG },
2388 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10002, WMDR_PATCH_LONG },
2389 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10003, WMDR_PATCH_LONG },
2390 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x10004, WMDR_PATCH_LONG },
2391 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x2f003, WMDR_PATCH_LONG },
2392 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x2f002, WMDR_PATCH_LONG },
2393 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x2f001, WMDR_PATCH_LONG },
2394 	{ .mem_type = WMFW_ADSP2_YM, .offset_words = 0x2f000, WMDR_PATCH_LONG },
2395 };
2396 
2397 /* Parameterize on ZM with a range of word offsets */
2398 static const struct bin_test_param z_and_offset_param_cases[] = {
2399 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 0,  WMDR_PATCH_SHORT },
2400 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 1,  WMDR_PATCH_SHORT },
2401 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 2,  WMDR_PATCH_SHORT },
2402 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 3,  WMDR_PATCH_SHORT },
2403 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 4,  WMDR_PATCH_SHORT },
2404 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 23, WMDR_PATCH_SHORT },
2405 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 22, WMDR_PATCH_SHORT },
2406 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 21, WMDR_PATCH_SHORT },
2407 	{ .mem_type = WMFW_ADSP2_ZM, .offset_words = 20, WMDR_PATCH_SHORT },
2408 };
2409 
2410 /* Parameterize on choice of packed XM or YM with a range of word offsets */
2411 static const struct bin_test_param packed_x_or_y_and_offset_param_cases[] = {
2412 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0,  WMDR_PATCH_SHORT },
2413 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 4,  WMDR_PATCH_SHORT },
2414 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 8,  WMDR_PATCH_SHORT },
2415 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 12, WMDR_PATCH_SHORT },
2416 
2417 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0,  WMDR_PATCH_SHORT },
2418 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 4,  WMDR_PATCH_SHORT },
2419 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 8,  WMDR_PATCH_SHORT },
2420 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 12, WMDR_PATCH_SHORT },
2421 };
2422 
2423 static const struct bin_test_param packed_x_or_y_and_long_offset_param_cases[] = {
2424 	/* Offset < 0xffff in long-offset block type */
2425 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0,  WMDR_PATCH_LONG },
2426 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 4,  WMDR_PATCH_LONG },
2427 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 8,  WMDR_PATCH_LONG },
2428 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 12, WMDR_PATCH_LONG },
2429 
2430 	/* Offset < 0xffff in long-offset block type */
2431 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0,  WMDR_PATCH_LONG },
2432 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 4,  WMDR_PATCH_LONG },
2433 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 8,  WMDR_PATCH_LONG },
2434 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 12, WMDR_PATCH_LONG },
2435 
2436 	/* Offset > 0xffff in long-offset block type */
2437 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x10000, WMDR_PATCH_LONG },
2438 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x10004, WMDR_PATCH_LONG },
2439 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x10008, WMDR_PATCH_LONG },
2440 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x2f000, WMDR_PATCH_LONG },
2441 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0x2f004, WMDR_PATCH_LONG },
2442 
2443 	/* Offset > 0xffff in long-offset block type */
2444 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x10000, WMDR_PATCH_LONG },
2445 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x10004, WMDR_PATCH_LONG },
2446 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x10008, WMDR_PATCH_LONG },
2447 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x2f000, WMDR_PATCH_LONG },
2448 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0x2f004, WMDR_PATCH_LONG },
2449 };
2450 
2451 static void x_or_y_or_z_and_offset_param_desc(const struct bin_test_param *param,
2452 					   char *desc)
2453 {
2454 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s@%u %s",
2455 		 cs_dsp_mem_region_name(param->mem_type),
2456 		 param->offset_words,
2457 		 (param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");
2458 }
2459 
2460 KUNIT_ARRAY_PARAM(x_or_y_and_offset,
2461 		  x_or_y_and_offset_param_cases,
2462 		  x_or_y_or_z_and_offset_param_desc);
2463 
2464 KUNIT_ARRAY_PARAM(x_or_y_and_long_offset,
2465 		  x_or_y_and_long_offset_param_cases,
2466 		  x_or_y_or_z_and_offset_param_desc);
2467 
2468 KUNIT_ARRAY_PARAM(z_and_offset,
2469 		  z_and_offset_param_cases,
2470 		  x_or_y_or_z_and_offset_param_desc);
2471 
2472 KUNIT_ARRAY_PARAM(packed_x_or_y_and_offset,
2473 		  packed_x_or_y_and_offset_param_cases,
2474 		  x_or_y_or_z_and_offset_param_desc);
2475 
2476 KUNIT_ARRAY_PARAM(packed_x_or_y_and_long_offset,
2477 		  packed_x_or_y_and_long_offset_param_cases,
2478 		  x_or_y_or_z_and_offset_param_desc);
2479 
2480 /* Parameterize on choice of packed XM or YM */
2481 static const struct bin_test_param packed_x_or_y_param_cases[] = {
2482 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0, WMDR_PATCH_SHORT },
2483 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0, WMDR_PATCH_SHORT },
2484 };
2485 
2486 static const struct bin_test_param packed_x_or_y_long_param_cases[] = {
2487 	{ .mem_type = WMFW_HALO_XM_PACKED, .offset_words = 0, WMDR_PATCH_LONG },
2488 	{ .mem_type = WMFW_HALO_YM_PACKED, .offset_words = 0, WMDR_PATCH_LONG },
2489 };
2490 
2491 static void x_or_y_or_z_param_desc(const struct bin_test_param *param,
2492 					   char *desc)
2493 {
2494 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s %s",
2495 		 cs_dsp_mem_region_name(param->mem_type),
2496 		 (param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");
2497 }
2498 
2499 KUNIT_ARRAY_PARAM(packed_x_or_y, packed_x_or_y_param_cases, x_or_y_or_z_param_desc);
2500 KUNIT_ARRAY_PARAM(packed_x_or_y_long, packed_x_or_y_long_param_cases, x_or_y_or_z_param_desc);
2501 
2502 static const struct bin_test_param offset_param_cases[] = {
2503 	{ .offset_words = 0,  WMDR_PATCH_SHORT },
2504 	{ .offset_words = 1,  WMDR_PATCH_SHORT },
2505 	{ .offset_words = 2,  WMDR_PATCH_SHORT },
2506 	{ .offset_words = 3,  WMDR_PATCH_SHORT },
2507 	{ .offset_words = 4,  WMDR_PATCH_SHORT },
2508 	{ .offset_words = 23, WMDR_PATCH_SHORT },
2509 	{ .offset_words = 22, WMDR_PATCH_SHORT },
2510 	{ .offset_words = 21, WMDR_PATCH_SHORT },
2511 	{ .offset_words = 20, WMDR_PATCH_SHORT },
2512 };
2513 
2514 static const struct bin_test_param long_offset_param_cases[] = {
2515 	/* Offset < 0xffff in long-offset block type */
2516 	{ .offset_words = 0,  WMDR_PATCH_LONG },
2517 	{ .offset_words = 1,  WMDR_PATCH_LONG },
2518 	{ .offset_words = 2,  WMDR_PATCH_LONG },
2519 	{ .offset_words = 3,  WMDR_PATCH_LONG },
2520 	{ .offset_words = 4,  WMDR_PATCH_LONG },
2521 	{ .offset_words = 23, WMDR_PATCH_LONG },
2522 	{ .offset_words = 22, WMDR_PATCH_LONG },
2523 	{ .offset_words = 21, WMDR_PATCH_LONG },
2524 	{ .offset_words = 20, WMDR_PATCH_LONG },
2525 
2526 	/* Offset > 0xffff in long-offset block type */
2527 	{ .offset_words = 0x10000, WMDR_PATCH_LONG },
2528 	{ .offset_words = 0x10001, WMDR_PATCH_LONG },
2529 	{ .offset_words = 0x10002, WMDR_PATCH_LONG },
2530 	{ .offset_words = 0x10003, WMDR_PATCH_LONG },
2531 	{ .offset_words = 0x10004, WMDR_PATCH_LONG },
2532 	{ .offset_words = 0x2f000, WMDR_PATCH_LONG },
2533 	{ .offset_words = 0x2f001, WMDR_PATCH_LONG },
2534 	{ .offset_words = 0x2f002, WMDR_PATCH_LONG },
2535 	{ .offset_words = 0x2f003, WMDR_PATCH_LONG },
2536 };
2537 
2538 static void offset_param_desc(const struct bin_test_param *param, char *desc)
2539 {
2540 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "@%u %s",
2541 		 param->offset_words,
2542 		 (param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");
2543 }
2544 
2545 KUNIT_ARRAY_PARAM(offset, offset_param_cases, offset_param_desc);
2546 KUNIT_ARRAY_PARAM(long_offset, long_offset_param_cases, offset_param_desc);
2547 
2548 static const struct bin_test_param alg_param_cases[] = {
2549 	{ .alg_idx = 0, WMDR_PATCH_SHORT },
2550 	{ .alg_idx = 1, WMDR_PATCH_SHORT },
2551 	{ .alg_idx = 2, WMDR_PATCH_SHORT },
2552 	{ .alg_idx = 3, WMDR_PATCH_SHORT },
2553 };
2554 
2555 static const struct bin_test_param alg_long_param_cases[] = {
2556 	{ .alg_idx = 0, WMDR_PATCH_LONG },
2557 	{ .alg_idx = 1, WMDR_PATCH_LONG },
2558 	{ .alg_idx = 2, WMDR_PATCH_LONG },
2559 	{ .alg_idx = 3, WMDR_PATCH_LONG },
2560 };
2561 
2562 static void alg_param_desc(const struct bin_test_param *param, char *desc)
2563 {
2564 	WARN_ON(param->alg_idx >= ARRAY_SIZE(bin_test_mock_algs));
2565 
2566 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg[%u] (%#x) %s",
2567 		 param->alg_idx, bin_test_mock_algs[param->alg_idx].id,
2568 		(param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");
2569 }
2570 
2571 KUNIT_ARRAY_PARAM(alg, alg_param_cases, alg_param_desc);
2572 KUNIT_ARRAY_PARAM(alg_long, alg_long_param_cases, alg_param_desc);
2573 
2574 static const struct bin_test_param x_or_y_and_alg_param_cases[] = {
2575 	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 0, WMDR_PATCH_SHORT },
2576 	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 1, WMDR_PATCH_SHORT },
2577 	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 2, WMDR_PATCH_SHORT },
2578 	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 3, WMDR_PATCH_SHORT },
2579 
2580 	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 0, WMDR_PATCH_SHORT },
2581 	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 1, WMDR_PATCH_SHORT },
2582 	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 2, WMDR_PATCH_SHORT },
2583 	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 3, WMDR_PATCH_SHORT },
2584 };
2585 
2586 static const struct bin_test_param x_or_y_and_alg_long_param_cases[] = {
2587 	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 0, WMDR_PATCH_LONG },
2588 	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 1, WMDR_PATCH_LONG },
2589 	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 2, WMDR_PATCH_LONG },
2590 	{ .mem_type = WMFW_ADSP2_XM, .alg_idx = 3, WMDR_PATCH_LONG },
2591 
2592 	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 0, WMDR_PATCH_LONG },
2593 	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 1, WMDR_PATCH_LONG },
2594 	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 2, WMDR_PATCH_LONG },
2595 	{ .mem_type = WMFW_ADSP2_YM, .alg_idx = 3, WMDR_PATCH_LONG },
2596 };
2597 
2598 static void x_or_y_or_z_and_alg_param_desc(const struct bin_test_param *param, char *desc)
2599 {
2600 	WARN_ON(param->alg_idx >= ARRAY_SIZE(bin_test_mock_algs));
2601 
2602 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s alg[%u] (%#x) %s",
2603 		 cs_dsp_mem_region_name(param->mem_type),
2604 		 param->alg_idx, bin_test_mock_algs[param->alg_idx].id,
2605 		 (param->add_patch == cs_dsp_mock_bin_add_patch_off32) ? "offs32" : "");
2606 }
2607 
2608 KUNIT_ARRAY_PARAM(x_or_y_and_alg, x_or_y_and_alg_param_cases, x_or_y_or_z_and_alg_param_desc);
2609 KUNIT_ARRAY_PARAM(x_or_y_and_alg_long, x_or_y_and_alg_long_param_cases,
2610 		  x_or_y_or_z_and_alg_param_desc);
2611 
2612 static const struct bin_test_param z_and_alg_param_cases[] = {
2613 	{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 0, WMDR_PATCH_SHORT },
2614 	{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 1, WMDR_PATCH_SHORT },
2615 	{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 2, WMDR_PATCH_SHORT },
2616 	{ .mem_type = WMFW_ADSP2_ZM, .alg_idx = 3, WMDR_PATCH_SHORT },
2617 };
2618 
2619 KUNIT_ARRAY_PARAM(z_and_alg, z_and_alg_param_cases, x_or_y_or_z_and_alg_param_desc);
2620 
2621 static const struct bin_test_param packed_x_or_y_and_alg_param_cases[] = {
2622 	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 0, WMDR_PATCH_SHORT },
2623 	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 1, WMDR_PATCH_SHORT },
2624 	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 2, WMDR_PATCH_SHORT },
2625 	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 3, WMDR_PATCH_SHORT },
2626 
2627 	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 0, WMDR_PATCH_SHORT },
2628 	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 1, WMDR_PATCH_SHORT },
2629 	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 2, WMDR_PATCH_SHORT },
2630 	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 3, WMDR_PATCH_SHORT },
2631 };
2632 
2633 static const struct bin_test_param packed_x_or_y_and_alg_long_param_cases[] = {
2634 	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 0, WMDR_PATCH_LONG },
2635 	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 1, WMDR_PATCH_LONG },
2636 	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 2, WMDR_PATCH_LONG },
2637 	{ .mem_type = WMFW_HALO_XM_PACKED, .alg_idx = 3, WMDR_PATCH_LONG },
2638 
2639 	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 0, WMDR_PATCH_LONG },
2640 	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 1, WMDR_PATCH_LONG },
2641 	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 2, WMDR_PATCH_LONG },
2642 	{ .mem_type = WMFW_HALO_YM_PACKED, .alg_idx = 3, WMDR_PATCH_LONG },
2643 };
2644 
2645 KUNIT_ARRAY_PARAM(packed_x_or_y_and_alg, packed_x_or_y_and_alg_param_cases,
2646 		  x_or_y_or_z_and_alg_param_desc);
2647 
2648 KUNIT_ARRAY_PARAM(packed_x_or_y_and_alg_long, packed_x_or_y_and_alg_long_param_cases,
2649 		  x_or_y_or_z_and_alg_param_desc);
2650 
2651 static struct kunit_case cs_dsp_bin_test_cases_halo[] = {
2652 	/* Unpacked memory */
2653 	KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),
2654 	KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),
2655 	KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),
2656 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),
2657 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),
2658 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),
2659 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),
2660 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),
2661 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),
2662 
2663 	/* Packed memory tests */
2664 	KUNIT_CASE_PARAM(bin_patch_1_packed,
2665 			 packed_x_or_y_and_offset_gen_params),
2666 	KUNIT_CASE_PARAM(bin_patch_1_packed_1_single_trailing,
2667 			 packed_x_or_y_and_offset_gen_params),
2668 	KUNIT_CASE_PARAM(bin_patch_1_packed_2_single_trailing,
2669 			 packed_x_or_y_and_offset_gen_params),
2670 	KUNIT_CASE_PARAM(bin_patch_1_packed_3_single_trailing,
2671 			 packed_x_or_y_and_offset_gen_params),
2672 	KUNIT_CASE_PARAM(bin_patch_1_packed_2_trailing,
2673 			 packed_x_or_y_and_offset_gen_params),
2674 	KUNIT_CASE_PARAM(bin_patch_1_packed_3_trailing,
2675 			 packed_x_or_y_and_offset_gen_params),
2676 	KUNIT_CASE_PARAM(bin_patch_1_single_leading_1_packed,
2677 			 packed_x_or_y_and_offset_gen_params),
2678 	KUNIT_CASE_PARAM(bin_patch_2_single_leading_1_packed,
2679 			 packed_x_or_y_and_offset_gen_params),
2680 	KUNIT_CASE_PARAM(bin_patch_2_leading_1_packed,
2681 			 packed_x_or_y_and_offset_gen_params),
2682 	KUNIT_CASE_PARAM(bin_patch_3_single_leading_1_packed,
2683 			 packed_x_or_y_and_offset_gen_params),
2684 	KUNIT_CASE_PARAM(bin_patch_3_leading_1_packed,
2685 			 packed_x_or_y_and_offset_gen_params),
2686 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked,
2687 			 packed_x_or_y_and_offset_gen_params),
2688 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked_unordered,
2689 			 packed_x_or_y_and_offset_gen_params),
2690 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, offset_gen_params),
2691 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, alg_gen_params),
2692 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked_sparse_unordered,
2693 			 packed_x_or_y_and_alg_gen_params),
2694 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs,
2695 			 packed_x_or_y_and_offset_gen_params),
2696 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs_unordered,
2697 			 packed_x_or_y_and_offset_gen_params),
2698 	KUNIT_CASE_PARAM(bin_patch_mixed_packed_unpacked_random,
2699 			 packed_x_or_y_gen_params),
2700 
2701 	KUNIT_CASE(bin_patch_name_and_info),
2702 
2703 	{ } /* terminator */
2704 };
2705 
2706 static struct kunit_case cs_dsp_bin_test_cases_halo_wmdr3[] = {
2707 	/* Unpacked memory */
2708 	KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),
2709 	KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),
2710 	KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),
2711 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),
2712 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),
2713 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),
2714 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),
2715 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),
2716 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),
2717 
2718 	/* Packed memory tests */
2719 	KUNIT_CASE_PARAM(bin_patch_1_packed,
2720 			 packed_x_or_y_and_offset_gen_params),
2721 	KUNIT_CASE_PARAM(bin_patch_1_packed_1_single_trailing,
2722 			 packed_x_or_y_and_offset_gen_params),
2723 	KUNIT_CASE_PARAM(bin_patch_1_packed_2_single_trailing,
2724 			 packed_x_or_y_and_offset_gen_params),
2725 	KUNIT_CASE_PARAM(bin_patch_1_packed_3_single_trailing,
2726 			 packed_x_or_y_and_offset_gen_params),
2727 	KUNIT_CASE_PARAM(bin_patch_1_packed_2_trailing,
2728 			 packed_x_or_y_and_offset_gen_params),
2729 	KUNIT_CASE_PARAM(bin_patch_1_packed_3_trailing,
2730 			 packed_x_or_y_and_offset_gen_params),
2731 	KUNIT_CASE_PARAM(bin_patch_1_single_leading_1_packed,
2732 			 packed_x_or_y_and_offset_gen_params),
2733 	KUNIT_CASE_PARAM(bin_patch_2_single_leading_1_packed,
2734 			 packed_x_or_y_and_offset_gen_params),
2735 	KUNIT_CASE_PARAM(bin_patch_2_leading_1_packed,
2736 			 packed_x_or_y_and_offset_gen_params),
2737 	KUNIT_CASE_PARAM(bin_patch_3_single_leading_1_packed,
2738 			 packed_x_or_y_and_offset_gen_params),
2739 	KUNIT_CASE_PARAM(bin_patch_3_leading_1_packed,
2740 			 packed_x_or_y_and_offset_gen_params),
2741 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked,
2742 			 packed_x_or_y_and_offset_gen_params),
2743 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked_unordered,
2744 			 packed_x_or_y_and_offset_gen_params),
2745 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, offset_gen_params),
2746 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, alg_gen_params),
2747 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked_sparse_unordered,
2748 			 packed_x_or_y_and_alg_gen_params),
2749 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs,
2750 			 packed_x_or_y_and_offset_gen_params),
2751 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs_unordered,
2752 			 packed_x_or_y_and_offset_gen_params),
2753 	KUNIT_CASE_PARAM(bin_patch_mixed_packed_unpacked_random,
2754 			 packed_x_or_y_gen_params),
2755 
2756 	/* Unpacked memory with long-offset blocks */
2757 	KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_long_offset_gen_params),
2758 	KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_long_offset_gen_params),
2759 	KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_long_offset_gen_params),
2760 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_long_offset_gen_params),
2761 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, long_offset_gen_params),
2762 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_long_gen_params),
2763 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_long_gen_params),
2764 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_long_offset_gen_params),
2765 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered,
2766 			   x_or_y_and_long_offset_gen_params),
2767 
2768 	/* Packed memory tests with long offset blocks */
2769 	KUNIT_CASE_PARAM(bin_patch_1_packed,
2770 			 packed_x_or_y_and_long_offset_gen_params),
2771 	KUNIT_CASE_PARAM(bin_patch_1_packed_1_single_trailing,
2772 			 packed_x_or_y_and_long_offset_gen_params),
2773 	KUNIT_CASE_PARAM(bin_patch_1_packed_2_single_trailing,
2774 			 packed_x_or_y_and_long_offset_gen_params),
2775 	KUNIT_CASE_PARAM(bin_patch_1_packed_3_single_trailing,
2776 			 packed_x_or_y_and_long_offset_gen_params),
2777 	KUNIT_CASE_PARAM(bin_patch_1_packed_2_trailing,
2778 			 packed_x_or_y_and_long_offset_gen_params),
2779 	KUNIT_CASE_PARAM(bin_patch_1_packed_3_trailing,
2780 			 packed_x_or_y_and_long_offset_gen_params),
2781 	KUNIT_CASE_PARAM(bin_patch_1_single_leading_1_packed,
2782 			 packed_x_or_y_and_long_offset_gen_params),
2783 	KUNIT_CASE_PARAM(bin_patch_2_single_leading_1_packed,
2784 			 packed_x_or_y_and_long_offset_gen_params),
2785 	KUNIT_CASE_PARAM(bin_patch_2_leading_1_packed,
2786 			 packed_x_or_y_and_long_offset_gen_params),
2787 	KUNIT_CASE_PARAM(bin_patch_3_single_leading_1_packed,
2788 			 packed_x_or_y_and_long_offset_gen_params),
2789 	KUNIT_CASE_PARAM(bin_patch_3_leading_1_packed,
2790 			 packed_x_or_y_and_long_offset_gen_params),
2791 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked,
2792 			 packed_x_or_y_and_long_offset_gen_params),
2793 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked_unordered,
2794 			 packed_x_or_y_and_long_offset_gen_params),
2795 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, long_offset_gen_params),
2796 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_mems, alg_long_gen_params),
2797 	KUNIT_CASE_PARAM(bin_patch_multi_onepacked_sparse_unordered,
2798 			 packed_x_or_y_and_alg_long_gen_params),
2799 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs,
2800 			 packed_x_or_y_and_long_offset_gen_params),
2801 	KUNIT_CASE_PARAM(bin_patch_1_packed_multiple_algs_unordered,
2802 			 packed_x_or_y_and_long_offset_gen_params),
2803 	KUNIT_CASE_PARAM(bin_patch_mixed_packed_unpacked_random,
2804 			 packed_x_or_y_long_gen_params),
2805 
2806 	KUNIT_CASE(bin_patch_name_and_info),
2807 
2808 	{ } /* terminator */
2809 };
2810 
2811 static struct kunit_case cs_dsp_bin_test_cases_adsp2[] = {
2812 	/* XM and YM */
2813 	KUNIT_CASE_PARAM(bin_patch_one_word, x_or_y_and_offset_gen_params),
2814 	KUNIT_CASE_PARAM(bin_patch_one_multiword, x_or_y_and_offset_gen_params),
2815 	KUNIT_CASE_PARAM(bin_patch_multi_oneword, x_or_y_and_offset_gen_params),
2816 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, x_or_y_and_offset_gen_params),
2817 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, x_or_y_and_alg_gen_params),
2818 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, x_or_y_and_offset_gen_params),
2819 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, x_or_y_and_offset_gen_params),
2820 
2821 	/* ZM */
2822 	KUNIT_CASE_PARAM(bin_patch_one_word, z_and_offset_gen_params),
2823 	KUNIT_CASE_PARAM(bin_patch_one_multiword, z_and_offset_gen_params),
2824 	KUNIT_CASE_PARAM(bin_patch_multi_oneword, z_and_offset_gen_params),
2825 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_unordered, z_and_offset_gen_params),
2826 	KUNIT_CASE_PARAM(bin_patch_multi_oneword_sparse_unordered, z_and_alg_gen_params),
2827 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs, z_and_offset_gen_params),
2828 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_algs_unordered, z_and_offset_gen_params),
2829 
2830 	/* Other */
2831 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, offset_gen_params),
2832 	KUNIT_CASE_PARAM(bin_patch_one_word_multiple_mems, alg_gen_params),
2833 
2834 	KUNIT_CASE(bin_patch_name_and_info),
2835 
2836 	{ } /* terminator */
2837 };
2838 
2839 static struct kunit_suite cs_dsp_bin_test_halo = {
2840 	.name = "cs_dsp_bin_halo",
2841 	.init = cs_dsp_bin_test_halo_init,
2842 	.test_cases = cs_dsp_bin_test_cases_halo,
2843 	.attr.speed = KUNIT_SPEED_SLOW,
2844 };
2845 
2846 static struct kunit_suite cs_dsp_bin_test_halo_wmdr3 = {
2847 	.name = "cs_dsp_bin_halo_wmdr_v3",
2848 	.init = cs_dsp_bin_test_halo_wmdr3_init,
2849 	.test_cases = cs_dsp_bin_test_cases_halo_wmdr3,
2850 	.attr.speed = KUNIT_SPEED_SLOW,
2851 };
2852 
2853 static struct kunit_suite cs_dsp_bin_test_adsp2_32bit = {
2854 	.name = "cs_dsp_bin_adsp2_32bit",
2855 	.init = cs_dsp_bin_test_adsp2_32bit_init,
2856 	.test_cases = cs_dsp_bin_test_cases_adsp2,
2857 	.attr.speed = KUNIT_SPEED_SLOW,
2858 };
2859 
2860 static struct kunit_suite cs_dsp_bin_test_adsp2_16bit = {
2861 	.name = "cs_dsp_bin_adsp2_16bit",
2862 	.init = cs_dsp_bin_test_adsp2_16bit_init,
2863 	.test_cases = cs_dsp_bin_test_cases_adsp2,
2864 	.attr.speed = KUNIT_SPEED_SLOW,
2865 };
2866 
2867 kunit_test_suites(&cs_dsp_bin_test_halo,
2868 		  &cs_dsp_bin_test_halo_wmdr3,
2869 		  &cs_dsp_bin_test_adsp2_32bit,
2870 		  &cs_dsp_bin_test_adsp2_16bit);
2871