[PATCH v5] 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 --- V4 -> V5: Do not use hpload interrupt with the new polling function V3 -> V4: - Removed unnecesary else and indentation - Changed cs43130_wait_for_completion return codes and updated callers accordingly - Changed approach for checking for presence of IRQ connection: see if client->irq equals 0 which seems to be a standard way of checking it used by other drivers (instead of inspecting devm_request_threaded_irq error code) V2 -> V3: Amended changelog message and subject line V1 -> V2: Add changelog message
sound/soc/codecs/cs43130.c | 77 ++++++++++++++++++++++++++------------ sound/soc/codecs/cs43130.h | 1 + 2 files changed, 55 insertions(+), 23 deletions(-)
diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index 02e7f45b9208..0f3ead84665f 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -326,6 +326,34 @@ static int cs43130_set_pll(struct snd_soc_component *component, int pll_id, int return ret; }
+static int cs43130_wait_for_completion(struct cs43130_private *cs43130, struct completion *to_poll, + int time) +{ + int stickies, offset, flag, ret; + + if (cs43130->has_irq_line) { + ret = wait_for_completion_timeout(to_poll, msecs_to_jiffies(time)); + if (ret == 0) + return -ETIMEDOUT; + else + return 0; // Discard number of jiffies left till timeout and return success + } + + if (to_poll == &cs43130->xtal_rdy) { + offset = 0; + flag = CS43130_XTAL_RDY_INT; + } else if (to_poll == &cs43130->pll_rdy) { + offset = 0; + flag = CS43130_PLL_RDY_INT; + } else { + return -EINVAL; + } + + return regmap_read_poll_timeout(cs43130->regmap, CS43130_INT_STATUS_1 + offset, + stickies, (stickies & flag), + 1000, time * 1000); +} + static int cs43130_change_clksrc(struct snd_soc_component *component, enum cs43130_mclk_src_sel src) { @@ -364,14 +392,13 @@ static int cs43130_change_clksrc(struct snd_soc_component *component, CS43130_XTAL_RDY_INT_MASK, 0); regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, CS43130_PDN_XTAL_MASK, 0); - ret = wait_for_completion_timeout(&cs43130->xtal_rdy, - msecs_to_jiffies(100)); + ret = cs43130_wait_for_completion(cs43130, &cs43130->xtal_rdy, 100); regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, CS43130_XTAL_RDY_INT_MASK, 1 << CS43130_XTAL_RDY_INT_SHIFT); - if (ret == 0) { - dev_err(cs43130->dev, "Timeout waiting for XTAL_READY interrupt\n"); - return -ETIMEDOUT; + if (ret) { + dev_err(cs43130->dev, "Error waiting for XTAL_READY interrupt: %d\n", ret); + return ret; } }
@@ -400,14 +427,13 @@ static int cs43130_change_clksrc(struct snd_soc_component *component, CS43130_XTAL_RDY_INT_MASK, 0); regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, CS43130_PDN_XTAL_MASK, 0); - ret = wait_for_completion_timeout(&cs43130->xtal_rdy, - msecs_to_jiffies(100)); + ret = cs43130_wait_for_completion(cs43130, &cs43130->xtal_rdy, 100); regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, CS43130_XTAL_RDY_INT_MASK, 1 << CS43130_XTAL_RDY_INT_SHIFT); - if (ret == 0) { - dev_err(cs43130->dev, "Timeout waiting for XTAL_READY interrupt\n"); - return -ETIMEDOUT; + if (ret) { + dev_err(cs43130->dev, "Error waiting for XTAL_READY interrupt: %d\n", ret); + return ret; } }
@@ -416,14 +442,13 @@ static int cs43130_change_clksrc(struct snd_soc_component *component, CS43130_PLL_RDY_INT_MASK, 0); regmap_update_bits(cs43130->regmap, CS43130_PWDN_CTL, CS43130_PDN_PLL_MASK, 0); - ret = wait_for_completion_timeout(&cs43130->pll_rdy, - msecs_to_jiffies(100)); + ret = cs43130_wait_for_completion(cs43130, &cs43130->pll_rdy, 100); regmap_update_bits(cs43130->regmap, CS43130_INT_MASK_1, CS43130_PLL_RDY_INT_MASK, 1 << CS43130_PLL_RDY_INT_SHIFT); - if (ret == 0) { - dev_err(cs43130->dev, "Timeout waiting for PLL_READY interrupt\n"); - return -ETIMEDOUT; + if (ret) { + dev_err(cs43130->dev, "Error waiting for PLL_READY interrupt: %d\n", ret); + return ret; }
regmap_update_bits(cs43130->regmap, CS43130_SYS_CLK_CTL_1, @@ -2053,7 +2078,7 @@ static int cs43130_hpload_proc(struct cs43130_private *cs43130, regmap_read(cs43130->regmap, CS43130_INT_MASK_4, &msk); if (!ret) { dev_err(cs43130->dev, "Timeout waiting for HPLOAD interrupt\n"); - return -1; + return -ETIMEDOUT; }
dev_dbg(cs43130->dev, "HP load stat: %x, INT_MASK_4: %x\n", @@ -2548,13 +2573,19 @@ static int cs43130_i2c_probe(struct i2c_client *client) init_completion(&cs43130->pll_rdy); init_completion(&cs43130->hpload_evt);
- ret = devm_request_threaded_irq(cs43130->dev, client->irq, - NULL, cs43130_irq_thread, - IRQF_ONESHOT | IRQF_TRIGGER_LOW, - "cs43130", cs43130); - if (ret != 0) { - dev_err(cs43130->dev, "Failed to request IRQ: %d\n", ret); - goto err; + if (!client->irq) { + dev_dbg(cs43130->dev, "IRQ not found, will poll instead\n"); + cs43130->has_irq_line = 0; + } else { + ret = devm_request_threaded_irq(cs43130->dev, client->irq, + NULL, cs43130_irq_thread, + IRQF_ONESHOT | IRQF_TRIGGER_LOW, + "cs43130", cs43130); + if (ret != 0) { + dev_err(cs43130->dev, "Failed to request IRQ: %d\n", ret); + goto err; + } + cs43130->has_irq_line = 1; }
cs43130->mclk_int_src = CS43130_MCLK_SRC_RCO; diff --git a/sound/soc/codecs/cs43130.h b/sound/soc/codecs/cs43130.h index d3f595bbd3ba..dbdb5b262f1b 100644 --- a/sound/soc/codecs/cs43130.h +++ b/sound/soc/codecs/cs43130.h @@ -508,6 +508,7 @@ struct cs43130_private { struct gpio_desc *reset_gpio; unsigned int dev_id; /* codec device ID */ int xtal_ibias; + bool has_irq_line;
/* shared by both DAIs */ struct mutex clk_mutex; -- 2.34.1
On Thu, Nov 23, 2023 at 09:06:58AM +0000, Maciej Strozek wrote:
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
Thanks, Charles
On Thu, Nov 23, 2023 at 09:06:58AM +0000, Maciej Strozek wrote:
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
Sorry hang on this doesn't apply to Mark's tree, will need a v6.
Thanks, Charles
On Thu, Nov 23, 2023 at 10:46:24AM +0000, Charles Keepax wrote:
On Thu, Nov 23, 2023 at 09:06:58AM +0000, Maciej Strozek wrote:
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
Sorry hang on this doesn't apply to Mark's tree, will need a v6.
No that is me being a moron, apologies ignore this noise.
Thanks, Charles
On Thu, 23 Nov 2023 09:06:58 +0000, Maciej Strozek wrote:
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.
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: cs43130: Allow driver to work without IRQ connection commit: fa91703dc2e010e48a230dc92967cb5ae23f8680
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (3)
-
Charles Keepax
-
Maciej Strozek
-
Mark Brown