int arizona_set_fll_refclk(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { struct arizona_fll_cfg ref, sync; int ret; if (fll->ref_src == source && fll->ref_freq == Fref) return 0; if (fll->fout) { if (Fref > 0) { ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); if (ret != 0) return ret; } if (fll->sync_src >= 0) { ret = arizona_calc_fll(fll, &sync, fll->sync_freq, fll->fout); if (ret != 0) return ret; } } fll->ref_src = source; fll->ref_freq = Fref; if (fll->fout && Fref > 0) { arizona_enable_fll(fll, &ref, &sync); } return 0; }
int arizona_set_fll(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { struct arizona_fll_cfg ref, sync; int ret; if (fll->sync_src == source && fll->sync_freq == Fref && fll->fout == Fout) return 0; if (Fout) { if (fll->ref_src >= 0) { ret = arizona_calc_fll(fll, &ref, fll->ref_freq, Fout); if (ret != 0) return ret; } ret = arizona_calc_fll(fll, &sync, Fref, Fout); if (ret != 0) return ret; } fll->sync_src = source; fll->sync_freq = Fref; fll->fout = Fout; if (Fout) { arizona_enable_fll(fll, &ref, &sync); } else { arizona_disable_fll(fll); } return 0; }
int arizona_set_fll(struct arizona_fll *fll, int source, unsigned int Fref, unsigned int Fout) { struct arizona *arizona = fll->arizona; struct arizona_fll_cfg cfg, sync; unsigned int reg, val; int syncsrc; bool ena; int ret; ret = regmap_read(arizona->regmap, fll->base + 1, ®); if (ret != 0) { arizona_fll_err(fll, "Failed to read current state: %d\n", ret); return ret; } ena = reg & ARIZONA_FLL1_ENA; if (Fout) { /* Do we have a 32kHz reference? */ regmap_read(arizona->regmap, ARIZONA_CLOCK_32K_1, &val); switch (val & ARIZONA_CLK_32K_SRC_MASK) { case ARIZONA_CLK_SRC_MCLK1: case ARIZONA_CLK_SRC_MCLK2: syncsrc = val & ARIZONA_CLK_32K_SRC_MASK; break; default: syncsrc = -1; } if (source == syncsrc) syncsrc = -1; if (syncsrc >= 0) { ret = arizona_calc_fll(fll, &sync, Fref, Fout); if (ret != 0) return ret; ret = arizona_calc_fll(fll, &cfg, 32768, Fout); if (ret != 0) return ret; } else { ret = arizona_calc_fll(fll, &cfg, Fref, Fout); if (ret != 0) return ret; } } else { regmap_update_bits(arizona->regmap, fll->base + 1, ARIZONA_FLL1_ENA, 0); regmap_update_bits(arizona->regmap, fll->base + 0x11, ARIZONA_FLL1_SYNC_ENA, 0); if (ena) pm_runtime_put_autosuspend(arizona->dev); return 0; } regmap_update_bits(arizona->regmap, fll->base + 5, ARIZONA_FLL1_OUTDIV_MASK, cfg.outdiv << ARIZONA_FLL1_OUTDIV_SHIFT); if (syncsrc >= 0) { arizona_apply_fll(arizona, fll->base, &cfg, syncsrc); arizona_apply_fll(arizona, fll->base + 0x10, &sync, source); } else { arizona_apply_fll(arizona, fll->base, &cfg, source); } if (!ena) pm_runtime_get(arizona->dev); /* Clear any pending completions */ try_wait_for_completion(&fll->ok); regmap_update_bits(arizona->regmap, fll->base + 1, ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA); if (syncsrc >= 0) regmap_update_bits(arizona->regmap, fll->base + 0x11, ARIZONA_FLL1_SYNC_ENA, ARIZONA_FLL1_SYNC_ENA); ret = wait_for_completion_timeout(&fll->ok, msecs_to_jiffies(25)); if (ret == 0) arizona_fll_warn(fll, "Timed out waiting for lock\n"); return 0; }