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