Skip to content

Commit

Permalink
ASoC: sta32x: add workaround for ESD reset issue
Browse files Browse the repository at this point in the history
sta32x resets and loses all configuration during ESD test.
Work around by polling the CONFA register once a second
and restore all coeffcients and registers when CONFA
changes unexpectedly.

Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Johannes Stezenbach authored and Mark Brown committed Nov 14, 2011
1 parent e012ba2 commit 3fb5eac
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/sound/sta32x.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct sta32x_platform_data {
int ch2_output_mapping;
int ch3_output_mapping;
int thermal_conf;
int needs_esd_watchdog;
};

#endif /* __LINUX_SND__STA32X_H */
50 changes: 49 additions & 1 deletion sound/soc/codecs/sta32x.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
Expand Down Expand Up @@ -80,6 +81,8 @@ struct sta32x_priv {
unsigned int format;

u32 coef_shadow[STA32X_COEF_COUNT];
struct delayed_work watchdog_work;
int shutdown;
};

static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
Expand Down Expand Up @@ -304,6 +307,46 @@ int sta32x_cache_sync(struct snd_soc_codec *codec)
return rc;
}

/* 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));
}

static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
{
if (sta32x->pdata->needs_esd_watchdog) {
sta32x->shutdown = 0;
schedule_delayed_work(&sta32x->watchdog_work,
round_jiffies_relative(HZ));
}
}

static void sta32x_watchdog_stop(struct sta32x_priv *sta32x)
{
if (sta32x->pdata->needs_esd_watchdog) {
sta32x->shutdown = 1;
cancel_delayed_work_sync(&sta32x->watchdog_work);
}
}

#define SINGLE_COEF(xname, index) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = sta32x_coefficient_info, \
Expand Down Expand Up @@ -714,6 +757,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
}

sta32x_cache_sync(codec);
sta32x_watchdog_start(sta32x);
}

/* Power up to mute */
Expand All @@ -730,7 +774,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
STA32X_CONFF_PWDN);
msleep(300);

sta32x_watchdog_stop(sta32x);
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
sta32x->supplies);
break;
Expand Down Expand Up @@ -863,6 +907,9 @@ static int sta32x_probe(struct snd_soc_codec *codec)
sta32x->coef_shadow[60] = 0x400000;
sta32x->coef_shadow[61] = 0x400000;

if (sta32x->pdata->needs_esd_watchdog)
INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog);

sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
Expand All @@ -879,6 +926,7 @@ static int sta32x_remove(struct snd_soc_codec *codec)
{
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);

sta32x_watchdog_stop(sta32x);
sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
Expand Down

0 comments on commit 3fb5eac

Please sign in to comment.