unsigned int hifi_fmt;
int dai_func;
+ struct delayed_work charge_work;
};
#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
return 0;
}
+static void wm8753_charge_work(struct work_struct *work)
+{
+ struct wm8753_priv *wm8753 =
+ container_of(work, struct wm8753_priv, charge_work.work);
+
+ /* Set to 500k */
+ regmap_update_bits(wm8753->regmap, WM8753_PWR1, 0x0180, 0x0100);
+}
+
static int wm8753_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;
switch (level) {
snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
break;
case SND_SOC_BIAS_PREPARE:
- /* set vmid to 5k for quick power up */
- snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
+ /* Wait until fully charged */
+ flush_delayed_work(&wm8753->charge_work);
break;
case SND_SOC_BIAS_STANDBY:
- /* mute dac and set vmid to 500k, enable VREF */
- snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ /* set vmid to 5k for quick power up */
+ snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
+ schedule_delayed_work(&wm8753->charge_work,
+ msecs_to_jiffies(caps_charge));
+ } else {
+ /* mute dac and set vmid to 500k, enable VREF */
+ snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
+ }
break;
case SND_SOC_BIAS_OFF:
+ cancel_delayed_work_sync(&wm8753->charge_work);
snd_soc_write(codec, WM8753_PWR1, 0x0001);
break;
}
},
};
-static void wm8753_work(struct work_struct *work)
-{
- struct snd_soc_dapm_context *dapm =
- container_of(work, struct snd_soc_dapm_context,
- delayed_work.work);
- struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
- wm8753_set_bias_level(codec, dapm->bias_level);
-}
-
static int wm8753_suspend(struct snd_soc_codec *codec)
{
wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
regcache_sync(wm8753->regmap);
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- /* charge wm8753 caps */
- if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
- wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
- codec->dapm.bias_level = SND_SOC_BIAS_ON;
- queue_delayed_work(system_power_efficient_wq,
- &codec->dapm.delayed_work,
- msecs_to_jiffies(caps_charge));
- }
-
return 0;
}
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
int ret;
- INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
+ INIT_DELAYED_WORK(&wm8753->charge_work, wm8753_charge_work);
ret = wm8753_reset(codec);
if (ret < 0) {
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8753->dai_func = 0;
- /* charge output caps */
- wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
- schedule_delayed_work(&codec->dapm.delayed_work,
- msecs_to_jiffies(caps_charge));
-
/* set the update bits */
snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
/* power down chip */
static int wm8753_remove(struct snd_soc_codec *codec)
{
- flush_delayed_work(&codec->dapm.delayed_work);
wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;