From d23f2688b991310d4f27d4abaf7769ea301c9a91 Mon Sep 17 00:00:00 2001 From: Nikesh Oswal Date: Wed, 19 Aug 2015 16:02:24 +0100 Subject: ASoC: arizona: Fix gain settings of FLL in free-run mode commit 1cf5a330c05ae37a0a98ac7c9800a6f50d5579ec upstream. The wrong register was used to set the gain of ref loop, when changing the FLL output on an active FLL. This patch corrects the offset of the gain register. Signed-off-by: Nikesh Oswal Signed-off-by: Charles Keepax Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/arizona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/codecs/arizona.c') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index eff4b4d512b7..92b813b74014 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1912,7 +1912,7 @@ static int arizona_enable_fll(struct arizona_fll *fll) if (already_enabled) { /* Facilitate smooth refclk across the transition */ - regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7, + regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x9, ARIZONA_FLL1_GAIN_MASK, 0); regmap_update_bits_async(fll->arizona->regmap, fll->base + 1, ARIZONA_FLL1_FREERUN, -- cgit v1.2.3 From b3100c898181590cabc652a925d268c78a69b77a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 25 Aug 2015 12:43:48 +0100 Subject: ASoC: arizona: Poll for FLL clock OK rather than use interrupts commit 0e7659712836ca59b4735bc5cc94de38698a5e01 upstream. The extcon driver takes the DAPM mutex from within the interrupt thread in several places, which makes it possible to get into a situation where the interrupt thread is blocked waiting on the DAPM mutex whilst a DAPM sequence is running which is attempting to configure the FLL. In this case the FLL completion can't be completed as as the IRQ handler is ONE_SHOT, which cause the FLL lock to use the full time out (250mS) and report that the process timed out. It is not really practical to make the extcon driver not take the DAPM mutex from within the interrupt thread, at least not without extensive modification. So this patch fixes the issue by switching the wait for the FLL lock to polling. A few fast polls are done first as the FLL should lock quickly for a good quality reference clock, (indeed it hits on the first poll on my system) and it will poll every 20mS after that until it times out. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/arizona.c | 47 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) (limited to 'sound/soc/codecs/arizona.c') diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 92b813b74014..ee91edcf3cb0 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1610,17 +1610,6 @@ int arizona_init_dai(struct arizona_priv *priv, int id) } EXPORT_SYMBOL_GPL(arizona_init_dai); -static irqreturn_t arizona_fll_clock_ok(int irq, void *data) -{ - struct arizona_fll *fll = data; - - arizona_fll_dbg(fll, "clock OK\n"); - - complete(&fll->ok); - - return IRQ_HANDLED; -} - static struct { unsigned int min; unsigned int max; @@ -1902,10 +1891,11 @@ static int arizona_is_enabled_fll(struct arizona_fll *fll) static int arizona_enable_fll(struct arizona_fll *fll) { struct arizona *arizona = fll->arizona; - unsigned long time_left; bool use_sync = false; int already_enabled = arizona_is_enabled_fll(fll); struct arizona_fll_cfg cfg; + int i; + unsigned int val; if (already_enabled < 0) return already_enabled; @@ -1964,9 +1954,6 @@ static int arizona_enable_fll(struct arizona_fll *fll) if (!already_enabled) pm_runtime_get(arizona->dev); - /* Clear any pending completions */ - try_wait_for_completion(&fll->ok); - regmap_update_bits_async(arizona->regmap, fll->base + 1, ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); if (use_sync) @@ -1978,10 +1965,24 @@ static int arizona_enable_fll(struct arizona_fll *fll) regmap_update_bits_async(arizona->regmap, fll->base + 1, ARIZONA_FLL1_FREERUN, 0); - time_left = wait_for_completion_timeout(&fll->ok, - msecs_to_jiffies(250)); - if (time_left == 0) + arizona_fll_dbg(fll, "Waiting for FLL lock...\n"); + val = 0; + for (i = 0; i < 15; i++) { + if (i < 5) + usleep_range(200, 400); + else + msleep(20); + + regmap_read(arizona->regmap, + ARIZONA_INTERRUPT_RAW_STATUS_5, + &val); + if (val & (ARIZONA_FLL1_CLOCK_OK_STS << (fll->id - 1))) + break; + } + if (i == 15) arizona_fll_warn(fll, "Timed out waiting for lock\n"); + else + arizona_fll_dbg(fll, "FLL locked (%d polls)\n", i); return 0; } @@ -2066,11 +2067,8 @@ EXPORT_SYMBOL_GPL(arizona_set_fll); int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, int ok_irq, struct arizona_fll *fll) { - int ret; unsigned int val; - init_completion(&fll->ok); - fll->id = id; fll->base = base; fll->arizona = arizona; @@ -2092,13 +2090,6 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, snprintf(fll->clock_ok_name, sizeof(fll->clock_ok_name), "FLL%d clock OK", id); - ret = arizona_request_irq(arizona, ok_irq, fll->clock_ok_name, - arizona_fll_clock_ok, fll); - if (ret != 0) { - dev_err(arizona->dev, "Failed to get FLL%d clock OK IRQ: %d\n", - id, ret); - } - regmap_update_bits(arizona->regmap, fll->base + 1, ARIZONA_FLL1_FREERUN, 0); -- cgit v1.2.3