* [PATCH v4] ASoC: cs43130: Allow driver to work without IRQ connection
@ 2023-11-22 14:34 Maciej Strozek
2023-11-22 15:42 ` Charles Keepax
0 siblings, 1 reply; 3+ messages in thread
From: Maciej Strozek @ 2023-11-22 14:34 UTC (permalink / raw)
To: Mark Brown
Cc: James Schulman, David Rhodes, Liam Girdwood, alsa-devel, patches,
linux-sound, linux-kernel, Maciej Strozek
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>
---
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 | 91 +++++++++++++++++++++++++++-----------
sound/soc/codecs/cs43130.h | 1 +
2 files changed, 65 insertions(+), 27 deletions(-)
diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c
index 02e7f45b9208..bd51bb5b6f14 100644
--- a/sound/soc/codecs/cs43130.c
+++ b/sound/soc/codecs/cs43130.c
@@ -326,6 +326,40 @@ 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 if (to_poll == &cs43130->hpload_evt) {
+ offset = 3;
+ flag = CS43130_HPLOAD_NO_DC_INT | CS43130_HPLOAD_UNPLUG_INT |
+ CS43130_HPLOAD_OOR_INT | CS43130_HPLOAD_AC_INT |
+ CS43130_HPLOAD_DC_INT | CS43130_HPLOAD_ON_INT |
+ CS43130_HPLOAD_OFF_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 +398,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 +433,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 +448,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,
@@ -2048,12 +2079,12 @@ static int cs43130_hpload_proc(struct cs43130_private *cs43130,
regmap_multi_reg_write(cs43130->regmap, seq,
seq_size);
- ret = wait_for_completion_timeout(&cs43130->hpload_evt,
- msecs_to_jiffies(1000));
+ ret = cs43130_wait_for_completion(cs43130, &cs43130->hpload_evt, 1000);
+
regmap_read(cs43130->regmap, CS43130_INT_MASK_4, &msk);
- if (!ret) {
- dev_err(cs43130->dev, "Timeout waiting for HPLOAD interrupt\n");
- return -1;
+ if (ret) {
+ dev_err(cs43130->dev, "Timeout waiting for HPLOAD interrupt: %d\n", ret);
+ return ret;
}
dev_dbg(cs43130->dev, "HP load stat: %x, INT_MASK_4: %x\n",
@@ -2548,13 +2579,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
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v4] ASoC: cs43130: Allow driver to work without IRQ connection
2023-11-22 14:34 [PATCH v4] ASoC: cs43130: Allow driver to work without IRQ connection Maciej Strozek
@ 2023-11-22 15:42 ` Charles Keepax
2023-11-22 15:51 ` Maciej Strozek
0 siblings, 1 reply; 3+ messages in thread
From: Charles Keepax @ 2023-11-22 15:42 UTC (permalink / raw)
To: Maciej Strozek
Cc: Mark Brown, James Schulman, David Rhodes, Liam Girdwood,
alsa-devel, patches, linux-sound, linux-kernel
On Wed, Nov 22, 2023 at 02:34:59PM +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>
> ---
Apologies Maciej, should have spotted this when I had a look this
morning but I have just spotted one more thing, we should actually
remove the polling for the hpload detect. The hpload detect can
actually only be triggered by the IRQ handler anyway so that code
will never run, and there would be much more work required to get
the jack detect working without the IRQ.
Thanks,
Charles
> 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 | 91 +++++++++++++++++++++++++++-----------
> sound/soc/codecs/cs43130.h | 1 +
> 2 files changed, 65 insertions(+), 27 deletions(-)
>
> diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c
> index 02e7f45b9208..bd51bb5b6f14 100644
> --- a/sound/soc/codecs/cs43130.c
> +++ b/sound/soc/codecs/cs43130.c
> @@ -326,6 +326,40 @@ 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 if (to_poll == &cs43130->hpload_evt) {
> + offset = 3;
> + flag = CS43130_HPLOAD_NO_DC_INT | CS43130_HPLOAD_UNPLUG_INT |
> + CS43130_HPLOAD_OOR_INT | CS43130_HPLOAD_AC_INT |
> + CS43130_HPLOAD_DC_INT | CS43130_HPLOAD_ON_INT |
> + CS43130_HPLOAD_OFF_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 +398,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 +433,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 +448,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,
> @@ -2048,12 +2079,12 @@ static int cs43130_hpload_proc(struct cs43130_private *cs43130,
> regmap_multi_reg_write(cs43130->regmap, seq,
> seq_size);
>
> - ret = wait_for_completion_timeout(&cs43130->hpload_evt,
> - msecs_to_jiffies(1000));
> + ret = cs43130_wait_for_completion(cs43130, &cs43130->hpload_evt, 1000);
> +
> regmap_read(cs43130->regmap, CS43130_INT_MASK_4, &msk);
> - if (!ret) {
> - dev_err(cs43130->dev, "Timeout waiting for HPLOAD interrupt\n");
> - return -1;
> + if (ret) {
> + dev_err(cs43130->dev, "Timeout waiting for HPLOAD interrupt: %d\n", ret);
> + return ret;
> }
>
> dev_dbg(cs43130->dev, "HP load stat: %x, INT_MASK_4: %x\n",
> @@ -2548,13 +2579,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
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v4] ASoC: cs43130: Allow driver to work without IRQ connection
2023-11-22 15:42 ` Charles Keepax
@ 2023-11-22 15:51 ` Maciej Strozek
0 siblings, 0 replies; 3+ messages in thread
From: Maciej Strozek @ 2023-11-22 15:51 UTC (permalink / raw)
To: Charles Keepax
Cc: Mark Brown, James Schulman, David Rhodes, Liam Girdwood,
alsa-devel, patches, linux-sound, linux-kernel
W dniu śro, 22.11.2023 o godzinie 15∶42 +0000, użytkownik Charles
Keepax napisał:
> On Wed, Nov 22, 2023 at 02:34:59PM +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>
> > ---
>
> Apologies Maciej, should have spotted this when I had a look this
> morning but I have just spotted one more thing, we should actually
> remove the polling for the hpload detect. The hpload detect can
> actually only be triggered by the IRQ handler anyway so that code
> will never run, and there would be much more work required to get
> the jack detect working without the IRQ.
>
> Thanks,
> Charles
No problem, will send V5 with the hpload detect deleted tomorrow
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-11-22 15:51 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-22 14:34 [PATCH v4] ASoC: cs43130: Allow driver to work without IRQ connection Maciej Strozek
2023-11-22 15:42 ` Charles Keepax
2023-11-22 15:51 ` Maciej Strozek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox