diff options
Diffstat (limited to 'sound/soc/codecs/rt5682s.c')
-rw-r--r-- | sound/soc/codecs/rt5682s.c | 265 |
1 files changed, 158 insertions, 107 deletions
diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index eb47e7cd485a..3b91a3442c68 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -739,6 +739,7 @@ static void rt5682s_disable_push_button_irq(struct snd_soc_component *component) */ static int rt5682s_headset_detect(struct snd_soc_component *component, int jack_insert) { + struct rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component); unsigned int val, count; int jack_type = 0; @@ -805,12 +806,10 @@ static int rt5682s_headset_detect(struct snd_soc_component *component, int jack_ snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_1, RT5682S_TRIG_JD_MASK, RT5682S_TRIG_JD_LOW); - if (!snd_soc_dapm_get_pin_status(&component->dapm, "MICBIAS")) - snd_soc_component_update_bits(component, - RT5682S_PWR_ANLG_1, RT5682S_PWR_MB, 0); - if (!snd_soc_dapm_get_pin_status(&component->dapm, "Vref2")) + if (!rt5682s->wclk_enabled) { snd_soc_component_update_bits(component, - RT5682S_PWR_ANLG_1, RT5682S_PWR_VREF2, 0); + RT5682S_PWR_ANLG_1, RT5682S_PWR_VREF2 | RT5682S_PWR_MB, 0); + } snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_3, RT5682S_PWR_CBJ, 0); @@ -845,6 +844,7 @@ static void rt5682s_jack_detect_handler(struct work_struct *work) snd_soc_dapm_mutex_lock(dapm); mutex_lock(&rt5682s->calibrate_mutex); + mutex_lock(&rt5682s->wclk_mutex); val = snd_soc_component_read(rt5682s->component, RT5682S_AJD1_CTRL) & RT5682S_JDH_RS_MASK; @@ -900,6 +900,7 @@ static void rt5682s_jack_detect_handler(struct work_struct *work) rt5682s->irq_work_delay_time = 50; } + mutex_unlock(&rt5682s->wclk_mutex); mutex_unlock(&rt5682s->calibrate_mutex); snd_soc_dapm_mutex_unlock(dapm); @@ -1154,29 +1155,52 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, return 0; } -static int set_filter_clk(struct snd_soc_dapm_widget *w, + +static int rt5682s_set_pllb_power(struct rt5682s_priv *rt5682s, int on) +{ + struct snd_soc_component *component = rt5682s->component; + + if (on) { + snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_3, + RT5682S_PWR_LDO_PLLB | RT5682S_PWR_BIAS_PLLB | RT5682S_PWR_PLLB, + RT5682S_PWR_LDO_PLLB | RT5682S_PWR_BIAS_PLLB | RT5682S_PWR_PLLB); + snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_3, + RT5682S_RSTB_PLLB, RT5682S_RSTB_PLLB); + } else { + snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_3, + RT5682S_PWR_LDO_PLLB | RT5682S_PWR_BIAS_PLLB | + RT5682S_RSTB_PLLB | RT5682S_PWR_PLLB, 0); + } + + return 0; +} + +static int set_pllb_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component); - int ref, val, reg, idx; - static const int div_f[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; - static const int div_o[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48}; + int on = 0; - val = snd_soc_component_read(component, RT5682S_GPIO_CTRL_1) - & RT5682S_GP4_PIN_MASK; + if (rt5682s->wclk_enabled) + return 0; - if (w->shift == RT5682S_PWR_ADC_S1F_BIT && val == RT5682S_GP4_PIN_ADCDAT2) - ref = 256 * rt5682s->lrck[RT5682S_AIF2]; - else - ref = 256 * rt5682s->lrck[RT5682S_AIF1]; + if (SND_SOC_DAPM_EVENT_ON(event)) + on = 1; - idx = rt5682s_div_sel(rt5682s, ref, div_f, ARRAY_SIZE(div_f)); + rt5682s_set_pllb_power(rt5682s, on); - if (w->shift == RT5682S_PWR_ADC_S1F_BIT) - reg = RT5682S_PLL_TRACK_3; - else - reg = RT5682S_PLL_TRACK_2; + return 0; +} + +static void rt5682s_set_filter_clk(struct rt5682s_priv *rt5682s, int reg, int ref) +{ + struct snd_soc_component *component = rt5682s->component; + int idx; + static const int div_f[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; + static const int div_o[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48}; + + idx = rt5682s_div_sel(rt5682s, ref, div_f, ARRAY_SIZE(div_f)); snd_soc_component_update_bits(component, reg, RT5682S_FILTER_CLK_DIV_MASK, idx << RT5682S_FILTER_CLK_DIV_SFT); @@ -1190,6 +1214,29 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, RT5682S_ADDA_CLK_1, RT5682S_ADC_OSR_MASK | RT5682S_DAC_OSR_MASK, (idx << RT5682S_ADC_OSR_SFT) | (idx << RT5682S_DAC_OSR_SFT)); +} + +static int set_filter_clk(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component); + int ref, reg, val; + + val = snd_soc_component_read(component, RT5682S_GPIO_CTRL_1) + & RT5682S_GP4_PIN_MASK; + + if (w->shift == RT5682S_PWR_ADC_S1F_BIT && val == RT5682S_GP4_PIN_ADCDAT2) + ref = 256 * rt5682s->lrck[RT5682S_AIF2]; + else + ref = 256 * rt5682s->lrck[RT5682S_AIF1]; + + if (w->shift == RT5682S_PWR_ADC_S1F_BIT) + reg = RT5682S_PLL_TRACK_3; + else + reg = RT5682S_PLL_TRACK_2; + + rt5682s_set_filter_clk(rt5682s, reg, ref); return 0; } @@ -1218,13 +1265,9 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMD: - if (!rt5682s->jack_type) { - if (!snd_soc_dapm_get_pin_status(w->dapm, "MICBIAS")) - snd_soc_component_update_bits(component, - RT5682S_PWR_ANLG_1, RT5682S_PWR_MB, 0); - if (!snd_soc_dapm_get_pin_status(w->dapm, "Vref2")) - snd_soc_component_update_bits(component, - RT5682S_PWR_ANLG_1, RT5682S_PWR_VREF2, 0); + if (!rt5682s->jack_type && !rt5682s->wclk_enabled) { + snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_1, + RT5682S_PWR_VREF2 | RT5682S_PWR_MB, 0); } break; } @@ -1232,41 +1275,58 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w, return 0; } -static int set_i2s_clk(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) +static void rt5682s_set_i2s(struct rt5682s_priv *rt5682s, int id, int on) { - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - struct rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component); - int pre_div, id; - unsigned int reg, mask, sft; - - if (event != SND_SOC_DAPM_PRE_PMU) - return 0; - - if (w->shift == RT5682S_PWR_I2S2_BIT) { - id = RT5682S_AIF2; - reg = RT5682S_I2S2_M_CLK_CTRL_1; - mask = RT5682S_I2S2_M_D_MASK; - sft = RT5682S_I2S2_M_D_SFT; + struct snd_soc_component *component = rt5682s->component; + int pre_div; + unsigned int p_reg, p_mask, p_sft; + unsigned int c_reg, c_mask, c_sft; + + if (id == RT5682S_AIF1) { + c_reg = RT5682S_ADDA_CLK_1; + c_mask = RT5682S_I2S_M_D_MASK; + c_sft = RT5682S_I2S_M_D_SFT; + p_reg = RT5682S_PWR_DIG_1; + p_mask = RT5682S_PWR_I2S1; + p_sft = RT5682S_PWR_I2S1_BIT; } else { - id = RT5682S_AIF1; - reg = RT5682S_ADDA_CLK_1; - mask = RT5682S_I2S_M_D_MASK; - sft = RT5682S_I2S_M_D_SFT; + c_reg = RT5682S_I2S2_M_CLK_CTRL_1; + c_mask = RT5682S_I2S2_M_D_MASK; + c_sft = RT5682S_I2S2_M_D_SFT; + p_reg = RT5682S_PWR_DIG_1; + p_mask = RT5682S_PWR_I2S2; + p_sft = RT5682S_PWR_I2S2_BIT; } - if (!rt5682s->master[id]) - return 0; + if (on && rt5682s->master[id]) { + pre_div = get_clk_info(rt5682s->sysclk, rt5682s->lrck[id]); + if (pre_div < 0) { + dev_err(component->dev, "get pre_div failed\n"); + return; + } - pre_div = get_clk_info(rt5682s->sysclk, rt5682s->lrck[id]); - if (pre_div < 0) { - dev_err(component->dev, "get pre_div failed\n"); - return -EINVAL; + dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d master\n", + rt5682s->lrck[id], pre_div, id); + snd_soc_component_update_bits(component, c_reg, c_mask, pre_div << c_sft); } - dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d master\n", - rt5682s->lrck[id], pre_div, id); - snd_soc_component_update_bits(component, reg, mask, pre_div << sft); + snd_soc_component_update_bits(component, p_reg, p_mask, on << p_sft); +} + +static int set_i2s_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component); + int on = 0; + + if (SND_SOC_DAPM_EVENT_ON(event)) + on = 1; + + if (!strcmp(w->name, "I2S1") && !rt5682s->wclk_enabled) + rt5682s_set_i2s(rt5682s, RT5682S_AIF1, on); + else if (!strcmp(w->name, "I2S2")) + rt5682s_set_i2s(rt5682s, RT5682S_AIF2, on); return 0; } @@ -1615,26 +1675,18 @@ static const struct snd_soc_dapm_widget rt5682s_dapm_widgets[] = { RT5682S_PWR_LDO_MB2_BIT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("LDO", RT5682S_PWR_ANLG_3, RT5682S_PWR_LDO_BIT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("Vref2", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, NULL, 0), /* PLL Powers */ SND_SOC_DAPM_SUPPLY_S("PLLA_LDO", 0, RT5682S_PWR_ANLG_3, RT5682S_PWR_LDO_PLLA_BIT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY_S("PLLB_LDO", 0, RT5682S_PWR_ANLG_3, - RT5682S_PWR_LDO_PLLB_BIT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("PLLA_BIAS", 0, RT5682S_PWR_ANLG_3, RT5682S_PWR_BIAS_PLLA_BIT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY_S("PLLB_BIAS", 0, RT5682S_PWR_ANLG_3, - RT5682S_PWR_BIAS_PLLB_BIT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY_S("PLLA", 0, RT5682S_PWR_ANLG_3, RT5682S_PWR_PLLA_BIT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY_S("PLLB", 0, RT5682S_PWR_ANLG_3, - RT5682S_PWR_PLLB_BIT, 0, set_filter_clk, SND_SOC_DAPM_PRE_PMU), SND_SOC_DAPM_SUPPLY_S("PLLA_RST", 1, RT5682S_PWR_ANLG_3, RT5682S_RSTB_PLLA_BIT, 0, NULL, 0), - SND_SOC_DAPM_SUPPLY_S("PLLB_RST", 1, RT5682S_PWR_ANLG_3, - RT5682S_RSTB_PLLB_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLLB", SND_SOC_NOPM, 0, 0, + set_pllb_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), /* ASRC */ SND_SOC_DAPM_SUPPLY_S("DAC STO1 ASRC", 1, RT5682S_PLL_TRACK_1, @@ -1720,10 +1772,10 @@ static const struct snd_soc_dapm_widget rt5682s_dapm_widgets[] = { SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), /* Digital Interface */ - SND_SOC_DAPM_SUPPLY("I2S1", RT5682S_PWR_DIG_1, RT5682S_PWR_I2S1_BIT, - 0, set_i2s_clk, SND_SOC_DAPM_PRE_PMU), - SND_SOC_DAPM_SUPPLY("I2S2", RT5682S_PWR_DIG_1, RT5682S_PWR_I2S2_BIT, - 0, set_i2s_clk, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SUPPLY("I2S1", SND_SOC_NOPM, 0, 0, + set_i2s_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("I2S2", SND_SOC_NOPM, 0, 0, + set_i2s_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), @@ -1801,9 +1853,6 @@ static const struct snd_soc_dapm_route rt5682s_dapm_routes[] = { {"PLLA", NULL, "PLLA_LDO"}, {"PLLA", NULL, "PLLA_BIAS"}, {"PLLA", NULL, "PLLA_RST"}, - {"PLLB", NULL, "PLLB_LDO"}, - {"PLLB", NULL, "PLLB_BIAS"}, - {"PLLB", NULL, "PLLB_RST"}, /*ASRC*/ {"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc}, @@ -2431,12 +2480,15 @@ static int rt5682s_set_bias_level(struct snd_soc_component *component, RT5682S_PWR_LDO, RT5682S_PWR_LDO); break; case SND_SOC_BIAS_STANDBY: - regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1, - RT5682S_DIG_GATE_CTRL, RT5682S_DIG_GATE_CTRL); + if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) + regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1, + RT5682S_DIG_GATE_CTRL, RT5682S_DIG_GATE_CTRL); break; case SND_SOC_BIAS_OFF: - regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1, - RT5682S_DIG_GATE_CTRL | RT5682S_PWR_LDO, 0); + regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1, RT5682S_PWR_LDO, 0); + if (!rt5682s->wclk_enabled) + regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1, + RT5682S_DIG_GATE_CTRL, 0); break; case SND_SOC_BIAS_ON: break; @@ -2464,30 +2516,34 @@ static int rt5682s_wclk_prepare(struct clk_hw *hw) struct rt5682s_priv *rt5682s = container_of(hw, struct rt5682s_priv, dai_clks_hw[RT5682S_DAI_WCLK_IDX]); struct snd_soc_component *component = rt5682s->component; - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + int ref, reg; if (!rt5682s_clk_check(rt5682s)) return -EINVAL; - snd_soc_dapm_mutex_lock(dapm); - - snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS"); - snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_1, - RT5682S_PWR_MB, RT5682S_PWR_MB); + mutex_lock(&rt5682s->wclk_mutex); - snd_soc_dapm_force_enable_pin_unlocked(dapm, "Vref2"); snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_1, - RT5682S_PWR_VREF2 | RT5682S_PWR_FV2, RT5682S_PWR_VREF2); + RT5682S_PWR_VREF2 | RT5682S_PWR_FV2 | RT5682S_PWR_MB, + RT5682S_PWR_VREF2 | RT5682S_PWR_MB); usleep_range(15000, 20000); snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_1, RT5682S_PWR_FV2, RT5682S_PWR_FV2); - snd_soc_dapm_force_enable_pin_unlocked(dapm, "I2S1"); - /* Only need to power PLLB due to the rate set restriction */ - snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLLB"); - snd_soc_dapm_sync_unlocked(dapm); + /* Set and power on I2S1 */ + snd_soc_component_update_bits(component, RT5682S_PWR_DIG_1, + RT5682S_DIG_GATE_CTRL, RT5682S_DIG_GATE_CTRL); + rt5682s_set_i2s(rt5682s, RT5682S_AIF1, 1); - snd_soc_dapm_mutex_unlock(dapm); + /* Only need to power on PLLB due to the rate set restriction */ + reg = RT5682S_PLL_TRACK_2; + ref = 256 * rt5682s->lrck[RT5682S_AIF1]; + rt5682s_set_filter_clk(rt5682s, reg, ref); + rt5682s_set_pllb_power(rt5682s, 1); + + rt5682s->wclk_enabled = 1; + + mutex_unlock(&rt5682s->wclk_mutex); return 0; } @@ -2497,24 +2553,27 @@ static void rt5682s_wclk_unprepare(struct clk_hw *hw) struct rt5682s_priv *rt5682s = container_of(hw, struct rt5682s_priv, dai_clks_hw[RT5682S_DAI_WCLK_IDX]); struct snd_soc_component *component = rt5682s->component; - struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); if (!rt5682s_clk_check(rt5682s)) return; - snd_soc_dapm_mutex_lock(dapm); + mutex_lock(&rt5682s->wclk_mutex); - snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS"); - snd_soc_dapm_disable_pin_unlocked(dapm, "Vref2"); if (!rt5682s->jack_type) snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_1, RT5682S_PWR_VREF2 | RT5682S_PWR_FV2 | RT5682S_PWR_MB, 0); - snd_soc_dapm_disable_pin_unlocked(dapm, "I2S1"); - snd_soc_dapm_disable_pin_unlocked(dapm, "PLLB"); - snd_soc_dapm_sync_unlocked(dapm); + /* Power down I2S1 */ + rt5682s_set_i2s(rt5682s, RT5682S_AIF1, 0); + snd_soc_component_update_bits(component, RT5682S_PWR_DIG_1, + RT5682S_DIG_GATE_CTRL, 0); - snd_soc_dapm_mutex_unlock(dapm); + /* Power down PLLB */ + rt5682s_set_pllb_power(rt5682s, 0); + + rt5682s->wclk_enabled = 0; + + mutex_unlock(&rt5682s->wclk_mutex); } static unsigned long rt5682s_wclk_recalc_rate(struct clk_hw *hw, @@ -2805,19 +2864,10 @@ static inline int rt5682s_dai_probe_clks(struct snd_soc_component *component) static int rt5682s_probe(struct snd_soc_component *component) { struct rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component); - struct snd_soc_dapm_context *dapm = &component->dapm; - int ret; rt5682s->component = component; - ret = rt5682s_dai_probe_clks(component); - if (ret) - return ret; - - snd_soc_dapm_disable_pin(dapm, "MICBIAS"); - snd_soc_dapm_disable_pin(dapm, "Vref2"); - snd_soc_dapm_sync(dapm); - return 0; + return rt5682s_dai_probe_clks(component); } static void rt5682s_remove(struct snd_soc_component *component) @@ -3113,6 +3163,7 @@ static int rt5682s_i2c_probe(struct i2c_client *i2c) mutex_init(&rt5682s->calibrate_mutex); mutex_init(&rt5682s->sar_mutex); + mutex_init(&rt5682s->wclk_mutex); rt5682s_calibrate(rt5682s); regmap_update_bits(rt5682s->regmap, RT5682S_MICBIAS_2, |