diff options
-rw-r--r-- | sound/soc/codecs/rt5645.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 28132375e427..672fafd8314a 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -245,7 +245,7 @@ struct rt5645_priv { | |||
245 | struct snd_soc_jack *hp_jack; | 245 | struct snd_soc_jack *hp_jack; |
246 | struct snd_soc_jack *mic_jack; | 246 | struct snd_soc_jack *mic_jack; |
247 | struct snd_soc_jack *btn_jack; | 247 | struct snd_soc_jack *btn_jack; |
248 | struct delayed_work jack_detect_work; | 248 | struct delayed_work jack_detect_work, rcclock_work; |
249 | struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)]; | 249 | struct regulator_bulk_data supplies[ARRAY_SIZE(rt5645_supply_names)]; |
250 | struct rt5645_eq_param_s *eq_param; | 250 | struct rt5645_eq_param_s *eq_param; |
251 | 251 | ||
@@ -565,12 +565,33 @@ static int rt5645_hweq_put(struct snd_kcontrol *kcontrol, | |||
565 | .put = rt5645_hweq_put \ | 565 | .put = rt5645_hweq_put \ |
566 | } | 566 | } |
567 | 567 | ||
568 | static int rt5645_spk_put_volsw(struct snd_kcontrol *kcontrol, | ||
569 | struct snd_ctl_elem_value *ucontrol) | ||
570 | { | ||
571 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | ||
572 | struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component); | ||
573 | int ret; | ||
574 | |||
575 | cancel_delayed_work_sync(&rt5645->rcclock_work); | ||
576 | |||
577 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, | ||
578 | RT5645_PWR_CLK25M_MASK, RT5645_PWR_CLK25M_PU); | ||
579 | |||
580 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | ||
581 | |||
582 | queue_delayed_work(system_power_efficient_wq, &rt5645->rcclock_work, | ||
583 | msecs_to_jiffies(200)); | ||
584 | |||
585 | return ret; | ||
586 | } | ||
587 | |||
568 | static const struct snd_kcontrol_new rt5645_snd_controls[] = { | 588 | static const struct snd_kcontrol_new rt5645_snd_controls[] = { |
569 | /* Speaker Output Volume */ | 589 | /* Speaker Output Volume */ |
570 | SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL, | 590 | SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL, |
571 | RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1), | 591 | RT5645_VOL_L_SFT, RT5645_VOL_R_SFT, 1, 1), |
572 | SOC_DOUBLE_TLV("Speaker Playback Volume", RT5645_SPK_VOL, | 592 | SOC_DOUBLE_EXT_TLV("Speaker Playback Volume", RT5645_SPK_VOL, |
573 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, out_vol_tlv), | 593 | RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 39, 1, snd_soc_get_volsw, |
594 | rt5645_spk_put_volsw, out_vol_tlv), | ||
574 | 595 | ||
575 | /* ClassD modulator Speaker Gain Ratio */ | 596 | /* ClassD modulator Speaker Gain Ratio */ |
576 | SOC_SINGLE_TLV("Speaker ClassD Playback Volume", RT5645_SPO_CLSD_RATIO, | 597 | SOC_SINGLE_TLV("Speaker ClassD Playback Volume", RT5645_SPO_CLSD_RATIO, |
@@ -3122,6 +3143,15 @@ static void rt5645_jack_detect_work(struct work_struct *work) | |||
3122 | SND_JACK_BTN_2 | SND_JACK_BTN_3); | 3143 | SND_JACK_BTN_2 | SND_JACK_BTN_3); |
3123 | } | 3144 | } |
3124 | 3145 | ||
3146 | static void rt5645_rcclock_work(struct work_struct *work) | ||
3147 | { | ||
3148 | struct rt5645_priv *rt5645 = | ||
3149 | container_of(work, struct rt5645_priv, rcclock_work.work); | ||
3150 | |||
3151 | regmap_update_bits(rt5645->regmap, RT5645_MICBIAS, | ||
3152 | RT5645_PWR_CLK25M_MASK, RT5645_PWR_CLK25M_PD); | ||
3153 | } | ||
3154 | |||
3125 | static irqreturn_t rt5645_irq(int irq, void *data) | 3155 | static irqreturn_t rt5645_irq(int irq, void *data) |
3126 | { | 3156 | { |
3127 | struct rt5645_priv *rt5645 = data; | 3157 | struct rt5645_priv *rt5645 = data; |
@@ -3587,6 +3617,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
3587 | } | 3617 | } |
3588 | 3618 | ||
3589 | INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work); | 3619 | INIT_DELAYED_WORK(&rt5645->jack_detect_work, rt5645_jack_detect_work); |
3620 | INIT_DELAYED_WORK(&rt5645->rcclock_work, rt5645_rcclock_work); | ||
3590 | 3621 | ||
3591 | if (rt5645->i2c->irq) { | 3622 | if (rt5645->i2c->irq) { |
3592 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, | 3623 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, |
@@ -3621,6 +3652,7 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) | |||
3621 | free_irq(i2c->irq, rt5645); | 3652 | free_irq(i2c->irq, rt5645); |
3622 | 3653 | ||
3623 | cancel_delayed_work_sync(&rt5645->jack_detect_work); | 3654 | cancel_delayed_work_sync(&rt5645->jack_detect_work); |
3655 | cancel_delayed_work_sync(&rt5645->rcclock_work); | ||
3624 | 3656 | ||
3625 | snd_soc_unregister_codec(&i2c->dev); | 3657 | snd_soc_unregister_codec(&i2c->dev); |
3626 | regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); | 3658 | regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); |