From b33af2811079c4cba9b9e1fb103fbe00a5da18ea Mon Sep 17 00:00:00 2001 From: Li Xu Date: Fri, 19 Oct 2018 17:18:13 -0500 Subject: [PATCH] ASoC: cs35l41: Use polling for mail box Use polling instead of interrupt for DSP mail box acknowledgement. With interrupt method, the amount of time for mail box acknowledgement can vary, and sometimes long. This is because interrupt handler reads all interrupt status registers and masks, which can take long time, especially on slow I2C bus. Use polling to directly check for DSP mail box acknowledgement reduces variability in amount of time needed, because only 1 register is read. Cirrus-JIRA-fixed: MMI-912 Change-Id: I21a223bbfdccb3593c61c7d04ae8355f2734c7a9 Signed-off-by: Li Xu Signed-off-by: Yoon (Seungyoon) Lee Reviewed-on: https://gerrit.mot.com/1259695 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Seungyoon Lee Submit-Approved: Jira Key --- include/sound/cs35l41.h | 1 - sound/soc/codecs/cs35l41.c | 42 +++++++++++++++++++------------------- sound/soc/codecs/cs35l41.h | 1 - 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index 5af4fb46b431..3add6367804b 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -72,7 +72,6 @@ struct cs35l41_private { struct gpio_desc *reset_gpio; struct completion global_pup_done; struct completion global_pdn_done; - struct completion mbox_cmd; }; int cs35l41_probe(struct cs35l41_private *cs35l41, diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 51d9d7aefb2f..8e806617bd35 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -254,8 +254,9 @@ static bool cs35l41_is_csplmboxsts_correct(enum cs35l41_cspl_mboxcmd cmd, static int cs35l41_set_csplmboxcmd(struct cs35l41_private *cs35l41, enum cs35l41_cspl_mboxcmd cmd) { - int ret; - unsigned int sts; + int ret = 0; + unsigned int sts, i; + bool ack = false; /* Reset DSP sticky bit */ regmap_write(cs35l41->regmap, CS35L41_IRQ2_STATUS2, @@ -268,26 +269,33 @@ static int cs35l41_set_csplmboxcmd(struct cs35l41_private *cs35l41, /* * Set mailbox cmd */ - reinit_completion(&cs35l41->mbox_cmd); + /* Unmask DSP INT */ regmap_update_bits(cs35l41->regmap, CS35L41_IRQ2_MASK2, 1 << CS35L41_CSPL_MBOX_CMD_DRV_SHIFT, 0); - /* Unmask AP INT */ - regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK2, - 1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT, 0); regmap_write(cs35l41->regmap, CS35L41_CSPL_MBOX_CMD_DRV, cmd); - ret = wait_for_completion_timeout(&cs35l41->mbox_cmd, - msecs_to_jiffies(CS35L41_MBOXWAIT)); - if (ret == 0) { + + /* Poll for DSP ACK */ + for (i = 0; i < 5; i++) { + usleep_range(1000, 1010); + regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS2, &sts); + if (sts & (1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT)) { + dev_dbg(cs35l41->dev, + "%u: Received ACK in EINT for mbox cmd (%d)\n", + i, cmd); + regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS2, + 1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT); + ack = true; + break; + } + } + + if (!ack) { dev_err(cs35l41->dev, "Timout waiting for DSP to set mbox cmd\n"); ret = -ETIMEDOUT; } - /* Mask AP INT */ - regmap_update_bits(cs35l41->regmap, CS35L41_IRQ1_MASK2, - 1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT, - 1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT); /* Mask DSP INT */ regmap_update_bits(cs35l41->regmap, CS35L41_IRQ2_MASK2, 1 << CS35L41_CSPL_MBOX_CMD_DRV_SHIFT, @@ -641,12 +649,6 @@ static irqreturn_t cs35l41_irq(int irq, void *data) !(status[2] & ~masks[2]) && !(status[3] & ~masks[3])) return IRQ_NONE; - if (status[1] & (1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT)) { - regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS2, - 1 << CS35L41_CSPL_MBOX_CMD_FW_SHIFT); - complete(&cs35l41->mbox_cmd); - } - if (status[0] & CS35L41_PUP_DONE_MASK) { regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, CS35L41_PUP_DONE_MASK); @@ -1925,8 +1927,6 @@ int cs35l41_probe(struct cs35l41_private *cs35l41, init_completion(&cs35l41->global_pdn_done); init_completion(&cs35l41->global_pup_done); - init_completion(&cs35l41->mbox_cmd); - ret = devm_request_threaded_irq(cs35l41->dev, cs35l41->irq, NULL, cs35l41_irq, IRQF_ONESHOT | irq_pol, "cs35l41", cs35l41); diff --git a/sound/soc/codecs/cs35l41.h b/sound/soc/codecs/cs35l41.h index 5b7bd79e0074..d285f802d168 100644 --- a/sound/soc/codecs/cs35l41.h +++ b/sound/soc/codecs/cs35l41.h @@ -736,7 +736,6 @@ extern const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[CS35L41_NUM_OTP_MAPS]; #define CS35L41_REGSTRIDE 4 -#define CS35L41_MBOXWAIT 5 #define CS35L41_DSP_VIRT1_MBOX_SHIFT 20 #define CS35L41_DSP_VIRT2_MBOX_SHIFT 21