Beispiel #1
0
/**
 * sta32x_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 sta32x_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
{
    int ret;
    struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);

    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(sta32x->regmap, STA32X_CONFF,
                           STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
                           STA32X_CONFF_PWDN | STA32X_CONFF_EAPD);
        break;

    case SND_SOC_BIAS_STANDBY:
        if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
            ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies),
                                        sta32x->supplies);
            if (ret != 0) {
                dev_err(codec->dev,
                        "Failed to enable supplies: %d\n", ret);
                return ret;
            }

            sta32x_startup_sequence(sta32x);
            sta32x_cache_sync(codec);
            sta32x_watchdog_start(sta32x);
        }

        /* Power down */
        regmap_update_bits(sta32x->regmap, STA32X_CONFF,
                           STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
                           0);

        break;

    case SND_SOC_BIAS_OFF:
        /* The chip runs through the power down sequence for us. */
        regmap_update_bits(sta32x->regmap, STA32X_CONFF,
                           STA32X_CONFF_PWDN | STA32X_CONFF_EAPD, 0);
        msleep(300);
        sta32x_watchdog_stop(sta32x);

        if (sta32x->gpiod_nreset)
            gpiod_set_value(sta32x->gpiod_nreset, 0);

        regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
                               sta32x->supplies);
        break;
    }
    codec->dapm.bias_level = level;
    return 0;
}
/* work around ESD issue where sta32x resets and loses all configuration */
static void sta32x_watchdog(struct work_struct *work)
{
	struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv,
						  watchdog_work.work);
	struct snd_soc_codec *codec = sta32x->codec;
	unsigned int confa, confa_cached;

	/* check if sta32x has reset itself */
	confa_cached = snd_soc_read(codec, STA32X_CONFA);
	codec->cache_bypass = 1;
	confa = snd_soc_read(codec, STA32X_CONFA);
	codec->cache_bypass = 0;
	if (confa != confa_cached) {
		codec->cache_sync = 1;
		sta32x_cache_sync(codec);
	}

	if (!sta32x->shutdown)
		schedule_delayed_work(&sta32x->watchdog_work,
				      round_jiffies_relative(HZ));
}
Beispiel #3
0
/* work around ESD issue where sta32x resets and loses all configuration */
static void sta32x_watchdog(struct work_struct *work)
{
	struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv,
						  watchdog_work.work);
	struct snd_soc_codec *codec = sta32x->codec;
	unsigned int confa, confa_cached;

	/* check if sta32x has reset itself */
	confa_cached = snd_soc_read(codec, STA32X_CONFA);
	regcache_cache_bypass(sta32x->regmap, true);
	confa = snd_soc_read(codec, STA32X_CONFA);
	regcache_cache_bypass(sta32x->regmap, false);
	if (confa != confa_cached) {
		regcache_mark_dirty(sta32x->regmap);
		sta32x_cache_sync(codec);
	}

	if (!sta32x->shutdown)
		queue_delayed_work(system_power_efficient_wq,
				   &sta32x->watchdog_work,
				   round_jiffies_relative(HZ));
}