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/random.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_stop_wrapper, cs_dsp_stop, struct cs_dsp *); 21 KUNIT_DEFINE_ACTION_WRAPPER(_cs_dsp_remove_wrapper, cs_dsp_remove, struct cs_dsp *); 22 23 struct cs_dsp_test_local { 24 struct cs_dsp_mock_xm_header *xm_header; 25 struct cs_dsp_mock_wmfw_builder *wmfw_builder; 26 int wmfw_version; 27 }; 28 29 struct cs_dsp_ctl_cache_test_param { 30 int mem_type; 31 int alg_id; 32 unsigned int offs_words; 33 unsigned int len_bytes; 34 u16 ctl_type; 35 u16 flags; 36 }; 37 38 static const struct cs_dsp_mock_alg_def cs_dsp_ctl_cache_test_algs[] = { 39 { 40 .id = 0xfafa, 41 .ver = 0x100000, 42 .xm_base_words = 60, 43 .xm_size_words = 1000, 44 .ym_base_words = 0, 45 .ym_size_words = 1000, 46 .zm_base_words = 0, 47 .zm_size_words = 1000, 48 }, 49 { 50 .id = 0xb, 51 .ver = 0x100001, 52 .xm_base_words = 1060, 53 .xm_size_words = 1000, 54 .ym_base_words = 1000, 55 .ym_size_words = 1000, 56 .zm_base_words = 1000, 57 .zm_size_words = 1000, 58 }, 59 { 60 .id = 0x9f1234, 61 .ver = 0x100500, 62 .xm_base_words = 2060, 63 .xm_size_words = 32, 64 .ym_base_words = 2000, 65 .ym_size_words = 32, 66 .zm_base_words = 2000, 67 .zm_size_words = 32, 68 }, 69 { 70 .id = 0xff00ff, 71 .ver = 0x300113, 72 .xm_base_words = 2100, 73 .xm_size_words = 32, 74 .ym_base_words = 2032, 75 .ym_size_words = 32, 76 .zm_base_words = 2032, 77 .zm_size_words = 32, 78 }, 79 }; 80 81 static const struct cs_dsp_mock_coeff_def mock_coeff_template = { 82 .shortname = "Dummy Coeff", 83 .type = WMFW_CTL_TYPE_BYTES, 84 .mem_type = WMFW_ADSP2_YM, 85 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE, 86 .length_bytes = 4, 87 }; 88 89 static const char * const cs_dsp_ctl_cache_test_fw_names[] = { 90 "misc", "mbc/vss", "haps", 91 }; 92 93 static int _find_alg_entry(struct kunit *test, unsigned int alg_id) 94 { 95 int i; 96 97 for (i = 0; i < ARRAY_SIZE(cs_dsp_ctl_cache_test_algs); ++i) { 98 if (cs_dsp_ctl_cache_test_algs[i].id == alg_id) 99 break; 100 } 101 102 KUNIT_ASSERT_LT(test, i, ARRAY_SIZE(cs_dsp_ctl_cache_test_algs)); 103 104 return i; 105 } 106 107 static int _get_alg_mem_base_words(struct kunit *test, int alg_index, int mem_type) 108 { 109 switch (mem_type) { 110 case WMFW_ADSP2_XM: 111 return cs_dsp_ctl_cache_test_algs[alg_index].xm_base_words; 112 case WMFW_ADSP2_YM: 113 return cs_dsp_ctl_cache_test_algs[alg_index].ym_base_words; 114 case WMFW_ADSP2_ZM: 115 return cs_dsp_ctl_cache_test_algs[alg_index].zm_base_words; 116 default: 117 KUNIT_FAIL(test, "Bug in test: illegal memory type %d\n", mem_type); 118 return 0; 119 } 120 } 121 122 static struct cs_dsp_mock_wmfw_builder *_create_dummy_wmfw(struct kunit *test) 123 { 124 struct cs_dsp_test *priv = test->priv; 125 struct cs_dsp_test_local *local = priv->local; 126 struct cs_dsp_mock_wmfw_builder *builder; 127 128 builder = cs_dsp_mock_wmfw_init(priv, local->wmfw_version); 129 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder); 130 131 /* Init an XM header */ 132 cs_dsp_mock_wmfw_add_data_block(builder, 133 WMFW_ADSP2_XM, 0, 134 local->xm_header->blob_data, 135 local->xm_header->blob_size_bytes); 136 137 return builder; 138 } 139 140 /* 141 * Memory allocated for control cache must be large enough. 142 * This creates multiple controls of different sizes so only works on 143 * wmfw V2 and later. 144 */ 145 static void cs_dsp_ctl_v2_cache_alloc(struct kunit *test) 146 { 147 struct cs_dsp_test *priv = test->priv; 148 struct cs_dsp_test_local *local = priv->local; 149 struct cs_dsp *dsp = priv->dsp; 150 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 151 unsigned int reg, alg_base_words, alg_size_bytes; 152 struct cs_dsp_coeff_ctl *ctl; 153 struct firmware *wmfw; 154 char ctl_name[4]; 155 u32 *reg_vals; 156 int num_ctls; 157 158 /* Create some DSP data to initialize the control cache */ 159 alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_YM); 160 alg_size_bytes = cs_dsp_ctl_cache_test_algs[0].ym_size_words * 161 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 162 reg_vals = kunit_kzalloc(test, alg_size_bytes, GFP_KERNEL); 163 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 164 reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM); 165 reg += alg_base_words * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 166 regmap_raw_write(dsp->regmap, reg, reg_vals, alg_size_bytes); 167 168 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 169 cs_dsp_ctl_cache_test_algs[0].id, 170 "dummyalg", NULL); 171 172 /* Create controls of different sizes */ 173 def.mem_type = WMFW_ADSP2_YM; 174 def.shortname = ctl_name; 175 num_ctls = 0; 176 for (def.length_bytes = 4; def.length_bytes <= 64; def.length_bytes += 4) { 177 snprintf(ctl_name, ARRAY_SIZE(ctl_name), "%x", def.length_bytes); 178 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 179 num_ctls++; 180 def.offset_dsp_words += def.length_bytes / sizeof(u32); 181 } 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(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 186 187 KUNIT_EXPECT_EQ(test, list_count_nodes(&dsp->ctl_list), num_ctls); 188 189 /* Check that the block allocated for the cache is large enough */ 190 list_for_each_entry(ctl, &dsp->ctl_list, list) 191 KUNIT_EXPECT_GE(test, ksize(ctl->cache), ctl->len); 192 } 193 194 /* 195 * Content of registers backing a control should be read into the 196 * control cache when the firmware is downloaded. 197 */ 198 static void cs_dsp_ctl_cache_init(struct kunit *test) 199 { 200 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 201 struct cs_dsp_test *priv = test->priv; 202 struct cs_dsp_test_local *local = priv->local; 203 struct cs_dsp *dsp = priv->dsp; 204 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 205 int alg_idx = _find_alg_entry(test, param->alg_id); 206 unsigned int reg, alg_base_words; 207 struct cs_dsp_coeff_ctl *ctl; 208 struct firmware *wmfw; 209 u32 *reg_vals, *readback; 210 211 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 212 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 213 214 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 215 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 216 217 /* Create some DSP data to be read into the control cache */ 218 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 219 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 220 reg += (alg_base_words + param->offs_words) * 221 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 222 get_random_bytes(reg_vals, param->len_bytes); 223 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 224 225 /* Create control pointing to this data */ 226 def.flags = param->flags; 227 def.mem_type = param->mem_type; 228 def.offset_dsp_words = param->offs_words; 229 def.length_bytes = param->len_bytes; 230 231 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 232 cs_dsp_ctl_cache_test_algs[alg_idx].id, 233 "dummyalg", NULL); 234 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 235 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 236 237 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 238 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 239 240 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 241 KUNIT_ASSERT_NOT_NULL(test, ctl); 242 243 /* 244 * The data should have been populated into the control cache 245 * so should be readable through the control. 246 */ 247 KUNIT_EXPECT_EQ(test, 248 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 249 0); 250 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 251 } 252 253 /* 254 * For a non-volatile write-only control the cache should be zero-filled 255 * when the firmware is downloaded. 256 */ 257 static void cs_dsp_ctl_cache_init_write_only(struct kunit *test) 258 { 259 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 260 struct cs_dsp_test *priv = test->priv; 261 struct cs_dsp_test_local *local = priv->local; 262 struct cs_dsp *dsp = priv->dsp; 263 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 264 int alg_idx = _find_alg_entry(test, param->alg_id); 265 struct cs_dsp_coeff_ctl *ctl; 266 struct firmware *wmfw; 267 u32 *readback, *zeros; 268 269 zeros = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 270 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, zeros); 271 272 readback = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 273 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 274 275 /* Create a non-volatile write-only control */ 276 def.flags = param->flags & ~WMFW_CTL_FLAG_VOLATILE; 277 def.mem_type = param->mem_type; 278 def.offset_dsp_words = param->offs_words; 279 def.length_bytes = param->len_bytes; 280 281 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 282 cs_dsp_ctl_cache_test_algs[alg_idx].id, 283 "dummyalg", NULL); 284 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 285 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 286 287 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 288 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 289 290 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 291 KUNIT_ASSERT_NOT_NULL(test, ctl); 292 293 /* 294 * The control cache should have been zero-filled so should be 295 * readable through the control. 296 */ 297 get_random_bytes(readback, param->len_bytes); 298 KUNIT_EXPECT_EQ(test, 299 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 300 0); 301 KUNIT_EXPECT_MEMEQ(test, readback, zeros, param->len_bytes); 302 } 303 304 /* 305 * Multiple different firmware with identical controls. 306 * This is legal because different firmwares could contain the same 307 * algorithm. 308 * The control cache should be initialized only with the data from 309 * the firmware containing it. 310 */ 311 static void cs_dsp_ctl_cache_init_multiple_fw_same_controls(struct kunit *test) 312 { 313 struct cs_dsp_test *priv = test->priv; 314 struct cs_dsp *dsp = priv->dsp; 315 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 316 struct cs_dsp_mock_wmfw_builder *builder[3]; 317 unsigned int reg, alg_base_words; 318 struct cs_dsp_coeff_ctl *walkctl, *ctl[3]; 319 struct firmware *wmfw; 320 u32 *reg_vals[3], *readback; 321 int i; 322 323 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(builder)); 324 static_assert(ARRAY_SIZE(reg_vals) == ARRAY_SIZE(builder)); 325 static_assert(ARRAY_SIZE(cs_dsp_ctl_cache_test_fw_names) >= ARRAY_SIZE(builder)); 326 327 /* Create an identical control in each firmware but with different alg id */ 328 for (i = 0; i < ARRAY_SIZE(builder); i++) { 329 builder[i] = _create_dummy_wmfw(test); 330 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder[i]); 331 332 cs_dsp_mock_wmfw_start_alg_info_block(builder[i], 333 cs_dsp_ctl_cache_test_algs[0].id, 334 "dummyalg", NULL); 335 cs_dsp_mock_wmfw_add_coeff_desc(builder[i], &def); 336 cs_dsp_mock_wmfw_end_alg_info_block(builder[i]); 337 } 338 339 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 340 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL); 341 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]); 342 } 343 344 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL); 345 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 346 347 /* 348 * For each firmware create random content in the register backing 349 * the control. Then download, start, stop and power-down. 350 */ 351 for (i = 0; i < ARRAY_SIZE(builder); i++) { 352 alg_base_words = _get_alg_mem_base_words(test, 0, def.mem_type); 353 reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type); 354 reg += (alg_base_words + def.offset_dsp_words) * 355 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 356 357 get_random_bytes(reg_vals[i], def.length_bytes); 358 regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes); 359 wmfw = cs_dsp_mock_wmfw_get_firmware(builder[i]); 360 KUNIT_ASSERT_EQ(test, 361 cs_dsp_power_up(dsp, wmfw, 362 cs_dsp_ctl_cache_test_fw_names[i], 363 NULL, NULL, 364 cs_dsp_ctl_cache_test_fw_names[i]), 365 0); 366 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 367 cs_dsp_stop(dsp); 368 cs_dsp_power_down(dsp); 369 } 370 371 /* There should now be 3 controls */ 372 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3); 373 374 /* 375 * There's no requirement for the control list to be in any 376 * particular order, so don't assume the order. 377 */ 378 for (i = 0; i < ARRAY_SIZE(ctl); i++) 379 ctl[i] = NULL; 380 381 list_for_each_entry(walkctl, &dsp->ctl_list, list) { 382 if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[0]) == 0) 383 ctl[0] = walkctl; 384 else if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[1]) == 0) 385 ctl[1] = walkctl; 386 else if (strcmp(walkctl->fw_name, cs_dsp_ctl_cache_test_fw_names[2]) == 0) 387 ctl[2] = walkctl; 388 } 389 390 KUNIT_ASSERT_NOT_NULL(test, ctl[0]); 391 KUNIT_ASSERT_NOT_NULL(test, ctl[1]); 392 KUNIT_ASSERT_NOT_NULL(test, ctl[2]); 393 394 /* 395 * The data should have been populated into the control cache 396 * so should be readable through the control. 397 */ 398 KUNIT_EXPECT_EQ(test, 399 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes), 400 0); 401 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes); 402 403 KUNIT_EXPECT_EQ(test, 404 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes), 405 0); 406 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes); 407 408 KUNIT_EXPECT_EQ(test, 409 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, def.length_bytes), 410 0); 411 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes); 412 } 413 414 /* 415 * Multiple different firmware with controls identical except for alg id. 416 * This is legal because the controls are qualified by algorithm id. 417 * The control cache should be initialized only with the data from 418 * the firmware containing it. 419 */ 420 static void cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls(struct kunit *test) 421 { 422 struct cs_dsp_test *priv = test->priv; 423 struct cs_dsp *dsp = priv->dsp; 424 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 425 struct cs_dsp_mock_wmfw_builder *builder[3]; 426 unsigned int reg, alg_base_words; 427 struct cs_dsp_coeff_ctl *walkctl, *ctl[3]; 428 struct firmware *wmfw; 429 u32 *reg_vals[3], *readback; 430 int i; 431 432 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(builder)); 433 static_assert(ARRAY_SIZE(reg_vals) == ARRAY_SIZE(builder)); 434 static_assert(ARRAY_SIZE(cs_dsp_ctl_cache_test_fw_names) >= ARRAY_SIZE(builder)); 435 436 /* Create an identical control in each firmware but with different alg id */ 437 for (i = 0; i < ARRAY_SIZE(builder); i++) { 438 builder[i] = _create_dummy_wmfw(test); 439 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, builder[i]); 440 441 cs_dsp_mock_wmfw_start_alg_info_block(builder[i], 442 cs_dsp_ctl_cache_test_algs[i].id, 443 "dummyalg", NULL); 444 cs_dsp_mock_wmfw_add_coeff_desc(builder[i], &def); 445 cs_dsp_mock_wmfw_end_alg_info_block(builder[i]); 446 } 447 448 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 449 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL); 450 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]); 451 } 452 453 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL); 454 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 455 456 /* 457 * For each firmware create random content in the register backing 458 * the control. Then download, start, stop and power-down. 459 */ 460 for (i = 0; i < ARRAY_SIZE(builder); i++) { 461 alg_base_words = _get_alg_mem_base_words(test, i, def.mem_type); 462 reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type); 463 reg += (alg_base_words + def.offset_dsp_words) * 464 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 465 466 get_random_bytes(reg_vals[i], def.length_bytes); 467 regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes); 468 wmfw = cs_dsp_mock_wmfw_get_firmware(builder[i]); 469 KUNIT_ASSERT_EQ(test, 470 cs_dsp_power_up(dsp, wmfw, 471 cs_dsp_ctl_cache_test_fw_names[i], 472 NULL, NULL, 473 cs_dsp_ctl_cache_test_fw_names[i]), 474 0); 475 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 476 cs_dsp_stop(dsp); 477 cs_dsp_power_down(dsp); 478 } 479 480 /* There should now be 3 controls */ 481 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3); 482 483 /* 484 * There's no requirement for the control list to be in any 485 * particular order, so don't assume the order. 486 */ 487 for (i = 0; i < ARRAY_SIZE(ctl); i++) 488 ctl[i] = NULL; 489 490 list_for_each_entry(walkctl, &dsp->ctl_list, list) { 491 if (cs_dsp_ctl_cache_test_algs[0].id == walkctl->alg_region.alg) 492 ctl[0] = walkctl; 493 else if (cs_dsp_ctl_cache_test_algs[1].id == walkctl->alg_region.alg) 494 ctl[1] = walkctl; 495 else if (cs_dsp_ctl_cache_test_algs[2].id == walkctl->alg_region.alg) 496 ctl[2] = walkctl; 497 } 498 499 KUNIT_ASSERT_NOT_NULL(test, ctl[0]); 500 KUNIT_ASSERT_NOT_NULL(test, ctl[1]); 501 KUNIT_ASSERT_NOT_NULL(test, ctl[2]); 502 503 /* 504 * The data should have been populated into the control cache 505 * so should be readable through the control. 506 */ 507 KUNIT_EXPECT_EQ(test, 508 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes), 509 0); 510 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes); 511 512 KUNIT_EXPECT_EQ(test, 513 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes), 514 0); 515 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes); 516 517 KUNIT_EXPECT_EQ(test, 518 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, def.length_bytes), 519 0); 520 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes); 521 } 522 523 /* 524 * Firmware with controls at the same position in different memories. 525 * The control cache should be initialized with content from the 526 * correct memory region. 527 */ 528 static void cs_dsp_ctl_cache_init_multiple_mems(struct kunit *test) 529 { 530 struct cs_dsp_test *priv = test->priv; 531 struct cs_dsp *dsp = priv->dsp; 532 struct cs_dsp_test_local *local = priv->local; 533 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 534 unsigned int reg, alg_base_words; 535 struct cs_dsp_coeff_ctl *walkctl, *ctl[3]; 536 struct firmware *wmfw; 537 u32 *reg_vals[3], *readback; 538 int i; 539 540 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(reg_vals)); 541 542 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 543 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL); 544 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]); 545 get_random_bytes(reg_vals[i], def.length_bytes); 546 } 547 548 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL); 549 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 550 551 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 552 cs_dsp_ctl_cache_test_algs[0].id, 553 "dummyalg", NULL); 554 555 /* Create controls identical except for memory region */ 556 def.mem_type = WMFW_ADSP2_YM; 557 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 558 559 def.mem_type = WMFW_ADSP2_XM; 560 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 561 562 if (cs_dsp_mock_has_zm(priv)) { 563 def.mem_type = WMFW_ADSP2_ZM; 564 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 565 } 566 567 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 568 569 /* Create random content in the registers backing each control */ 570 alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_YM); 571 reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_YM); 572 reg += (alg_base_words + def.offset_dsp_words) * 573 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 574 regmap_raw_write(dsp->regmap, reg, reg_vals[0], def.length_bytes); 575 576 alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_XM); 577 reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_XM); 578 reg += (alg_base_words + def.offset_dsp_words) * 579 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 580 regmap_raw_write(dsp->regmap, reg, reg_vals[1], def.length_bytes); 581 582 if (cs_dsp_mock_has_zm(priv)) { 583 alg_base_words = _get_alg_mem_base_words(test, 0, WMFW_ADSP2_ZM); 584 reg = cs_dsp_mock_base_addr_for_mem(priv, WMFW_ADSP2_ZM); 585 reg += (alg_base_words + def.offset_dsp_words) * 586 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 587 regmap_raw_write(dsp->regmap, reg, reg_vals[2], def.length_bytes); 588 } 589 590 /* Download, run, stop and power-down the firmware */ 591 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); 592 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 593 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 594 cs_dsp_stop(dsp); 595 cs_dsp_power_down(dsp); 596 597 /* There should now be 2 or 3 controls */ 598 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 599 cs_dsp_mock_has_zm(priv) ? 3 : 2); 600 601 /* 602 * There's no requirement for the control list to be in any 603 * particular order, so don't assume the order. 604 */ 605 for (i = 0; i < ARRAY_SIZE(ctl); i++) 606 ctl[i] = NULL; 607 608 list_for_each_entry(walkctl, &dsp->ctl_list, list) { 609 if (walkctl->alg_region.type == WMFW_ADSP2_YM) 610 ctl[0] = walkctl; 611 if (walkctl->alg_region.type == WMFW_ADSP2_XM) 612 ctl[1] = walkctl; 613 if (walkctl->alg_region.type == WMFW_ADSP2_ZM) 614 ctl[2] = walkctl; 615 } 616 617 618 /* 619 * The data should have been populated into the control cache 620 * so should be readable through the control. 621 */ 622 KUNIT_ASSERT_NOT_NULL(test, ctl[0]); 623 KUNIT_EXPECT_EQ(test, 624 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes), 625 0); 626 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes); 627 628 KUNIT_ASSERT_NOT_NULL(test, ctl[1]); 629 KUNIT_EXPECT_EQ(test, 630 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes), 631 0); 632 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes); 633 634 if (cs_dsp_mock_has_zm(priv)) { 635 KUNIT_ASSERT_NOT_NULL(test, ctl[2]); 636 KUNIT_EXPECT_EQ(test, 637 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, 638 def.length_bytes), 639 0); 640 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes); 641 } 642 } 643 644 /* 645 * Firmware with controls at the same position in different algorithms 646 * The control cache should be initialized with content from the 647 * memory of the algorithm it points to. 648 */ 649 static void cs_dsp_ctl_cache_init_multiple_algs(struct kunit *test) 650 { 651 struct cs_dsp_test *priv = test->priv; 652 struct cs_dsp *dsp = priv->dsp; 653 struct cs_dsp_test_local *local = priv->local; 654 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 655 unsigned int reg, alg_base_words; 656 struct cs_dsp_coeff_ctl *walkctl, *ctl[3]; 657 struct firmware *wmfw; 658 u32 *reg_vals[3], *readback; 659 int i; 660 661 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(reg_vals)); 662 static_assert(ARRAY_SIZE(reg_vals) <= ARRAY_SIZE(cs_dsp_ctl_cache_test_algs)); 663 664 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 665 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL); 666 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]); 667 get_random_bytes(reg_vals[i], def.length_bytes); 668 } 669 670 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL); 671 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 672 673 /* Create controls identical except for algorithm */ 674 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 675 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 676 cs_dsp_ctl_cache_test_algs[i].id, 677 "dummyalg", NULL); 678 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 679 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 680 } 681 682 /* Create random content in the registers backing each control */ 683 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 684 alg_base_words = _get_alg_mem_base_words(test, i, def.mem_type); 685 reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type); 686 reg += (alg_base_words + def.offset_dsp_words) * 687 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 688 regmap_raw_write(dsp->regmap, reg, reg_vals[i], def.length_bytes); 689 } 690 691 /* Download, run, stop and power-down the firmware */ 692 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); 693 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 694 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 695 cs_dsp_stop(dsp); 696 cs_dsp_power_down(dsp); 697 698 /* There should now be 3 controls */ 699 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3); 700 701 /* 702 * There's no requirement for the control list to be in any 703 * particular order, so don't assume the order. 704 */ 705 for (i = 0; i < ARRAY_SIZE(ctl); i++) 706 ctl[i] = NULL; 707 708 list_for_each_entry(walkctl, &dsp->ctl_list, list) { 709 if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[0].id) 710 ctl[0] = walkctl; 711 if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[1].id) 712 ctl[1] = walkctl; 713 if (walkctl->alg_region.alg == cs_dsp_ctl_cache_test_algs[2].id) 714 ctl[2] = walkctl; 715 } 716 717 KUNIT_ASSERT_NOT_NULL(test, ctl[0]); 718 KUNIT_ASSERT_NOT_NULL(test, ctl[1]); 719 KUNIT_ASSERT_NOT_NULL(test, ctl[2]); 720 721 /* 722 * The data should have been populated into the control cache 723 * so should be readable through the control. 724 */ 725 KUNIT_EXPECT_EQ(test, 726 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes), 727 0); 728 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes); 729 730 KUNIT_EXPECT_EQ(test, 731 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes), 732 0); 733 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes); 734 735 KUNIT_EXPECT_EQ(test, 736 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, 737 def.length_bytes), 738 0); 739 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes); 740 } 741 742 /* 743 * Firmware with controls in the same algorithm and memory but at 744 * different offsets. 745 * The control cache should be initialized with content from the 746 * correct offset. 747 * Only for wmfw format V2 and later. V1 only supports one control per 748 * memory per algorithm. 749 */ 750 static void cs_dsp_ctl_cache_init_multiple_offsets(struct kunit *test) 751 { 752 struct cs_dsp_test *priv = test->priv; 753 struct cs_dsp *dsp = priv->dsp; 754 struct cs_dsp_test_local *local = priv->local; 755 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 756 unsigned int reg, alg_base_words, alg_base_reg; 757 struct cs_dsp_coeff_ctl *walkctl, *ctl[3]; 758 struct firmware *wmfw; 759 u32 *reg_vals[3], *readback; 760 int i; 761 762 static_assert(ARRAY_SIZE(ctl) == ARRAY_SIZE(reg_vals)); 763 static_assert(ARRAY_SIZE(reg_vals) <= ARRAY_SIZE(cs_dsp_ctl_cache_test_algs)); 764 765 for (i = 0; i < ARRAY_SIZE(reg_vals); i++) { 766 reg_vals[i] = kunit_kmalloc(test, def.length_bytes, GFP_KERNEL); 767 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals[i]); 768 get_random_bytes(reg_vals[i], def.length_bytes); 769 } 770 771 readback = kunit_kzalloc(test, def.length_bytes, GFP_KERNEL); 772 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 773 774 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 775 cs_dsp_ctl_cache_test_algs[0].id, 776 "dummyalg", NULL); 777 778 /* Create controls identical except for offset */ 779 def.length_bytes = 8; 780 def.offset_dsp_words = 0; 781 def.shortname = "CtlA"; 782 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 783 784 def.offset_dsp_words = 5; 785 def.shortname = "CtlB"; 786 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 787 788 def.offset_dsp_words = 8; 789 def.shortname = "CtlC"; 790 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 791 792 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 793 794 /* Create random content in the registers backing each control */ 795 alg_base_words = _get_alg_mem_base_words(test, 0, def.mem_type); 796 alg_base_reg = cs_dsp_mock_base_addr_for_mem(priv, def.mem_type); 797 alg_base_reg += alg_base_words * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 798 799 reg = alg_base_reg; 800 regmap_raw_write(dsp->regmap, reg, reg_vals[0], def.length_bytes); 801 reg = alg_base_reg + (5 * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv)); 802 regmap_raw_write(dsp->regmap, reg, reg_vals[1], def.length_bytes); 803 reg = alg_base_reg + (8 * cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv)); 804 regmap_raw_write(dsp->regmap, reg, reg_vals[2], def.length_bytes); 805 806 /* Download, run, stop and power-down the firmware */ 807 wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder); 808 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 809 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 810 cs_dsp_stop(dsp); 811 cs_dsp_power_down(dsp); 812 813 /* There should now be 3 controls */ 814 KUNIT_ASSERT_EQ(test, list_count_nodes(&dsp->ctl_list), 3); 815 816 /* 817 * There's no requirement for the control list to be in any 818 * particular order, so don't assume the order. 819 */ 820 for (i = 0; i < ARRAY_SIZE(ctl); i++) 821 ctl[i] = NULL; 822 823 list_for_each_entry(walkctl, &dsp->ctl_list, list) { 824 if (walkctl->offset == 0) 825 ctl[0] = walkctl; 826 if (walkctl->offset == 5) 827 ctl[1] = walkctl; 828 if (walkctl->offset == 8) 829 ctl[2] = walkctl; 830 } 831 832 KUNIT_ASSERT_NOT_NULL(test, ctl[0]); 833 KUNIT_ASSERT_NOT_NULL(test, ctl[1]); 834 KUNIT_ASSERT_NOT_NULL(test, ctl[2]); 835 836 /* 837 * The data should have been populated into the control cache 838 * so should be readable through the control. 839 */ 840 KUNIT_EXPECT_EQ(test, 841 cs_dsp_coeff_lock_and_read_ctrl(ctl[0], 0, readback, def.length_bytes), 842 0); 843 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[0], def.length_bytes); 844 845 KUNIT_EXPECT_EQ(test, 846 cs_dsp_coeff_lock_and_read_ctrl(ctl[1], 0, readback, def.length_bytes), 847 0); 848 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[1], def.length_bytes); 849 850 KUNIT_EXPECT_EQ(test, 851 cs_dsp_coeff_lock_and_read_ctrl(ctl[2], 0, readback, 852 def.length_bytes), 853 0); 854 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals[2], def.length_bytes); 855 } 856 857 /* 858 * Read from a cached control before the firmware is started. 859 * Should return the data in the cache. 860 */ 861 static void cs_dsp_ctl_cache_read_not_started(struct kunit *test) 862 { 863 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 864 struct cs_dsp_test *priv = test->priv; 865 struct cs_dsp_test_local *local = priv->local; 866 struct cs_dsp *dsp = priv->dsp; 867 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 868 int alg_idx = _find_alg_entry(test, param->alg_id); 869 unsigned int reg, alg_base_words; 870 struct cs_dsp_coeff_ctl *ctl; 871 struct firmware *wmfw; 872 u32 *reg_vals, *readback; 873 874 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 875 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 876 877 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 878 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 879 880 /* Create some DSP data to be read into the control cache */ 881 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 882 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 883 reg += (alg_base_words + param->offs_words) * 884 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 885 get_random_bytes(reg_vals, param->len_bytes); 886 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 887 888 /* Create control pointing to this data */ 889 def.flags = param->flags; 890 def.mem_type = param->mem_type; 891 def.offset_dsp_words = param->offs_words; 892 def.length_bytes = param->len_bytes; 893 894 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 895 cs_dsp_ctl_cache_test_algs[alg_idx].id, 896 "dummyalg", NULL); 897 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 898 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 899 900 /* Power-up DSP but don't start firmware */ 901 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 902 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 903 904 /* Drop expected writes and the regmap cache should be clean */ 905 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 906 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 907 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 908 909 /* Control should readback the data from the control cache */ 910 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 911 KUNIT_ASSERT_NOT_NULL(test, ctl); 912 KUNIT_EXPECT_EQ(test, 913 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 914 0); 915 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 916 } 917 918 /* 919 * Read from a cached control after the firmware has been stopped. 920 * Should return the data in the cache. 921 */ 922 static void cs_dsp_ctl_cache_read_stopped(struct kunit *test) 923 { 924 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 925 struct cs_dsp_test *priv = test->priv; 926 struct cs_dsp_test_local *local = priv->local; 927 struct cs_dsp *dsp = priv->dsp; 928 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 929 int alg_idx = _find_alg_entry(test, param->alg_id); 930 unsigned int reg, alg_base_words; 931 struct cs_dsp_coeff_ctl *ctl; 932 struct firmware *wmfw; 933 u32 *reg_vals, *readback; 934 935 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 936 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 937 938 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 939 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 940 941 /* Create some DSP data to be read into the control cache */ 942 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 943 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 944 reg += (alg_base_words + param->offs_words) * 945 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 946 get_random_bytes(reg_vals, param->len_bytes); 947 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 948 949 /* Create control pointing to this data */ 950 def.flags = param->flags; 951 def.mem_type = param->mem_type; 952 def.offset_dsp_words = param->offs_words; 953 def.length_bytes = param->len_bytes; 954 955 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 956 cs_dsp_ctl_cache_test_algs[alg_idx].id, 957 "dummyalg", NULL); 958 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 959 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 960 961 /* Power-up DSP */ 962 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 963 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 964 965 /* Start and stop the firmware */ 966 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 967 cs_dsp_stop(dsp); 968 969 /* Drop expected writes and the regmap cache should be clean */ 970 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 971 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 972 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 973 974 /* Control should readback the data from the control cache */ 975 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 976 KUNIT_ASSERT_NOT_NULL(test, ctl); 977 KUNIT_EXPECT_EQ(test, 978 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 979 0); 980 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 981 } 982 983 /* 984 * Read from a cached control after the DSP has been powered-up and 985 * then powered-down without running. 986 * Should return the data in the cache. 987 */ 988 static void cs_dsp_ctl_cache_read_powered_down(struct kunit *test) 989 { 990 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 991 struct cs_dsp_test *priv = test->priv; 992 struct cs_dsp_test_local *local = priv->local; 993 struct cs_dsp *dsp = priv->dsp; 994 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 995 int alg_idx = _find_alg_entry(test, param->alg_id); 996 unsigned int reg, alg_base_words; 997 struct cs_dsp_coeff_ctl *ctl; 998 struct firmware *wmfw; 999 u32 *reg_vals, *readback; 1000 1001 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1002 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1003 1004 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1005 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1006 1007 /* Create some DSP data to be read into the control cache */ 1008 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1009 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1010 reg += (alg_base_words + param->offs_words) * 1011 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1012 get_random_bytes(reg_vals, param->len_bytes); 1013 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1014 1015 /* Create control pointing to this data */ 1016 def.flags = param->flags; 1017 def.mem_type = param->mem_type; 1018 def.offset_dsp_words = param->offs_words; 1019 def.length_bytes = param->len_bytes; 1020 1021 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1022 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1023 "dummyalg", NULL); 1024 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1025 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1026 1027 /* Power-up DSP then power-down */ 1028 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1029 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1030 cs_dsp_power_down(dsp); 1031 1032 /* Drop expected writes and the regmap cache should be clean */ 1033 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1034 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1035 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1036 1037 /* Control should readback the data from the control cache */ 1038 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1039 KUNIT_ASSERT_NOT_NULL(test, ctl); 1040 KUNIT_EXPECT_EQ(test, 1041 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1042 0); 1043 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1044 } 1045 1046 /* 1047 * Read from a cached control after the firmware has been run and 1048 * stopped, then the DSP has been powered-down. 1049 * Should return the data in the cache. 1050 */ 1051 static void cs_dsp_ctl_cache_read_stopped_powered_down(struct kunit *test) 1052 { 1053 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1054 struct cs_dsp_test *priv = test->priv; 1055 struct cs_dsp_test_local *local = priv->local; 1056 struct cs_dsp *dsp = priv->dsp; 1057 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1058 int alg_idx = _find_alg_entry(test, param->alg_id); 1059 unsigned int reg, alg_base_words; 1060 struct cs_dsp_coeff_ctl *ctl; 1061 struct firmware *wmfw; 1062 u32 *reg_vals, *readback; 1063 1064 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1065 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1066 1067 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1068 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1069 1070 /* Create some DSP data to be read into the control cache */ 1071 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1072 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1073 reg += (alg_base_words + param->offs_words) * 1074 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1075 get_random_bytes(reg_vals, param->len_bytes); 1076 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1077 1078 /* Create control pointing to this data */ 1079 def.flags = param->flags; 1080 def.mem_type = param->mem_type; 1081 def.offset_dsp_words = param->offs_words; 1082 def.length_bytes = param->len_bytes; 1083 1084 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1085 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1086 "dummyalg", NULL); 1087 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1088 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1089 1090 /* Power-up DSP */ 1091 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1092 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1093 1094 /* Start and stop the firmware then power-down */ 1095 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 1096 cs_dsp_stop(dsp); 1097 cs_dsp_power_down(dsp); 1098 1099 /* Drop expected writes and the regmap cache should be clean */ 1100 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1101 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1102 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1103 1104 /* Control should readback the data from the control cache */ 1105 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1106 KUNIT_ASSERT_NOT_NULL(test, ctl); 1107 KUNIT_EXPECT_EQ(test, 1108 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1109 0); 1110 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1111 } 1112 1113 /* 1114 * Read from a cached control when a different firmware is currently 1115 * loaded into the DSP. 1116 * Should return the data in the cache. 1117 */ 1118 static void cs_dsp_ctl_cache_read_not_current_loaded_fw(struct kunit *test) 1119 { 1120 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1121 struct cs_dsp_test *priv = test->priv; 1122 struct cs_dsp_test_local *local = priv->local; 1123 struct cs_dsp *dsp = priv->dsp; 1124 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1125 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test); 1126 int alg_idx = _find_alg_entry(test, param->alg_id); 1127 unsigned int reg, alg_base_words; 1128 struct cs_dsp_coeff_ctl *ctl; 1129 struct firmware *wmfw; 1130 u32 *reg_vals, *readback; 1131 1132 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1133 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1134 1135 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1136 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1137 1138 /* Create some DSP data to be read into the control cache */ 1139 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1140 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1141 reg += (alg_base_words + param->offs_words) * 1142 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1143 get_random_bytes(reg_vals, param->len_bytes); 1144 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1145 1146 /* Create control pointing to this data */ 1147 def.flags = param->flags; 1148 def.mem_type = param->mem_type; 1149 def.offset_dsp_words = param->offs_words; 1150 def.length_bytes = param->len_bytes; 1151 1152 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1153 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1154 "dummyalg", NULL); 1155 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1156 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1157 1158 /* Power-up DSP */ 1159 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1160 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1161 1162 /* Power-down DSP then power-up with a different firmware */ 1163 cs_dsp_power_down(dsp); 1164 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 1165 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0); 1166 1167 /* Drop expected writes and the regmap cache should be clean */ 1168 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1169 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1170 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1171 1172 /* Control should readback the data from the control cache */ 1173 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1174 KUNIT_ASSERT_NOT_NULL(test, ctl); 1175 KUNIT_EXPECT_EQ(test, 1176 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1177 0); 1178 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1179 } 1180 1181 /* 1182 * Read from a cached control when a different firmware is currently 1183 * running. 1184 * Should return the data in the cache. 1185 */ 1186 static void cs_dsp_ctl_cache_read_not_current_running_fw(struct kunit *test) 1187 { 1188 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1189 struct cs_dsp_test *priv = test->priv; 1190 struct cs_dsp_test_local *local = priv->local; 1191 struct cs_dsp *dsp = priv->dsp; 1192 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1193 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test); 1194 int alg_idx = _find_alg_entry(test, param->alg_id); 1195 unsigned int reg, alg_base_words; 1196 struct cs_dsp_coeff_ctl *ctl; 1197 struct firmware *wmfw; 1198 u32 *reg_vals, *readback; 1199 1200 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1201 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1202 1203 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1204 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1205 1206 /* Create some DSP data to be read into the control cache */ 1207 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1208 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1209 reg += (alg_base_words + param->offs_words) * 1210 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1211 get_random_bytes(reg_vals, param->len_bytes); 1212 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1213 1214 /* Create control pointing to this data */ 1215 def.flags = param->flags; 1216 def.mem_type = param->mem_type; 1217 def.offset_dsp_words = param->offs_words; 1218 def.length_bytes = param->len_bytes; 1219 1220 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1221 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1222 "dummyalg", NULL); 1223 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1224 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1225 1226 /* Power-up DSP then power-down */ 1227 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1228 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1229 cs_dsp_power_down(dsp); 1230 1231 /* Power-up with a different firmware and run it */ 1232 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 1233 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0); 1234 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 1235 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 1236 1237 /* Drop expected writes and the regmap cache should be clean */ 1238 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1239 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1240 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1241 1242 /* Control should readback the data from the control cache */ 1243 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1244 KUNIT_ASSERT_NOT_NULL(test, ctl); 1245 KUNIT_EXPECT_EQ(test, 1246 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1247 0); 1248 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1249 } 1250 1251 /* 1252 * Read from a cached control with non-zero flags while the firmware is 1253 * running. 1254 * Should return the data in the cache, not from the registers. 1255 */ 1256 static void cs_dsp_ctl_cache_read_running(struct kunit *test) 1257 { 1258 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1259 struct cs_dsp_test *priv = test->priv; 1260 struct cs_dsp_test_local *local = priv->local; 1261 struct cs_dsp *dsp = priv->dsp; 1262 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1263 int alg_idx = _find_alg_entry(test, param->alg_id); 1264 unsigned int reg, alg_base_words; 1265 struct cs_dsp_coeff_ctl *ctl; 1266 struct firmware *wmfw; 1267 u32 *init_reg_vals, *new_reg_vals, *readback; 1268 1269 init_reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1270 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_reg_vals); 1271 1272 new_reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1273 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_reg_vals); 1274 1275 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1276 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1277 1278 /* Create data in the registers backing the control */ 1279 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1280 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1281 reg += (alg_base_words + param->offs_words) * 1282 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1283 get_random_bytes(init_reg_vals, param->len_bytes); 1284 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes); 1285 1286 /* Create control pointing to this data */ 1287 def.flags = param->flags; 1288 def.mem_type = param->mem_type; 1289 def.offset_dsp_words = param->offs_words; 1290 def.length_bytes = param->len_bytes; 1291 1292 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1293 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1294 "dummyalg", NULL); 1295 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1296 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1297 1298 /* Power-up DSP */ 1299 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1300 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1301 1302 /* Start the firmware running */ 1303 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 1304 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 1305 1306 /* 1307 * Change the values in the registers backing the control then drop 1308 * them from the regmap cache. This allows checking that the control 1309 * read is returning values from the control cache and not accessing 1310 * the registers. 1311 */ 1312 KUNIT_ASSERT_EQ(test, 1313 regmap_raw_write(dsp->regmap, reg, new_reg_vals, param->len_bytes), 1314 0); 1315 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1316 1317 /* Control should readback the origin data from its cache */ 1318 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1319 KUNIT_ASSERT_NOT_NULL(test, ctl); 1320 KUNIT_EXPECT_EQ(test, 1321 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1322 0); 1323 KUNIT_EXPECT_MEMEQ(test, readback, init_reg_vals, param->len_bytes); 1324 1325 /* Stop and power-down the DSP */ 1326 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp); 1327 cs_dsp_power_down(dsp); 1328 1329 /* Control should readback from the cache */ 1330 KUNIT_EXPECT_EQ(test, 1331 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1332 0); 1333 KUNIT_EXPECT_MEMEQ(test, readback, init_reg_vals, param->len_bytes); 1334 } 1335 1336 /* 1337 * Read from a cached control with flags == 0 while the firmware is 1338 * running. 1339 * Should behave as volatile and read from the registers. 1340 * (This is for backwards compatibility with old firmware versions) 1341 */ 1342 static void cs_dsp_ctl_cache_read_running_zero_flags(struct kunit *test) 1343 { 1344 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1345 struct cs_dsp_test *priv = test->priv; 1346 struct cs_dsp_test_local *local = priv->local; 1347 struct cs_dsp *dsp = priv->dsp; 1348 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1349 int alg_idx = _find_alg_entry(test, param->alg_id); 1350 unsigned int reg, alg_base_words; 1351 struct cs_dsp_coeff_ctl *ctl; 1352 struct firmware *wmfw; 1353 u32 *init_reg_vals, *new_reg_vals, *readback; 1354 1355 init_reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1356 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_reg_vals); 1357 1358 new_reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1359 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_reg_vals); 1360 1361 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1362 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1363 1364 /* Zero-fill the registers backing the control */ 1365 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1366 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1367 reg += (alg_base_words + param->offs_words) * 1368 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1369 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes); 1370 1371 /* Create control pointing to this data */ 1372 def.flags = 0; 1373 def.mem_type = param->mem_type; 1374 def.offset_dsp_words = param->offs_words; 1375 def.length_bytes = param->len_bytes; 1376 1377 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1378 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1379 "dummyalg", NULL); 1380 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1381 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1382 1383 /* Power-up DSP */ 1384 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1385 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1386 1387 /* Start the firmware running */ 1388 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 1389 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 1390 1391 /* Change the values in the registers backing the control */ 1392 get_random_bytes(new_reg_vals, param->len_bytes); 1393 regmap_raw_write(dsp->regmap, reg, new_reg_vals, param->len_bytes); 1394 1395 /* Control should readback the new data from the registers */ 1396 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1397 KUNIT_ASSERT_NOT_NULL(test, ctl); 1398 KUNIT_EXPECT_EQ(test, 1399 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1400 0); 1401 KUNIT_EXPECT_MEMEQ(test, readback, new_reg_vals, param->len_bytes); 1402 1403 /* Stop and power-down the DSP */ 1404 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp); 1405 cs_dsp_power_down(dsp); 1406 1407 /* Change the values in the registers backing the control */ 1408 regmap_raw_write(dsp->regmap, reg, init_reg_vals, param->len_bytes); 1409 1410 /* Control should readback from the cache */ 1411 KUNIT_EXPECT_EQ(test, 1412 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1413 0); 1414 KUNIT_EXPECT_MEMEQ(test, readback, new_reg_vals, param->len_bytes); 1415 } 1416 1417 /* 1418 * Write to a cached control while the firmware is running. 1419 * This should be a writethrough operation, writing to the cache and 1420 * the registers. 1421 */ 1422 static void cs_dsp_ctl_cache_writethrough(struct kunit *test) 1423 { 1424 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1425 struct cs_dsp_test *priv = test->priv; 1426 struct cs_dsp_test_local *local = priv->local; 1427 struct cs_dsp *dsp = priv->dsp; 1428 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1429 int alg_idx = _find_alg_entry(test, param->alg_id); 1430 unsigned int reg, alg_base_words; 1431 struct cs_dsp_coeff_ctl *ctl; 1432 struct firmware *wmfw; 1433 u32 *reg_vals, *readback; 1434 1435 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1436 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1437 1438 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1439 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1440 1441 /* Create some DSP data to be read into the control cache */ 1442 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1443 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1444 reg += (alg_base_words + param->offs_words) * 1445 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1446 memset(reg_vals, 0, param->len_bytes); 1447 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1448 1449 /* Create control pointing to this data */ 1450 def.flags = param->flags; 1451 def.mem_type = param->mem_type; 1452 def.offset_dsp_words = param->offs_words; 1453 def.length_bytes = param->len_bytes; 1454 1455 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1456 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1457 "dummyalg", NULL); 1458 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1459 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1460 1461 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1462 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1463 1464 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1465 KUNIT_ASSERT_NOT_NULL(test, ctl); 1466 1467 /* Start the firmware and add an action to stop it during cleanup */ 1468 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 1469 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 1470 1471 /* Write new data to the control, it should be written to the registers */ 1472 get_random_bytes(reg_vals, param->len_bytes); 1473 KUNIT_EXPECT_EQ(test, 1474 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 1475 1); 1476 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 1477 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1478 } 1479 1480 /* 1481 * Write unchanged data to a cached control while the firmware is running. 1482 * The control write should return 0 to indicate that the content 1483 * didn't change. 1484 */ 1485 static void cs_dsp_ctl_cache_writethrough_unchanged(struct kunit *test) 1486 { 1487 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1488 struct cs_dsp_test *priv = test->priv; 1489 struct cs_dsp_test_local *local = priv->local; 1490 struct cs_dsp *dsp = priv->dsp; 1491 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1492 int alg_idx = _find_alg_entry(test, param->alg_id); 1493 unsigned int reg, alg_base_words; 1494 struct cs_dsp_coeff_ctl *ctl; 1495 struct firmware *wmfw; 1496 u32 *reg_vals, *readback; 1497 1498 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1499 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1500 1501 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1502 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1503 1504 /* Create some DSP data to be read into the control cache */ 1505 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1506 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1507 reg += (alg_base_words + param->offs_words) * 1508 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1509 get_random_bytes(reg_vals, param->len_bytes); 1510 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1511 1512 /* Create control pointing to this data */ 1513 def.flags = param->flags; 1514 def.mem_type = param->mem_type; 1515 def.offset_dsp_words = param->offs_words; 1516 def.length_bytes = param->len_bytes; 1517 1518 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1519 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1520 "dummyalg", NULL); 1521 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1522 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1523 1524 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1525 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1526 1527 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1528 KUNIT_ASSERT_NOT_NULL(test, ctl); 1529 1530 /* Start the firmware and add an action to stop it during cleanup */ 1531 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 1532 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 1533 1534 /* 1535 * If the control is write-only the cache will have been zero-initialized 1536 * so the first write will always indicate a change. 1537 */ 1538 if (def.flags && !(def.flags & WMFW_CTL_FLAG_READABLE)) { 1539 KUNIT_EXPECT_EQ(test, 1540 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, 1541 param->len_bytes), 1542 1); 1543 } 1544 1545 /* 1546 * Write the same data to the control, cs_dsp_coeff_lock_and_write_ctrl() 1547 * should return 0 to indicate the content didn't change. 1548 */ 1549 KUNIT_EXPECT_EQ(test, 1550 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 1551 0); 1552 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 1553 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1554 } 1555 1556 /* 1557 * Write unchanged data to a cached control while the firmware is not started. 1558 * The control write should return 0 to indicate that the cache content 1559 * didn't change. 1560 */ 1561 static void cs_dsp_ctl_cache_write_unchanged_not_started(struct kunit *test) 1562 { 1563 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1564 struct cs_dsp_test *priv = test->priv; 1565 struct cs_dsp_test_local *local = priv->local; 1566 struct cs_dsp *dsp = priv->dsp; 1567 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1568 int alg_idx = _find_alg_entry(test, param->alg_id); 1569 unsigned int reg, alg_base_words; 1570 struct cs_dsp_coeff_ctl *ctl; 1571 struct firmware *wmfw; 1572 u32 *reg_vals, *readback; 1573 1574 reg_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 1575 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1576 1577 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1578 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1579 1580 /* Create some DSP data to be read into the control cache */ 1581 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1582 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1583 reg += (alg_base_words + param->offs_words) * 1584 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1585 get_random_bytes(reg_vals, param->len_bytes); 1586 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1587 1588 /* Create control pointing to this data */ 1589 def.flags = param->flags; 1590 def.mem_type = param->mem_type; 1591 def.offset_dsp_words = param->offs_words; 1592 def.length_bytes = param->len_bytes; 1593 1594 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1595 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1596 "dummyalg", NULL); 1597 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1598 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1599 1600 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1601 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1602 1603 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1604 KUNIT_ASSERT_NOT_NULL(test, ctl); 1605 1606 /* 1607 * If the control is write-only the cache will have been zero-initialized 1608 * so the first write will always indicate a change. 1609 */ 1610 if (def.flags && !(def.flags & WMFW_CTL_FLAG_READABLE)) { 1611 KUNIT_EXPECT_EQ(test, 1612 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, 1613 param->len_bytes), 1614 1); 1615 } 1616 1617 /* 1618 * Write the same data to the control, cs_dsp_coeff_lock_and_write_ctrl() 1619 * should return 0 to indicate the content didn't change. 1620 */ 1621 KUNIT_EXPECT_EQ(test, 1622 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 1623 0); 1624 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 1625 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1626 } 1627 1628 /* 1629 * Write to a cached control while the firmware is loaded but not 1630 * started. 1631 * This should write to the cache only. 1632 */ 1633 static void cs_dsp_ctl_cache_write_not_started(struct kunit *test) 1634 { 1635 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1636 struct cs_dsp_test *priv = test->priv; 1637 struct cs_dsp_test_local *local = priv->local; 1638 struct cs_dsp *dsp = priv->dsp; 1639 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1640 int alg_idx = _find_alg_entry(test, param->alg_id); 1641 unsigned int reg, alg_base_words; 1642 struct cs_dsp_coeff_ctl *ctl; 1643 struct firmware *wmfw; 1644 u32 *reg_vals, *readback; 1645 1646 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1647 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1648 1649 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1650 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1651 1652 /* Create some DSP data to be read into the control cache */ 1653 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1654 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1655 reg += (alg_base_words + param->offs_words) * 1656 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1657 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1658 1659 /* Create control pointing to this data */ 1660 def.flags = param->flags; 1661 def.mem_type = param->mem_type; 1662 def.offset_dsp_words = param->offs_words; 1663 def.length_bytes = param->len_bytes; 1664 1665 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1666 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1667 "dummyalg", NULL); 1668 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1669 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1670 1671 /* Power-up DSP but don't start firmware */ 1672 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1673 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1674 1675 /* Drop expected writes and the regmap cache should be clean */ 1676 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1677 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1678 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1679 1680 /* Write new data to the control, it should not be written to the registers */ 1681 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1682 KUNIT_ASSERT_NOT_NULL(test, ctl); 1683 1684 get_random_bytes(reg_vals, param->len_bytes); 1685 KUNIT_EXPECT_EQ(test, 1686 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 1687 1); 1688 1689 /* Registers should not have been written so regmap cache should still be clean */ 1690 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1691 1692 /* Control should readback the new data from the control cache */ 1693 KUNIT_EXPECT_EQ(test, 1694 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1695 0); 1696 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1697 } 1698 1699 /* 1700 * Write to a cached control after the firmware has been loaded, 1701 * started and stopped. 1702 * This should write to the cache only. 1703 */ 1704 static void cs_dsp_ctl_cache_write_stopped(struct kunit *test) 1705 { 1706 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1707 struct cs_dsp_test *priv = test->priv; 1708 struct cs_dsp_test_local *local = priv->local; 1709 struct cs_dsp *dsp = priv->dsp; 1710 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1711 int alg_idx = _find_alg_entry(test, param->alg_id); 1712 unsigned int reg, alg_base_words; 1713 struct cs_dsp_coeff_ctl *ctl; 1714 struct firmware *wmfw; 1715 u32 *reg_vals, *readback; 1716 1717 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1718 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1719 1720 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1721 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1722 1723 /* Create some DSP data to be read into the control cache */ 1724 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1725 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1726 reg += (alg_base_words + param->offs_words) * 1727 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1728 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1729 1730 /* Create control pointing to this data */ 1731 def.flags = param->flags; 1732 def.mem_type = param->mem_type; 1733 def.offset_dsp_words = param->offs_words; 1734 def.length_bytes = param->len_bytes; 1735 1736 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1737 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1738 "dummyalg", NULL); 1739 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1740 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1741 1742 /* Power-up DSP */ 1743 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1744 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1745 1746 /* Start and stop the firmware */ 1747 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 1748 cs_dsp_stop(dsp); 1749 1750 /* Drop expected writes and the regmap cache should be clean */ 1751 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1752 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1753 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1754 1755 /* Write new data to the control, it should not be written to the registers */ 1756 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1757 KUNIT_ASSERT_NOT_NULL(test, ctl); 1758 1759 get_random_bytes(reg_vals, param->len_bytes); 1760 KUNIT_EXPECT_EQ(test, 1761 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 1762 1); 1763 1764 /* Registers should not have been written so regmap cache should still be clean */ 1765 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1766 1767 /* Control should readback the new data from the control cache */ 1768 KUNIT_EXPECT_EQ(test, 1769 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1770 0); 1771 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1772 } 1773 1774 /* 1775 * Write to a cached control after the firmware has been loaded, 1776 * then the DSP powered-down. 1777 * This should write to the cache only. 1778 */ 1779 static void cs_dsp_ctl_cache_write_powered_down(struct kunit *test) 1780 { 1781 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1782 struct cs_dsp_test *priv = test->priv; 1783 struct cs_dsp_test_local *local = priv->local; 1784 struct cs_dsp *dsp = priv->dsp; 1785 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1786 int alg_idx = _find_alg_entry(test, param->alg_id); 1787 unsigned int reg, alg_base_words; 1788 struct cs_dsp_coeff_ctl *ctl; 1789 struct firmware *wmfw; 1790 u32 *reg_vals, *readback; 1791 1792 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1793 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1794 1795 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1796 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1797 1798 /* Create some DSP data to be read into the control cache */ 1799 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1800 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1801 reg += (alg_base_words + param->offs_words) * 1802 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1803 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1804 1805 /* Create control pointing to this data */ 1806 def.flags = param->flags; 1807 def.mem_type = param->mem_type; 1808 def.offset_dsp_words = param->offs_words; 1809 def.length_bytes = param->len_bytes; 1810 1811 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1812 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1813 "dummyalg", NULL); 1814 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1815 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1816 1817 /* Power-up DSP then power-down */ 1818 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1819 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1820 cs_dsp_power_down(dsp); 1821 1822 /* Drop expected writes and the regmap cache should be clean */ 1823 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1824 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1825 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1826 1827 /* Write new data to the control, it should not be written to the registers */ 1828 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1829 KUNIT_ASSERT_NOT_NULL(test, ctl); 1830 1831 get_random_bytes(reg_vals, param->len_bytes); 1832 KUNIT_EXPECT_EQ(test, 1833 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 1834 1); 1835 1836 /* Registers should not have been written so regmap cache should still be clean */ 1837 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1838 1839 /* Control should readback the new data from the control cache */ 1840 KUNIT_EXPECT_EQ(test, 1841 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1842 0); 1843 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1844 } 1845 1846 /* 1847 * Write to a cached control after the firmware has been loaded, 1848 * started, stopped, and then the DSP powered-down. 1849 * This should write to the cache only. 1850 */ 1851 static void cs_dsp_ctl_cache_write_stopped_powered_down(struct kunit *test) 1852 { 1853 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1854 struct cs_dsp_test *priv = test->priv; 1855 struct cs_dsp_test_local *local = priv->local; 1856 struct cs_dsp *dsp = priv->dsp; 1857 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1858 int alg_idx = _find_alg_entry(test, param->alg_id); 1859 unsigned int reg, alg_base_words; 1860 struct cs_dsp_coeff_ctl *ctl; 1861 struct firmware *wmfw; 1862 u32 *reg_vals, *readback; 1863 1864 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1865 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1866 1867 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1868 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1869 1870 /* Create some DSP data to be read into the control cache */ 1871 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1872 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1873 reg += (alg_base_words + param->offs_words) * 1874 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1875 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1876 1877 /* Create control pointing to this data */ 1878 def.flags = param->flags; 1879 def.mem_type = param->mem_type; 1880 def.offset_dsp_words = param->offs_words; 1881 def.length_bytes = param->len_bytes; 1882 1883 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1884 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1885 "dummyalg", NULL); 1886 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1887 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1888 1889 /* Power-up DSP */ 1890 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1891 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1892 1893 /* Start and stop the firmware then power-down */ 1894 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 1895 cs_dsp_stop(dsp); 1896 cs_dsp_power_down(dsp); 1897 1898 /* Drop expected writes and the regmap cache should be clean */ 1899 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1900 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1901 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1902 1903 /* Write new data to the control, it should not be written to the registers */ 1904 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1905 KUNIT_ASSERT_NOT_NULL(test, ctl); 1906 1907 get_random_bytes(reg_vals, param->len_bytes); 1908 KUNIT_EXPECT_EQ(test, 1909 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 1910 1); 1911 1912 /* Registers should not have been written so regmap cache should still be clean */ 1913 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1914 1915 /* Control should readback the new data from the control cache */ 1916 KUNIT_EXPECT_EQ(test, 1917 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 1918 0); 1919 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 1920 } 1921 1922 /* 1923 * Write to a cached control that is not in the currently loaded firmware. 1924 * This should write to the cache only. 1925 */ 1926 static void cs_dsp_ctl_cache_write_not_current_loaded_fw(struct kunit *test) 1927 { 1928 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 1929 struct cs_dsp_test *priv = test->priv; 1930 struct cs_dsp_test_local *local = priv->local; 1931 struct cs_dsp *dsp = priv->dsp; 1932 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 1933 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test); 1934 int alg_idx = _find_alg_entry(test, param->alg_id); 1935 unsigned int reg, alg_base_words; 1936 struct cs_dsp_coeff_ctl *ctl; 1937 struct firmware *wmfw; 1938 u32 *reg_vals, *readback; 1939 1940 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1941 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 1942 1943 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 1944 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 1945 1946 /* Create some DSP data to be read into the control cache */ 1947 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 1948 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 1949 reg += (alg_base_words + param->offs_words) * 1950 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 1951 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 1952 1953 /* Create control pointing to this data */ 1954 def.flags = param->flags; 1955 def.mem_type = param->mem_type; 1956 def.offset_dsp_words = param->offs_words; 1957 def.length_bytes = param->len_bytes; 1958 1959 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 1960 cs_dsp_ctl_cache_test_algs[alg_idx].id, 1961 "dummyalg", NULL); 1962 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 1963 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 1964 1965 /* Power-up DSP */ 1966 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 1967 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 1968 1969 /* Get the control */ 1970 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 1971 KUNIT_ASSERT_NOT_NULL(test, ctl); 1972 1973 /* Power-down DSP then power-up with a different firmware */ 1974 cs_dsp_power_down(dsp); 1975 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 1976 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0); 1977 1978 /* Control from unloaded firmware should be disabled */ 1979 KUNIT_EXPECT_FALSE(test, ctl->enabled); 1980 1981 /* Drop expected writes and the regmap cache should be clean */ 1982 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 1983 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 1984 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1985 1986 /* 1987 * It should be possible to write new data to the control from 1988 * the first firmware. But this should not be written to the 1989 * registers. 1990 */ 1991 get_random_bytes(reg_vals, param->len_bytes); 1992 KUNIT_EXPECT_EQ(test, 1993 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 1994 1); 1995 1996 /* Registers should not have been written so regmap cache should still be clean */ 1997 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 1998 1999 /* Control should readback the new data from the control cache */ 2000 KUNIT_EXPECT_EQ(test, 2001 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2002 0); 2003 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 2004 } 2005 2006 /* 2007 * Write to a cached control that is not in the currently running firmware. 2008 * This should write to the cache only. 2009 */ 2010 static void cs_dsp_ctl_cache_write_not_current_running_fw(struct kunit *test) 2011 { 2012 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 2013 struct cs_dsp_test *priv = test->priv; 2014 struct cs_dsp_test_local *local = priv->local; 2015 struct cs_dsp *dsp = priv->dsp; 2016 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 2017 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test); 2018 int alg_idx = _find_alg_entry(test, param->alg_id); 2019 unsigned int reg, alg_base_words; 2020 struct cs_dsp_coeff_ctl *ctl; 2021 struct firmware *wmfw; 2022 u32 *reg_vals, *readback; 2023 2024 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2025 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 2026 2027 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2028 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 2029 2030 /* Create some DSP data to be read into the control cache */ 2031 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 2032 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 2033 reg += (alg_base_words + param->offs_words) * 2034 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 2035 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 2036 2037 /* Create control pointing to this data */ 2038 def.flags = param->flags; 2039 def.mem_type = param->mem_type; 2040 def.offset_dsp_words = param->offs_words; 2041 def.length_bytes = param->len_bytes; 2042 2043 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 2044 cs_dsp_ctl_cache_test_algs[alg_idx].id, 2045 "dummyalg", NULL); 2046 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 2047 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 2048 2049 /* Power-up DSP then power-down */ 2050 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2051 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2052 cs_dsp_power_down(dsp); 2053 2054 /* Get the control */ 2055 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 2056 KUNIT_ASSERT_NOT_NULL(test, ctl); 2057 2058 /* Power-up with a different firmware and run it */ 2059 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 2060 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0); 2061 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2062 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2063 2064 /* Control from unloaded firmware should be disabled */ 2065 KUNIT_EXPECT_FALSE(test, ctl->enabled); 2066 2067 /* Drop expected writes and the regmap cache should be clean */ 2068 cs_dsp_mock_xm_header_drop_from_regmap_cache(priv); 2069 cs_dsp_mock_regmap_drop_bytes(priv, reg, param->len_bytes); 2070 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 2071 2072 /* 2073 * It should be possible to write new data to the control from 2074 * the first firmware. But this should not be written to the 2075 * registers. 2076 */ 2077 get_random_bytes(reg_vals, param->len_bytes); 2078 KUNIT_EXPECT_EQ(test, 2079 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 2080 1); 2081 2082 /* Registers should not have been written so regmap cache should still be clean */ 2083 KUNIT_EXPECT_FALSE(test, cs_dsp_mock_regmap_is_dirty(priv, true)); 2084 2085 /* Control should readback the new data from the control cache */ 2086 KUNIT_EXPECT_EQ(test, 2087 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2088 0); 2089 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 2090 } 2091 2092 /* 2093 * Write to a cached control before running the firmware. 2094 * The value written to the cache should be synced out to the registers 2095 * backing the control when the firmware is run. 2096 */ 2097 static void cs_dsp_ctl_cache_sync_write_before_run(struct kunit *test) 2098 { 2099 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 2100 struct cs_dsp_test *priv = test->priv; 2101 struct cs_dsp_test_local *local = priv->local; 2102 struct cs_dsp *dsp = priv->dsp; 2103 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 2104 int alg_idx = _find_alg_entry(test, param->alg_id); 2105 unsigned int reg, alg_base_words; 2106 struct cs_dsp_coeff_ctl *ctl; 2107 struct firmware *wmfw; 2108 u32 *reg_vals, *readback; 2109 2110 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2111 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 2112 2113 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2114 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 2115 2116 /* Create some DSP data to be read into the control cache */ 2117 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 2118 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 2119 reg += (alg_base_words + param->offs_words) * 2120 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 2121 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 2122 2123 /* Create control pointing to this data */ 2124 def.flags = param->flags; 2125 def.mem_type = param->mem_type; 2126 def.offset_dsp_words = param->offs_words; 2127 def.length_bytes = param->len_bytes; 2128 2129 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 2130 cs_dsp_ctl_cache_test_algs[alg_idx].id, 2131 "dummyalg", NULL); 2132 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 2133 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 2134 2135 /* Power-up DSP but don't start firmware */ 2136 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2137 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2138 2139 /* Write new data to the control, it should not be written to the registers */ 2140 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 2141 KUNIT_ASSERT_NOT_NULL(test, ctl); 2142 2143 get_random_bytes(reg_vals, param->len_bytes); 2144 KUNIT_EXPECT_EQ(test, 2145 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 2146 1); 2147 2148 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2149 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes); 2150 2151 /* Start the firmware and the cached data should be written to registers */ 2152 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2153 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2154 2155 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2156 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 2157 2158 /* Control should readback the new data from the control cache */ 2159 KUNIT_EXPECT_EQ(test, 2160 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2161 0); 2162 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 2163 } 2164 2165 /* 2166 * Write to a cached control while the firmware is running. 2167 * The value written should be synced out to the registers 2168 * backing the control when the firmware is next run. 2169 */ 2170 static void cs_dsp_ctl_cache_sync_write_while_running(struct kunit *test) 2171 { 2172 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 2173 struct cs_dsp_test *priv = test->priv; 2174 struct cs_dsp_test_local *local = priv->local; 2175 struct cs_dsp *dsp = priv->dsp; 2176 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 2177 int alg_idx = _find_alg_entry(test, param->alg_id); 2178 unsigned int reg, alg_base_words; 2179 struct cs_dsp_coeff_ctl *ctl; 2180 struct firmware *wmfw; 2181 u32 *init_vals, *ctl_vals, *readback; 2182 2183 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2184 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals); 2185 2186 ctl_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2187 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals); 2188 2189 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2190 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 2191 2192 /* Zero-fill the registers backing the control */ 2193 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 2194 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 2195 reg += (alg_base_words + param->offs_words) * 2196 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 2197 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2198 2199 /* Create control pointing to this data */ 2200 def.flags = param->flags; 2201 def.mem_type = param->mem_type; 2202 def.offset_dsp_words = param->offs_words; 2203 def.length_bytes = param->len_bytes; 2204 2205 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 2206 cs_dsp_ctl_cache_test_algs[alg_idx].id, 2207 "dummyalg", NULL); 2208 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 2209 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 2210 2211 /* Power-up DSP and start firmware */ 2212 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2213 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2214 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2215 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2216 2217 /* Write new data to the control */ 2218 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 2219 KUNIT_ASSERT_NOT_NULL(test, ctl); 2220 2221 get_random_bytes(ctl_vals, param->len_bytes); 2222 KUNIT_EXPECT_EQ(test, 2223 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes), 2224 1); 2225 2226 /* Stop firmware and zero the registers backing the control */ 2227 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp); 2228 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2229 KUNIT_ASSERT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2230 KUNIT_EXPECT_MEMEQ(test, readback, init_vals, param->len_bytes); 2231 2232 /* Start the firmware and the cached data should be written to registers */ 2233 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2234 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2235 2236 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2237 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2238 2239 /* Control should readback the new data from the control cache */ 2240 KUNIT_EXPECT_EQ(test, 2241 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2242 0); 2243 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2244 } 2245 2246 /* 2247 * Write to a cached control after stopping the firmware. 2248 * The value written to the cache should be synced out to the registers 2249 * backing the control when the firmware is next run. 2250 */ 2251 static void cs_dsp_ctl_cache_sync_write_after_stop(struct kunit *test) 2252 { 2253 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 2254 struct cs_dsp_test *priv = test->priv; 2255 struct cs_dsp_test_local *local = priv->local; 2256 struct cs_dsp *dsp = priv->dsp; 2257 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 2258 int alg_idx = _find_alg_entry(test, param->alg_id); 2259 unsigned int reg, alg_base_words; 2260 struct cs_dsp_coeff_ctl *ctl; 2261 struct firmware *wmfw; 2262 u32 *reg_vals, *readback; 2263 2264 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2265 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 2266 2267 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2268 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 2269 2270 /* Create some DSP data to be read into the control cache */ 2271 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 2272 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 2273 reg += (alg_base_words + param->offs_words) * 2274 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 2275 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 2276 2277 /* Create control pointing to this data */ 2278 def.flags = param->flags; 2279 def.mem_type = param->mem_type; 2280 def.offset_dsp_words = param->offs_words; 2281 def.length_bytes = param->len_bytes; 2282 2283 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 2284 cs_dsp_ctl_cache_test_algs[alg_idx].id, 2285 "dummyalg", NULL); 2286 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 2287 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 2288 2289 /* Power-up DSP but don't start firmware */ 2290 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2291 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2292 2293 /* Start and stop the firmware */ 2294 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2295 cs_dsp_stop(dsp); 2296 2297 /* Write new data to the control, it should not be written to the registers */ 2298 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 2299 KUNIT_ASSERT_NOT_NULL(test, ctl); 2300 2301 get_random_bytes(reg_vals, param->len_bytes); 2302 KUNIT_EXPECT_EQ(test, 2303 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 2304 1); 2305 2306 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2307 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes); 2308 2309 /* Start the firmware and the cached data should be written to registers */ 2310 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2311 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2312 2313 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2314 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 2315 2316 /* Control should readback the new data from the control cache */ 2317 KUNIT_EXPECT_EQ(test, 2318 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2319 0); 2320 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 2321 } 2322 2323 /* 2324 * Write to a cached control that is not in the currently loaded firmware. 2325 * The value written to the cache should be synced out to the registers 2326 * backing the control the next time the firmware containing the 2327 * control is run. 2328 */ 2329 static void cs_dsp_ctl_cache_sync_write_not_current_fw(struct kunit *test) 2330 { 2331 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 2332 struct cs_dsp_test *priv = test->priv; 2333 struct cs_dsp_test_local *local = priv->local; 2334 struct cs_dsp *dsp = priv->dsp; 2335 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 2336 int alg_idx = _find_alg_entry(test, param->alg_id); 2337 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test); 2338 unsigned int reg, alg_base_words; 2339 struct cs_dsp_coeff_ctl *ctl; 2340 struct firmware *wmfw; 2341 u32 *reg_vals, *readback; 2342 2343 reg_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2344 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reg_vals); 2345 2346 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2347 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 2348 2349 /* Create some DSP data to be read into the control cache */ 2350 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 2351 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 2352 reg += (alg_base_words + param->offs_words) * 2353 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 2354 regmap_raw_write(dsp->regmap, reg, reg_vals, param->len_bytes); 2355 2356 /* Create control pointing to this data */ 2357 def.flags = param->flags; 2358 def.mem_type = param->mem_type; 2359 def.offset_dsp_words = param->offs_words; 2360 def.length_bytes = param->len_bytes; 2361 2362 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 2363 cs_dsp_ctl_cache_test_algs[alg_idx].id, 2364 "dummyalg", NULL); 2365 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 2366 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 2367 2368 /* Power-up DSP but don't start firmware */ 2369 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2370 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2371 2372 /* Get the control */ 2373 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 2374 KUNIT_ASSERT_NOT_NULL(test, ctl); 2375 2376 /* Power-down DSP then power-up with a different firmware */ 2377 cs_dsp_power_down(dsp); 2378 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 2379 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0); 2380 2381 /* Write new data to the control, it should not be written to the registers */ 2382 get_random_bytes(reg_vals, param->len_bytes); 2383 KUNIT_EXPECT_EQ(test, 2384 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, reg_vals, param->len_bytes), 2385 1); 2386 2387 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2388 KUNIT_EXPECT_MEMNEQ(test, readback, reg_vals, param->len_bytes); 2389 2390 /* Power-down DSP then power-up with the original firmware */ 2391 cs_dsp_power_down(dsp); 2392 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2393 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2394 2395 /* Start the firmware and the cached data should be written to registers */ 2396 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2397 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2398 2399 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2400 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 2401 2402 /* Control should readback the new data from the control cache */ 2403 KUNIT_EXPECT_EQ(test, 2404 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2405 0); 2406 KUNIT_EXPECT_MEMEQ(test, readback, reg_vals, param->len_bytes); 2407 } 2408 2409 /* 2410 * The value in the control cache should be synced out to the registers 2411 * backing the control every time the firmware containing the control 2412 * is run. 2413 */ 2414 static void cs_dsp_ctl_cache_sync_reapply_every_run(struct kunit *test) 2415 { 2416 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 2417 struct cs_dsp_test *priv = test->priv; 2418 struct cs_dsp_test_local *local = priv->local; 2419 struct cs_dsp *dsp = priv->dsp; 2420 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 2421 int alg_idx = _find_alg_entry(test, param->alg_id); 2422 unsigned int reg, alg_base_words; 2423 struct cs_dsp_coeff_ctl *ctl; 2424 struct firmware *wmfw; 2425 u32 *init_vals, *readback, *ctl_vals; 2426 2427 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2428 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals); 2429 2430 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2431 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 2432 2433 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 2434 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals); 2435 2436 /* Zero-fill the registers backing the control */ 2437 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 2438 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 2439 reg += (alg_base_words + param->offs_words) * 2440 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 2441 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2442 2443 /* Create control pointing to this data */ 2444 def.flags = param->flags; 2445 def.mem_type = param->mem_type; 2446 def.offset_dsp_words = param->offs_words; 2447 def.length_bytes = param->len_bytes; 2448 2449 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 2450 cs_dsp_ctl_cache_test_algs[alg_idx].id, 2451 "dummyalg", NULL); 2452 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 2453 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 2454 2455 /* Power-up DSP but don't start firmware */ 2456 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2457 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2458 2459 /* Write new data to the control */ 2460 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 2461 KUNIT_ASSERT_NOT_NULL(test, ctl); 2462 2463 get_random_bytes(ctl_vals, param->len_bytes); 2464 KUNIT_EXPECT_EQ(test, 2465 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes), 2466 1); 2467 2468 /* Start the firmware and the cached data should be written to registers */ 2469 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2470 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2471 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2472 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2473 2474 /* Stop the firmware and reset the registers */ 2475 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp); 2476 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2477 2478 /* Start the firmware again and the cached data should be written to registers */ 2479 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2480 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2481 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2482 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2483 2484 /* Control should readback the new data from the control cache */ 2485 KUNIT_EXPECT_EQ(test, 2486 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2487 0); 2488 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2489 } 2490 2491 /* 2492 * The value in the control cache should be retained if the same 2493 * firmware is downloaded again. It should be synced out to the 2494 * registers backing the control after the firmware containing the 2495 * control is downloaded again and run. 2496 */ 2497 static void cs_dsp_ctl_cache_sync_reapply_after_fw_reload(struct kunit *test) 2498 { 2499 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 2500 struct cs_dsp_test *priv = test->priv; 2501 struct cs_dsp_test_local *local = priv->local; 2502 struct cs_dsp *dsp = priv->dsp; 2503 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 2504 int alg_idx = _find_alg_entry(test, param->alg_id); 2505 unsigned int reg, alg_base_words; 2506 struct cs_dsp_coeff_ctl *ctl; 2507 struct firmware *wmfw; 2508 u32 *init_vals, *readback, *ctl_vals; 2509 2510 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2511 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals); 2512 2513 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2514 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 2515 2516 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 2517 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals); 2518 2519 /* Zero-fill the registers backing the control */ 2520 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 2521 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 2522 reg += (alg_base_words + param->offs_words) * 2523 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 2524 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2525 2526 /* Create control pointing to this data */ 2527 def.flags = param->flags; 2528 def.mem_type = param->mem_type; 2529 def.offset_dsp_words = param->offs_words; 2530 def.length_bytes = param->len_bytes; 2531 2532 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 2533 cs_dsp_ctl_cache_test_algs[alg_idx].id, 2534 "dummyalg", NULL); 2535 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 2536 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 2537 2538 /* Power-up DSP but don't start firmware */ 2539 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2540 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2541 2542 /* Write new data to the control */ 2543 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 2544 KUNIT_ASSERT_NOT_NULL(test, ctl); 2545 2546 get_random_bytes(ctl_vals, param->len_bytes); 2547 KUNIT_EXPECT_EQ(test, 2548 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes), 2549 1); 2550 2551 /* Start the firmware and the cached data should be written to registers */ 2552 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2553 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2554 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2555 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2556 2557 /* Stop the firmware and power-down the DSP */ 2558 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp); 2559 cs_dsp_power_down(dsp); 2560 2561 /* Reset the registers */ 2562 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2563 2564 /* Download the firmware again, the cache content should not change */ 2565 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2566 2567 /* Start the firmware and the cached data should be written to registers */ 2568 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2569 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2570 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2571 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2572 2573 /* Control should readback the new data from the control cache */ 2574 KUNIT_EXPECT_EQ(test, 2575 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2576 0); 2577 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2578 } 2579 2580 /* 2581 * The value in the control cache should be retained after a different 2582 * firmware is downloaded. 2583 * When the firmware containing the control is downloaded and run 2584 * the value in the control cache should be synced out to the registers 2585 * backing the control. 2586 */ 2587 static void cs_dsp_ctl_cache_sync_reapply_after_fw_swap(struct kunit *test) 2588 { 2589 const struct cs_dsp_ctl_cache_test_param *param = test->param_value; 2590 struct cs_dsp_test *priv = test->priv; 2591 struct cs_dsp_test_local *local = priv->local; 2592 struct cs_dsp *dsp = priv->dsp; 2593 struct cs_dsp_mock_coeff_def def = mock_coeff_template; 2594 int alg_idx = _find_alg_entry(test, param->alg_id); 2595 struct cs_dsp_mock_wmfw_builder *builder2 = _create_dummy_wmfw(test); 2596 unsigned int reg, alg_base_words; 2597 struct cs_dsp_coeff_ctl *ctl; 2598 struct firmware *wmfw; 2599 u32 *init_vals, *readback, *ctl_vals; 2600 2601 init_vals = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2602 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, init_vals); 2603 2604 readback = kunit_kzalloc(test, param->len_bytes, GFP_KERNEL); 2605 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, readback); 2606 2607 ctl_vals = kunit_kmalloc(test, param->len_bytes, GFP_KERNEL); 2608 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctl_vals); 2609 2610 /* Zero-fill the registers backing the control */ 2611 alg_base_words = _get_alg_mem_base_words(test, alg_idx, param->mem_type); 2612 reg = cs_dsp_mock_base_addr_for_mem(priv, param->mem_type); 2613 reg += (alg_base_words + param->offs_words) * 2614 cs_dsp_mock_reg_addr_inc_per_unpacked_word(priv); 2615 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2616 2617 /* Create control pointing to this data */ 2618 def.flags = param->flags; 2619 def.mem_type = param->mem_type; 2620 def.offset_dsp_words = param->offs_words; 2621 def.length_bytes = param->len_bytes; 2622 2623 cs_dsp_mock_wmfw_start_alg_info_block(local->wmfw_builder, 2624 cs_dsp_ctl_cache_test_algs[alg_idx].id, 2625 "dummyalg", NULL); 2626 cs_dsp_mock_wmfw_add_coeff_desc(local->wmfw_builder, &def); 2627 cs_dsp_mock_wmfw_end_alg_info_block(local->wmfw_builder); 2628 2629 /* Power-up DSP but don't start firmware */ 2630 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2631 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2632 2633 /* Write new data to the control */ 2634 ctl = list_first_entry_or_null(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list); 2635 KUNIT_ASSERT_NOT_NULL(test, ctl); 2636 2637 get_random_bytes(ctl_vals, param->len_bytes); 2638 KUNIT_EXPECT_EQ(test, 2639 cs_dsp_coeff_lock_and_write_ctrl(ctl, 0, ctl_vals, param->len_bytes), 2640 1); 2641 2642 /* Start the firmware and the cached data should be written to registers */ 2643 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2644 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2645 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2646 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2647 2648 /* Stop the firmware and power-down the DSP */ 2649 kunit_release_action(test, _cs_dsp_stop_wrapper, dsp); 2650 cs_dsp_power_down(dsp); 2651 2652 /* Reset the registers */ 2653 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2654 2655 /* Download and run a different firmware */ 2656 wmfw = cs_dsp_mock_wmfw_get_firmware(builder2); 2657 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw2", NULL, NULL, "mbc.vss"), 0); 2658 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2659 cs_dsp_power_down(dsp); 2660 2661 /* Reset the registers */ 2662 regmap_raw_write(dsp->regmap, reg, init_vals, param->len_bytes); 2663 2664 /* Download the original firmware again */ 2665 wmfw = cs_dsp_mock_wmfw_get_firmware(priv->local->wmfw_builder); 2666 KUNIT_ASSERT_EQ(test, cs_dsp_power_up(dsp, wmfw, "mock_fw", NULL, NULL, "misc"), 0); 2667 KUNIT_EXPECT_TRUE(test, ctl->set); 2668 2669 /* Start the firmware and the cached data should be written to registers */ 2670 KUNIT_ASSERT_EQ(test, cs_dsp_run(dsp), 0); 2671 KUNIT_ASSERT_EQ(test, kunit_add_action_or_reset(test, _cs_dsp_stop_wrapper, dsp), 0); 2672 KUNIT_EXPECT_EQ(test, regmap_raw_read(dsp->regmap, reg, readback, param->len_bytes), 0); 2673 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2674 2675 /* Control should readback the new data from the control cache */ 2676 KUNIT_EXPECT_EQ(test, 2677 cs_dsp_coeff_lock_and_read_ctrl(ctl, 0, readback, param->len_bytes), 2678 0); 2679 KUNIT_EXPECT_MEMEQ(test, readback, ctl_vals, param->len_bytes); 2680 } 2681 2682 static int cs_dsp_ctl_cache_test_common_init(struct kunit *test, struct cs_dsp *dsp, 2683 int wmfw_version) 2684 { 2685 struct cs_dsp_test *priv; 2686 struct cs_dsp_test_local *local; 2687 struct device *test_dev; 2688 int ret; 2689 2690 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 2691 if (!priv) 2692 return -ENOMEM; 2693 2694 local = kunit_kzalloc(test, sizeof(struct cs_dsp_test_local), GFP_KERNEL); 2695 if (!local) 2696 return -ENOMEM; 2697 2698 priv->test = test; 2699 priv->dsp = dsp; 2700 test->priv = priv; 2701 priv->local = local; 2702 priv->local->wmfw_version = wmfw_version; 2703 2704 /* Create dummy struct device */ 2705 test_dev = kunit_device_register(test, "cs_dsp_test_drv"); 2706 if (IS_ERR(test_dev)) 2707 return PTR_ERR(test_dev); 2708 2709 dsp->dev = get_device(test_dev); 2710 if (!dsp->dev) 2711 return -ENODEV; 2712 2713 ret = kunit_add_action_or_reset(test, _put_device_wrapper, dsp->dev); 2714 if (ret) 2715 return ret; 2716 2717 dev_set_drvdata(dsp->dev, priv); 2718 2719 /* Allocate regmap */ 2720 ret = cs_dsp_mock_regmap_init(priv); 2721 if (ret) 2722 return ret; 2723 2724 /* 2725 * There must always be a XM header with at least 1 algorithm, so create 2726 * a dummy one that tests can use and extract it to a data blob. 2727 */ 2728 local->xm_header = cs_dsp_create_mock_xm_header(priv, 2729 cs_dsp_ctl_cache_test_algs, 2730 ARRAY_SIZE(cs_dsp_ctl_cache_test_algs)); 2731 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, local->xm_header); 2732 2733 /* Create wmfw builder */ 2734 local->wmfw_builder = _create_dummy_wmfw(test); 2735 2736 /* Init cs_dsp */ 2737 dsp->client_ops = kunit_kzalloc(test, sizeof(*dsp->client_ops), GFP_KERNEL); 2738 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dsp->client_ops); 2739 2740 switch (dsp->type) { 2741 case WMFW_ADSP2: 2742 ret = cs_dsp_adsp2_init(dsp); 2743 break; 2744 case WMFW_HALO: 2745 ret = cs_dsp_halo_init(dsp); 2746 break; 2747 default: 2748 KUNIT_FAIL(test, "Untested DSP type %d\n", dsp->type); 2749 return -EINVAL; 2750 } 2751 2752 if (ret) 2753 return ret; 2754 2755 /* Automatically call cs_dsp_remove() when test case ends */ 2756 return kunit_add_action_or_reset(priv->test, _cs_dsp_remove_wrapper, dsp); 2757 } 2758 2759 static int cs_dsp_ctl_cache_test_halo_init(struct kunit *test) 2760 { 2761 struct cs_dsp *dsp; 2762 2763 /* Fill in cs_dsp and initialize */ 2764 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); 2765 if (!dsp) 2766 return -ENOMEM; 2767 2768 dsp->num = 1; 2769 dsp->type = WMFW_HALO; 2770 dsp->mem = cs_dsp_mock_halo_dsp1_regions; 2771 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_halo_dsp1_region_sizes); 2772 dsp->base = cs_dsp_mock_halo_core_base; 2773 dsp->base_sysinfo = cs_dsp_mock_halo_sysinfo_base; 2774 2775 return cs_dsp_ctl_cache_test_common_init(test, dsp, 3); 2776 } 2777 2778 static int cs_dsp_ctl_cache_test_adsp2_32bit_init(struct kunit *test, int wmfw_ver) 2779 { 2780 struct cs_dsp *dsp; 2781 2782 /* Fill in cs_dsp and initialize */ 2783 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); 2784 if (!dsp) 2785 return -ENOMEM; 2786 2787 dsp->num = 1; 2788 dsp->type = WMFW_ADSP2; 2789 dsp->rev = 1; 2790 dsp->mem = cs_dsp_mock_adsp2_32bit_dsp1_regions; 2791 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_32bit_dsp1_region_sizes); 2792 dsp->base = cs_dsp_mock_adsp2_32bit_sysbase; 2793 2794 return cs_dsp_ctl_cache_test_common_init(test, dsp, wmfw_ver); 2795 } 2796 2797 static int cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init(struct kunit *test) 2798 { 2799 return cs_dsp_ctl_cache_test_adsp2_32bit_init(test, 1); 2800 } 2801 2802 static int cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init(struct kunit *test) 2803 { 2804 return cs_dsp_ctl_cache_test_adsp2_32bit_init(test, 2); 2805 } 2806 2807 static int cs_dsp_ctl_cache_test_adsp2_16bit_init(struct kunit *test, int wmfw_ver) 2808 { 2809 struct cs_dsp *dsp; 2810 2811 /* Fill in cs_dsp and initialize */ 2812 dsp = kunit_kzalloc(test, sizeof(*dsp), GFP_KERNEL); 2813 if (!dsp) 2814 return -ENOMEM; 2815 2816 dsp->num = 1; 2817 dsp->type = WMFW_ADSP2; 2818 dsp->rev = 0; 2819 dsp->mem = cs_dsp_mock_adsp2_16bit_dsp1_regions; 2820 dsp->num_mems = cs_dsp_mock_count_regions(cs_dsp_mock_adsp2_16bit_dsp1_region_sizes); 2821 dsp->base = cs_dsp_mock_adsp2_16bit_sysbase; 2822 2823 return cs_dsp_ctl_cache_test_common_init(test, dsp, wmfw_ver); 2824 } 2825 2826 static int cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init(struct kunit *test) 2827 { 2828 return cs_dsp_ctl_cache_test_adsp2_16bit_init(test, 1); 2829 } 2830 2831 static int cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init(struct kunit *test) 2832 { 2833 return cs_dsp_ctl_cache_test_adsp2_16bit_init(test, 2); 2834 } 2835 2836 static void cs_dsp_ctl_all_param_desc(const struct cs_dsp_ctl_cache_test_param *param, 2837 char *desc) 2838 { 2839 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "alg:%#x %s@%u len:%u flags:%#x", 2840 param->alg_id, cs_dsp_mem_region_name(param->mem_type), 2841 param->offs_words, param->len_bytes, param->flags); 2842 } 2843 2844 /* All parameters populated, with various lengths */ 2845 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_len_cases[] = { 2846 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 }, 2847 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 8 }, 2848 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 12 }, 2849 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 16 }, 2850 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 48 }, 2851 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 100 }, 2852 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512 }, 2853 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 1000 }, 2854 }; 2855 KUNIT_ARRAY_PARAM(all_pop_varying_len, all_pop_varying_len_cases, 2856 cs_dsp_ctl_all_param_desc); 2857 2858 /* All parameters populated, with various offsets */ 2859 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_offset_cases[] = { 2860 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 0, .len_bytes = 4 }, 2861 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 }, 2862 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 2, .len_bytes = 4 }, 2863 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 3, .len_bytes = 4 }, 2864 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 8, .len_bytes = 4 }, 2865 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 10, .len_bytes = 4 }, 2866 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 128, .len_bytes = 4 }, 2867 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 180, .len_bytes = 4 }, 2868 }; 2869 KUNIT_ARRAY_PARAM(all_pop_varying_offset, all_pop_varying_offset_cases, 2870 cs_dsp_ctl_all_param_desc); 2871 2872 /* All parameters populated, with various X and Y memory regions */ 2873 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_xy_cases[] = { 2874 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_XM, .offs_words = 1, .len_bytes = 4 }, 2875 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 }, 2876 }; 2877 KUNIT_ARRAY_PARAM(all_pop_varying_xy, all_pop_varying_xy_cases, 2878 cs_dsp_ctl_all_param_desc); 2879 2880 /* All parameters populated, using ZM */ 2881 static const struct cs_dsp_ctl_cache_test_param all_pop_z_cases[] = { 2882 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_ZM, .offs_words = 1, .len_bytes = 4 }, 2883 }; 2884 KUNIT_ARRAY_PARAM(all_pop_z, all_pop_z_cases, cs_dsp_ctl_all_param_desc); 2885 2886 /* All parameters populated, with various algorithm ids */ 2887 static const struct cs_dsp_ctl_cache_test_param all_pop_varying_alg_cases[] = { 2888 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 }, 2889 { .alg_id = 0xb, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 }, 2890 { .alg_id = 0x9f1234, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 }, 2891 { .alg_id = 0xff00ff, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4 }, 2892 }; 2893 KUNIT_ARRAY_PARAM(all_pop_varying_alg, all_pop_varying_alg_cases, 2894 cs_dsp_ctl_all_param_desc); 2895 2896 /* 2897 * All parameters populated, with all combinations of flags for a 2898 * non-volatile readable control 2899 */ 2900 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_readable_flags_cases[] = { 2901 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2902 .flags = 0 2903 }, 2904 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2905 .flags = WMFW_CTL_FLAG_READABLE, 2906 }, 2907 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2908 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE, 2909 }, 2910 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2911 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE, 2912 }, 2913 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2914 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE, 2915 }, 2916 }; 2917 KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_flags, 2918 all_pop_nonvol_readable_flags_cases, 2919 cs_dsp_ctl_all_param_desc); 2920 2921 /* 2922 * All parameters populated, with all combinations of flags for a 2923 * non-volatile readable control, except flags==0 2924 */ 2925 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_readable_nonzero_flags_cases[] = { 2926 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2927 .flags = WMFW_CTL_FLAG_READABLE, 2928 }, 2929 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2930 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE, 2931 }, 2932 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2933 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE, 2934 }, 2935 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2936 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE, 2937 }, 2938 }; 2939 KUNIT_ARRAY_PARAM(all_pop_nonvol_readable_nonzero_flags, 2940 all_pop_nonvol_readable_nonzero_flags_cases, 2941 cs_dsp_ctl_all_param_desc); 2942 2943 /* 2944 * All parameters populated, with all combinations of flags for a 2945 * non-volatile writeable control 2946 */ 2947 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_writeable_flags_cases[] = { 2948 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2949 .flags = 0 2950 }, 2951 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2952 .flags = WMFW_CTL_FLAG_WRITEABLE, 2953 }, 2954 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2955 .flags = WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE, 2956 }, 2957 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2958 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE, 2959 }, 2960 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2961 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_READABLE | WMFW_CTL_FLAG_WRITEABLE, 2962 }, 2963 }; 2964 KUNIT_ARRAY_PARAM(all_pop_nonvol_writeable_flags, 2965 all_pop_nonvol_writeable_flags_cases, 2966 cs_dsp_ctl_all_param_desc); 2967 2968 /* 2969 * All parameters populated, with all combinations of flags for a 2970 * non-volatile write-only control of varying lengths 2971 */ 2972 static const struct cs_dsp_ctl_cache_test_param all_pop_nonvol_write_only_length_cases[] = { 2973 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2974 .flags = WMFW_CTL_FLAG_WRITEABLE, 2975 }, 2976 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512, 2977 .flags = WMFW_CTL_FLAG_WRITEABLE, 2978 }, 2979 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 4, 2980 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE, 2981 }, 2982 { .alg_id = 0xfafa, .mem_type = WMFW_ADSP2_YM, .offs_words = 1, .len_bytes = 512, 2983 .flags = WMFW_CTL_FLAG_SYS | WMFW_CTL_FLAG_WRITEABLE, 2984 }, 2985 }; 2986 KUNIT_ARRAY_PARAM(all_pop_nonvol_write_only_length, 2987 all_pop_nonvol_write_only_length_cases, 2988 cs_dsp_ctl_all_param_desc); 2989 2990 static struct kunit_case cs_dsp_ctl_cache_test_cases_v1[] = { 2991 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params), 2992 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params), 2993 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params), 2994 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_z_gen_params), 2995 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params), 2996 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params), 2997 2998 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only, 2999 all_pop_nonvol_write_only_length_gen_params), 3000 3001 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls), 3002 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls), 3003 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems), 3004 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs), 3005 3006 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started, 3007 all_pop_nonvol_readable_flags_gen_params), 3008 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped, 3009 all_pop_nonvol_readable_flags_gen_params), 3010 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down, 3011 all_pop_nonvol_readable_flags_gen_params), 3012 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down, 3013 all_pop_nonvol_readable_flags_gen_params), 3014 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw, 3015 all_pop_nonvol_readable_flags_gen_params), 3016 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw, 3017 all_pop_nonvol_readable_flags_gen_params), 3018 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running, 3019 all_pop_nonvol_readable_nonzero_flags_gen_params), 3020 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running_zero_flags, 3021 all_pop_varying_len_gen_params), 3022 3023 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params), 3024 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params), 3025 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params), 3026 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_z_gen_params), 3027 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params), 3028 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params), 3029 3030 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3031 all_pop_varying_len_gen_params), 3032 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3033 all_pop_varying_offset_gen_params), 3034 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3035 all_pop_varying_xy_gen_params), 3036 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3037 all_pop_z_gen_params), 3038 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3039 all_pop_varying_alg_gen_params), 3040 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3041 all_pop_nonvol_writeable_flags_gen_params), 3042 3043 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started, 3044 all_pop_nonvol_writeable_flags_gen_params), 3045 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started, 3046 all_pop_nonvol_writeable_flags_gen_params), 3047 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped, 3048 all_pop_nonvol_writeable_flags_gen_params), 3049 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down, 3050 all_pop_nonvol_writeable_flags_gen_params), 3051 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down, 3052 all_pop_nonvol_writeable_flags_gen_params), 3053 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw, 3054 all_pop_nonvol_writeable_flags_gen_params), 3055 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw, 3056 all_pop_nonvol_writeable_flags_gen_params), 3057 3058 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run, 3059 all_pop_nonvol_writeable_flags_gen_params), 3060 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running, 3061 all_pop_nonvol_writeable_flags_gen_params), 3062 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop, 3063 all_pop_nonvol_writeable_flags_gen_params), 3064 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw, 3065 all_pop_nonvol_writeable_flags_gen_params), 3066 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run, 3067 all_pop_nonvol_writeable_flags_gen_params), 3068 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload, 3069 all_pop_nonvol_writeable_flags_gen_params), 3070 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap, 3071 all_pop_nonvol_writeable_flags_gen_params), 3072 3073 { } /* terminator */ 3074 }; 3075 3076 static struct kunit_case cs_dsp_ctl_cache_test_cases_v2[] = { 3077 KUNIT_CASE(cs_dsp_ctl_v2_cache_alloc), 3078 3079 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params), 3080 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params), 3081 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params), 3082 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_z_gen_params), 3083 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params), 3084 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params), 3085 3086 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only, 3087 all_pop_nonvol_write_only_length_gen_params), 3088 3089 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls), 3090 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls), 3091 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems), 3092 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs), 3093 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_offsets), 3094 3095 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started, 3096 all_pop_nonvol_readable_flags_gen_params), 3097 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped, 3098 all_pop_nonvol_readable_flags_gen_params), 3099 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down, 3100 all_pop_nonvol_readable_flags_gen_params), 3101 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down, 3102 all_pop_nonvol_readable_flags_gen_params), 3103 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw, 3104 all_pop_nonvol_readable_flags_gen_params), 3105 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw, 3106 all_pop_nonvol_readable_flags_gen_params), 3107 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running, 3108 all_pop_nonvol_readable_nonzero_flags_gen_params), 3109 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running_zero_flags, 3110 all_pop_varying_len_gen_params), 3111 3112 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params), 3113 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params), 3114 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params), 3115 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_z_gen_params), 3116 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params), 3117 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params), 3118 3119 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3120 all_pop_varying_len_gen_params), 3121 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3122 all_pop_varying_offset_gen_params), 3123 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3124 all_pop_varying_xy_gen_params), 3125 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3126 all_pop_z_gen_params), 3127 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3128 all_pop_varying_alg_gen_params), 3129 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3130 all_pop_nonvol_writeable_flags_gen_params), 3131 3132 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started, 3133 all_pop_nonvol_writeable_flags_gen_params), 3134 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started, 3135 all_pop_nonvol_writeable_flags_gen_params), 3136 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped, 3137 all_pop_nonvol_writeable_flags_gen_params), 3138 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down, 3139 all_pop_nonvol_writeable_flags_gen_params), 3140 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down, 3141 all_pop_nonvol_writeable_flags_gen_params), 3142 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw, 3143 all_pop_nonvol_writeable_flags_gen_params), 3144 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw, 3145 all_pop_nonvol_writeable_flags_gen_params), 3146 3147 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run, 3148 all_pop_nonvol_writeable_flags_gen_params), 3149 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running, 3150 all_pop_nonvol_writeable_flags_gen_params), 3151 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop, 3152 all_pop_nonvol_writeable_flags_gen_params), 3153 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw, 3154 all_pop_nonvol_writeable_flags_gen_params), 3155 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run, 3156 all_pop_nonvol_writeable_flags_gen_params), 3157 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload, 3158 all_pop_nonvol_writeable_flags_gen_params), 3159 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap, 3160 all_pop_nonvol_writeable_flags_gen_params), 3161 3162 { } /* terminator */ 3163 }; 3164 3165 static struct kunit_case cs_dsp_ctl_cache_test_cases_v3[] = { 3166 KUNIT_CASE(cs_dsp_ctl_v2_cache_alloc), 3167 3168 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_len_gen_params), 3169 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_offset_gen_params), 3170 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_xy_gen_params), 3171 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_varying_alg_gen_params), 3172 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init, all_pop_nonvol_readable_flags_gen_params), 3173 3174 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_init_write_only, 3175 all_pop_nonvol_write_only_length_gen_params), 3176 3177 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fw_same_controls), 3178 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_fwalgid_same_controls), 3179 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_mems), 3180 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_algs), 3181 KUNIT_CASE(cs_dsp_ctl_cache_init_multiple_offsets), 3182 3183 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_started, 3184 all_pop_nonvol_readable_flags_gen_params), 3185 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped, 3186 all_pop_nonvol_readable_flags_gen_params), 3187 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_powered_down, 3188 all_pop_nonvol_readable_flags_gen_params), 3189 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_stopped_powered_down, 3190 all_pop_nonvol_readable_flags_gen_params), 3191 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_loaded_fw, 3192 all_pop_nonvol_readable_flags_gen_params), 3193 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_not_current_running_fw, 3194 all_pop_nonvol_readable_flags_gen_params), 3195 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_read_running, 3196 all_pop_nonvol_readable_nonzero_flags_gen_params), 3197 3198 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_len_gen_params), 3199 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_offset_gen_params), 3200 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_xy_gen_params), 3201 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_varying_alg_gen_params), 3202 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough, all_pop_nonvol_writeable_flags_gen_params), 3203 3204 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3205 all_pop_varying_len_gen_params), 3206 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3207 all_pop_varying_offset_gen_params), 3208 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3209 all_pop_varying_xy_gen_params), 3210 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3211 all_pop_varying_alg_gen_params), 3212 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_writethrough_unchanged, 3213 all_pop_nonvol_writeable_flags_gen_params), 3214 3215 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_unchanged_not_started, 3216 all_pop_nonvol_writeable_flags_gen_params), 3217 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_started, 3218 all_pop_nonvol_writeable_flags_gen_params), 3219 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped, 3220 all_pop_nonvol_writeable_flags_gen_params), 3221 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_powered_down, 3222 all_pop_nonvol_writeable_flags_gen_params), 3223 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_stopped_powered_down, 3224 all_pop_nonvol_writeable_flags_gen_params), 3225 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_loaded_fw, 3226 all_pop_nonvol_writeable_flags_gen_params), 3227 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_write_not_current_running_fw, 3228 all_pop_nonvol_writeable_flags_gen_params), 3229 3230 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_before_run, 3231 all_pop_nonvol_writeable_flags_gen_params), 3232 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_while_running, 3233 all_pop_nonvol_writeable_flags_gen_params), 3234 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_after_stop, 3235 all_pop_nonvol_writeable_flags_gen_params), 3236 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_write_not_current_fw, 3237 all_pop_nonvol_writeable_flags_gen_params), 3238 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_every_run, 3239 all_pop_nonvol_writeable_flags_gen_params), 3240 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_reload, 3241 all_pop_nonvol_writeable_flags_gen_params), 3242 KUNIT_CASE_PARAM(cs_dsp_ctl_cache_sync_reapply_after_fw_swap, 3243 all_pop_nonvol_writeable_flags_gen_params), 3244 3245 { } /* terminator */ 3246 }; 3247 3248 static struct kunit_suite cs_dsp_ctl_cache_test_halo = { 3249 .name = "cs_dsp_ctl_cache_wmfwV3_halo", 3250 .init = cs_dsp_ctl_cache_test_halo_init, 3251 .test_cases = cs_dsp_ctl_cache_test_cases_v3, 3252 }; 3253 3254 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1 = { 3255 .name = "cs_dsp_ctl_cache_wmfwV1_adsp2_32bit", 3256 .init = cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1_init, 3257 .test_cases = cs_dsp_ctl_cache_test_cases_v1, 3258 }; 3259 3260 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2 = { 3261 .name = "cs_dsp_ctl_cache_wmfwV2_adsp2_32bit", 3262 .init = cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2_init, 3263 .test_cases = cs_dsp_ctl_cache_test_cases_v2, 3264 }; 3265 3266 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1 = { 3267 .name = "cs_dsp_ctl_cache_wmfwV1_adsp2_16bit", 3268 .init = cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1_init, 3269 .test_cases = cs_dsp_ctl_cache_test_cases_v1, 3270 }; 3271 3272 static struct kunit_suite cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2 = { 3273 .name = "cs_dsp_ctl_cache_wmfwV2_adsp2_16bit", 3274 .init = cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2_init, 3275 .test_cases = cs_dsp_ctl_cache_test_cases_v2, 3276 }; 3277 3278 kunit_test_suites(&cs_dsp_ctl_cache_test_halo, 3279 &cs_dsp_ctl_cache_test_adsp2_32bit_wmfw1, 3280 &cs_dsp_ctl_cache_test_adsp2_32bit_wmfw2, 3281 &cs_dsp_ctl_cache_test_adsp2_16bit_wmfw1, 3282 &cs_dsp_ctl_cache_test_adsp2_16bit_wmfw2); 3283