static int wm8350_set_fll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { struct snd_soc_codec *codec = codec_dai->codec; struct wm8350 *wm8350 = codec->control_data; struct wm8350_data *priv = codec->private_data; struct _fll_div fll_div; int ret = 0; u16 fll_1, fll_4; if (freq_in == priv->fll_freq_in && freq_out == priv->fll_freq_out) return 0; /* power down FLL - we need to do this for reconfiguration */ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); if (freq_out == 0 || freq_in == 0) return ret; ret = fll_factors(&fll_div, freq_in, freq_out); if (ret < 0) return ret; dev_dbg(wm8350->dev, "FLL in %u FLL out %u N 0x%x K 0x%x div %d ratio %d", freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div, fll_div.ratio); /* set up N.K & dividers */ fll_1 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_1) & ~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000); wm8350_codec_write(codec, WM8350_FLL_CONTROL_1, fll_1 | (fll_div.div << 8) | 0x50); wm8350_codec_write(codec, WM8350_FLL_CONTROL_2, (fll_div.ratio << 11) | (fll_div. n & WM8350_FLL_N_MASK)); wm8350_codec_write(codec, WM8350_FLL_CONTROL_3, fll_div.k); fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) & ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF); wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) | (fll_div.ratio == 8 ? WM8350_FLL_SLOW_LOCK_REF : 0)); /* power FLL on */ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); priv->fll_freq_out = freq_out; priv->fll_freq_in = freq_in; return 0; }
static int wm8350_set_fll(struct snd_soc_dai *codec_dai, int pll_id, unsigned int freq_in, unsigned int freq_out) { struct snd_soc_codec *codec = codec_dai->codec; struct wm8350* wm8350 = codec->control_data; struct _fll_div fll_div; int ret = 0; u16 fll_1, fll_4; if (freq_out == 0 || freq_in == 0) { /* power down FLL */ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); return ret; } ret = fll_factors(&fll_div, freq_in, freq_out); if (ret < 0) return ret; /* set up N.K & dividers */ fll_1 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_1) & ~(WM8350_FLL_OUTDIV_MASK | 0xc000); wm8350_codec_write(codec, WM8350_FLL_CONTROL_1, fll_1 | (fll_div.div << 8)); wm8350_codec_write(codec, WM8350_FLL_CONTROL_2, (fll_div.ratio << 11) | (fll_div.n & WM8350_FLL_N_MASK)); wm8350_codec_write(codec, WM8350_FLL_CONTROL_3, fll_div.k); fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) & ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF); wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) | (fll_div.ratio == 8 ? WM8350_FLL_SLOW_LOCK_REF : 0)); /* power FLL on */ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); /* do we need to wait here ? */ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); return 0; }
static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source, unsigned int Fref, unsigned int Fout) { struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); struct i2c_client *i2c = to_i2c_client(codec->dev); u16 reg1, reg4, reg5; struct _fll_div fll_div; unsigned int timeout; int ret; /* Any change? */ if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout) return 0; /* Disable the FLL */ if (Fout == 0) { dev_dbg(codec->dev, "FLL disabled\n"); wm8993->fll_fref = 0; wm8993->fll_fout = 0; reg1 = snd_soc_read(codec, WM8993_FLL_CONTROL_1); reg1 &= ~WM8993_FLL_ENA; snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); return 0; } ret = fll_factors(&fll_div, Fref, Fout); if (ret != 0) return ret; reg5 = snd_soc_read(codec, WM8993_FLL_CONTROL_5); reg5 &= ~WM8993_FLL_CLK_SRC_MASK; switch (fll_id) { case WM8993_FLL_MCLK: break; case WM8993_FLL_LRCLK: reg5 |= 1; break; case WM8993_FLL_BCLK: reg5 |= 2; break; default: dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); return -EINVAL; } /* Any FLL configuration change requires that the FLL be * disabled first. */ reg1 = snd_soc_read(codec, WM8993_FLL_CONTROL_1); reg1 &= ~WM8993_FLL_ENA; snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); /* Apply the configuration */ if (fll_div.k) reg1 |= WM8993_FLL_FRAC_MASK; else reg1 &= ~WM8993_FLL_FRAC_MASK; snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); snd_soc_write(codec, WM8993_FLL_CONTROL_2, (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) | (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); snd_soc_write(codec, WM8993_FLL_CONTROL_3, fll_div.k); reg4 = snd_soc_read(codec, WM8993_FLL_CONTROL_4); reg4 &= ~WM8993_FLL_N_MASK; reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; snd_soc_write(codec, WM8993_FLL_CONTROL_4, reg4); reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK; reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT; snd_soc_write(codec, WM8993_FLL_CONTROL_5, reg5); /* If we've got an interrupt wired up make sure we get it */ if (i2c->irq) timeout = msecs_to_jiffies(20); else if (Fref < 1000000) timeout = msecs_to_jiffies(3); else timeout = msecs_to_jiffies(1); try_wait_for_completion(&wm8993->fll_lock); /* Enable the FLL */ snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA); timeout = wait_for_completion_timeout(&wm8993->fll_lock, timeout); if (i2c->irq && !timeout) dev_warn(codec->dev, "Timed out waiting for FLL\n"); dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); wm8993->fll_fref = Fref; wm8993->fll_fout = Fout; wm8993->fll_src = source; return 0; }
static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id, unsigned int Fref, unsigned int Fout) { struct wm9081_priv *wm9081 = codec->private_data; u16 reg1, reg4, reg5; struct _fll_div fll_div; int ret; int clk_sys_reg; /* Any change? */ if (Fref == wm9081->fll_fref && Fout == wm9081->fll_fout) return 0; /* Disable the FLL */ if (Fout == 0) { dev_dbg(codec->dev, "FLL disabled\n"); wm9081->fll_fref = 0; wm9081->fll_fout = 0; return 0; } ret = fll_factors(&fll_div, Fref, Fout); if (ret != 0) return ret; reg5 = snd_soc_read(codec, WM9081_FLL_CONTROL_5); reg5 &= ~WM9081_FLL_CLK_SRC_MASK; switch (fll_id) { case WM9081_SYSCLK_FLL_MCLK: reg5 |= 0x1; break; default: dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); return -EINVAL; } /* Disable CLK_SYS while we reconfigure */ clk_sys_reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3); if (clk_sys_reg & WM9081_CLK_SYS_ENA) snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg & ~WM9081_CLK_SYS_ENA); /* Any FLL configuration change requires that the FLL be * disabled first. */ reg1 = snd_soc_read(codec, WM9081_FLL_CONTROL_1); reg1 &= ~WM9081_FLL_ENA; snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1); /* Apply the configuration */ if (fll_div.k) reg1 |= WM9081_FLL_FRAC_MASK; else reg1 &= ~WM9081_FLL_FRAC_MASK; snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1); snd_soc_write(codec, WM9081_FLL_CONTROL_2, (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) | (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT)); snd_soc_write(codec, WM9081_FLL_CONTROL_3, fll_div.k); reg4 = snd_soc_read(codec, WM9081_FLL_CONTROL_4); reg4 &= ~WM9081_FLL_N_MASK; reg4 |= fll_div.n << WM9081_FLL_N_SHIFT; snd_soc_write(codec, WM9081_FLL_CONTROL_4, reg4); reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK; reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT; snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5); /* Enable the FLL */ snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA); /* Then bring CLK_SYS up again if it was disabled */ if (clk_sys_reg & WM9081_CLK_SYS_ENA) snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg); dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); wm9081->fll_fref = Fref; wm9081->fll_fout = Fout; return 0; }
static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, unsigned int Fref, unsigned int Fout) { struct snd_soc_codec *codec = dai->codec; struct wm8993_priv *wm8993 = codec->private_data; u16 reg1, reg4, reg5; struct _fll_div fll_div; int ret; /* Any change? */ if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout) return 0; /* Disable the FLL */ if (Fout == 0) { dev_dbg(codec->dev, "FLL disabled\n"); wm8993->fll_fref = 0; wm8993->fll_fout = 0; reg1 = snd_soc_read(codec, WM8993_FLL_CONTROL_1); reg1 &= ~WM8993_FLL_ENA; snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); return 0; } ret = fll_factors(&fll_div, Fref, Fout); if (ret != 0) return ret; reg5 = snd_soc_read(codec, WM8993_FLL_CONTROL_5); reg5 &= ~WM8993_FLL_CLK_SRC_MASK; switch (fll_id) { case WM8993_FLL_MCLK: break; case WM8993_FLL_LRCLK: reg5 |= 1; break; case WM8993_FLL_BCLK: reg5 |= 2; break; default: dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); return -EINVAL; } /* Any FLL configuration change requires that the FLL be * disabled first. */ reg1 = snd_soc_read(codec, WM8993_FLL_CONTROL_1); reg1 &= ~WM8993_FLL_ENA; snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); /* Apply the configuration */ if (fll_div.k) reg1 |= WM8993_FLL_FRAC_MASK; else reg1 &= ~WM8993_FLL_FRAC_MASK; snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1); snd_soc_write(codec, WM8993_FLL_CONTROL_2, (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) | (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); snd_soc_write(codec, WM8993_FLL_CONTROL_3, fll_div.k); reg4 = snd_soc_read(codec, WM8993_FLL_CONTROL_4); reg4 &= ~WM8993_FLL_N_MASK; reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; snd_soc_write(codec, WM8993_FLL_CONTROL_4, reg4); reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK; reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT; snd_soc_write(codec, WM8993_FLL_CONTROL_5, reg5); /* Enable the FLL */ snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA); dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); wm8993->fll_fref = Fref; wm8993->fll_fout = Fout; wm8993->fll_src = source; return 0; }
static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id, unsigned int Fref, unsigned int Fout) { struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); u16 reg1, reg4, reg5; struct _fll_div fll_div; int ret; int clk_sys_reg; if (Fref == wm9081->fll_fref && Fout == wm9081->fll_fout) return 0; if (Fout == 0) { dev_dbg(codec->dev, "FLL disabled\n"); wm9081->fll_fref = 0; wm9081->fll_fout = 0; return 0; } ret = fll_factors(&fll_div, Fref, Fout); if (ret != 0) return ret; reg5 = snd_soc_read(codec, WM9081_FLL_CONTROL_5); reg5 &= ~WM9081_FLL_CLK_SRC_MASK; switch (fll_id) { case WM9081_SYSCLK_FLL_MCLK: reg5 |= 0x1; break; default: dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); return -EINVAL; } clk_sys_reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3); if (clk_sys_reg & WM9081_CLK_SYS_ENA) snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg & ~WM9081_CLK_SYS_ENA); reg1 = snd_soc_read(codec, WM9081_FLL_CONTROL_1); reg1 &= ~WM9081_FLL_ENA; snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1); if (fll_div.k) reg1 |= WM9081_FLL_FRAC_MASK; else reg1 &= ~WM9081_FLL_FRAC_MASK; snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1); snd_soc_write(codec, WM9081_FLL_CONTROL_2, (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) | (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT)); snd_soc_write(codec, WM9081_FLL_CONTROL_3, fll_div.k); reg4 = snd_soc_read(codec, WM9081_FLL_CONTROL_4); reg4 &= ~WM9081_FLL_N_MASK; reg4 |= fll_div.n << WM9081_FLL_N_SHIFT; snd_soc_write(codec, WM9081_FLL_CONTROL_4, reg4); reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK; reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT; snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5); snd_soc_update_bits(codec, WM9081_FLL_CONTROL_4, WM9081_FLL_GAIN_MASK, 0); snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA); if (clk_sys_reg & WM9081_CLK_SYS_ENA) snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg); dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); wm9081->fll_fref = Fref; wm9081->fll_fout = Fout; return 0; }