1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // KUnit test for the Cirrus Logic cs35l56-shared module. 4 // 5 // Copyright (C) 2026 Cirrus Logic, Inc. and 6 // Cirrus Logic International Semiconductor Ltd. 7 8 #include <kunit/resource.h> 9 #include <kunit/test.h> 10 #include <kunit/static_stub.h> 11 #include <linux/bitfield.h> 12 #include <linux/bitops.h> 13 #include <linux/device/faux.h> 14 #include <linux/module.h> 15 #include <linux/random.h> 16 #include <linux/regmap.h> 17 #include <linux/seq_buf.h> 18 #include <sound/cs35l56.h> 19 20 struct cs35l56_shared_test_priv { 21 struct kunit *test; 22 struct faux_device *amp_dev; 23 struct regmap *registers; 24 struct cs35l56_base *cs35l56_base; 25 u8 applied_pad_pull_state[CS35L56_MAX_GPIO]; 26 }; 27 28 struct cs35l56_shared_test_param { 29 int spkid_gpios[4]; 30 int spkid_pulls[4]; 31 unsigned long gpio_status; 32 int spkid; 33 }; 34 35 KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy, 36 struct faux_device *) 37 38 KUNIT_DEFINE_ACTION_WRAPPER(regmap_exit_wrapper, regmap_exit, struct regmap *) 39 40 static const struct regmap_config cs35l56_shared_test_mock_registers_regmap = { 41 .reg_bits = 32, 42 .val_bits = 32, 43 .reg_stride = 4, 44 .max_register = CS35L56_DSP1_PMEM_5114, 45 .cache_type = REGCACHE_MAPLE, 46 }; 47 48 static const struct regmap_bus cs35l56_shared_test_mock_registers_regmap_bus = { 49 /* No handlers because it is always in cache-only */ 50 }; 51 52 static unsigned int cs35l56_shared_test_read_gpio_status(struct cs35l56_shared_test_priv *priv) 53 { 54 const struct cs35l56_shared_test_param *param = priv->test->param_value; 55 unsigned int reg_offs, pad_cfg, val; 56 unsigned int status = 0; 57 unsigned int mask = 1; 58 59 for (reg_offs = 0; reg_offs < CS35L56_MAX_GPIO * sizeof(u32); reg_offs += sizeof(u32)) { 60 regmap_read(priv->registers, CS35L56_SYNC_GPIO1_CFG + reg_offs, &pad_cfg); 61 regmap_read(priv->registers, CS35L56_GPIO1_CTRL1 + reg_offs, &val); 62 63 /* Only read a value if set as an input pin and as a GPIO */ 64 val &= (CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_MASK); 65 if ((pad_cfg & CS35L56_PAD_GPIO_IE) && 66 (val == (CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_GPIO))) 67 status |= (param->gpio_status & mask); 68 69 mask <<= 1; 70 } 71 72 return status; 73 } 74 75 static int cs35l56_shared_test_updt_gpio_pres(struct cs35l56_shared_test_priv *priv, 76 unsigned int reg, unsigned int val) 77 { 78 int i, ret; 79 80 ret = regmap_write(priv->registers, reg, val); 81 if (ret) 82 return ret; 83 84 if (val & CS35L56_UPDT_GPIO_PRES) { 85 /* Simulate transferring register state to internal latches */ 86 for (i = 0; i < ARRAY_SIZE(priv->applied_pad_pull_state); i++) { 87 reg = CS35L56_SYNC_GPIO1_CFG + (i * sizeof(u32)); 88 regmap_read(priv->registers, reg, &val); 89 val = FIELD_GET(CS35L56_PAD_GPIO_PULL_MASK, val); 90 priv->applied_pad_pull_state[i] = val; 91 } 92 } 93 94 return 0; 95 } 96 97 static int cs35l56_shared_test_reg_read(void *context, unsigned int reg, unsigned int *val) 98 { 99 struct cs35l56_shared_test_priv *priv = context; 100 101 switch (reg) { 102 case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG: 103 case CS35L56_GPIO1_CTRL1 ... CS35L56_GPIO13_CTRL1: 104 return regmap_read(priv->registers, reg, val); 105 case CS35L56_UPDATE_REGS: 106 *val = 0; 107 return 0; 108 case CS35L56_GPIO_STATUS1: 109 *val = cs35l56_shared_test_read_gpio_status(priv); 110 return 0; 111 default: 112 kunit_fail_current_test("Bad regmap read address %#x\n", reg); 113 return -EINVAL; 114 } 115 } 116 117 static int cs35l56_shared_test_reg_write(void *context, unsigned int reg, unsigned int val) 118 { 119 struct cs35l56_shared_test_priv *priv = context; 120 121 switch (reg) { 122 case CS35L56_UPDATE_REGS: 123 return cs35l56_shared_test_updt_gpio_pres(priv, reg, val); 124 case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG: 125 case CS35L56_GPIO1_CTRL1 ... CS35L56_GPIO13_CTRL1: 126 return regmap_write(priv->registers, reg, val); 127 default: 128 kunit_fail_current_test("Bad regmap write address %#x\n", reg); 129 return -EINVAL; 130 } 131 } 132 133 static const struct regmap_bus cs35l56_shared_test_regmap_bus = { 134 .reg_read = cs35l56_shared_test_reg_read, 135 .reg_write = cs35l56_shared_test_reg_write, 136 .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, 137 .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 138 }; 139 140 /* 141 * Self-test that the mock GPIO registers obey the configuration bits. 142 * Other tests rely on the mocked registers only returning a GPIO state 143 * if the pin is correctly set as a GPIO input. 144 */ 145 static void cs35l56_shared_test_mock_gpio_status_selftest(struct kunit *test) 146 { 147 const struct cs35l56_shared_test_param *param = test->param_value; 148 struct cs35l56_shared_test_priv *priv = test->priv; 149 struct cs35l56_base *cs35l56_base = priv->cs35l56_base; 150 unsigned int reg, val; 151 152 KUNIT_ASSERT_NOT_NULL(test, param); 153 154 /* Set all pins non-GPIO and output. Mock GPIO_STATUS should read 0 */ 155 for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) 156 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); 157 158 /* Set all pads as inputs */ 159 for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32)) 160 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_PAD_GPIO_IE)); 161 162 KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); 163 KUNIT_EXPECT_EQ(test, val, 0); 164 165 /* Set all pins as GPIO outputs. Mock GPIO_STATUS should read 0 */ 166 for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) 167 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_GPIO_FN_GPIO)); 168 169 KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); 170 KUNIT_EXPECT_EQ(test, val, 0); 171 172 /* Set all pins as non-GPIO inputs. Mock GPIO_STATUS should read 0 */ 173 for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) 174 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, CS35L56_GPIO_DIR_MASK)); 175 176 KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); 177 KUNIT_EXPECT_EQ(test, val, 0); 178 179 /* Set all pins as GPIO inputs. Mock GPIO_STATUS should match param->gpio_status */ 180 for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) 181 KUNIT_ASSERT_EQ(test, 0, 182 regmap_write(priv->registers, reg, 183 CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_GPIO)); 184 185 KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); 186 KUNIT_EXPECT_EQ(test, val, param->gpio_status); 187 188 /* Set all pads as outputs. Mock GPIO_STATUS should read 0 */ 189 for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32)) 190 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); 191 192 KUNIT_ASSERT_EQ(test, 0, regmap_read(cs35l56_base->regmap, CS35L56_GPIO_STATUS1, &val)); 193 KUNIT_EXPECT_EQ(test, val, 0); 194 } 195 196 /* Test that the listed chip pins are assembled into a speaker ID integer. */ 197 static void cs35l56_shared_test_get_onchip_speaker_id(struct kunit *test) 198 { 199 const struct cs35l56_shared_test_param *param = test->param_value; 200 struct cs35l56_shared_test_priv *priv = test->priv; 201 struct cs35l56_base *cs35l56_base = priv->cs35l56_base; 202 unsigned int i, reg; 203 204 /* Set all pins non-GPIO and output */ 205 for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) 206 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); 207 208 for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32)) 209 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); 210 211 /* Init GPIO array */ 212 for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { 213 if (param->spkid_gpios[i] < 0) 214 break; 215 216 cs35l56_base->onchip_spkid_gpios[i] = param->spkid_gpios[i] - 1; 217 cs35l56_base->num_onchip_spkid_gpios++; 218 } 219 220 cs35l56_base->num_onchip_spkid_pulls = 0; 221 222 KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0); 223 KUNIT_EXPECT_EQ(test, cs35l56_read_onchip_spkid(cs35l56_base), param->spkid); 224 } 225 226 /* Test that the listed chip pins and the corresponding pads are configured correctly. */ 227 static void cs35l56_shared_test_onchip_speaker_id_pad_config(struct kunit *test) 228 { 229 const struct cs35l56_shared_test_param *param = test->param_value; 230 struct cs35l56_shared_test_priv *priv = test->priv; 231 struct cs35l56_base *cs35l56_base = priv->cs35l56_base; 232 unsigned int i, reg, val; 233 234 /* Init values in all pin registers */ 235 for (reg = CS35L56_GPIO1_CTRL1; reg <= CS35L56_GPIO13_CTRL1; reg += sizeof(u32)) 236 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); 237 238 for (reg = CS35L56_SYNC_GPIO1_CFG; reg <= CS35L56_ASP2_DIO_GPIO13_CFG; reg += sizeof(u32)) 239 KUNIT_ASSERT_EQ(test, 0, regmap_write(priv->registers, reg, 0)); 240 241 /* Init GPIO array */ 242 for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { 243 if (param->spkid_gpios[i] < 0) 244 break; 245 246 cs35l56_base->onchip_spkid_gpios[i] = param->spkid_gpios[i] - 1; 247 cs35l56_base->num_onchip_spkid_gpios++; 248 } 249 250 /* Init pulls array */ 251 for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) { 252 if (param->spkid_pulls[i] < 0) 253 break; 254 255 cs35l56_base->onchip_spkid_pulls[i] = param->spkid_pulls[i]; 256 cs35l56_base->num_onchip_spkid_pulls++; 257 } 258 259 KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0); 260 261 for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { 262 if (param->spkid_gpios[i] < 0) 263 break; 264 265 /* Pad should be an input */ 266 reg = CS35L56_SYNC_GPIO1_CFG + ((param->spkid_gpios[i] - 1) * sizeof(u32)); 267 KUNIT_EXPECT_EQ(test, regmap_read(priv->registers, reg, &val), 0); 268 KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_IE, CS35L56_PAD_GPIO_IE); 269 270 /* Specified pulls should be set, others should be none */ 271 if (i < cs35l56_base->num_onchip_spkid_pulls) { 272 KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_PULL_MASK, 273 FIELD_PREP(CS35L56_PAD_GPIO_PULL_MASK, 274 param->spkid_pulls[i])); 275 } else { 276 KUNIT_EXPECT_EQ(test, val & CS35L56_PAD_GPIO_PULL_MASK, 277 CS35L56_PAD_PULL_NONE); 278 } 279 280 /* Pulls for all specfied GPIOs should have been transferred to AO latch */ 281 if (i < cs35l56_base->num_onchip_spkid_pulls) { 282 KUNIT_EXPECT_EQ(test, 283 priv->applied_pad_pull_state[param->spkid_gpios[i] - 1], 284 param->spkid_pulls[i]); 285 } else { 286 KUNIT_EXPECT_EQ(test, 287 priv->applied_pad_pull_state[param->spkid_gpios[i] - 1], 288 CS35L56_PAD_PULL_NONE); 289 } 290 } 291 } 292 293 /* Test that the listed chip pins are stashed correctly. */ 294 static void cs35l56_shared_test_stash_onchip_spkid_pins(struct kunit *test) 295 { 296 const struct cs35l56_shared_test_param *param = test->param_value; 297 struct cs35l56_shared_test_priv *priv = test->priv; 298 struct cs35l56_base *cs35l56_base = priv->cs35l56_base; 299 u32 gpios[5], pulls[5]; 300 int i, num_gpios, num_pulls; 301 302 static_assert(ARRAY_SIZE(gpios) >= ARRAY_SIZE(param->spkid_gpios)); 303 static_assert(ARRAY_SIZE(pulls) >= ARRAY_SIZE(param->spkid_pulls)); 304 305 num_gpios = 0; 306 for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { 307 if (param->spkid_gpios[i] < 0) 308 break; 309 310 gpios[i] = (u32)param->spkid_gpios[i]; 311 num_gpios++; 312 } 313 314 num_pulls = 0; 315 for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) { 316 if (param->spkid_pulls[i] < 0) 317 break; 318 319 pulls[i] = (u32)param->spkid_pulls[i]; 320 num_pulls++; 321 } 322 323 cs35l56_base->num_onchip_spkid_gpios = 0; 324 cs35l56_base->num_onchip_spkid_pulls = 0; 325 326 KUNIT_ASSERT_LE(test, num_gpios, ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios)); 327 KUNIT_ASSERT_LE(test, num_pulls, ARRAY_SIZE(cs35l56_base->onchip_spkid_pulls)); 328 329 KUNIT_EXPECT_EQ(test, 330 cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, 331 gpios, num_gpios, 332 pulls, num_pulls), 333 0); 334 335 KUNIT_EXPECT_EQ(test, cs35l56_base->num_onchip_spkid_gpios, num_gpios); 336 KUNIT_EXPECT_EQ(test, cs35l56_base->num_onchip_spkid_pulls, num_pulls); 337 338 /* GPIO numbers are adjusted from 1-based to 0-based */ 339 for (i = 0; i < num_gpios; i++) 340 KUNIT_EXPECT_EQ(test, cs35l56_base->onchip_spkid_gpios[i], gpios[i] - 1); 341 342 for (i = 0; i < num_pulls; i++) 343 KUNIT_EXPECT_EQ(test, cs35l56_base->onchip_spkid_pulls[i], pulls[i]); 344 } 345 346 /* Test that illegal GPIO numbers are rejected. */ 347 static void cs35l56_shared_test_stash_onchip_spkid_pins_reject_invalid(struct kunit *test) 348 { 349 struct cs35l56_shared_test_priv *priv = test->priv; 350 struct cs35l56_base *cs35l56_base = priv->cs35l56_base; 351 u32 gpios[8] = { }, pulls[8] = { }; 352 353 KUNIT_EXPECT_LE(test, 354 cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, 355 gpios, 1, 356 pulls, 0), 357 0); 358 359 switch (cs35l56_base->type) { 360 case 0x54: 361 case 0x56: 362 case 0x57: 363 gpios[0] = CS35L56_MAX_GPIO + 1; 364 break; 365 case 0x63: 366 gpios[0] = CS35L63_MAX_GPIO + 1; 367 break; 368 default: 369 kunit_fail_current_test("Unsupported type:%#x\n", cs35l56_base->type); 370 return; 371 } 372 KUNIT_EXPECT_LE(test, 373 cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, 374 gpios, 1, 375 pulls, 0), 376 0); 377 378 gpios[0] = 1; 379 pulls[0] = 3; 380 KUNIT_EXPECT_LE(test, 381 cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, 382 gpios, 1, 383 pulls, 1), 384 0); 385 386 static_assert(ARRAY_SIZE(gpios) > ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios)); 387 static_assert(ARRAY_SIZE(pulls) > ARRAY_SIZE(cs35l56_base->onchip_spkid_pulls)); 388 KUNIT_EXPECT_EQ(test, 389 cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, 390 gpios, ARRAY_SIZE(gpios), 391 pulls, 0), 392 -EOVERFLOW); 393 KUNIT_EXPECT_EQ(test, 394 cs35l56_check_and_save_onchip_spkid_gpios(cs35l56_base, 395 gpios, 1, 396 pulls, ARRAY_SIZE(pulls)), 397 -EOVERFLOW); 398 } 399 400 static void cs35l56_shared_test_onchip_speaker_id_not_defined(struct kunit *test) 401 { 402 struct cs35l56_shared_test_priv *priv = test->priv; 403 struct cs35l56_base *cs35l56_base = priv->cs35l56_base; 404 405 memset(cs35l56_base->onchip_spkid_gpios, 0, sizeof(cs35l56_base->onchip_spkid_gpios)); 406 memset(cs35l56_base->onchip_spkid_pulls, 0, sizeof(cs35l56_base->onchip_spkid_pulls)); 407 cs35l56_base->num_onchip_spkid_gpios = 0; 408 cs35l56_base->num_onchip_spkid_pulls = 0; 409 KUNIT_EXPECT_EQ(test, cs35l56_configure_onchip_spkid_pads(cs35l56_base), 0); 410 KUNIT_EXPECT_EQ(test, cs35l56_read_onchip_spkid(cs35l56_base), -ENOENT); 411 } 412 413 static int cs35l56_shared_test_case_regmap_init(struct kunit *test, 414 const struct regmap_config *regmap_config) 415 { 416 struct cs35l56_shared_test_priv *priv = test->priv; 417 struct cs35l56_base *cs35l56_base; 418 419 /* 420 * Create a dummy regmap to simulate a register map by holding the 421 * values of all simulated registers in the regmap cache. 422 */ 423 priv->registers = regmap_init(&priv->amp_dev->dev, 424 &cs35l56_shared_test_mock_registers_regmap_bus, 425 priv, 426 &cs35l56_shared_test_mock_registers_regmap); 427 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->registers); 428 KUNIT_ASSERT_EQ(test, 0, 429 kunit_add_action_or_reset(test, regmap_exit_wrapper, 430 priv->registers)); 431 regcache_cache_only(priv->registers, true); 432 433 /* Create dummy regmap for cs35l56 driver */ 434 cs35l56_base = priv->cs35l56_base; 435 cs35l56_base->regmap = regmap_init(cs35l56_base->dev, 436 &cs35l56_shared_test_regmap_bus, 437 priv, 438 regmap_config); 439 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cs35l56_base->regmap); 440 KUNIT_ASSERT_EQ(test, 0, 441 kunit_add_action_or_reset(test, regmap_exit_wrapper, 442 cs35l56_base->regmap)); 443 444 return 0; 445 } 446 447 static int cs35l56_shared_test_case_base_init(struct kunit *test, u8 type, u8 rev, 448 const struct regmap_config *regmap_config) 449 { 450 struct cs35l56_shared_test_priv *priv; 451 int ret; 452 453 KUNIT_ASSERT_NOT_NULL(test, cs_amp_test_hooks); 454 455 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 456 if (!priv) 457 return -ENOMEM; 458 459 test->priv = priv; 460 priv->test = test; 461 462 /* Create dummy amp driver dev */ 463 priv->amp_dev = faux_device_create("cs35l56_shared_test_drv", NULL, NULL); 464 KUNIT_ASSERT_NOT_NULL(test, priv->amp_dev); 465 KUNIT_ASSERT_EQ(test, 0, 466 kunit_add_action_or_reset(test, 467 faux_device_destroy_wrapper, 468 priv->amp_dev)); 469 470 priv->cs35l56_base = kunit_kzalloc(test, sizeof(*priv->cs35l56_base), GFP_KERNEL); 471 KUNIT_ASSERT_NOT_NULL(test, priv->cs35l56_base); 472 priv->cs35l56_base->dev = &priv->amp_dev->dev; 473 priv->cs35l56_base->type = type; 474 priv->cs35l56_base->rev = rev; 475 476 if (regmap_config) { 477 ret = cs35l56_shared_test_case_regmap_init(test, regmap_config); 478 if (ret) 479 return ret; 480 } 481 482 return 0; 483 } 484 485 static int cs35l56_shared_test_case_regmap_init_L56_B0_sdw(struct kunit *test) 486 { 487 return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_sdw); 488 } 489 490 static int cs35l56_shared_test_case_regmap_init_L56_B0_spi(struct kunit *test) 491 { 492 return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_spi); 493 } 494 495 static int cs35l56_shared_test_case_regmap_init_L56_B0_i2c(struct kunit *test) 496 { 497 return cs35l56_shared_test_case_base_init(test, 0x56, 0xb0, &cs35l56_regmap_i2c); 498 } 499 500 static int cs35l56_shared_test_case_regmap_init_L56_B2_sdw(struct kunit *test) 501 { 502 return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_sdw); 503 } 504 505 static int cs35l56_shared_test_case_regmap_init_L56_B2_spi(struct kunit *test) 506 { 507 return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_spi); 508 } 509 510 static int cs35l56_shared_test_case_regmap_init_L56_B2_i2c(struct kunit *test) 511 { 512 return cs35l56_shared_test_case_base_init(test, 0x56, 0xb2, &cs35l56_regmap_i2c); 513 } 514 515 static int cs35l56_shared_test_case_regmap_init_L63_A1_sdw(struct kunit *test) 516 { 517 return cs35l56_shared_test_case_base_init(test, 0x63, 0xa1, &cs35l63_regmap_sdw); 518 } 519 520 static void cs35l56_shared_test_gpio_param_desc(const struct cs35l56_shared_test_param *param, 521 char *desc) 522 { 523 DECLARE_SEQ_BUF(gpios, 1 + (2 * ARRAY_SIZE(param->spkid_gpios))); 524 DECLARE_SEQ_BUF(pulls, 1 + (2 * ARRAY_SIZE(param->spkid_pulls))); 525 int i; 526 527 for (i = 0; i < ARRAY_SIZE(param->spkid_gpios); i++) { 528 if (param->spkid_gpios[i] < 0) 529 break; 530 531 seq_buf_printf(&gpios, "%s%d", (i == 0) ? "" : ",", param->spkid_gpios[i]); 532 } 533 534 for (i = 0; i < ARRAY_SIZE(param->spkid_pulls); i++) { 535 if (param->spkid_pulls[i] < 0) 536 break; 537 538 seq_buf_printf(&pulls, "%s%d", (i == 0) ? "" : ",", param->spkid_pulls[i]); 539 } 540 541 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "gpios:{%s} pulls:{%s} status:%#lx spkid:%d", 542 seq_buf_str(&gpios), seq_buf_str(&pulls), param->gpio_status, param->spkid); 543 } 544 545 static const struct cs35l56_shared_test_param cs35l56_shared_test_gpios_selftest_cases[] = { 546 { .spkid_gpios = { -1 }, .gpio_status = GENMASK(12, 0) }, 547 }; 548 KUNIT_ARRAY_PARAM(cs35l56_shared_test_gpios_selftest, 549 cs35l56_shared_test_gpios_selftest_cases, 550 cs35l56_shared_test_gpio_param_desc); 551 552 static const struct cs35l56_shared_test_param cs35l56_shared_test_onchip_spkid_cases[] = { 553 { .spkid_gpios = { 1, -1 }, .gpio_status = 0, .spkid = 0 }, 554 { .spkid_gpios = { 1, -1 }, .gpio_status = ~BIT(0), .spkid = 0 }, 555 { .spkid_gpios = { 1, -1 }, .gpio_status = BIT(0), .spkid = 1 }, 556 557 { .spkid_gpios = { 7, -1 }, .gpio_status = 0, .spkid = 0 }, 558 { .spkid_gpios = { 7, -1 }, .gpio_status = ~BIT(6), .spkid = 0 }, 559 { .spkid_gpios = { 7, -1 }, .gpio_status = BIT(6), .spkid = 1 }, 560 561 { .spkid_gpios = { 1, 7, -1 }, .gpio_status = 0, .spkid = 0 }, 562 { .spkid_gpios = { 1, 7, -1 }, .gpio_status = ~(BIT(0) | BIT(6)), .spkid = 0 }, 563 { .spkid_gpios = { 1, 7, -1 }, .gpio_status = BIT(6), .spkid = 1 }, 564 { .spkid_gpios = { 1, 7, -1 }, .gpio_status = BIT(0), .spkid = 2 }, 565 { .spkid_gpios = { 1, 7, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, 566 567 { .spkid_gpios = { 7, 1, -1 }, .gpio_status = 0, .spkid = 0 }, 568 { .spkid_gpios = { 7, 1, -1 }, .gpio_status = ~(BIT(6) | BIT(0)), .spkid = 0 }, 569 { .spkid_gpios = { 7, 1, -1 }, .gpio_status = BIT(0), .spkid = 1 }, 570 { .spkid_gpios = { 7, 1, -1 }, .gpio_status = BIT(6), .spkid = 2 }, 571 { .spkid_gpios = { 7, 1, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, 572 573 { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = 0, .spkid = 0 }, 574 { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(0), .spkid = 1 }, 575 { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(6), .spkid = 2 }, 576 { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(6) | BIT(0), .spkid = 3 }, 577 { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2), .spkid = 4 }, 578 { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(0), .spkid = 5 }, 579 { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(6), .spkid = 6 }, 580 { .spkid_gpios = { 3, 7, 1, -1 }, .gpio_status = BIT(2) | BIT(6) | BIT(0), .spkid = 7 }, 581 }; 582 KUNIT_ARRAY_PARAM(cs35l56_shared_test_onchip_spkid, cs35l56_shared_test_onchip_spkid_cases, 583 cs35l56_shared_test_gpio_param_desc); 584 585 static const struct cs35l56_shared_test_param cs35l56_shared_test_onchip_spkid_pull_cases[] = { 586 { .spkid_gpios = { 1, -1 }, .spkid_pulls = { 1, -1 }, }, 587 { .spkid_gpios = { 1, -1 }, .spkid_pulls = { 2, -1 }, }, 588 589 { .spkid_gpios = { 7, -1 }, .spkid_pulls = { 1, -1 }, }, 590 { .spkid_gpios = { 7, -1 }, .spkid_pulls = { 2, -1 }, }, 591 592 { .spkid_gpios = { 1, 7, -1 }, .spkid_pulls = { 1, 1, -1 }, }, 593 { .spkid_gpios = { 1, 7, -1 }, .spkid_pulls = { 2, 2, -1 }, }, 594 595 { .spkid_gpios = { 7, 1, -1 }, .spkid_pulls = { 1, 1, -1 }, }, 596 { .spkid_gpios = { 7, 1, -1 }, .spkid_pulls = { 2, 2, -1 }, }, 597 598 { .spkid_gpios = { 3, 7, 1, -1 }, .spkid_pulls = { 1, 1, 1, -1 }, }, 599 { .spkid_gpios = { 3, 7, 1, -1 }, .spkid_pulls = { 2, 2, 2, -1 }, }, 600 }; 601 KUNIT_ARRAY_PARAM(cs35l56_shared_test_onchip_spkid_pull, 602 cs35l56_shared_test_onchip_spkid_pull_cases, 603 cs35l56_shared_test_gpio_param_desc); 604 605 static struct kunit_case cs35l56_shared_test_cases[] = { 606 /* Tests for speaker id */ 607 KUNIT_CASE_PARAM(cs35l56_shared_test_mock_gpio_status_selftest, 608 cs35l56_shared_test_gpios_selftest_gen_params), 609 KUNIT_CASE_PARAM(cs35l56_shared_test_get_onchip_speaker_id, 610 cs35l56_shared_test_onchip_spkid_gen_params), 611 KUNIT_CASE_PARAM(cs35l56_shared_test_onchip_speaker_id_pad_config, 612 cs35l56_shared_test_onchip_spkid_gen_params), 613 KUNIT_CASE_PARAM(cs35l56_shared_test_onchip_speaker_id_pad_config, 614 cs35l56_shared_test_onchip_spkid_pull_gen_params), 615 KUNIT_CASE_PARAM(cs35l56_shared_test_stash_onchip_spkid_pins, 616 cs35l56_shared_test_onchip_spkid_pull_gen_params), 617 KUNIT_CASE(cs35l56_shared_test_stash_onchip_spkid_pins_reject_invalid), 618 KUNIT_CASE(cs35l56_shared_test_onchip_speaker_id_not_defined), 619 { } 620 }; 621 622 static struct kunit_suite cs35l56_shared_test_suite_L56_B0_sdw = { 623 .name = "snd-soc-cs35l56-shared-test_L56_B0_sdw", 624 .init = cs35l56_shared_test_case_regmap_init_L56_B0_sdw, 625 .test_cases = cs35l56_shared_test_cases, 626 }; 627 628 static struct kunit_suite cs35l56_shared_test_suite_L56_B2_sdw = { 629 .name = "snd-soc-cs35l56-shared-test_L56_B2_sdw", 630 .init = cs35l56_shared_test_case_regmap_init_L56_B2_sdw, 631 .test_cases = cs35l56_shared_test_cases, 632 }; 633 634 static struct kunit_suite cs35l56_shared_test_suite_L63_A1_sdw = { 635 .name = "snd-soc-cs35l56-shared-test_L63_A1_sdw", 636 .init = cs35l56_shared_test_case_regmap_init_L63_A1_sdw, 637 .test_cases = cs35l56_shared_test_cases, 638 }; 639 640 static struct kunit_suite cs35l56_shared_test_suite_L56_B0_spi = { 641 .name = "snd-soc-cs35l56-shared-test_L56_B0_spi", 642 .init = cs35l56_shared_test_case_regmap_init_L56_B0_spi, 643 .test_cases = cs35l56_shared_test_cases, 644 }; 645 646 static struct kunit_suite cs35l56_shared_test_suite_L56_B2_spi = { 647 .name = "snd-soc-cs35l56-shared-test_L56_B2_spi", 648 .init = cs35l56_shared_test_case_regmap_init_L56_B2_spi, 649 .test_cases = cs35l56_shared_test_cases, 650 }; 651 652 static struct kunit_suite cs35l56_shared_test_suite_L56_B0_i2c = { 653 .name = "snd-soc-cs35l56-shared-test_L56_B0_i2c", 654 .init = cs35l56_shared_test_case_regmap_init_L56_B0_i2c, 655 .test_cases = cs35l56_shared_test_cases, 656 }; 657 658 static struct kunit_suite cs35l56_shared_test_suite_L56_B2_i2c = { 659 .name = "snd-soc-cs35l56-shared-test_L56_B2_i2c", 660 .init = cs35l56_shared_test_case_regmap_init_L56_B2_i2c, 661 .test_cases = cs35l56_shared_test_cases, 662 }; 663 664 kunit_test_suites( 665 &cs35l56_shared_test_suite_L56_B0_sdw, 666 &cs35l56_shared_test_suite_L56_B2_sdw, 667 &cs35l56_shared_test_suite_L63_A1_sdw, 668 669 &cs35l56_shared_test_suite_L56_B0_spi, 670 &cs35l56_shared_test_suite_L56_B2_spi, 671 672 &cs35l56_shared_test_suite_L56_B0_i2c, 673 &cs35l56_shared_test_suite_L56_B2_i2c, 674 ); 675 676 MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED"); 677 MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB"); 678 MODULE_DESCRIPTION("KUnit test for cs35l56-shared module"); 679 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>"); 680 MODULE_LICENSE("GPL"); 681