static int aic31xx_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { dev_dbg(codec->dev, "## %s: %d -> %d\n", __func__, snd_soc_codec_get_bias_level(codec), level); switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) aic31xx_clk_on(codec); break; case SND_SOC_BIAS_STANDBY: switch (snd_soc_codec_get_bias_level(codec)) { case SND_SOC_BIAS_OFF: aic31xx_power_on(codec); break; case SND_SOC_BIAS_PREPARE: aic31xx_clk_off(codec); break; default: BUG(); } break; case SND_SOC_BIAS_OFF: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) aic31xx_power_off(codec); break; } return 0; }
static int wm0010_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) wm0010_boot(codec); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) { mutex_lock(&wm0010->lock); wm0010_halt(codec); mutex_unlock(&wm0010->lock); } break; case SND_SOC_BIAS_OFF: break; } return 0; }
static int wm8961_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { u16 reg; /* This is all slightly unusual since we have no bypass paths * and the output amplifier structure means we can just slam * the biases straight up rather than having to ramp them * slowly. */ switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { /* Enable bias generation */ reg = snd_soc_read(codec, WM8961_ANTI_POP); reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; snd_soc_write(codec, WM8961_ANTI_POP, reg); /* VMID=2*50k, VREF */ reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); reg &= ~WM8961_VMIDSEL_MASK; reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF; snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); } break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_PREPARE) { /* VREF off */ reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); reg &= ~WM8961_VREF; snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); /* Bias generation off */ reg = snd_soc_read(codec, WM8961_ANTI_POP); reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN); snd_soc_write(codec, WM8961_ANTI_POP, reg); /* VMID off */ reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); reg &= ~WM8961_VMIDSEL_MASK; snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); } break; case SND_SOC_BIAS_OFF: break; } return 0; }
static int wm8711_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; switch (level) { case SND_SOC_BIAS_ON: snd_soc_write(codec, WM8711_PWR, reg); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) regcache_sync(wm8711->regmap); snd_soc_write(codec, WM8711_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: snd_soc_write(codec, WM8711_ACTIVE, 0x0); snd_soc_write(codec, WM8711_PWR, 0xffff); break; } return 0; }
static int sta529_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: snd_soc_update_bits(codec, STA529_FFXCFG0, POWER_CNTLMSAK, POWER_UP); snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK, FFX_CLK_ENB); break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) regcache_sync(sta529->regmap); snd_soc_update_bits(codec, STA529_FFXCFG0, POWER_CNTLMSAK, POWER_STDBY); /* Making FFX output to zero */ snd_soc_update_bits(codec, STA529_FFXCFG0, FFX_MASK, FFX_OFF); snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK, FFX_CLK_DIS); break; case SND_SOC_BIAS_OFF: break; } return 0; }
static int wm8728_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); u16 reg; switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Power everything up... */ reg = snd_soc_read(codec, WM8728_DACCTL); snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); /* ..then sync in the register cache. */ regcache_sync(wm8728->regmap); } break; case SND_SOC_BIAS_OFF: reg = snd_soc_read(codec, WM8728_DACCTL); snd_soc_write(codec, WM8728_DACCTL, reg | 0x4); break; } return 0; }
static int ml26124_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: snd_soc_update_bits(codec, ML26124_PW_SPAMP_PW_MNG, ML26124_R26_MASK, ML26124_BLT_PREAMP_ON); msleep(100); snd_soc_update_bits(codec, ML26124_PW_SPAMP_PW_MNG, ML26124_R26_MASK, ML26124_MICBEN_ON | ML26124_BLT_ALL_ON); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* VMID ON */ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG, ML26124_VMID, ML26124_VMID); msleep(500); regcache_sync(priv->regmap); } break; case SND_SOC_BIAS_OFF: /* VMID OFF */ snd_soc_update_bits(codec, ML26124_PW_REF_PW_MNG, ML26124_VMID, 0); break; } return 0; }
static int adau1761_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct adau *adau = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: regcache_cache_only(adau->regmap, false); regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, ADAU17X1_CLOCK_CONTROL_SYSCLK_EN); if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) regcache_sync(adau->regmap); break; case SND_SOC_BIAS_OFF: regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0); regcache_cache_only(adau->regmap, true); break; } return 0; }
static int wm8776_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { regcache_sync(wm8776->regmap); /* Disable the global powerdown; DAPM does the rest */ snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); } break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1); break; } return 0; }
/** * sta350_set_bias_level - DAPM callback * @codec: the codec device * @level: DAPM power level * * This is called by ALSA to put the codec into low power mode * or to wake it up. If the codec is powered off completely * all registers must be restored after power on. */ static int sta350_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct sta350_priv *sta350 = snd_soc_codec_get_drvdata(codec); int ret; dev_dbg(codec->dev, "level = %d\n", level); switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* Full power on */ regmap_update_bits(sta350->regmap, STA350_CONFF, STA350_CONFF_PWDN | STA350_CONFF_EAPD, STA350_CONFF_PWDN | STA350_CONFF_EAPD); break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { ret = regulator_bulk_enable( ARRAY_SIZE(sta350->supplies), sta350->supplies); if (ret < 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); return ret; } sta350_startup_sequence(sta350); sta350_cache_sync(codec); } /* Power down */ regmap_update_bits(sta350->regmap, STA350_CONFF, STA350_CONFF_PWDN | STA350_CONFF_EAPD, 0); break; case SND_SOC_BIAS_OFF: /* The chip runs through the power down sequence for us */ regmap_update_bits(sta350->regmap, STA350_CONFF, STA350_CONFF_PWDN | STA350_CONFF_EAPD, 0); /* power down: low */ if (sta350->gpiod_power_down) gpiod_set_value(sta350->gpiod_power_down, 0); if (sta350->gpiod_nreset) gpiod_set_value(sta350->gpiod_nreset, 0); regulator_bulk_disable(ARRAY_SIZE(sta350->supplies), sta350->supplies); break; } return 0; }
static int wm8523_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* Full power on */ snd_soc_update_bits(codec, WM8523_PSCTRL1, WM8523_SYS_ENA_MASK, 3); break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); return ret; } /* Sync back default/cached values */ regcache_sync(wm8523->regmap); /* Initial power up */ snd_soc_update_bits(codec, WM8523_PSCTRL1, WM8523_SYS_ENA_MASK, 1); msleep(100); } /* Power up to mute */ snd_soc_update_bits(codec, WM8523_PSCTRL1, WM8523_SYS_ENA_MASK, 2); break; case SND_SOC_BIAS_OFF: /* The chip runs through the power down sequence for us. */ snd_soc_update_bits(codec, WM8523_PSCTRL1, WM8523_SYS_ENA_MASK, 0); msleep(100); regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); break; } return 0; }
static int es8328_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* VREF, VMID=2x50k, digital enabled */ snd_soc_write(codec, ES8328_CHIPPOWER, 0); snd_soc_update_bits(codec, ES8328_CONTROL1, ES8328_CONTROL1_VMIDSEL_MASK | ES8328_CONTROL1_ENREF, ES8328_CONTROL1_VMIDSEL_50k | ES8328_CONTROL1_ENREF); break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { snd_soc_update_bits(codec, ES8328_CONTROL1, ES8328_CONTROL1_VMIDSEL_MASK | ES8328_CONTROL1_ENREF, ES8328_CONTROL1_VMIDSEL_5k | ES8328_CONTROL1_ENREF); /* Charge caps */ msleep(100); } snd_soc_write(codec, ES8328_CONTROL2, ES8328_CONTROL2_OVERCURRENT_ON | ES8328_CONTROL2_THERMAL_SHUTDOWN_ON); /* VREF, VMID=2*500k, digital stopped */ snd_soc_update_bits(codec, ES8328_CONTROL1, ES8328_CONTROL1_VMIDSEL_MASK | ES8328_CONTROL1_ENREF, ES8328_CONTROL1_VMIDSEL_500k | ES8328_CONTROL1_ENREF); break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, ES8328_CONTROL1, ES8328_CONTROL1_VMIDSEL_MASK | ES8328_CONTROL1_ENREF, 0); break; } return 0; }
static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); switch (snd_soc_codec_get_bias_level(codec)) { case SND_SOC_BIAS_OFF: case SND_SOC_BIAS_STANDBY: break; default: return -EBUSY; } pcm512x->overclock_dac = ucontrol->value.integer.value[0]; return 0; }
static int wm8940_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec); u16 val; u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0; int ret = 0; switch (level) { case SND_SOC_BIAS_ON: /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* Enable thermal shutdown */ val = snd_soc_read(codec, WM8940_OUTPUTCTL); ret = snd_soc_write(codec, WM8940_OUTPUTCTL, val | 0x2); if (ret) break; /* set vmid to 75k */ ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); break; case SND_SOC_BIAS_PREPARE: /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { ret = regcache_sync(wm8940->regmap); if (ret < 0) { dev_err(codec->dev, "Failed to sync cache: %d\n", ret); return ret; } } /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* set vmid to 300k for standby */ ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x2); break; case SND_SOC_BIAS_OFF: ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg); break; } return ret; }
static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); struct regmap *regmap = jz4740_codec->regmap; unsigned int mask; unsigned int value; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: mask = JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE | JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; value = 0; regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value); break; case SND_SOC_BIAS_STANDBY: /* The only way to clear the suspend flag is to reset the codec */ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) jz4740_codec_wakeup(regmap); mask = JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE | JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; value = JZ4740_CODEC_1_VREF_DISABLE | JZ4740_CODEC_1_VREF_AMP_DISABLE | JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value); break; case SND_SOC_BIAS_OFF: mask = JZ4740_CODEC_1_SUSPEND; value = JZ4740_CODEC_1_SUSPEND; regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value); regcache_mark_dirty(regmap); break; default: break; } return 0; }
static int tas6424_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { dev_dbg(codec->dev, "%s() level=%d\n", __func__, level); switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) tas6424_power_on(codec); break; case SND_SOC_BIAS_OFF: tas6424_power_off(codec); break; } return 0; }
static int adau1977_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct adau1977 *adau1977 = snd_soc_codec_get_drvdata(codec); int ret = 0; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) ret = adau1977_power_enable(adau1977); break; case SND_SOC_BIAS_OFF: ret = adau1977_power_disable(adau1977); break; } return ret; }
static int cs42l73_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 0); snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 0); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { regcache_cache_only(cs42l73->regmap, false); regcache_sync(cs42l73->regmap); } snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 1); break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 1); if (cs42l73->shutdwn_delay > 0) { mdelay(cs42l73->shutdwn_delay); cs42l73->shutdwn_delay = 0; } else { mdelay(15); /* Min amount of time requred to power * down. */ } snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 1); break; } return 0; }
static int wm8988_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* VREF, VMID=2x50k, digital enabled */ snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { regcache_sync(wm8988->regmap); /* VREF, VMID=2x5k */ snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); /* Charge caps */ msleep(100); } /* VREF, VMID=2*500k, digital stopped */ snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141); break; case SND_SOC_BIAS_OFF: snd_soc_write(codec, WM8988_PWR1, 0x0000); break; } return 0; }
static int rt5616_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { switch (level) { case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { snd_soc_update_bits(codec, RT5616_PWR_ANLG1, RT5616_PWR_VREF1 | RT5616_PWR_MB | RT5616_PWR_BG | RT5616_PWR_VREF2, RT5616_PWR_VREF1 | RT5616_PWR_MB | RT5616_PWR_BG | RT5616_PWR_VREF2); mdelay(10); snd_soc_update_bits(codec, RT5616_PWR_ANLG1, RT5616_PWR_FV1 | RT5616_PWR_FV2, RT5616_PWR_FV1 | RT5616_PWR_FV2); snd_soc_update_bits(codec, RT5616_D_MISC, RT5616_D_GATE_EN, RT5616_D_GATE_EN); } break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, RT5616_D_MISC, RT5616_D_GATE_EN, 0); snd_soc_write(codec, RT5616_PWR_DIG1, 0x0000); snd_soc_write(codec, RT5616_PWR_DIG2, 0x0000); snd_soc_write(codec, RT5616_PWR_VOL, 0x0000); snd_soc_write(codec, RT5616_PWR_MIXER, 0x0000); snd_soc_write(codec, RT5616_PWR_ANLG1, 0x0000); snd_soc_write(codec, RT5616_PWR_ANLG2, 0x0000); break; default: break; } return 0; }
static int rt5616_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec); int ret; switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* * SND_SOC_BIAS_PREPARE is called while preparing for a * transition to ON or away from ON. If current bias_level * is SND_SOC_BIAS_ON, then it is preparing for a transition * away from ON. Disable the clock in that case, otherwise * enable it. */ if (IS_ERR(rt5616->mclk)) break; if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { clk_disable_unprepare(rt5616->mclk); } else { ret = clk_prepare_enable(rt5616->mclk); if (ret) return ret; } break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { snd_soc_update_bits(codec, RT5616_PWR_ANLG1, RT5616_PWR_VREF1 | RT5616_PWR_MB | RT5616_PWR_BG | RT5616_PWR_VREF2, RT5616_PWR_VREF1 | RT5616_PWR_MB | RT5616_PWR_BG | RT5616_PWR_VREF2); mdelay(10); snd_soc_update_bits(codec, RT5616_PWR_ANLG1, RT5616_PWR_FV1 | RT5616_PWR_FV2, RT5616_PWR_FV1 | RT5616_PWR_FV2); snd_soc_update_bits(codec, RT5616_D_MISC, RT5616_D_GATE_EN, RT5616_D_GATE_EN); } break; case SND_SOC_BIAS_OFF: snd_soc_update_bits(codec, RT5616_D_MISC, RT5616_D_GATE_EN, 0); snd_soc_write(codec, RT5616_PWR_DIG1, 0x0000); snd_soc_write(codec, RT5616_PWR_DIG2, 0x0000); snd_soc_write(codec, RT5616_PWR_VOL, 0x0000); snd_soc_write(codec, RT5616_PWR_MIXER, 0x0000); snd_soc_write(codec, RT5616_PWR_ANLG1, 0x0000); snd_soc_write(codec, RT5616_PWR_ANLG2, 0x0000); break; default: break; } return 0; }
static int wm9081_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: /* VMID=2*40k */ snd_soc_update_bits(codec, WM9081_VMID_CONTROL, WM9081_VMID_SEL_MASK, 0x2); /* Normal bias current */ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, WM9081_STBY_BIAS_ENA, 0); break; case SND_SOC_BIAS_STANDBY: /* Initial cold start */ if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { regcache_cache_only(wm9081->regmap, false); regcache_sync(wm9081->regmap); /* Disable LINEOUT discharge */ snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL, WM9081_LINEOUT_DISCH, 0); /* Select startup bias source */ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, WM9081_BIAS_SRC | WM9081_BIAS_ENA, WM9081_BIAS_SRC | WM9081_BIAS_ENA); /* VMID 2*4k; Soft VMID ramp enable */ snd_soc_update_bits(codec, WM9081_VMID_CONTROL, WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK, WM9081_VMID_RAMP | 0x6); mdelay(100); /* Normal bias enable & soft start off */ snd_soc_update_bits(codec, WM9081_VMID_CONTROL, WM9081_VMID_RAMP, 0); /* Standard bias source */ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, WM9081_BIAS_SRC, 0); } /* VMID 2*240k */ snd_soc_update_bits(codec, WM9081_VMID_CONTROL, WM9081_VMID_SEL_MASK, 0x04); /* Standby bias current on */ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, WM9081_STBY_BIAS_ENA, WM9081_STBY_BIAS_ENA); break; case SND_SOC_BIAS_OFF: /* Startup bias source and disable bias */ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1, WM9081_BIAS_SRC | WM9081_BIAS_ENA, WM9081_BIAS_SRC); /* Disable VMID with soft ramping */ snd_soc_update_bits(codec, WM9081_VMID_CONTROL, WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK, WM9081_VMID_RAMP); /* Actively discharge LINEOUT */ snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL, WM9081_LINEOUT_DISCH, WM9081_LINEOUT_DISCH); regcache_cache_only(wm9081->regmap, true); break; } return 0; }