Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: cs43130: Allow driver to work without IRQ connection

Add a polling mechanism that will keep the driver operational even in
absence of physical IRQ connection. If IRQ line is detected, the driver
will continue working as usual, in case of missing IRQ line it will
fallback to the polling mechanism introduced in this change.
This will support users which choose not to connect an IRQ line as it
is not critical to part's operation.

Signed-off-by: Maciej Strozek <mstrozek@opensource.cirrus.com>
Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20231123090658.10418-1-mstrozek@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Maciej Strozek and committed by
Mark Brown
fa91703d b1cea462

+55 -23
+54 -23
sound/soc/codecs/cs43130.c
··· 326 326 return ret; 327 327 } 328 328 329 + static int cs43130_wait_for_completion(struct cs43130_private *cs43130, struct completion *to_poll, 330 + int time) 331 + { 332 + int stickies, offset, flag, ret; 333 + 334 + if (cs43130->has_irq_line) { 335 + ret = wait_for_completion_timeout(to_poll, msecs_to_jiffies(time)); 336 + if (ret == 0) 337 + return -ETIMEDOUT; 338 + else 339 + return 0; // Discard number of jiffies left till timeout and return success 340 + } 341 + 342 + if (to_poll == &cs43130->xtal_rdy) { 343 + offset = 0; 344 + flag = CS43130_XTAL_RDY_INT; 345 + } else if (to_poll == &cs43130->pll_rdy) { 346 + offset = 0; 347 + flag = CS43130_PLL_RDY_INT; 348 + } else { 349 + return -EINVAL; 350 + } 351 + 352 + return regmap_read_poll_timeout(cs43130->regmap, CS43130_INT_STATUS_1 + offset, 353 + stickies, (stickies & flag), 354 + 1000, time * 1000); 355 + } 356 + 329 357 static int cs43130_change_clksrc(struct snd_soc_component *component, 330 358 enum cs43130_mclk_src_sel src) 331 359 { ··· 392 364 CS43130_XTAL_RDY_INT_MASK, 0); 393 365 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, 394 366 CS43130_PDN_XTAL_MASK, 0); 395 - ret = wait_for_completion_timeout(&cs43130->xtal_rdy, 396 - msecs_to_jiffies(100)); 367 + ret = cs43130_wait_for_completion(cs43130, &cs43130->xtal_rdy, 100); 397 368 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, 398 369 CS43130_XTAL_RDY_INT_MASK, 399 370 1 << CS43130_XTAL_RDY_INT_SHIFT); 400 - if (ret == 0) { 401 - dev_err(cs43130->dev, "Timeout waiting for XTAL_READY interrupt\n"); 402 - return -ETIMEDOUT; 371 + if (ret) { 372 + dev_err(cs43130->dev, "Error waiting for XTAL_READY interrupt: %d\n", ret); 373 + return ret; 403 374 } 404 375 } 405 376 ··· 427 400 CS43130_XTAL_RDY_INT_MASK, 0); 428 401 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, 429 402 CS43130_PDN_XTAL_MASK, 0); 430 - ret = wait_for_completion_timeout(&cs43130->xtal_rdy, 431 - msecs_to_jiffies(100)); 403 + ret = cs43130_wait_for_completion(cs43130, &cs43130->xtal_rdy, 100); 432 404 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, 433 405 CS43130_XTAL_RDY_INT_MASK, 434 406 1 << CS43130_XTAL_RDY_INT_SHIFT); 435 - if (ret == 0) { 436 - dev_err(cs43130->dev, "Timeout waiting for XTAL_READY interrupt\n"); 437 - return -ETIMEDOUT; 407 + if (ret) { 408 + dev_err(cs43130->dev, "Error waiting for XTAL_READY interrupt: %d\n", ret); 409 + return ret; 438 410 } 439 411 } 440 412 ··· 442 416 CS43130_PLL_RDY_INT_MASK, 0); 443 417 regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, 444 418 CS43130_PDN_PLL_MASK, 0); 445 - ret = wait_for_completion_timeout(&cs43130->pll_rdy, 446 - msecs_to_jiffies(100)); 419 + ret = cs43130_wait_for_completion(cs43130, &cs43130->pll_rdy, 100); 447 420 regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, 448 421 CS43130_PLL_RDY_INT_MASK, 449 422 1 << CS43130_PLL_RDY_INT_SHIFT); 450 - if (ret == 0) { 451 - dev_err(cs43130->dev, "Timeout waiting for PLL_READY interrupt\n"); 452 - return -ETIMEDOUT; 423 + if (ret) { 424 + dev_err(cs43130->dev, "Error waiting for PLL_READY interrupt: %d\n", ret); 425 + return ret; 453 426 } 454 427 455 428 regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1, ··· 2040 2015 regmap_read(cs43130->regmap, CS43130_INT_MASK_4, &msk); 2041 2016 if (!ret) { 2042 2017 dev_err(cs43130->dev, "Timeout waiting for HPLOAD interrupt\n"); 2043 - return -1; 2018 + return -ETIMEDOUT; 2044 2019 } 2045 2020 2046 2021 dev_dbg(cs43130->dev, "HP load stat: %x, INT_MASK_4: %x\n", ··· 2535 2510 init_completion(&cs43130->pll_rdy); 2536 2511 init_completion(&cs43130->hpload_evt); 2537 2512 2538 - ret = devm_request_threaded_irq(cs43130->dev, client->irq, 2539 - NULL, cs43130_irq_thread, 2540 - IRQF_ONESHOT | IRQF_TRIGGER_LOW, 2541 - "cs43130", cs43130); 2542 - if (ret != 0) { 2543 - dev_err(cs43130->dev, "Failed to request IRQ: %d\n", ret); 2544 - goto err; 2513 + if (!client->irq) { 2514 + dev_dbg(cs43130->dev, "IRQ not found, will poll instead\n"); 2515 + cs43130->has_irq_line = 0; 2516 + } else { 2517 + ret = devm_request_threaded_irq(cs43130->dev, client->irq, 2518 + NULL, cs43130_irq_thread, 2519 + IRQF_ONESHOT | IRQF_TRIGGER_LOW, 2520 + "cs43130", cs43130); 2521 + if (ret != 0) { 2522 + dev_err(cs43130->dev, "Failed to request IRQ: %d\n", ret); 2523 + goto err; 2524 + } 2525 + cs43130->has_irq_line = 1; 2545 2526 } 2546 2527 2547 2528 cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO;
+1
sound/soc/codecs/cs43130.h
··· 507 507 struct gpio_desc *reset_gpio; 508 508 unsigned int dev_id; /* codec device ID */ 509 509 int xtal_ibias; 510 + bool has_irq_line; 510 511 511 512 /* shared by both DAIs */ 512 513 struct mutex clk_mutex;