[alsa-devel] [PATCH 0/9] ASoC: codecs: Fix register cache incoherencies
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. Most of the drivers where converted to use this new framework. But there are also some drivers now which use a mixture of their own register cache and the generic register cache. Thus these end up with two from each other incoherent register caches, which can lead to undefined behaviour. This patch series tries to fix these drivers by converting them to always use the generic register cache framework instead of their own.
There are also quite a few drivers left, which do not use their own register cache, but still have a field for it in their private device structure. The first patch of this series addresses those drivers and removes the unused register cache arrays from their private device structs.
Please note, these patches, with the exception of wm8753, were only compile tested.
- Lars
Lars-Peter Clausen (9): ASoC: codecs: Remove unused reg_cache fields from device structs ASoC: codecs: max98088: Fix register cache incoherency ASoC: codecs: wm8523: Fix register cache incoherency ASoC: codecs: wm8741: Fix register cache incoherency ASoC: codecs: wm8904: Fix register cache incoherency ASoC: codecs: wm8955: Fix register cache incoherency ASoC: codecs: wm8962: Fix register cache incoherency ASoC: codecs: wm9090: Fix register cache incoherency ASoC: codecs: wm8753: Fix register cache incoherency
sound/soc/codecs/88pm860x-codec.c | 1 - sound/soc/codecs/ad193x.c | 1 - sound/soc/codecs/ak4671.c | 1 - sound/soc/codecs/cs4270.c | 1 - sound/soc/codecs/cs42l51.c | 1 - sound/soc/codecs/cx20442.c | 1 - sound/soc/codecs/max98088.c | 13 +- sound/soc/codecs/tlv320aic26.c | 4 +- sound/soc/codecs/uda1380.c | 1 - sound/soc/codecs/wm8523.c | 9 +- sound/soc/codecs/wm8580.c | 1 - sound/soc/codecs/wm8711.c | 1 - sound/soc/codecs/wm8731.c | 1 - sound/soc/codecs/wm8741.c | 10 +- sound/soc/codecs/wm8750.c | 1 - sound/soc/codecs/wm8753.c | 267 ++++++++++++++----------------------- sound/soc/codecs/wm8900.c | 1 - sound/soc/codecs/wm8903.c | 2 - sound/soc/codecs/wm8904.c | 37 +++--- sound/soc/codecs/wm8940.c | 1 - sound/soc/codecs/wm8955.c | 30 ++-- sound/soc/codecs/wm8960.c | 1 - sound/soc/codecs/wm8961.c | 1 - sound/soc/codecs/wm8962.c | 45 +++---- sound/soc/codecs/wm8974.c | 1 - sound/soc/codecs/wm8978.c | 1 - sound/soc/codecs/wm8988.c | 1 - sound/soc/codecs/wm8993.c | 1 - sound/soc/codecs/wm9081.c | 1 - sound/soc/codecs/wm9090.c | 18 ++-- 30 files changed, 179 insertions(+), 276 deletions(-)
The multi-component patch (commit f0fba2ad1) introduced a generic register cache handling framework in the ASoC core and most drivers where converted to use it. But there are quite a few drivers left which now have an unused reg_cache field in their private device struct. This patch removes these unused fields.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Zhuang haojian.zhuang@marvell.com Cc: Barry Song 21cnbao@gmail.com Cc: Joonyoung Shim jy0922.shim@samsung.com Cc: Timur Tabi timur@freescale.com Cc: Arnaud Patard arnaud.patard@rtp-net.org Cc: Grant Likely grant.likely@secretlab.ca Cc: Richard Purdie richard@openedhand.com Cc: Mike Arthur Mike.Arthur@wolfsonmicro.com Cc: Jonathan Cameron jic23@cam.ac.uk Cc: Guennadi Liakhovetski g.liakhovetski@gmx.de
--- Compile tested only --- sound/soc/codecs/88pm860x-codec.c | 1 - sound/soc/codecs/ad193x.c | 1 - sound/soc/codecs/ak4671.c | 1 - sound/soc/codecs/cs4270.c | 1 - sound/soc/codecs/cs42l51.c | 1 - sound/soc/codecs/cx20442.c | 1 - sound/soc/codecs/tlv320aic26.c | 4 +--- sound/soc/codecs/uda1380.c | 1 - sound/soc/codecs/wm8580.c | 1 - sound/soc/codecs/wm8711.c | 1 - sound/soc/codecs/wm8731.c | 1 - sound/soc/codecs/wm8750.c | 1 - sound/soc/codecs/wm8900.c | 1 - sound/soc/codecs/wm8903.c | 2 -- sound/soc/codecs/wm8940.c | 1 - sound/soc/codecs/wm8960.c | 1 - sound/soc/codecs/wm8961.c | 1 - sound/soc/codecs/wm8974.c | 1 - sound/soc/codecs/wm8978.c | 1 - sound/soc/codecs/wm8988.c | 1 - sound/soc/codecs/wm8993.c | 1 - sound/soc/codecs/wm9081.c | 1 - 22 files changed, 1 insertions(+), 25 deletions(-)
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 3e798a1..5da8207 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -146,7 +146,6 @@ struct pm860x_priv {
int irq[4]; unsigned char name[4][MAX_NAME_LEN]; - unsigned char reg_cache[REG_CACHE_SIZE]; };
/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */ diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index a007bd7..da46479 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -23,7 +23,6 @@
/* codec private data */ struct ad193x_priv { - u8 reg_cache[AD193X_NUM_REGS]; enum snd_soc_control_type bus_type; void *control_data; int sysclk; diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 4faf105..2ec75ab 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -27,7 +27,6 @@ struct ak4671_priv { enum snd_soc_control_type control_type; void *control_data; - u8 reg_cache[AK4671_CACHEREGNUM]; };
/* ak4671 register cache & default register settings */ diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 6d4bdc6..3a582ca 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -114,7 +114,6 @@ static const char *supply_names[] = { struct cs4270_private { enum snd_soc_control_type control_type; void *control_data; - u8 reg_cache[CS4270_NUMREGS]; unsigned int mclk; /* Input frequency of the MCLK pin */ unsigned int mode; /* The mode (I2S or left-justified) */ unsigned int slave_mode; diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index d4e60dc..8fb7070 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c @@ -46,7 +46,6 @@ struct cs42l51_private { unsigned int mclk; unsigned int audio_mode; /* The mode (I2S or left-justified) */ enum master_slave_mode func; - u8 reg_cache[CS42L51_NUMREGS]; };
#define CS42L51_FORMATS ( \ diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index a9521ac..03d1e86 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -26,7 +26,6 @@ struct cx20442_priv { enum snd_soc_control_type control_type; void *control_data; - u8 reg_cache[1]; };
#define CX20442_PM 0x0 diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 68f0ae47..e2a7608 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -30,7 +30,6 @@ MODULE_LICENSE("GPL"); struct aic26 { struct spi_device *spi; struct snd_soc_codec codec; - u16 reg_cache[AIC26_NUM_REGS]; /* shadow registers */ int master; int datfm; int mclk; @@ -354,7 +353,6 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); */ static int aic26_probe(struct snd_soc_codec *codec) { - struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); int ret, err, i, reg;
dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n"); @@ -372,7 +370,7 @@ static int aic26_probe(struct snd_soc_codec *codec) aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
/* Fill register cache */ - for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) + for (i = 0; i < codec->driver->reg_cache_size; i++) aic26_reg_read(codec, i);
/* Register the sysfs files for debugging */ diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 800980e..c5ca8cf 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -35,7 +35,6 @@ /* codec private data */ struct uda1380_priv { struct snd_soc_codec *codec; - u16 reg_cache[UDA1380_CACHEREGNUM]; unsigned int dac_clk; struct work_struct work; void *control_data; diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 0ebdecf..8f6b5ee 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -190,7 +190,6 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { struct wm8580_priv { enum snd_soc_control_type control_type; struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; - u16 reg_cache[WM8580_MAX_REGISTER + 1]; struct pll_state a; struct pll_state b; int sysclk[2]; diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index fec37eb..97c3038 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -33,7 +33,6 @@ /* codec private data */ struct wm8711_priv { enum snd_soc_control_type bus_type; - u16 reg_cache[WM8711_CACHEREGNUM]; unsigned int sysclk; };
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 71122dc..0a67c31 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -43,7 +43,6 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { struct wm8731_priv { enum snd_soc_control_type control_type; struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; - u16 reg_cache[WM8731_CACHEREGNUM]; unsigned int sysclk; int sysclk_type; int playback_fs; diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 51280e9..38f38fd 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -52,7 +52,6 @@ static const u16 wm8750_reg[] = { struct wm8750_priv { unsigned int sysclk; enum snd_soc_control_type control_type; - u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; };
#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index cfbaac1..cd09599 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -139,7 +139,6 @@
struct wm8900_priv { enum snd_soc_control_type control_type; - u16 reg_cache[WM8900_MAXREG];
u32 fll_in; /* FLL input frequency */ u32 fll_out; /* FLL output frequency */ diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 02de5ae..6ad6932 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -214,8 +214,6 @@ static u16 wm8903_reg_defaults[] = {
struct wm8903_priv {
- u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; - int sysclk; int irq;
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 381934f..fc7761f 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -42,7 +42,6 @@
struct wm8940_priv { unsigned int sysclk; - u16 reg_cache[WM8940_CACHEREGNUM]; enum snd_soc_control_type control_type; void *control_data; }; diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 054f573..2bb8561 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -71,7 +71,6 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { };
struct wm8960_priv { - u16 reg_cache[WM8960_CACHEREGNUM]; enum snd_soc_control_type control_type; void *control_data; int (*set_bias_level)(struct snd_soc_codec *, diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 6b22ef2..55252e7 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -289,7 +289,6 @@ static u16 wm8961_reg_defaults[] = { struct wm8961_priv { enum snd_soc_control_type control_type; int sysclk; - u16 reg_cache[WM8961_MAX_REGISTER]; };
static int wm8961_volatile_register(unsigned int reg) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 5d28642..ca646a8 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -51,7 +51,6 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
struct wm8974_priv { enum snd_soc_control_type control_type; - u16 reg_cache[WM8974_CACHEREGNUM]; };
#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a195af9..4bbc344 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -59,7 +59,6 @@ struct wm8978_priv { unsigned int f_opclk; int mclk_idx; enum wm8978_sysclk_src sysclk; - u16 reg_cache[WM8978_CACHEREGNUM]; };
static const char *wm8978_companding[] = {"Off", "NC", "u-law", "A-law"}; diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 65807b1..d7170f1 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -53,7 +53,6 @@ struct wm8988_priv { unsigned int sysclk; enum snd_soc_control_type control_type; struct snd_pcm_hw_constraint_list *sysclk_constraints; - u16 reg_cache[WM8988_NUM_REG]; };
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 15f34a2..18c0d9c 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -225,7 +225,6 @@ static struct {
struct wm8993_priv { struct wm_hubs_data hubs_data; - u16 reg_cache[WM8993_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; struct wm8993_platform_data pdata; enum snd_soc_control_type control_type; diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index e5055b2..702db69 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -157,7 +157,6 @@ static struct { struct wm9081_priv { enum snd_soc_control_type control_type; void *control_data; - u16 reg_cache[WM9081_MAX_REGISTER + 1]; int sysclk_source; int mclk_rate; int sysclk_rate;
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Thus we end up with two from each other incoherent caches, which leads to undefined behaviour. This pachtes fixes the issue by changing the max98088 driver to use the generic cache framework.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Peter Hsiang Peter.Hsiang@maxim-ic.com
--- Compile tested only --- sound/soc/codecs/max98088.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 335a002..c7e57fb 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -39,7 +39,6 @@ struct max98088_cdata { };
struct max98088_priv { - u8 reg_cache[M98088_REG_CNT]; enum max98088_type devtype; void *control_data; struct max98088_pdata *pdata; @@ -1589,7 +1588,7 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai,
static void max98088_sync_cache(struct snd_soc_codec *codec) { - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); + unsigned int val; int i;
if (!codec->cache_sync) @@ -1600,14 +1599,17 @@ static void max98088_sync_cache(struct snd_soc_codec *codec) /* write back cached values if they're writeable and * different from the hardware default. */ - for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { if (!max98088_access[i].writable) continue;
- if (max98088->reg_cache[i] == max98088_reg[i]) + if (snd_soc_cache_read(codec, i, &val)) + continue; + + if (val == max98088_reg[i]) continue;
- snd_soc_write(codec, i, max98088->reg_cache[i]); + snd_soc_write(codec, i, val); }
codec->cache_sync = 0; @@ -1952,7 +1954,6 @@ static int max98088_probe(struct snd_soc_codec *codec) int ret = 0;
codec->cache_sync = 1; - memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); if (ret != 0) {
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Thus we end up with two from each other incoherent caches, which leads to undefined behaviour. This pachtes fixes the issue by changing the wm8523 driver to use the generic cache framework.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Ian Lartey ian@opensource.wolfsonmicro.com Cc: Dimitris Papastamos dp@opensource.wolfsonmicro.com
--- Compile tested only --- sound/soc/codecs/wm8523.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 08f3189..5eb2f50 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -40,7 +40,6 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { /* codec private data */ struct wm8523_priv { enum snd_soc_control_type control_type; - u16 reg_cache[WM8523_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; unsigned int sysclk; unsigned int rate_constraint_list[WM8523_NUM_RATES]; @@ -314,6 +313,7 @@ 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); + u16 *reg_cache = codec->reg_cache; int ret, i;
switch (level) { @@ -344,7 +344,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, /* Sync back default/cached values */ for (i = WM8523_AIF_CTRL1; i < WM8523_MAX_REGISTER; i++) - snd_soc_write(codec, i, wm8523->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]);
msleep(100); @@ -414,6 +414,7 @@ static int wm8523_resume(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret, i;
codec->hw_write = (hw_write_t)i2c_master_send; @@ -470,8 +471,8 @@ static int wm8523_probe(struct snd_soc_codec *codec) }
/* Change some default settings - latch VU and enable ZC */ - wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; - wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; + reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; + reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
On Fri, Dec 24, 2010 at 02:47:58PM +0100, Lars-Peter Clausen wrote:
/* Change some default settings - latch VU and enable ZC */
- wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
- wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
- reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
- reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
All the drivers where you're making this substitution should in principle be changed to use snd_soc_update_bits() since we now have support for multiple cache memory formats so may not have this flat in memory structure, though for the sake of getting the fixes in it's probably best to ignore that and fix it up later.
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Thus we end up with two from each other incoherent caches, which leads to undefined behaviour. This pachtes fixes the issue by changing the wm8741 driver to use the generic cache framework.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Ian Lartey ian@opensource.wolfsonmicro.com Cc: Dimitris Papastamos dp@opensource.wolfsonmicro.com
--- Compile tested only --- sound/soc/codecs/wm8741.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 35789b7..494f2d3 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -40,7 +40,6 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { /* codec private data */ struct wm8741_priv { enum snd_soc_control_type control_type; - u16 reg_cache[WM8741_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; @@ -422,6 +421,7 @@ static int wm8741_resume(struct snd_soc_codec *codec) static int wm8741_probe(struct snd_soc_codec *codec) { struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret = 0;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); @@ -437,10 +437,10 @@ static int wm8741_probe(struct snd_soc_codec *codec) }
/* Change some default settings - latch VU */ - wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; - wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; - wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; - wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; + reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; + reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; + reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; + reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
snd_soc_add_controls(codec, wm8741_snd_controls, ARRAY_SIZE(wm8741_snd_controls));
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Thus we end up with two from each other incoherent caches, which leads to undefined behaviour. This pachtes fixes the issue by changing the wm8904 driver to use the generic cache framework.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Ian Lartey ian@opensource.wolfsonmicro.com Cc: Dimitris Papastamos dp@opensource.wolfsonmicro.com
--- Compile tested only --- sound/soc/codecs/wm8904.c | 37 ++++++++++++++++++------------------- 1 files changed, 18 insertions(+), 19 deletions(-)
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 8ba142a..9de44a4 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -49,8 +49,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { /* codec private data */ struct wm8904_priv {
- u16 reg_cache[WM8904_MAX_REGISTER + 1]; - enum wm8904_type devtype; void *control_data;
@@ -2094,7 +2092,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
static void wm8904_sync_cache(struct snd_soc_codec *codec) { - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int i;
if (!codec->cache_sync) @@ -2105,14 +2103,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec) /* Sync back cached values if they're different from the * hardware default. */ - for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { if (!wm8904_access[i].writable) continue;
- if (wm8904->reg_cache[i] == wm8904_reg[i]) + if (reg_cache[i] == wm8904_reg[i]) continue;
- snd_soc_write(codec, i, wm8904->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]); }
codec->cache_sync = 0; @@ -2371,6 +2369,7 @@ static int wm8904_probe(struct snd_soc_codec *codec) { struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; + u16 *reg_cache = codec->reg_cache; int ret, i;
codec->cache_sync = 1; @@ -2437,19 +2436,19 @@ static int wm8904_probe(struct snd_soc_codec *codec) }
/* Change some default settings - latch VU and enable ZC */ - wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; - wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; - wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; - wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; - wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | + reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; + reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; + reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; + reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; + reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | WM8904_HPOUTLZC; - wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | + reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | WM8904_HPOUTRZC; - wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | + reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | WM8904_LINEOUTLZC; - wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | + reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | WM8904_LINEOUTRZC; - wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; + reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
/* Apply configuration from the platform data. */ if (wm8904->pdata) { @@ -2457,23 +2456,23 @@ static int wm8904_probe(struct snd_soc_codec *codec) if (!pdata->gpio_cfg[i]) continue;
- wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i] + reg_cache[WM8904_GPIO_CONTROL_1 + i] = pdata->gpio_cfg[i] & 0xffff; }
/* Zero is the default value for these anyway */ for (i = 0; i < WM8904_MIC_REGS; i++) - wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] + reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] = pdata->mic_cfg[i]; }
/* Set Class W by default - this will be managed by the Class * G widget at runtime where bypass paths are available. */ - wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; + reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
/* Use normal bias source */ - wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; + reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Thus we end up with two from each other incoherent caches, which leads to undefined behaviour. This pachtes fixes the issue by changing the wm8955 driver to use the generic cache framework.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Ian Lartey ian@opensource.wolfsonmicro.com Cc: Dimitris Papastamos dp@opensource.wolfsonmicro.com
--- Compile tested only --- sound/soc/codecs/wm8955.c | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index ca0265f..70e9516 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -41,8 +41,6 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { struct wm8955_priv { enum snd_soc_control_type control_type;
- u16 reg_cache[WM8955_MAX_REGISTER + 1]; - unsigned int mclk_rate;
int deemph; @@ -768,6 +766,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret, i;
switch (level) { @@ -800,14 +799,14 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, /* Sync back cached values if they're * different from the hardware default. */ - for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) { + for (i = 0; i < codec->driver->reg_cache_size; i++) { if (i == WM8955_RESET) continue;
- if (wm8955->reg_cache[i] == wm8955_reg[i]) + if (reg_cache[i] == wm8955_reg[i]) continue;
- snd_soc_write(codec, i, wm8955->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]); }
/* Enable VREF and VMID */ @@ -902,6 +901,7 @@ static int wm8955_probe(struct snd_soc_codec *codec) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); + u16 *reg_cache = codec->reg_cache; int ret, i;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); @@ -934,25 +934,25 @@ static int wm8955_probe(struct snd_soc_codec *codec) }
/* Change some default settings - latch VU and enable ZC */ - wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; - wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; - wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; - wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; - wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; - wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; - wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; + reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; + reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; + reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; + reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; + reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; + reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; + reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
/* Also enable adaptive bass boost by default */ - wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; + reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
/* Set platform data values */ if (pdata) { if (pdata->out2_speaker) - wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] + reg_cache[WM8955_ADDITIONAL_CONTROL_2] |= WM8955_ROUT2INV;
if (pdata->monoin_diff) - wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] + reg_cache[WM8955_MONO_OUT_MIX_1] |= WM8955_DMEN; }
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Thus we end up with two from each other incoherent caches, which leads to undefined behaviour. This pachtes fixes the issue by changing the wm8962 driver to use the generic cache framework.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Ian Lartey ian@opensource.wolfsonmicro.com Cc: Dimitris Papastamos dp@opensource.wolfsonmicro.com
--- Compile tested only --- sound/soc/codecs/wm8962.c | 45 ++++++++++++++++++++------------------------- 1 files changed, 20 insertions(+), 25 deletions(-)
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index b311b46..82826f5 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -52,8 +52,6 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { struct wm8962_priv { struct snd_soc_codec *codec;
- u16 reg_cache[WM8962_MAX_REGISTER + 1]; - int sysclk; int sysclk_rate;
@@ -1991,8 +1989,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = wm8962->reg_cache; + u16 *reg_cache = codec->reg_cache; int ret;
/* Apply the update (if any) */ @@ -2020,8 +2017,7 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = wm8962->reg_cache; + u16 *reg_cache = codec->reg_cache; int ret;
/* Apply the update (if any) */ @@ -2329,8 +2325,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = wm8962->reg_cache; + u16 *reg_cache = codec->reg_cache; int reg;
switch (w->shift) { @@ -2720,7 +2715,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
static void wm8962_sync_cache(struct snd_soc_codec *codec) { - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int i;
if (!codec->cache_sync) @@ -2733,13 +2728,13 @@ static void wm8962_sync_cache(struct snd_soc_codec *codec) /* Sync back cached values if they're different from the * hardware default. */ - for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { if (i == WM8962_SOFTWARE_RESET) continue; - if (wm8962->reg_cache[i] == wm8962_reg[i]) + if (reg_cache[i] == wm8962_reg[i]) continue;
- snd_soc_write(codec, i, wm8962->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]); }
codec->cache_sync = 0; @@ -3413,12 +3408,11 @@ EXPORT_SYMBOL_GPL(wm8962_mic_detect); #ifdef CONFIG_PM static int wm8962_resume(struct snd_soc_codec *codec) { - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache; int i;
/* Restore the registers */ - for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { switch (i) { case WM8962_SOFTWARE_RESET: continue; @@ -3713,6 +3707,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, dev); + u16 *reg_cache = codec->reg_cache; int i, trigger, irq_pol;
wm8962->codec = codec; @@ -3812,7 +3807,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
/* Put the speakers into mono mode? */ if (pdata->spk_mono) - wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2] + reg_cache[WM8962_CLASS_D_CONTROL_2] |= WM8962_SPK_MONO;
/* Micbias setup, detection enable and detection @@ -3827,16 +3822,16 @@ static int wm8962_probe(struct snd_soc_codec *codec) }
/* Latch volume update bits */ - wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; - wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; - wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; - wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; - wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; - wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; - wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; - wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; - wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; - wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; + reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; + reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; + reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; + reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; + reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; + reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; + reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; + reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; + reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; + reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
wm8962_add_widgets(codec);
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Thus we end up with two from each other incoherent caches, which leads to undefined behaviour. This pachtes fixes the issue by changing the wm9090 driver to use the generic cache framework.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Ian Lartey ian@opensource.wolfsonmicro.com Cc: Dimitris Papastamos dp@opensource.wolfsonmicro.com
--- Compile tested only --- sound/soc/codecs/wm9090.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 7ba5807..a788c42 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -140,7 +140,6 @@ static const u16 wm9090_reg_defaults[] = { /* This struct is used to save the context */ struct wm9090_priv { struct mutex mutex; - u16 reg_cache[WM9090_MAX_REGISTER + 1]; struct wm9090_platform_data pdata; void *control_data; }; @@ -552,6 +551,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, static int wm9090_probe(struct snd_soc_codec *codec) { struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret;
codec->control_data = wm9090->control_data; @@ -576,22 +576,22 @@ static int wm9090_probe(struct snd_soc_codec *codec) /* Configure some defaults; they will be written out when we * bring the bias up. */ - wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU + reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU | WM9090_IN1A_ZC; - wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU + reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU | WM9090_IN1B_ZC; - wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU + reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU | WM9090_IN2A_ZC; - wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU + reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU | WM9090_IN2B_ZC; - wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= + reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; - wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= + reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; - wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= + reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
- wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; + reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its private functions, while functions from the ASoC core use the generic cache. Furthermore the generic cache uses zero-based numbering while the wm8753 cache uses one-based numbering. Thus we end up with two from each other incoherent caches, which leads to undefined behaviour. This patch fixes the issue by changing the wm8753 driver to use the generic cache framework.
Signed-off-by: Lars-Peter Clausen lars@metafoo.de Cc: Ian Lartey ian@opensource.wolfsonmicro.com Cc: Dimitris Papastamos dp@opensource.wolfsonmicro.com --- sound/soc/codecs/wm8753.c | 267 +++++++++++++++++---------------------------- 1 files changed, 99 insertions(+), 168 deletions(-)
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 73507e7..12c647a 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -64,22 +64,22 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec, * are using 2 wire for device control, so we cache them instead. */ static const u16 wm8753_reg[] = { - 0x0008, 0x0000, 0x000a, 0x000a, - 0x0033, 0x0000, 0x0007, 0x00ff, - 0x00ff, 0x000f, 0x000f, 0x007b, - 0x0000, 0x0032, 0x0000, 0x00c3, - 0x00c3, 0x00c0, 0x0000, 0x0000, + 0x0000, 0x0008, 0x0000, 0x000a, + 0x000a, 0x0033, 0x0000, 0x0007, + 0x00ff, 0x00ff, 0x000f, 0x000f, + 0x007b, 0x0000, 0x0032, 0x0000, + 0x00c3, 0x00c3, 0x00c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0055, - 0x0005, 0x0050, 0x0055, 0x0050, - 0x0055, 0x0050, 0x0055, 0x0079, - 0x0079, 0x0079, 0x0079, 0x0079, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0097, 0x0097, 0x0000, 0x0004, - 0x0000, 0x0083, 0x0024, 0x01ba, - 0x0000, 0x0083, 0x0024, 0x01ba, - 0x0000, 0x0000, 0x0000 + 0x0055, 0x0005, 0x0050, 0x0055, + 0x0050, 0x0055, 0x0050, 0x0055, + 0x0079, 0x0079, 0x0079, 0x0079, + 0x0079, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0097, 0x0097, 0x0000, + 0x0004, 0x0000, 0x0083, 0x0024, + 0x01ba, 0x0000, 0x0083, 0x0024, + 0x01ba, 0x0000, 0x0000, 0x0000 };
/* codec private data */ @@ -87,57 +87,10 @@ struct wm8753_priv { enum snd_soc_control_type control_type; unsigned int sysclk; unsigned int pcmclk; - u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; int dai_func; };
-/* - * read wm8753 register cache - */ -static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) - return -1; - return cache[reg - 1]; -} - -/* - * write wm8753 register cache - */ -static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) - return; - cache[reg - 1] = value; -} - -/* - * write to the WM8753 register space - */ -static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8753 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8753_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0) +#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
/* * WM8753 Controls @@ -217,7 +170,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); + int mode = snd_soc_read(codec, WM8753_IOCTL);
ucontrol->value.integer.value[0] = (mode & 0xc) >> 2; return 0; @@ -227,7 +180,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); + int mode = snd_soc_read(codec, WM8753_IOCTL); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) @@ -738,17 +691,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (pll_id == WM8753_PLL1) { offset = 0; enable = 0x10; - reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef; + reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef; } else { offset = 4; enable = 0x8; - reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7; + reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7; }
if (!freq_in || !freq_out) { /* disable PLL */ - wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); - wm8753_write(codec, WM8753_CLOCK, reg); + snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); + snd_soc_write(codec, WM8753_CLOCK, reg); return 0; } else { u16 value = 0; @@ -759,20 +712,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, /* set up N and K PLL divisor ratios */ /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */ value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); - wm8753_write(codec, WM8753_PLL1CTL2 + offset, value); + snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value);
/* bits 8:0 = PLL_K[17:9] */ value = (pll_div.k & 0x03fe00) >> 9; - wm8753_write(codec, WM8753_PLL1CTL3 + offset, value); + snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value);
/* bits 8:0 = PLL_K[8:0] */ value = pll_div.k & 0x0001ff; - wm8753_write(codec, WM8753_PLL1CTL4 + offset, value); + snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value);
/* set PLL as input and enable */ - wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | + snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | (pll_div.div2 << 3)); - wm8753_write(codec, WM8753_CLOCK, reg | enable); + snd_soc_write(codec, WM8753_CLOCK, reg | enable); } return 0; } @@ -879,29 +832,30 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec; + u16 voice;
/* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - voice |= 0x0002; + voice = 0x0002; break; case SND_SOC_DAIFMT_RIGHT_J: + voice = 0x0000; break; case SND_SOC_DAIFMT_LEFT_J: - voice |= 0x0001; + voice = 0x0001; break; case SND_SOC_DAIFMT_DSP_A: - voice |= 0x0003; + voice = 0x0003; break; case SND_SOC_DAIFMT_DSP_B: - voice |= 0x0013; + voice = 0x0013; break; default: return -EINVAL; }
- wm8753_write(codec, WM8753_PCM, voice); + snd_soc_update_bits(codec, WM8753_PCM, 0x0013, voice); return 0; }
@@ -922,30 +876,32 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; - u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; + u16 voice = 0x0000; + u16 srate;
/* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; case SNDRV_PCM_FORMAT_S20_3LE: - voice |= 0x0004; + voice = 0x0004; break; case SNDRV_PCM_FORMAT_S24_LE: - voice |= 0x0008; + voice = 0x0008; break; case SNDRV_PCM_FORMAT_S32_LE: - voice |= 0x000c; + voice = 0x000c; break; }
/* sample rate */ if (params_rate(params) * 384 == wm8753->pcmclk) - srate |= 0x80; - wm8753_write(codec, WM8753_SRATE1, srate); + srate = 0x80; + else + srate = 0x00;
- wm8753_write(codec, WM8753_PCM, voice); + snd_soc_update_bits(codec, WM8753_SRATE1, 0x0080, srate); + snd_soc_update_bits(codec, WM8753_PCM, 0x000c, voice); return 0; }
@@ -956,17 +912,16 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 voice, ioctl; + u16 voice, ioctl = 0;
- voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f; - ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d; + voice = snd_soc_read(codec, WM8753_PCM) & 0x011f;
/* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: break; case SND_SOC_DAIFMT_CBM_CFM: - ioctl |= 0x2; + ioctl = 0x2; case SND_SOC_DAIFMT_CBM_CFS: voice |= 0x0040; break; @@ -1013,8 +968,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; }
- wm8753_write(codec, WM8753_PCM, voice); - wm8753_write(codec, WM8753_IOCTL, ioctl); + snd_soc_write(codec, WM8753_PCM, voice); + snd_soc_update_bits(codec, WM8753_IOCTL, 0x00a2, ioctl); return 0; }
@@ -1022,20 +977,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) { struct snd_soc_codec *codec = codec_dai->codec; - u16 reg;
switch (div_id) { case WM8753_PCMDIV: - reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f; - wm8753_write(codec, WM8753_CLOCK, reg | div); + snd_soc_update_bits(codec, WM8753_CLOCK, 0x01c0, div); break; case WM8753_BCLKDIV: - reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7; - wm8753_write(codec, WM8753_SRATE2, reg | div); + snd_soc_update_bits(codec, WM8753_SRATE2, 0x0038, div); break; case WM8753_VXCLKDIV: - reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f; - wm8753_write(codec, WM8753_SRATE2, reg | div); + snd_soc_update_bits(codec, WM8753_SRATE2, 0x01c0, div); break; default: return -EINVAL; @@ -1050,29 +1001,30 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0; + u16 hifi;
/* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - hifi |= 0x0002; + hifi = 0x0002; break; case SND_SOC_DAIFMT_RIGHT_J: + hifi = 0x0000; break; case SND_SOC_DAIFMT_LEFT_J: - hifi |= 0x0001; + hifi = 0x0001; break; case SND_SOC_DAIFMT_DSP_A: - hifi |= 0x0003; + hifi = 0x0003; break; case SND_SOC_DAIFMT_DSP_B: - hifi |= 0x0013; + hifi = 0x0013; break; default: return -EINVAL; }
- wm8753_write(codec, WM8753_HIFI, hifi); + snd_soc_update_bits(codec, WM8753_HIFI, 0x001f, hifi); return 0; }
@@ -1083,17 +1035,16 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 ioctl, hifi; + u16 hifi, ioctl = 0x0;
- hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f; - ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae; + hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f;
/* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: break; case SND_SOC_DAIFMT_CBM_CFM: - ioctl |= 0x1; + ioctl = 0x1; case SND_SOC_DAIFMT_CBM_CFS: hifi |= 0x0040; break; @@ -1140,8 +1091,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; }
- wm8753_write(codec, WM8753_HIFI, hifi); - wm8753_write(codec, WM8753_IOCTL, ioctl); + snd_soc_write(codec, WM8753_HIFI, hifi); + snd_soc_update_bits(codec, WM8753_IOCTL, 0x0151, ioctl); return 0; }
@@ -1162,8 +1113,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; - u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; + u16 hifi = 0x0000; int coeff;
/* is digital filter coefficient valid ? */ @@ -1172,25 +1122,25 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, printk(KERN_ERR "wm8753 invalid MCLK or rate\n"); return coeff; } - wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | - coeff_div[coeff].usb); + snd_soc_update_bits(codec, WM8753_SRATE1, 0x003f, + (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
/* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; case SNDRV_PCM_FORMAT_S20_3LE: - hifi |= 0x0004; + hifi = 0x0004; break; case SNDRV_PCM_FORMAT_S24_LE: - hifi |= 0x0008; + hifi = 0x0008; break; case SNDRV_PCM_FORMAT_S32_LE: - hifi |= 0x000c; + hifi = 0x000c; break; }
- wm8753_write(codec, WM8753_HIFI, hifi); + snd_soc_update_bits(codec, WM8753_HIFI, 0x000c, hifi); return 0; }
@@ -1198,11 +1148,9 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 clock;
/* set clk source as pcmclk */ - clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; - wm8753_write(codec, WM8753_CLOCK, clock); + snd_soc_update_bits(codec, WM8753_CLOCK, 0x0004, 0x0);
if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1221,11 +1169,9 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 clock;
/* set clk source as pcmclk */ - clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; - wm8753_write(codec, WM8753_CLOCK, clock); + snd_soc_update_bits(codec, WM8753_CLOCK, 0x0004, 0x0);
if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1236,11 +1182,9 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 clock;
/* set clk source as mclk */ - clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; - wm8753_write(codec, WM8753_CLOCK, clock | 0x4); + snd_soc_update_bits(codec, WM8753_CLOCK, 0x0004, 0x4);
if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1252,19 +1196,18 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, static int wm8753_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
/* the digital mute covers the HiFi and Voice DAC's on the WM8753. * make sure we check if they are not both active when we mute */ if (mute && wm8753->dai_func == 1) { if (!codec->active) - wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); + snd_soc_update_bits(codec, WM8753_DAC, 0x0008, 0x8); } else { if (mute) - wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); + snd_soc_update_bits(codec, WM8753_DAC, 0x0008, 0x8); else - wm8753_write(codec, WM8753_DAC, mute_reg); + snd_soc_update_bits(codec, WM8753_DAC, 0x0008, 0x0); }
return 0; @@ -1273,23 +1216,21 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) static int wm8753_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; - switch (level) { case SND_SOC_BIAS_ON: /* set vmid to 50k and unmute dac */ - wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); + snd_soc_update_bits(codec, WM8753_PWR1, 0x01c1, 0x00c0); break; case SND_SOC_BIAS_PREPARE: /* set vmid to 5k for quick power up */ - wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); + snd_soc_update_bits(codec, WM8753_PWR1, 0x01c1, 0x01c1); break; case SND_SOC_BIAS_STANDBY: /* mute dac and set vmid to 500k, enable VREF */ - wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); + snd_soc_update_bits(codec, WM8753_PWR1, 0x01c1, 0x0141); break; case SND_SOC_BIAS_OFF: - wm8753_write(codec, WM8753_PWR1, 0x0001); + snd_soc_write(codec, WM8753_PWR1, 0x0001); break; } codec->dapm.bias_level = level; @@ -1477,7 +1418,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec, else dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; } - wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); + snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func); }
static void wm8753_work(struct work_struct *work) @@ -1498,21 +1439,21 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8753_resume(struct snd_soc_codec *codec) { int i; - u8 data[2]; - u16 *cache = codec->reg_cache; + unsigned int val;
/* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { - if (i + 1 == WM8753_RESET) + for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) { + if (i == WM8753_RESET) + continue; + + if (snd_soc_cache_read(codec, i, &val)) continue;
/* No point in writing hardware default values back */ - if (cache[i] == wm8753_reg[i]) + if (val == wm8753_reg[i]) continue;
- data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); + snd_soc_write(codec, i, val); }
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1531,7 +1472,7 @@ static int wm8753_resume(struct snd_soc_codec *codec) static int wm8753_probe(struct snd_soc_codec *codec) { struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - int ret = 0, reg; + int ret;
INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
@@ -1556,26 +1497,16 @@ static int wm8753_probe(struct snd_soc_codec *codec) msecs_to_jiffies(caps_charge));
/* set the update bits */ - reg = wm8753_read_reg_cache(codec, WM8753_LDAC); - wm8753_write(codec, WM8753_LDAC, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_RDAC); - wm8753_write(codec, WM8753_RDAC, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_LADC); - wm8753_write(codec, WM8753_LADC, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_RADC); - wm8753_write(codec, WM8753_RADC, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V); - wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V); - wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V); - wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V); - wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_LINVOL); - wm8753_write(codec, WM8753_LINVOL, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); - wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); + snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
snd_soc_add_controls(codec, wm8753_snd_controls, ARRAY_SIZE(wm8753_snd_controls));
On Fri, Dec 24, 2010 at 02:48:04PM +0100, Lars-Peter Clausen wrote:
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. But the wm8753 driver still uses its own register cache for its
So, the actual relevant thing that the multi component patch did was to introduce a new way of initialising the cache and setting up the pointer that soc-cache uses to reference it, with some of the drivers being partially converted.
Since most of the drivers were already using the soc-cache code they mostly have some initialisation errors, others (like WM8753) weren't using soc-cache at all and probably shouldn't have been flipped over.
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S:
voice |= 0x0002;
break;voice = 0x0002;
This is more than a straight conversion of the driver - since changes like this aren't simple substitutions they're much harder to review, if you want to make changes such as this they should be split out into separate patches. There's quite a few other bits like this in the patch, some of which make it pretty confusing.
- u16 voice, ioctl;
- u16 voice, ioctl = 0;
Please don't mix variable declarations of initialised and uninitialised variables like this.
- wm8753_write(codec, WM8753_PCM, voice);
- wm8753_write(codec, WM8753_IOCTL, ioctl);
- snd_soc_write(codec, WM8753_PCM, voice);
- snd_soc_update_bits(codec, WM8753_IOCTL, 0x00a2, ioctl);
This bit is especially confusing, we've now got a mixture of both writing the full register and use of update_bits.
- for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
if (i == WM8753_RESET)
continue;
If you make the register reset function write the default value of the reset register you can use the standard cache sync implementation.
On Fri, Dec 24, 2010 at 02:47:55PM +0100, Lars-Peter Clausen wrote:
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. Most of the drivers where converted to use this new framework. But
No it didn't - soc-cache.c has been present since the middle of 2009.
On 12/24/2010 03:57 PM, Mark Brown wrote:
On Fri, Dec 24, 2010 at 02:47:55PM +0100, Lars-Peter Clausen wrote:
The multi-component patch(commit f0fba2ad1) introduced a generic register cache framework. Most of the drivers where converted to use this new framework. But
No it didn't - soc-cache.c has been present since the middle of 2009.
Hm. Ok, you are right, I've should have checked more closely. Only the allocation of the register cache was moved from the drivers to the core.
So the commit messages should have been along the lines of: The multi-component patch(commit f0fba2ad1) moved the alloction of the register cache from drivers to the ASoC core. While most of the drivers were converted to respect this change, some still maintain their own register cache besides the one used and allocated by the core. Thus the device ends up with two from each other incoherent caches, which can lead to undefined behaviour.
If there are no other issues with this series, I'll resend it with adjusted commit messages in a few days.
- Lars
On Fri, Dec 24, 2010 at 04:38:41PM +0100, Lars-Peter Clausen wrote:
If there are no other issues with this series, I'll resend it with adjusted commit messages in a few days.
Everything except the WM8753 patch looks OK - I *think* the WM8753 patch is fine, but on the other hand the driver is clearly quite badly broken at the moment so we can hardly make the situation worse.
participants (2)
-
Lars-Peter Clausen
-
Mark Brown