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/test.h> 11 #include <linux/build_bug.h> 12 #include <linux/firmware/cirrus/cs_dsp.h> 13 #include <linux/firmware/cirrus/cs_dsp_test_utils.h> 14 #include <linux/firmware/cirrus/wmfw.h> 15 #include <linux/list.h> 16 #include <linux/mutex.h> 17 #include <linux/regmap.h> 18 19 KUNIT_DEFINE_ACTION_WRAPPER(_put_device_wrapper, put_device, struct device *); 20 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *); 21 22 struct cs_dsp_test_local { 23 struct cs_dsp_mock_xm_header *xm_header; 24 struct cs_dsp_mock_wmfw_builder *wmfw_builder; 25 int wmfw_version; 26 }; 27 28 struct cs_dsp_ctl_parse_test_param { 29 int mem_type; 30 int alg_id; 31 unsigned int offset; 32 unsigned int length; 33 u16 ctl_type; 34 u16 flags; 35 }; 36 37 static const struct cs_dsp_mock_alg_def cs_dsp_ctl_parse_test_algs[] = { 38 { 39 .id = 0xfafa, 40 .ver = 0x100000, 41 .xm_size_words = 164, 42 .ym_size_words = 164, 43 .zm_size_words = 164, 44 }, 45 { 46 .id = 0xb, 47 .ver = 0x100001, 48 .xm_size_words = 8, 49 .ym_size_words = 8, 50 .zm_size_words = 8, 51 }, 52 { 53 .id = 0x9f1234, 54 .ver = 0x100500, 55 .xm_size_words = 16, 56 .ym_size_words = 16, 57 .zm_size_words = 16, 58 }, 59 { 60 .id = 0xff00ff, 61 .ver = 0x300113, 62 .xm_size_words = 16, 63 .ym_size_words = 16, 64 .zm_size_words = 16, 65 }, 66 }; 67 68 static const struct cs_dsp_mock_coeff_def mock_coeff_template = { 69 .shortname = "Dummy Coeff", 70 .type = WMFW_CTL_TYPE_BYTES, 71 .mem_type = WMFW_ADSP2_YM, 72 .flags = WMFW_CTL_FLAG_VOLATILE, 73 .length_bytes = 4, 74 }; 75 76 static char *cs_dsp_ctl_alloc_test_string(struct kunit *test, char c, size_t len) 77 { 78 char *str; 79 80 str = kunit_kmalloc(test, len + 1, GFP_KERNEL); 81 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str); 82 memset(str, c, len); 83 str[len] = '\0'; 84 85 return str; 86 } 87 88 /* Algorithm info block without controls should load */ 89 static void cs_dsp_ctl_parse_no_coeffs(struct kunit *test) 90 { 91 struct cs_dsp_test *priv = test->priv; 92 struct cs_dsp_test_local *local = priv->local; 93 struct firmware *wmfw; 94 95 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 96 cs_dsp_ctl_parse_test_algs[0].id, 97 "dummyalg", NULL); 98 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 99 100 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 101 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 102 } 103 104 /* 105 * V1 controls do not have names, the name field in the coefficient entry 106 * should be ignored. 107 */ 108 static void cs_dsp_ctl_parse_v1_name(struct kunit *test) 109 { 110 struct cs_dsp_test *priv = test->priv; 111 struct cs_dsp_test_local *local = priv->local; 112 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 113 struct cs_dsp_coeff_ctl *ctl; 114 struct firmware *wmfw; 115 116 def.fullname = "Dummy"; 117 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 118 cs_dsp_ctl_parse_test_algs[0].id, 119 "dummyalg", NULL); 120 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 121 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 122 123 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 124 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 125 126 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 127 KUNIT_ASSERT_NOT_NULL(test, ctl); 128 KUNIT_EXPECT_EQ(test, ctl->subname_len, 0); 129 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 130 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 131 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 132 } 133 134 /* 135 * V1 controls do not have names, the name field in the coefficient entry 136 * should be ignored. Test with a zero-length name string. 137 */ 138 static void cs_dsp_ctl_parse_empty_v1_name(struct kunit *test) 139 { 140 struct cs_dsp_test *priv = test->priv; 141 struct cs_dsp_test_local *local = priv->local; 142 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 143 struct cs_dsp_coeff_ctl *ctl; 144 struct firmware *wmfw; 145 146 def.fullname = "\0"; 147 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 148 cs_dsp_ctl_parse_test_algs[0].id, 149 "dummyalg", NULL); 150 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 151 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 152 153 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 154 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 155 156 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 157 KUNIT_ASSERT_NOT_NULL(test, ctl); 158 KUNIT_EXPECT_EQ(test, ctl->subname_len, 0); 159 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 160 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 161 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 162 } 163 164 /* 165 * V1 controls do not have names, the name field in the coefficient entry 166 * should be ignored. Test with a maximum length name string. 167 */ 168 static void cs_dsp_ctl_parse_max_v1_name(struct kunit *test) 169 { 170 struct cs_dsp_test *priv = test->priv; 171 struct cs_dsp_test_local *local = priv->local; 172 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 173 struct cs_dsp_coeff_ctl *ctl; 174 struct firmware *wmfw; 175 176 def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255); 177 178 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 179 cs_dsp_ctl_parse_test_algs[0].id, 180 "dummyalg", NULL); 181 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 182 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 183 184 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 185 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 186 187 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 188 KUNIT_ASSERT_NOT_NULL(test, ctl); 189 KUNIT_EXPECT_EQ(test, ctl->subname_len, 0); 190 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 191 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 192 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 193 } 194 195 /* Short name from coeff descriptor should be used as control name. */ 196 static void cs_dsp_ctl_parse_short_name(struct kunit *test) 197 { 198 struct cs_dsp_test *priv = test->priv; 199 struct cs_dsp_test_local *local = priv->local; 200 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 201 struct cs_dsp_coeff_ctl *ctl; 202 struct firmware *wmfw; 203 204 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 205 cs_dsp_ctl_parse_test_algs[0].id, 206 "dummyalg", NULL); 207 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 208 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 209 210 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 211 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 212 213 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 214 KUNIT_ASSERT_NOT_NULL(test, ctl); 215 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname)); 216 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len); 217 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 218 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 219 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 220 } 221 222 /* 223 * Short name from coeff descriptor should be used as control name. 224 * Test with a short name that is a single character. 225 */ 226 static void cs_dsp_ctl_parse_min_short_name(struct kunit *test) 227 { 228 struct cs_dsp_test *priv = test->priv; 229 struct cs_dsp_test_local *local = priv->local; 230 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 231 struct cs_dsp_coeff_ctl *ctl; 232 struct firmware *wmfw; 233 234 def.shortname = "Q"; 235 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 236 cs_dsp_ctl_parse_test_algs[0].id, 237 "dummyalg", NULL); 238 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 239 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 240 241 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 242 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 243 244 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 245 KUNIT_ASSERT_NOT_NULL(test, ctl); 246 KUNIT_EXPECT_EQ(test, ctl->subname_len, 1); 247 KUNIT_EXPECT_EQ(test, ctl->subname[0], 'Q'); 248 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 249 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 250 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 251 } 252 253 /* 254 * Short name from coeff descriptor should be used as control name. 255 * Test with a maximum length name. 256 */ 257 static void cs_dsp_ctl_parse_max_short_name(struct kunit *test) 258 { 259 struct cs_dsp_test *priv = test->priv; 260 struct cs_dsp_test_local *local = priv->local; 261 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 262 struct cs_dsp_coeff_ctl *ctl; 263 struct firmware *wmfw; 264 265 def.shortname = cs_dsp_ctl_alloc_test_string(test, 'A', 255); 266 267 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 268 cs_dsp_ctl_parse_test_algs[0].id, 269 "dummyalg", NULL); 270 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 271 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 272 273 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 274 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 275 276 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 277 KUNIT_ASSERT_NOT_NULL(test, ctl); 278 KUNIT_EXPECT_EQ(test, ctl->subname_len, 255); 279 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len); 280 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 281 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 282 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 283 } 284 285 /* 286 * Full name from coeff descriptor should be ignored. It is a variable 287 * length field so affects the position of subsequent fields. 288 * Test with a 1-character full name. 289 */ 290 static void cs_dsp_ctl_parse_with_min_fullname(struct kunit *test) 291 { 292 struct cs_dsp_test *priv = test->priv; 293 struct cs_dsp_test_local *local = priv->local; 294 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 295 struct cs_dsp_coeff_ctl *ctl; 296 struct firmware *wmfw; 297 298 def.fullname = "Q"; 299 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 300 cs_dsp_ctl_parse_test_algs[0].id, 301 "dummyalg", NULL); 302 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 303 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 304 305 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 306 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 307 308 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 309 KUNIT_ASSERT_NOT_NULL(test, ctl); 310 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname)); 311 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len); 312 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 313 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 314 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 315 } 316 317 /* 318 * Full name from coeff descriptor should be ignored. It is a variable 319 * length field so affects the position of subsequent fields. 320 * Test with a maximum length full name. 321 */ 322 static void cs_dsp_ctl_parse_with_max_fullname(struct kunit *test) 323 { 324 struct cs_dsp_test *priv = test->priv; 325 struct cs_dsp_test_local *local = priv->local; 326 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 327 struct cs_dsp_coeff_ctl *ctl; 328 struct firmware *wmfw; 329 330 def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255); 331 332 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 333 cs_dsp_ctl_parse_test_algs[0].id, 334 "dummyalg", NULL); 335 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 336 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 337 338 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 339 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 340 341 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 342 KUNIT_ASSERT_NOT_NULL(test, ctl); 343 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname)); 344 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len); 345 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 346 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 347 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 348 } 349 350 /* 351 * Description from coeff descriptor should be ignored. It is a variable 352 * length field so affects the position of subsequent fields. 353 * Test with a 1-character description 354 */ 355 static void cs_dsp_ctl_parse_with_min_description(struct kunit *test) 356 { 357 struct cs_dsp_test *priv = test->priv; 358 struct cs_dsp_test_local *local = priv->local; 359 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 360 struct cs_dsp_coeff_ctl *ctl; 361 struct firmware *wmfw; 362 363 def.description = "Q"; 364 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 365 cs_dsp_ctl_parse_test_algs[0].id, 366 "dummyalg", NULL); 367 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 368 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 369 370 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 371 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 372 373 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 374 KUNIT_ASSERT_NOT_NULL(test, ctl); 375 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname)); 376 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len); 377 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 378 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 379 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 380 } 381 382 /* 383 * Description from coeff descriptor should be ignored. It is a variable 384 * length field so affects the position of subsequent fields. 385 * Test with a maximum length description 386 */ 387 static void cs_dsp_ctl_parse_with_max_description(struct kunit *test) 388 { 389 struct cs_dsp_test *priv = test->priv; 390 struct cs_dsp_test_local *local = priv->local; 391 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 392 struct cs_dsp_coeff_ctl *ctl; 393 struct firmware *wmfw; 394 395 def.description = cs_dsp_ctl_alloc_test_string(test, 'A', 65535); 396 397 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 398 cs_dsp_ctl_parse_test_algs[0].id, 399 "dummyalg", NULL); 400 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 401 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 402 403 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 404 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 405 406 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 407 KUNIT_ASSERT_NOT_NULL(test, ctl); 408 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname)); 409 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len); 410 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 411 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 412 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 413 } 414 415 /* 416 * Full name and description from coeff descriptor are variable length 417 * fields so affects the position of subsequent fields. 418 * Test with a maximum length full name and description 419 */ 420 static void cs_dsp_ctl_parse_with_max_fullname_and_description(struct kunit *test) 421 { 422 struct cs_dsp_test *priv = test->priv; 423 struct cs_dsp_test_local *local = priv->local; 424 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 425 struct cs_dsp_coeff_ctl *ctl; 426 struct firmware *wmfw; 427 428 def.fullname = cs_dsp_ctl_alloc_test_string(test, 'A', 255); 429 def.description = cs_dsp_ctl_alloc_test_string(test, 'A', 65535); 430 431 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 432 cs_dsp_ctl_parse_test_algs[0].id, 433 "dummyalg", NULL); 434 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 435 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 436 437 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 438 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 439 440 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 441 KUNIT_ASSERT_NOT_NULL(test, ctl); 442 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(def.shortname)); 443 KUNIT_EXPECT_MEMEQ(test, ctl->subname, def.shortname, ctl->subname_len); 444 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 445 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 446 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 447 } 448 449 static const char * const cs_dsp_ctl_alignment_test_names[] = { 450 "1", "12", "123", "1234", "12345", "123456", "1234567", 451 "12345678", "123456789", "123456789A", "123456789AB", 452 "123456789ABC", "123456789ABCD", "123456789ABCDE", 453 "123456789ABCDEF", 454 }; 455 456 /* 457 * Variable-length string fields are padded to a multiple of 4-bytes. 458 * Test this with various lengths of short name. 459 */ 460 static void cs_dsp_ctl_shortname_alignment(struct kunit *test) 461 { 462 struct cs_dsp_test *priv = test->priv; 463 struct cs_dsp_test_local *local = priv->local; 464 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 465 struct cs_dsp_coeff_ctl *ctl; 466 struct firmware *wmfw; 467 int i; 468 469 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 470 cs_dsp_ctl_parse_test_algs[0].id, 471 "dummyalg", NULL); 472 473 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) { 474 def.shortname = cs_dsp_ctl_alignment_test_names[i]; 475 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 476 } 477 478 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 479 480 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 481 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 482 483 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) { 484 mutex_lock(&priv->dsp->pwr_lock); 485 ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_ctl_alignment_test_names[i], 486 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id); 487 mutex_unlock(&priv->dsp->pwr_lock); 488 KUNIT_ASSERT_NOT_NULL(test, ctl); 489 KUNIT_EXPECT_EQ(test, ctl->subname_len, i + 1); 490 KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_ctl_alignment_test_names[i], 491 ctl->subname_len); 492 /* Test fields that are parsed after the variable-length fields */ 493 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 494 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 495 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 496 } 497 } 498 499 /* 500 * Variable-length string fields are padded to a multiple of 4-bytes. 501 * Test this with various lengths of full name. 502 */ 503 static void cs_dsp_ctl_fullname_alignment(struct kunit *test) 504 { 505 struct cs_dsp_test *priv = test->priv; 506 struct cs_dsp_test_local *local = priv->local; 507 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 508 struct cs_dsp_coeff_ctl *ctl; 509 char ctl_name[4]; 510 struct firmware *wmfw; 511 int i; 512 513 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 514 cs_dsp_ctl_parse_test_algs[0].id, 515 "dummyalg", NULL); 516 517 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) { 518 /* 519 * Create a unique control name of 3 characters so that 520 * the shortname field is exactly 4 bytes long including 521 * the length byte. 522 */ 523 snprintf(ctl_name, sizeof(ctl_name), "%03d", i); 524 KUNIT_ASSERT_EQ(test, strlen(ctl_name), 3); 525 def.shortname = ctl_name; 526 527 def.fullname = cs_dsp_ctl_alignment_test_names[i]; 528 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 529 } 530 531 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 532 533 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 534 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 535 536 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) { 537 snprintf(ctl_name, sizeof(ctl_name), "%03d", i); 538 539 mutex_lock(&priv->dsp->pwr_lock); 540 ctl = cs_dsp_get_ctl(priv->dsp, ctl_name, def.mem_type, 541 cs_dsp_ctl_parse_test_algs[0].id); 542 mutex_unlock(&priv->dsp->pwr_lock); 543 KUNIT_ASSERT_NOT_NULL(test, ctl); 544 KUNIT_EXPECT_EQ(test, ctl->subname_len, 3); 545 KUNIT_EXPECT_MEMEQ(test, ctl->subname, ctl_name, ctl->subname_len); 546 /* Test fields that are parsed after the variable-length fields */ 547 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 548 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 549 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 550 } 551 } 552 553 /* 554 * Variable-length string fields are padded to a multiple of 4-bytes. 555 * Test this with various lengths of description. 556 */ 557 static void cs_dsp_ctl_description_alignment(struct kunit *test) 558 { 559 struct cs_dsp_test *priv = test->priv; 560 struct cs_dsp_test_local *local = priv->local; 561 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 562 struct cs_dsp_coeff_ctl *ctl; 563 char ctl_name[4]; 564 struct firmware *wmfw; 565 int i; 566 567 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 568 cs_dsp_ctl_parse_test_algs[0].id, 569 "dummyalg", NULL); 570 571 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) { 572 /* 573 * Create a unique control name of 3 characters so that 574 * the shortname field is exactly 4 bytes long including 575 * the length byte. 576 */ 577 snprintf(ctl_name, sizeof(ctl_name), "%03d", i); 578 KUNIT_ASSERT_EQ(test, strlen(ctl_name), 3); 579 def.shortname = ctl_name; 580 581 def.description = cs_dsp_ctl_alignment_test_names[i]; 582 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 583 } 584 585 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 586 587 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 588 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 589 590 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_alignment_test_names); i++) { 591 snprintf(ctl_name, sizeof(ctl_name), "%03d", i); 592 593 mutex_lock(&priv->dsp->pwr_lock); 594 ctl = cs_dsp_get_ctl(priv->dsp, ctl_name, def.mem_type, 595 cs_dsp_ctl_parse_test_algs[0].id); 596 mutex_unlock(&priv->dsp->pwr_lock); 597 KUNIT_ASSERT_NOT_NULL(test, ctl); 598 KUNIT_EXPECT_EQ(test, ctl->subname_len, 3); 599 KUNIT_EXPECT_MEMEQ(test, ctl->subname, ctl_name, ctl->subname_len); 600 /* Test fields that are parsed after the variable-length fields */ 601 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 602 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 603 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 604 } 605 } 606 607 static const char * const cs_dsp_get_ctl_test_names[] = { 608 "Up", "Down", "Switch", "Mute", 609 "Left Up", "Left Down", "Right Up", "Right Down", 610 "Left Mute", "Right Mute", 611 "_trunc_1", "_trunc_2", " trunc", 612 }; 613 614 /* Test using cs_dsp_get_ctl() to lookup various controls. */ 615 static void cs_dsp_get_ctl_test(struct kunit *test) 616 { 617 struct cs_dsp_test *priv = test->priv; 618 struct cs_dsp_test_local *local = priv->local; 619 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 620 struct cs_dsp_coeff_ctl *ctl; 621 struct firmware *wmfw; 622 int i; 623 624 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 625 cs_dsp_ctl_parse_test_algs[0].id, 626 "dummyalg", NULL); 627 628 for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) { 629 def.shortname = cs_dsp_get_ctl_test_names[i]; 630 def.offset_dsp_words = i; 631 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 632 } 633 634 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 635 636 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 637 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 638 639 for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) { 640 mutex_lock(&priv->dsp->pwr_lock); 641 ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_get_ctl_test_names[i], 642 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id); 643 mutex_unlock(&priv->dsp->pwr_lock); 644 KUNIT_ASSERT_NOT_NULL(test, ctl); 645 KUNIT_EXPECT_EQ(test, ctl->subname_len, strlen(cs_dsp_get_ctl_test_names[i])); 646 KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_get_ctl_test_names[i], 647 ctl->subname_len); 648 KUNIT_EXPECT_EQ(test, ctl->offset, i); 649 } 650 } 651 652 /* 653 * cs_dsp_get_ctl() searches for the control in the currently loaded 654 * firmware, so create identical controls in multiple firmware and 655 * test that the correct one is found. 656 */ 657 static void cs_dsp_get_ctl_test_multiple_wmfw(struct kunit *test) 658 { 659 struct cs_dsp_test *priv = test->priv; 660 struct cs_dsp_test_local *local = priv->local; 661 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 662 struct cs_dsp_coeff_ctl *ctl; 663 struct cs_dsp_mock_wmfw_builder *builder2; 664 struct firmware *wmfw; 665 666 def.shortname = "_A_CONTROL"; 667 668 /* Create a second mock wmfw builder */ 669 builder2 = cs_dsp_mock_wmfw_init(priv, 670 cs_dsp_mock_wmfw_format_version(local->wmfw_builder)); 671 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2); 672 cs_dsp_mock_wmfw_add_data_block(builder2, 673 WMFW_ADSP2_XM, 0, 674 local->xm_header->blob_data, 675 local->xm_header->blob_size_bytes); 676 677 /* Load a 'misc' firmware with a control */ 678 def.offset_dsp_words = 1; 679 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 680 cs_dsp_ctl_parse_test_algs[0].id, 681 "dummyalg", NULL); 682 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 683 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 684 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 685 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 686 cs_dsp_power_down(priv->dsp); 687 688 /* Load a 'mbc/vss' firmware with a control of the same name */ 689 def.offset_dsp_words = 2; 690 cs_dsp_mock_wmfw_start_alg_info_block(builder2, 691 cs_dsp_ctl_parse_test_algs[0].id, 692 "dummyalg", NULL); 693 cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def); 694 cs_dsp_mock_wmfw_end_alg_info_block(builder2); 695 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 696 KUNIT_ASSERT_EQ(test, 697 cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2", NULL, NULL, "mbc/vss"), 0); 698 699 /* A lookup should return the control for the current firmware */ 700 mutex_lock(&priv->dsp->pwr_lock); 701 ctl = cs_dsp_get_ctl(priv->dsp, def.shortname, 702 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id); 703 mutex_unlock(&priv->dsp->pwr_lock); 704 KUNIT_ASSERT_NOT_NULL(test, ctl); 705 KUNIT_EXPECT_EQ(test, ctl->offset, 2); 706 707 /* Re-load the 'misc' firmware and a lookup should return its control */ 708 cs_dsp_power_down(priv->dsp); 709 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 710 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 711 712 mutex_lock(&priv->dsp->pwr_lock); 713 ctl = cs_dsp_get_ctl(priv->dsp, def.shortname, 714 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id); 715 mutex_unlock(&priv->dsp->pwr_lock); 716 KUNIT_ASSERT_NOT_NULL(test, ctl); 717 KUNIT_EXPECT_EQ(test, ctl->offset, 1); 718 } 719 720 /* Test that the value of the memory type field is parsed correctly. */ 721 static void cs_dsp_ctl_parse_memory_type(struct kunit *test) 722 { 723 const struct cs_dsp_ctl_parse_test_param *param = test->param_value; 724 struct cs_dsp_test *priv = test->priv; 725 struct cs_dsp_test_local *local = priv->local; 726 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 727 struct cs_dsp_coeff_ctl *ctl; 728 struct firmware *wmfw; 729 730 /* kunit_skip() marks the test skipped forever, so just return */ 731 if ((param->mem_type == WMFW_ADSP2_ZM) && !cs_dsp_mock_has_zm(priv)) 732 return; 733 734 def.mem_type = param->mem_type; 735 736 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 737 cs_dsp_ctl_parse_test_algs[0].id, 738 "dummyalg", NULL); 739 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 740 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 741 742 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 743 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 744 745 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 746 KUNIT_ASSERT_NOT_NULL(test, ctl); 747 KUNIT_EXPECT_EQ(test, ctl->alg_region.type, param->mem_type); 748 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 749 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 750 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 751 } 752 753 /* 754 * Test that the algorithm id from the parent alg-info block is 755 * correctly stored in the cs_dsp_coeff_ctl. 756 */ 757 static void cs_dsp_ctl_parse_alg_id(struct kunit *test) 758 { 759 const struct cs_dsp_ctl_parse_test_param *param = test->param_value; 760 struct cs_dsp_test *priv = test->priv; 761 struct cs_dsp_test_local *local = priv->local; 762 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 763 struct cs_dsp_coeff_ctl *ctl; 764 struct firmware *wmfw; 765 766 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 767 param->alg_id, 768 "dummyalg", NULL); 769 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 770 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 771 772 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 773 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 774 775 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 776 KUNIT_ASSERT_NOT_NULL(test, ctl); 777 KUNIT_EXPECT_EQ(test, ctl->alg_region.alg, param->alg_id); 778 KUNIT_EXPECT_EQ(test, ctl->alg_region.type, def.mem_type); 779 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 780 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 781 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 782 } 783 784 /* 785 * Test that the values of (alg id, memory type) tuple is parsed correctly. 786 * The alg id is parsed from the alg-info block, but the memory type is 787 * parsed from the coefficient info descriptor. 788 */ 789 static void cs_dsp_ctl_parse_alg_mem(struct kunit *test) 790 { 791 const struct cs_dsp_ctl_parse_test_param *param = test->param_value; 792 struct cs_dsp_test *priv = test->priv; 793 struct cs_dsp_test_local *local = priv->local; 794 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 795 struct cs_dsp_coeff_ctl *ctl; 796 struct firmware *wmfw; 797 798 /* kunit_skip() marks the test skipped forever, so just return */ 799 if ((param->mem_type == WMFW_ADSP2_ZM) && !cs_dsp_mock_has_zm(priv)) 800 return; 801 802 def.mem_type = param->mem_type; 803 804 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 805 param->alg_id, 806 "dummyalg", NULL); 807 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 808 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 809 810 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 811 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 812 813 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 814 KUNIT_ASSERT_NOT_NULL(test, ctl); 815 KUNIT_EXPECT_EQ(test, ctl->alg_region.alg, param->alg_id); 816 KUNIT_EXPECT_EQ(test, ctl->alg_region.type, param->mem_type); 817 } 818 819 /* Test that the value of the offset field is parsed correctly. */ 820 static void cs_dsp_ctl_parse_offset(struct kunit *test) 821 { 822 const struct cs_dsp_ctl_parse_test_param *param = test->param_value; 823 struct cs_dsp_test *priv = test->priv; 824 struct cs_dsp_test_local *local = priv->local; 825 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 826 struct cs_dsp_coeff_ctl *ctl; 827 struct firmware *wmfw; 828 829 def.offset_dsp_words = param->offset; 830 831 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 832 cs_dsp_ctl_parse_test_algs[0].id, 833 "dummyalg", NULL); 834 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 835 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 836 837 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 838 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 839 840 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 841 KUNIT_ASSERT_NOT_NULL(test, ctl); 842 KUNIT_EXPECT_EQ(test, ctl->offset, param->offset); 843 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 844 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 845 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 846 } 847 848 /* Test that the value of the length field is parsed correctly. */ 849 static void cs_dsp_ctl_parse_length(struct kunit *test) 850 { 851 const struct cs_dsp_ctl_parse_test_param *param = test->param_value; 852 struct cs_dsp_test *priv = test->priv; 853 struct cs_dsp_test_local *local = priv->local; 854 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 855 struct cs_dsp_coeff_ctl *ctl; 856 struct firmware *wmfw; 857 858 def.length_bytes = param->length; 859 860 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 861 cs_dsp_ctl_parse_test_algs[0].id, 862 "dummyalg", NULL); 863 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 864 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 865 866 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 867 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 868 869 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 870 KUNIT_ASSERT_NOT_NULL(test, ctl); 871 KUNIT_EXPECT_EQ(test, ctl->offset, def.offset_dsp_words); 872 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 873 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 874 KUNIT_EXPECT_EQ(test, ctl->len, param->length); 875 } 876 877 /* Test that the value of the control type field is parsed correctly. */ 878 static void cs_dsp_ctl_parse_ctl_type(struct kunit *test) 879 { 880 const struct cs_dsp_ctl_parse_test_param *param = test->param_value; 881 struct cs_dsp_test *priv = test->priv; 882 struct cs_dsp_test_local *local = priv->local; 883 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 884 struct cs_dsp_coeff_ctl *ctl; 885 struct firmware *wmfw; 886 887 def.type = param->ctl_type; 888 def.flags = param->flags; 889 890 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 891 cs_dsp_ctl_parse_test_algs[0].id, 892 "dummyalg", NULL); 893 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 894 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 895 896 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 897 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 898 899 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 900 KUNIT_ASSERT_NOT_NULL(test, ctl); 901 KUNIT_EXPECT_EQ(test, ctl->type, param->ctl_type); 902 KUNIT_EXPECT_EQ(test, ctl->flags, def.flags); 903 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 904 } 905 906 /* Test that the value of the flags field is parsed correctly. */ 907 static void cs_dsp_ctl_parse_flags(struct kunit *test) 908 { 909 const struct cs_dsp_ctl_parse_test_param *param = test->param_value; 910 struct cs_dsp_test *priv = test->priv; 911 struct cs_dsp_test_local *local = priv->local; 912 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 913 struct cs_dsp_coeff_ctl *ctl; 914 struct firmware *wmfw; 915 u32 reg_val; 916 917 /* 918 * Non volatile controls will be read to initialize the cache 919 * so the regmap cache must contain something to read. 920 */ 921 reg_val = 0xf11100; 922 regmap_raw_write(priv->dsp->regmap, 923 cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM), 924 ®_val, sizeof(reg_val)); 925 926 def.flags = param->flags; 927 def.mem_type = WMFW_ADSP2_YM; 928 929 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 930 cs_dsp_ctl_parse_test_algs[0].id, 931 "dummyalg", NULL); 932 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 933 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 934 935 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 936 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 937 938 ctl = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 939 KUNIT_ASSERT_NOT_NULL(test, ctl); 940 KUNIT_EXPECT_EQ(test, ctl->type, def.type); 941 KUNIT_EXPECT_EQ(test, ctl->flags, param->flags); 942 KUNIT_EXPECT_EQ(test, ctl->len, def.length_bytes); 943 } 944 945 /* Test that invalid combinations of (control type, flags) are rejected. */ 946 static void cs_dsp_ctl_illegal_type_flags(struct kunit *test) 947 { 948 const struct cs_dsp_ctl_parse_test_param *param = test->param_value; 949 struct cs_dsp_test *priv = test->priv; 950 struct cs_dsp_test_local *local = priv->local; 951 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 952 struct firmware *wmfw; 953 u32 reg_val; 954 955 /* 956 * Non volatile controls will be read to initialize the cache 957 * so the regmap cache must contain something to read. 958 */ 959 reg_val = 0xf11100; 960 regmap_raw_write(priv->dsp->regmap, 961 cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM), 962 ®_val, sizeof(reg_val)); 963 964 def.type = param->ctl_type; 965 def.flags = param->flags; 966 def.mem_type = WMFW_ADSP2_YM; 967 968 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 969 cs_dsp_ctl_parse_test_algs[0].id, 970 "dummyalg", NULL); 971 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 972 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 973 974 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 975 KUNIT_ASSERT_LT(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 976 } 977 978 /* Test that the correct firmware name is entered in the cs_dsp_coeff_ctl. */ 979 static void cs_dsp_ctl_parse_fw_name(struct kunit *test) 980 { 981 struct cs_dsp_test *priv = test->priv; 982 struct cs_dsp_test_local *local = priv->local; 983 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 984 struct cs_dsp_coeff_ctl *walkctl, *ctl1, *ctl2; 985 struct cs_dsp_mock_wmfw_builder *builder2; 986 struct firmware *wmfw; 987 988 /* Create a second mock wmfw builder */ 989 builder2 = cs_dsp_mock_wmfw_init(priv, 990 cs_dsp_mock_wmfw_format_version(local->wmfw_builder)); 991 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2); 992 cs_dsp_mock_wmfw_add_data_block(builder2, 993 WMFW_ADSP2_XM, 0, 994 local->xm_header->blob_data, 995 local->xm_header->blob_size_bytes); 996 997 /* Load a 'misc' firmware with a control */ 998 def.offset_dsp_words = 1; 999 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1000 cs_dsp_ctl_parse_test_algs[0].id, 1001 "dummyalg", NULL); 1002 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1003 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1004 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1005 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1006 cs_dsp_power_down(priv->dsp); 1007 1008 /* Load a 'mbc/vss' firmware with a control */ 1009 def.offset_dsp_words = 2; 1010 cs_dsp_mock_wmfw_start_alg_info_block(builder2, 1011 cs_dsp_ctl_parse_test_algs[0].id, 1012 "dummyalg", NULL); 1013 cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def); 1014 cs_dsp_mock_wmfw_end_alg_info_block(builder2); 1015 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 1016 KUNIT_ASSERT_EQ(test, 1017 cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2", NULL, NULL, "mbc/vss"), 0); 1018 1019 /* Both controls should be in the list (order not guaranteed) */ 1020 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2); 1021 ctl1 = NULL; 1022 ctl2 = NULL; 1023 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) { 1024 if (strcmp(walkctl->fw_name, "misc") == 0) 1025 ctl1 = walkctl; 1026 else if (strcmp(walkctl->fw_name, "mbc/vss") == 0) 1027 ctl2 = walkctl; 1028 } 1029 1030 KUNIT_EXPECT_NOT_NULL(test, ctl1); 1031 KUNIT_EXPECT_NOT_NULL(test, ctl2); 1032 KUNIT_EXPECT_EQ(test, ctl1->offset, 1); 1033 KUNIT_EXPECT_EQ(test, ctl2->offset, 2); 1034 } 1035 1036 /* Controls are unique if the algorithm ID is different */ 1037 static void cs_dsp_ctl_alg_id_uniqueness(struct kunit *test) 1038 { 1039 struct cs_dsp_test *priv = test->priv; 1040 struct cs_dsp_test_local *local = priv->local; 1041 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1042 struct cs_dsp_coeff_ctl *ctl1, *ctl2; 1043 struct firmware *wmfw; 1044 1045 /* Create an algorithm containing the control */ 1046 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1047 cs_dsp_ctl_parse_test_algs[0].id, 1048 "dummyalg", NULL); 1049 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1050 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1051 1052 /* Create a different algorithm containing an identical control */ 1053 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1054 cs_dsp_ctl_parse_test_algs[1].id, 1055 "dummyalg", NULL); 1056 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1057 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1058 1059 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1060 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1061 cs_dsp_power_down(priv->dsp); 1062 1063 /* Both controls should be in the list */ 1064 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2); 1065 ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1066 ctl2 = list_next_entry(ctl1, list); 1067 KUNIT_EXPECT_NOT_NULL(test, ctl1); 1068 KUNIT_EXPECT_NOT_NULL(test, ctl2); 1069 KUNIT_EXPECT_NE(test, ctl1->alg_region.alg, ctl2->alg_region.alg); 1070 KUNIT_EXPECT_EQ(test, ctl1->alg_region.type, ctl2->alg_region.type); 1071 KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset); 1072 KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type); 1073 KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags); 1074 KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len); 1075 KUNIT_EXPECT_STREQ(test, ctl1->fw_name, ctl2->fw_name); 1076 KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len); 1077 if (ctl1->subname_len) 1078 KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len); 1079 } 1080 1081 /* Controls are unique if the memory region is different */ 1082 static void cs_dsp_ctl_mem_uniqueness(struct kunit *test) 1083 { 1084 struct cs_dsp_test *priv = test->priv; 1085 struct cs_dsp_test_local *local = priv->local; 1086 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1087 struct cs_dsp_coeff_ctl *ctl1, *ctl2; 1088 struct firmware *wmfw; 1089 1090 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1091 cs_dsp_ctl_parse_test_algs[0].id, 1092 "dummyalg", NULL); 1093 /* Create control in XM */ 1094 def.mem_type = WMFW_ADSP2_XM; 1095 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1096 1097 /* Create control in YM */ 1098 def.mem_type = WMFW_ADSP2_YM; 1099 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1100 1101 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1102 1103 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1104 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1105 cs_dsp_power_down(priv->dsp); 1106 1107 /* Both controls should be in the list */ 1108 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2); 1109 ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1110 ctl2 = list_next_entry(ctl1, list); 1111 KUNIT_EXPECT_NOT_NULL(test, ctl1); 1112 KUNIT_EXPECT_NOT_NULL(test, ctl2); 1113 KUNIT_EXPECT_EQ(test, ctl1->alg_region.alg, ctl2->alg_region.alg); 1114 KUNIT_EXPECT_NE(test, ctl1->alg_region.type, ctl2->alg_region.type); 1115 KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset); 1116 KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type); 1117 KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags); 1118 KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len); 1119 KUNIT_EXPECT_STREQ(test, ctl1->fw_name, ctl2->fw_name); 1120 KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len); 1121 if (ctl1->subname_len) 1122 KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len); 1123 } 1124 1125 /* Controls are unique if they are in different firmware */ 1126 static void cs_dsp_ctl_fw_uniqueness(struct kunit *test) 1127 { 1128 struct cs_dsp_test *priv = test->priv; 1129 struct cs_dsp_test_local *local = priv->local; 1130 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1131 struct cs_dsp_coeff_ctl *ctl1, *ctl2; 1132 struct cs_dsp_mock_wmfw_builder *builder2; 1133 struct firmware *wmfw; 1134 1135 /* Create a second mock wmfw builder */ 1136 builder2 = cs_dsp_mock_wmfw_init(priv, 1137 cs_dsp_mock_wmfw_format_version(local->wmfw_builder)); 1138 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder2); 1139 cs_dsp_mock_wmfw_add_data_block(builder2, 1140 WMFW_ADSP2_XM, 0, 1141 local->xm_header->blob_data, 1142 local->xm_header->blob_size_bytes); 1143 1144 /* Load a 'misc' firmware with a control */ 1145 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1146 cs_dsp_ctl_parse_test_algs[0].id, 1147 "dummyalg", NULL); 1148 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1149 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1150 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1151 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1152 cs_dsp_power_down(priv->dsp); 1153 1154 /* Load a 'mbc/vss' firmware with the same control */ 1155 cs_dsp_mock_wmfw_start_alg_info_block(builder2, 1156 cs_dsp_ctl_parse_test_algs[0].id, 1157 "dummyalg", NULL); 1158 cs_dsp_mock_wmfw_add_coeff_desc(builder2, &def); 1159 cs_dsp_mock_wmfw_end_alg_info_block(builder2); 1160 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 1161 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw2", 1162 NULL, NULL, "mbc/vss"), 0); 1163 cs_dsp_power_down(priv->dsp); 1164 1165 /* Both controls should be in the list */ 1166 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 2); 1167 ctl1 = list_first_entry_or_null(&priv->dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1168 ctl2 = list_next_entry(ctl1, list); 1169 KUNIT_EXPECT_NOT_NULL(test, ctl1); 1170 KUNIT_EXPECT_NOT_NULL(test, ctl2); 1171 KUNIT_EXPECT_EQ(test, ctl1->alg_region.alg, ctl2->alg_region.alg); 1172 KUNIT_EXPECT_EQ(test, ctl1->alg_region.type, ctl2->alg_region.type); 1173 KUNIT_EXPECT_EQ(test, ctl1->offset, ctl2->offset); 1174 KUNIT_EXPECT_EQ(test, ctl1->type, ctl2->type); 1175 KUNIT_EXPECT_EQ(test, ctl1->flags, ctl2->flags); 1176 KUNIT_EXPECT_EQ(test, ctl1->len, ctl2->len); 1177 KUNIT_EXPECT_STRNEQ(test, ctl1->fw_name, ctl2->fw_name); 1178 KUNIT_EXPECT_EQ(test, ctl1->subname_len, ctl2->subname_len); 1179 if (ctl1->subname_len) 1180 KUNIT_EXPECT_MEMEQ(test, ctl1->subname, ctl2->subname, ctl1->subname_len); 1181 } 1182 1183 /* 1184 * Controls from a wmfw are only added to the list once. If the same 1185 * wmfw is reloaded the controls are not added again. 1186 * This creates multiple algorithms with one control each, which will 1187 * work on both V1 format and >=V2 format controls. 1188 */ 1189 static void cs_dsp_ctl_squash_reloaded_controls(struct kunit *test) 1190 { 1191 struct cs_dsp_test *priv = test->priv; 1192 struct cs_dsp_test_local *local = priv->local; 1193 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1194 struct cs_dsp_coeff_ctl *ctls[ARRAY_SIZE(cs_dsp_ctl_parse_test_algs)]; 1195 struct cs_dsp_coeff_ctl *walkctl; 1196 struct firmware *wmfw; 1197 int i; 1198 1199 /* Create some algorithms with a control */ 1200 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_parse_test_algs); i++) { 1201 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1202 cs_dsp_ctl_parse_test_algs[i].id, 1203 "dummyalg", NULL); 1204 def.mem_type = WMFW_ADSP2_YM; 1205 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1206 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1207 } 1208 1209 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1210 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1211 cs_dsp_power_down(priv->dsp); 1212 1213 /* All controls should be in the list */ 1214 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 1215 ARRAY_SIZE(cs_dsp_ctl_parse_test_algs)); 1216 1217 /* Take a copy of the pointers to controls to compare against. */ 1218 i = 0; 1219 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) { 1220 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls)); 1221 ctls[i++] = walkctl; 1222 } 1223 1224 1225 /* Load the wmfw again */ 1226 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1227 cs_dsp_power_down(priv->dsp); 1228 1229 /* The number of controls should be the same */ 1230 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 1231 ARRAY_SIZE(cs_dsp_ctl_parse_test_algs)); 1232 1233 /* And they should be the same objects */ 1234 i = 0; 1235 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) { 1236 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls)); 1237 KUNIT_ASSERT_PTR_EQ(test, walkctl, ctls[i++]); 1238 } 1239 } 1240 1241 /* 1242 * Controls from a wmfw are only added to the list once. If the same 1243 * wmfw is reloaded the controls are not added again. 1244 * This tests >=V2 firmware that can have multiple named controls in 1245 * the same algorithm. 1246 */ 1247 static void cs_dsp_ctl_v2_squash_reloaded_controls(struct kunit *test) 1248 { 1249 struct cs_dsp_test *priv = test->priv; 1250 struct cs_dsp_test_local *local = priv->local; 1251 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1252 struct cs_dsp_coeff_ctl *ctls[ARRAY_SIZE(cs_dsp_get_ctl_test_names)]; 1253 struct cs_dsp_coeff_ctl *walkctl; 1254 struct firmware *wmfw; 1255 int i; 1256 1257 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1258 cs_dsp_ctl_parse_test_algs[0].id, 1259 "dummyalg", NULL); 1260 1261 /* Create some controls */ 1262 for (i = 0; i < ARRAY_SIZE(cs_dsp_get_ctl_test_names); i++) { 1263 def.shortname = cs_dsp_get_ctl_test_names[i]; 1264 def.offset_dsp_words = i; 1265 if (i & BIT(0)) 1266 def.mem_type = WMFW_ADSP2_XM; 1267 else 1268 def.mem_type = WMFW_ADSP2_YM; 1269 1270 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1271 } 1272 1273 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1274 1275 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1276 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1277 cs_dsp_power_down(priv->dsp); 1278 1279 /* All controls should be in the list */ 1280 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 1281 ARRAY_SIZE(cs_dsp_get_ctl_test_names)); 1282 1283 /* Take a copy of the pointers to controls to compare against. */ 1284 i = 0; 1285 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) { 1286 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls)); 1287 ctls[i++] = walkctl; 1288 } 1289 1290 1291 /* Load the wmfw again */ 1292 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1293 cs_dsp_power_down(priv->dsp); 1294 1295 /* The number of controls should be the same */ 1296 KUNIT_EXPECT_EQ(test, list_count_nodes(&priv->dsp->ctl_list), 1297 ARRAY_SIZE(cs_dsp_get_ctl_test_names)); 1298 1299 /* And they should be the same objects */ 1300 i = 0; 1301 list_for_each_entry(walkctl, &priv->dsp->ctl_list, list) { 1302 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(ctls)); 1303 KUNIT_ASSERT_PTR_EQ(test, walkctl, ctls[i++]); 1304 } 1305 } 1306 1307 static const char * const cs_dsp_ctl_v2_compare_len_names[] = { 1308 "LEFT", 1309 "LEFT_", 1310 "LEFT_SPK", 1311 "LEFT_SPK_V", 1312 "LEFT_SPK_VOL", 1313 "LEFT_SPK_MUTE", 1314 "LEFT_SPK_1", 1315 "LEFT_X", 1316 "LEFT2", 1317 }; 1318 1319 /* 1320 * When comparing shortnames the full length of both strings is 1321 * considered, not only the characters in of the shortest string. 1322 * So that "LEFT" is not the same as "LEFT2". 1323 * This is specifically to test for the bug that was fixed by commit: 1324 * 7ac1102b227b ("firmware: cs_dsp: Fix new control name check") 1325 */ 1326 static void cs_dsp_ctl_v2_compare_len(struct kunit *test) 1327 { 1328 struct cs_dsp_test *priv = test->priv; 1329 struct cs_dsp_test_local *local = priv->local; 1330 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1331 struct cs_dsp_coeff_ctl *ctl; 1332 struct firmware *wmfw; 1333 int i; 1334 1335 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1336 cs_dsp_ctl_parse_test_algs[0].id, 1337 "dummyalg", NULL); 1338 1339 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_v2_compare_len_names); i++) { 1340 def.shortname = cs_dsp_ctl_v2_compare_len_names[i]; 1341 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1342 } 1343 1344 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1345 1346 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1347 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(priv->dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1348 1349 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_v2_compare_len_names); i++) { 1350 mutex_lock(&priv->dsp->pwr_lock); 1351 ctl = cs_dsp_get_ctl(priv->dsp, cs_dsp_ctl_v2_compare_len_names[i], 1352 def.mem_type, cs_dsp_ctl_parse_test_algs[0].id); 1353 mutex_unlock(&priv->dsp->pwr_lock); 1354 KUNIT_ASSERT_NOT_NULL(test, ctl); 1355 KUNIT_EXPECT_EQ(test, ctl->subname_len, 1356 strlen(cs_dsp_ctl_v2_compare_len_names[i])); 1357 KUNIT_EXPECT_MEMEQ(test, ctl->subname, cs_dsp_ctl_v2_compare_len_names[i], 1358 ctl->subname_len); 1359 } 1360 } 1361 1362 static int cs_dsp_ctl_parse_test_common_init(struct kunit *test, struct cs_dsp *dsp, 1363 int wmfw_version) 1364 { 1365 struct cs_dsp_test *priv; 1366 struct cs_dsp_test_local *local; 1367 struct device *test_dev; 1368 int ret; 1369 1370 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 1371 if (!priv) 1372 return -ENOMEM; 1373 1374 local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL); 1375 if (!local) 1376 return -ENOMEM; 1377 1378 priv->test = test; 1379 priv->dsp = dsp; 1380 test->priv = priv; 1381 priv->local = local; 1382 priv->local->wmfw_version = wmfw_version; 1383 1384 /* Create dummy struct device */ 1385 test_dev = kunit_device_register(test, "cs_dsp_test_drv"); 1386 if (IS_ERR(test_dev)) 1387 return PTR_ERR(test_dev); 1388 1389 dsp->dev = get_device(test_dev); 1390 if (!dsp->dev) 1391 return -ENODEV; 1392 1393 ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev); 1394 if (ret) 1395 return ret; 1396 1397 dev_set_drvdata(dsp->dev, priv); 1398 1399 /* Allocate regmap */ 1400 ret = cs_dsp_mock_regmap_init(priv); 1401 if (ret) 1402 return ret; 1403 1404 /* 1405 * There must always be a XM header with at least 1 algorithm, so create 1406 * a dummy one that tests can use and extract it to a data blob. 1407 */ 1408 local->xm_header = cs_dsp_create_mock_xm_header(priv, 1409 cs_dsp_ctl_parse_test_algs, 1410 ARRAY_SIZE(cs_dsp_ctl_parse_test_algs)); 1411 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header); 1412 1413 local->wmfw_builder = cs_dsp_mock_wmfw_init(priv, priv->local->wmfw_version); 1414 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->wmfw_builder); 1415 1416 /* Add dummy XM header blob to wmfw */ 1417 cs_dsp_mock_wmfw_add_data_block(local->wmfw_builder, 1418 WMFW_ADSP2_XM, 0, 1419 local->xm_header->blob_data, 1420 local->xm_header->blob_size_bytes); 1421 1422 /* Init cs_dsp */ 1423 dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL); 1424 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops); 1425 1426 switch (dsp->type) { 1427 case WMFW_ADSP2: 1428 ret = cs_dsp_adsp2_init(dsp); 1429 break; 1430 case WMFW_HALO: 1431 ret = cs_dsp_halo_init(dsp); 1432 break; 1433 default: 1434 KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type); 1435 return -EINVAL; 1436 } 1437 1438 if (ret) 1439 return ret; 1440 1441 /* Automatically call cs_dsp_remove() when test case ends */ 1442 return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp); 1443 } 1444 1445 static int cs_dsp_ctl_parse_test_halo_init(struct kunit *test) 1446 { 1447 struct cs_dsp *dsp; 1448 1449 /* Fill in cs_dsp and initialize */ 1450 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); 1451 if (!dsp) 1452 return -ENOMEM; 1453 1454 dsp->num = 1; 1455 dsp->type = WMFW_HALO; 1456 dsp->mem = cs_dsp_mock_halo_dsp1_regions; 1457 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes); 1458 dsp->base = cs_dsp_mock_halo_core_base; 1459 dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base; 1460 1461 return cs_dsp_ctl_parse_test_common_init(test, dsp, 3); 1462 } 1463 1464 static int cs_dsp_ctl_parse_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver) 1465 { 1466 struct cs_dsp *dsp; 1467 1468 /* Fill in cs_dsp and initialize */ 1469 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); 1470 if (!dsp) 1471 return -ENOMEM; 1472 1473 dsp->num = 1; 1474 dsp->type = WMFW_ADSP2; 1475 dsp->rev = 1; 1476 dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions; 1477 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes); 1478 dsp->base = cs_dsp_mock_adsp2_32bit_sysbase; 1479 1480 return cs_dsp_ctl_parse_test_common_init(test, dsp, wmfw_ver); 1481 } 1482 1483 static int cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1_init(struct kunit *test) 1484 { 1485 return cs_dsp_ctl_parse_test_adsp2_32bit_init(test, 1); 1486 } 1487 1488 static int cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2_init(struct kunit *test) 1489 { 1490 return cs_dsp_ctl_parse_test_adsp2_32bit_init(test, 2); 1491 } 1492 1493 static int cs_dsp_ctl_parse_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver) 1494 { 1495 struct cs_dsp *dsp; 1496 1497 /* Fill in cs_dsp and initialize */ 1498 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); 1499 if (!dsp) 1500 return -ENOMEM; 1501 1502 dsp->num = 1; 1503 dsp->type = WMFW_ADSP2; 1504 dsp->rev = 0; 1505 dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions; 1506 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes); 1507 dsp->base = cs_dsp_mock_adsp2_16bit_sysbase; 1508 1509 return cs_dsp_ctl_parse_test_common_init(test, dsp, wmfw_ver); 1510 } 1511 1512 static int cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1_init(struct kunit *test) 1513 { 1514 return cs_dsp_ctl_parse_test_adsp2_16bit_init(test, 1); 1515 } 1516 1517 static int cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2_init(struct kunit *test) 1518 { 1519 return cs_dsp_ctl_parse_test_adsp2_16bit_init(test, 2); 1520 } 1521 1522 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_mem_type_param_cases[] = { 1523 { .mem_type = WMFW_ADSP2_XM }, 1524 { .mem_type = WMFW_ADSP2_YM }, 1525 { .mem_type = WMFW_ADSP2_ZM }, 1526 }; 1527 1528 static void cs_dsp_ctl_mem_type_desc(const struct cs_dsp_ctl_parse_test_param *param, 1529 char *desc) 1530 { 1531 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s", 1532 cs_dsp_mem_region_name(param->mem_type)); 1533 } 1534 1535 KUNIT_ARRAY_PARAM(cs_dsp_ctl_mem_type, 1536 cs_dsp_ctl_mem_type_param_cases, 1537 cs_dsp_ctl_mem_type_desc); 1538 1539 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_alg_id_param_cases[] = { 1540 { .alg_id = 0xb }, 1541 { .alg_id = 0xfafa }, 1542 { .alg_id = 0x9f1234 }, 1543 { .alg_id = 0xff00ff }, 1544 }; 1545 1546 static void cs_dsp_ctl_alg_id_desc(const struct cs_dsp_ctl_parse_test_param *param, 1547 char *desc) 1548 { 1549 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg_id:%#x", param->alg_id); 1550 } 1551 1552 KUNIT_ARRAY_PARAM(cs_dsp_ctl_alg_id, 1553 cs_dsp_ctl_alg_id_param_cases, 1554 cs_dsp_ctl_alg_id_desc); 1555 1556 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_offset_param_cases[] = { 1557 { .offset = 0x0 }, 1558 { .offset = 0x1 }, 1559 { .offset = 0x2 }, 1560 { .offset = 0x3 }, 1561 { .offset = 0x4 }, 1562 { .offset = 0x5 }, 1563 { .offset = 0x6 }, 1564 { .offset = 0x7 }, 1565 { .offset = 0xe0 }, 1566 { .offset = 0xf1 }, 1567 { .offset = 0xfffe }, 1568 { .offset = 0xffff }, 1569 }; 1570 1571 static void cs_dsp_ctl_offset_desc(const struct cs_dsp_ctl_parse_test_param *param, 1572 char *desc) 1573 { 1574 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "offset:%#x", param->offset); 1575 } 1576 1577 KUNIT_ARRAY_PARAM(cs_dsp_ctl_offset, 1578 cs_dsp_ctl_offset_param_cases, 1579 cs_dsp_ctl_offset_desc); 1580 1581 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_length_param_cases[] = { 1582 { .length = 0x4 }, 1583 { .length = 0x8 }, 1584 { .length = 0x18 }, 1585 { .length = 0xf000 }, 1586 }; 1587 1588 static void cs_dsp_ctl_length_desc(const struct cs_dsp_ctl_parse_test_param *param, 1589 char *desc) 1590 { 1591 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "length:%#x", param->length); 1592 } 1593 1594 KUNIT_ARRAY_PARAM(cs_dsp_ctl_length, 1595 cs_dsp_ctl_length_param_cases, 1596 cs_dsp_ctl_length_desc); 1597 1598 /* Note: some control types mandate specific flags settings */ 1599 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_type_param_cases[] = { 1600 { .ctl_type = WMFW_CTL_TYPE_BYTES, 1601 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1602 { .ctl_type = WMFW_CTL_TYPE_ACKED, 1603 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1604 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1605 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE | 1606 WMFW_CTL_FLAG_SYS }, 1607 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1608 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_SYS }, 1609 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1610 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE | 1611 WMFW_CTL_FLAG_SYS }, 1612 }; 1613 1614 static void cs_dsp_ctl_type_flags_desc(const struct cs_dsp_ctl_parse_test_param *param, 1615 char *desc) 1616 { 1617 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "ctl_type:%#x flags:%#x", 1618 param->ctl_type, param->flags); 1619 } 1620 1621 KUNIT_ARRAY_PARAM(cs_dsp_ctl_type, 1622 cs_dsp_ctl_type_param_cases, 1623 cs_dsp_ctl_type_flags_desc); 1624 1625 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_flags_param_cases[] = { 1626 { .flags = 0 }, 1627 { .flags = WMFW_CTL_FLAG_READABLE }, 1628 { .flags = WMFW_CTL_FLAG_WRITEABLE }, 1629 { .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1630 { .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1631 { .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1632 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE }, 1633 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE }, 1634 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1635 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1636 { .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | 1637 WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1638 }; 1639 1640 static void cs_dsp_ctl_flags_desc(const struct cs_dsp_ctl_parse_test_param *param, 1641 char *desc) 1642 { 1643 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "flags:%#x", param->flags); 1644 } 1645 1646 KUNIT_ARRAY_PARAM(cs_dsp_ctl_flags, 1647 cs_dsp_ctl_flags_param_cases, 1648 cs_dsp_ctl_flags_desc); 1649 1650 static const struct cs_dsp_ctl_parse_test_param cs_dsp_ctl_illegal_type_flags_param_cases[] = { 1651 /* ACKED control must be volatile + read + write */ 1652 { .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = 0 }, 1653 { .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_READABLE }, 1654 { .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_WRITEABLE }, 1655 { .ctl_type = WMFW_CTL_TYPE_ACKED, .flags = WMFW_CTL_FLAG_VOLATILE }, 1656 { .ctl_type = WMFW_CTL_TYPE_ACKED, 1657 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1658 { .ctl_type = WMFW_CTL_TYPE_ACKED, 1659 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE }, 1660 1661 /* HOSTEVENT must be system + volatile + read + write */ 1662 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = 0 }, 1663 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_READABLE }, 1664 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_WRITEABLE }, 1665 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1666 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1667 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_VOLATILE }, 1668 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1669 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1670 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1671 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE }, 1672 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1673 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1674 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, .flags = WMFW_CTL_FLAG_SYS }, 1675 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1676 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE }, 1677 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1678 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE }, 1679 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1680 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE }, 1681 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1682 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1683 { .ctl_type = WMFW_CTL_TYPE_HOSTEVENT, 1684 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE }, 1685 1686 /* FWEVENT rules same as HOSTEVENT */ 1687 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = 0 }, 1688 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_READABLE }, 1689 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_WRITEABLE }, 1690 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1691 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1692 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_VOLATILE }, 1693 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1694 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1695 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1696 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE }, 1697 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1698 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1699 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, .flags = WMFW_CTL_FLAG_SYS }, 1700 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1701 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE }, 1702 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1703 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE }, 1704 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1705 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE }, 1706 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1707 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1708 { .ctl_type = WMFW_CTL_TYPE_FWEVENT, 1709 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE }, 1710 1711 /* 1712 * HOSTBUFFER must be system + volatile + readable or 1713 * system + volatile + readable + writeable 1714 */ 1715 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = 0 }, 1716 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_READABLE }, 1717 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_WRITEABLE }, 1718 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1719 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE}, 1720 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_VOLATILE }, 1721 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1722 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE }, 1723 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1724 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE }, 1725 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1726 .flags = WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1727 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, .flags = WMFW_CTL_FLAG_SYS }, 1728 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1729 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE }, 1730 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1731 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE }, 1732 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1733 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE }, 1734 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1735 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE }, 1736 { .ctl_type = WMFW_CTL_TYPE_HOST_BUFFER, 1737 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_VOLATILE | WMFW_CTL_FLAG_WRITEABLE }, 1738 }; 1739 1740 KUNIT_ARRAY_PARAM(cs_dsp_ctl_illegal_type_flags, 1741 cs_dsp_ctl_illegal_type_flags_param_cases, 1742 cs_dsp_ctl_type_flags_desc); 1743 1744 static struct kunit_case cs_dsp_ctl_parse_test_cases_v1[] = { 1745 KUNIT_CASE(cs_dsp_ctl_parse_no_coeffs), 1746 KUNIT_CASE(cs_dsp_ctl_parse_v1_name), 1747 KUNIT_CASE(cs_dsp_ctl_parse_empty_v1_name), 1748 KUNIT_CASE(cs_dsp_ctl_parse_max_v1_name), 1749 1750 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_memory_type, cs_dsp_ctl_mem_type_gen_params), 1751 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_id, cs_dsp_ctl_alg_id_gen_params), 1752 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_mem, cs_dsp_ctl_mem_type_gen_params), 1753 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_offset, cs_dsp_ctl_offset_gen_params), 1754 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_length, cs_dsp_ctl_length_gen_params), 1755 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_ctl_type, cs_dsp_ctl_type_gen_params), 1756 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_flags, cs_dsp_ctl_flags_gen_params), 1757 KUNIT_CASE(cs_dsp_ctl_parse_fw_name), 1758 1759 KUNIT_CASE(cs_dsp_ctl_alg_id_uniqueness), 1760 KUNIT_CASE(cs_dsp_ctl_mem_uniqueness), 1761 KUNIT_CASE(cs_dsp_ctl_fw_uniqueness), 1762 KUNIT_CASE(cs_dsp_ctl_squash_reloaded_controls), 1763 1764 { } /* terminator */ 1765 }; 1766 1767 static struct kunit_case cs_dsp_ctl_parse_test_cases_v2_v3[] = { 1768 KUNIT_CASE(cs_dsp_ctl_parse_no_coeffs), 1769 KUNIT_CASE(cs_dsp_ctl_parse_short_name), 1770 KUNIT_CASE(cs_dsp_ctl_parse_min_short_name), 1771 KUNIT_CASE(cs_dsp_ctl_parse_max_short_name), 1772 KUNIT_CASE(cs_dsp_ctl_parse_with_min_fullname), 1773 KUNIT_CASE(cs_dsp_ctl_parse_with_max_fullname), 1774 KUNIT_CASE(cs_dsp_ctl_parse_with_min_description), 1775 KUNIT_CASE(cs_dsp_ctl_parse_with_max_description), 1776 KUNIT_CASE(cs_dsp_ctl_parse_with_max_fullname_and_description), 1777 KUNIT_CASE(cs_dsp_ctl_shortname_alignment), 1778 KUNIT_CASE(cs_dsp_ctl_fullname_alignment), 1779 KUNIT_CASE(cs_dsp_ctl_description_alignment), 1780 KUNIT_CASE(cs_dsp_get_ctl_test), 1781 KUNIT_CASE(cs_dsp_get_ctl_test_multiple_wmfw), 1782 1783 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_memory_type, cs_dsp_ctl_mem_type_gen_params), 1784 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_id, cs_dsp_ctl_alg_id_gen_params), 1785 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_alg_mem, cs_dsp_ctl_mem_type_gen_params), 1786 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_offset, cs_dsp_ctl_offset_gen_params), 1787 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_length, cs_dsp_ctl_length_gen_params), 1788 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_ctl_type, cs_dsp_ctl_type_gen_params), 1789 KUNIT_CASE_PARAM(cs_dsp_ctl_parse_flags, cs_dsp_ctl_flags_gen_params), 1790 KUNIT_CASE_PARAM(cs_dsp_ctl_illegal_type_flags, 1791 cs_dsp_ctl_illegal_type_flags_gen_params), 1792 KUNIT_CASE(cs_dsp_ctl_parse_fw_name), 1793 1794 KUNIT_CASE(cs_dsp_ctl_alg_id_uniqueness), 1795 KUNIT_CASE(cs_dsp_ctl_mem_uniqueness), 1796 KUNIT_CASE(cs_dsp_ctl_fw_uniqueness), 1797 KUNIT_CASE(cs_dsp_ctl_squash_reloaded_controls), 1798 KUNIT_CASE(cs_dsp_ctl_v2_squash_reloaded_controls), 1799 KUNIT_CASE(cs_dsp_ctl_v2_compare_len), 1800 1801 { } /* terminator */ 1802 }; 1803 1804 static struct kunit_suite cs_dsp_ctl_parse_test_halo = { 1805 .name = "cs_dsp_ctl_parse_wmfwV3_halo", 1806 .init = cs_dsp_ctl_parse_test_halo_init, 1807 .test_cases = cs_dsp_ctl_parse_test_cases_v2_v3, 1808 }; 1809 1810 static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1 = { 1811 .name = "cs_dsp_ctl_parse_wmfwV1_adsp2_32bit", 1812 .init = cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1_init, 1813 .test_cases = cs_dsp_ctl_parse_test_cases_v1, 1814 }; 1815 1816 static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2 = { 1817 .name = "cs_dsp_ctl_parse_wmfwV2_adsp2_32bit", 1818 .init = cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2_init, 1819 .test_cases = cs_dsp_ctl_parse_test_cases_v2_v3, 1820 }; 1821 1822 static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1 = { 1823 .name = "cs_dsp_ctl_parse_wmfwV1_adsp2_16bit", 1824 .init = cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1_init, 1825 .test_cases = cs_dsp_ctl_parse_test_cases_v1, 1826 }; 1827 1828 static struct kunit_suite cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2 = { 1829 .name = "cs_dsp_ctl_parse_wmfwV2_adsp2_16bit", 1830 .init = cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2_init, 1831 .test_cases = cs_dsp_ctl_parse_test_cases_v2_v3, 1832 }; 1833 1834 kunit_test_suites(&cs_dsp_ctl_parse_test_halo, 1835 &cs_dsp_ctl_parse_test_adsp2_32bit_wmfw1, 1836 &cs_dsp_ctl_parse_test_adsp2_32bit_wmfw2, 1837 &cs_dsp_ctl_parse_test_adsp2_16bit_wmfw1, 1838 &cs_dsp_ctl_parse_test_adsp2_16bit_wmfw2); 1839