lkml.org 
[lkml]   [2015]   [Sep]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.2 079/120] ASoC: arizona: Poll for FLL clock OK rather than use interrupts
    Date
    4.2-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>

    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 <ckeepax@opensource.wolfsonmicro.com>
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    sound/soc/codecs/arizona.c | 47 ++++++++++++++++++---------------------------
    sound/soc/codecs/arizona.h | 1
    2 files changed, 19 insertions(+), 29 deletions(-)

    --- a/sound/soc/codecs/arizona.c
    +++ b/sound/soc/codecs/arizona.c
    @@ -1756,17 +1756,6 @@ int arizona_init_dai(struct arizona_priv
    }
    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;
    @@ -2048,10 +2037,11 @@ static int arizona_is_enabled_fll(struct
    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;
    @@ -2110,9 +2100,6 @@ static int arizona_enable_fll(struct ari
    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)
    @@ -2124,10 +2111,24 @@ static int arizona_enable_fll(struct ari
    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;
    }
    @@ -2212,11 +2213,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;
    @@ -2238,13 +2236,6 @@ int arizona_init_fll(struct arizona *ari
    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);

    --- a/sound/soc/codecs/arizona.h
    +++ b/sound/soc/codecs/arizona.h
    @@ -242,7 +242,6 @@ struct arizona_fll {
    int id;
    unsigned int base;
    unsigned int vco_mult;
    - struct completion ok;

    unsigned int fout;
    int sync_src;



    \
     
     \ /
      Last update: 2015-09-19 20:21    [W:6.062 / U:0.244 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site