diff options
Diffstat (limited to '0002-ALSA-cs35l41-Poll-for-Power-Up-Down-rather-than-wait.patch')
-rw-r--r-- | 0002-ALSA-cs35l41-Poll-for-Power-Up-Down-rather-than-wait.patch | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/0002-ALSA-cs35l41-Poll-for-Power-Up-Down-rather-than-wait.patch b/0002-ALSA-cs35l41-Poll-for-Power-Up-Down-rather-than-wait.patch new file mode 100644 index 000000000000..396384f9a457 --- /dev/null +++ b/0002-ALSA-cs35l41-Poll-for-Power-Up-Down-rather-than-wait.patch @@ -0,0 +1,141 @@ +From 437f5415c5ac8e49b0675f74132b6e1308b6e5c7 Mon Sep 17 00:00:00 2001 +From: Stefan Binding <sbinding@opensource.cirrus.com> +Date: Fri, 21 Jul 2023 16:18:07 +0100 +Subject: [PATCH 02/11] ALSA: cs35l41: Poll for Power Up/Down rather than + waiting a fixed delay + +To ensure the chip has correctly powered up or down before continuing, +the driver will now poll a register, rather than wait a fixed delay. + +Acked-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com> +--- + sound/soc/codecs/cs35l41-lib.c | 48 +++++++++++++++++++++++++++++++--- + sound/soc/codecs/cs35l41.c | 10 ------- + 2 files changed, 44 insertions(+), 14 deletions(-) + +diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c +index a7556fa33cdd..a9c559a676e7 100644 +--- a/sound/soc/codecs/cs35l41-lib.c ++++ b/sound/soc/codecs/cs35l41-lib.c +@@ -1196,7 +1196,8 @@ int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l4 + int enable, struct completion *pll_lock, bool firmware_running) + { + int ret; +- unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3, int_status; ++ unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3, int_status, pup_pdn_mask; ++ unsigned int pwr_ctl1_val; + struct reg_sequence cs35l41_mdsync_down_seq[] = { + {CS35L41_PWR_CTRL3, 0}, + {CS35L41_GPIO_PAD_CONTROL, 0}, +@@ -1208,6 +1209,12 @@ int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l4 + {CS35L41_PWR_CTRL1, 0x00000001, 3000}, + }; + ++ pup_pdn_mask = enable ? CS35L41_PUP_DONE_MASK : CS35L41_PDN_DONE_MASK; ++ ++ ret = regmap_read(regmap, CS35L41_PWR_CTRL1, &pwr_ctl1_val); ++ if (ret) ++ return ret; ++ + if ((pwr_ctl1_val & CS35L41_GLOBAL_EN_MASK) && enable) { + dev_dbg(dev, "Cannot set Global Enable - already set.\n"); + return 0; +@@ -1252,6 +1259,15 @@ int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l4 + ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_up_seq, + ARRAY_SIZE(cs35l41_mdsync_up_seq)); + } ++ ++ ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, ++ int_status, int_status & pup_pdn_mask, ++ 1000, 100000); ++ if (ret) ++ dev_err(dev, "Enable(%d) failed: %d\n", enable, ret); ++ ++ // Clear PUP/PDN status ++ regmap_write(regmap, CS35L41_IRQ1_STATUS1, pup_pdn_mask); + break; + case CS35L41_INT_BOOST: + ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK, +@@ -1260,7 +1276,15 @@ int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l4 + dev_err(dev, "CS35L41_PWR_CTRL1 set failed: %d\n", ret); + return ret; + } +- usleep_range(3000, 3100); ++ ++ ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, ++ int_status, int_status & pup_pdn_mask, ++ 1000, 100000); ++ if (ret) ++ dev_err(dev, "Enable(%d) failed: %d\n", enable, ret); ++ ++ /* Clear PUP/PDN status */ ++ regmap_write(regmap, CS35L41_IRQ1_STATUS1, pup_pdn_mask); + break; + case CS35L41_EXT_BOOST: + case CS35L41_EXT_BOOST_NO_VSPK_SWITCH: +@@ -1271,7 +1295,15 @@ int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l4 + if (ret) + return ret; + +- usleep_range(3000, 3100); ++ ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, int_status, ++ int_status & CS35L41_PUP_DONE_MASK, 1000, 100000); ++ if (ret) { ++ dev_err(dev, "Failed waiting for CS35L41_PUP_DONE_MASK: %d\n", ret); ++ /* Lock the test key, it was unlocked during the multi_reg_write */ ++ cs35l41_test_key_lock(dev, regmap); ++ return ret; ++ } ++ regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PUP_DONE_MASK); + + if (firmware_running) + ret = cs35l41_set_cspl_mbox_cmd(dev, regmap, +@@ -1292,7 +1324,15 @@ int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l4 + return ret; + } + +- usleep_range(3000, 3100); ++ ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, int_status, ++ int_status & CS35L41_PDN_DONE_MASK, 1000, 100000); ++ if (ret) { ++ dev_err(dev, "Failed waiting for CS35L41_PDN_DONE_MASK: %d\n", ret); ++ /* Lock the test key, it was unlocked during the multi_reg_write */ ++ cs35l41_test_key_lock(dev, regmap); ++ return ret; ++ } ++ regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PDN_DONE_MASK); + + /* Test Key is locked here */ + ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe_end, +diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c +index d4e9c9d9b50a..2b3c36f02edb 100644 +--- a/sound/soc/codecs/cs35l41.c ++++ b/sound/soc/codecs/cs35l41.c +@@ -491,7 +491,6 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w, + { + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct cs35l41_private *cs35l41 = snd_soc_component_get_drvdata(component); +- unsigned int val; + int ret = 0; + + switch (event) { +@@ -507,15 +506,6 @@ static int cs35l41_main_amp_event(struct snd_soc_dapm_widget *w, + ret = cs35l41_global_enable(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type, + 0, &cs35l41->pll_lock, cs35l41->dsp.cs_dsp.running); + +- ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS1, +- val, val & CS35L41_PDN_DONE_MASK, +- 1000, 100000); +- if (ret) +- dev_warn(cs35l41->dev, "PDN failed: %d\n", ret); +- +- regmap_write(cs35l41->regmap, CS35L41_IRQ1_STATUS1, +- CS35L41_PDN_DONE_MASK); +- + regmap_multi_reg_write_bypassed(cs35l41->regmap, + cs35l41_pdn_patch, + ARRAY_SIZE(cs35l41_pdn_patch)); +-- +2.41.0 + |