Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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;

}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
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;
}
Пример #13
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;
}
Пример #14
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;
}
Пример #15
0
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;
}
Пример #16
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;
}
Пример #17
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;
}
Пример #18
0
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;
}
Пример #19
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;
}
Пример #20
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;
}
Пример #21
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;
}
Пример #22
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;
}