Commit ca9aef50 authored by Mark Brown's avatar Mark Brown

ASoC: Convert WM8994 to use soc-cache.c cache functions

In the process we convert the driver to read registers one at a time
when initialising the cache. This has the effect of working around
limitations in the sizes of I2C transactions which can be done by some
CPUs. Due to the sparseness of the register map the overhead from this
should be minimual unless I2C transactions are very expensive to start.
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: default avatarLiam Girdwood <lrg@slimlogic.co.uk>
parent 821edd2f
This diff is collapsed.
...@@ -57,8 +57,6 @@ static int wm8994_retune_mobile_base[] = { ...@@ -57,8 +57,6 @@ static int wm8994_retune_mobile_base[] = {
WM8994_AIF2_EQ_GAINS_1, WM8994_AIF2_EQ_GAINS_1,
}; };
#define WM8994_REG_CACHE_SIZE 0x621
struct wm8994_micdet { struct wm8994_micdet {
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
int det; int det;
...@@ -71,7 +69,6 @@ struct wm8994_priv { ...@@ -71,7 +69,6 @@ struct wm8994_priv {
enum snd_soc_control_type control_type; enum snd_soc_control_type control_type;
void *control_data; void *control_data;
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
u16 reg_cache[WM8994_REG_CACHE_SIZE + 1];
int sysclk[2]; int sysclk[2];
int sysclk_rate[2]; int sysclk_rate[2];
int mclk[2]; int mclk[2];
...@@ -134,7 +131,7 @@ static int wm8994_readable(unsigned int reg) ...@@ -134,7 +131,7 @@ static int wm8994_readable(unsigned int reg)
static int wm8994_volatile(unsigned int reg) static int wm8994_volatile(unsigned int reg)
{ {
if (reg >= WM8994_REG_CACHE_SIZE) if (reg >= WM8994_CACHE_SIZE)
return 1; return 1;
switch (reg) { switch (reg) {
...@@ -156,12 +153,16 @@ static int wm8994_volatile(unsigned int reg) ...@@ -156,12 +153,16 @@ static int wm8994_volatile(unsigned int reg)
static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg, static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value) unsigned int value)
{ {
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); int ret;
BUG_ON(reg > WM8994_MAX_REGISTER); BUG_ON(reg > WM8994_MAX_REGISTER);
if (!wm8994_volatile(reg)) if (!wm8994_volatile(reg)) {
wm8994->reg_cache[reg] = value; ret = snd_soc_cache_write(codec, reg, value);
if (ret != 0)
dev_err(codec->dev, "Cache write to %x failed: %d\n",
reg, ret);
}
return wm8994_reg_write(codec->control_data, reg, value); return wm8994_reg_write(codec->control_data, reg, value);
} }
...@@ -169,14 +170,22 @@ static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg, ...@@ -169,14 +170,22 @@ static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg,
static unsigned int wm8994_read(struct snd_soc_codec *codec, static unsigned int wm8994_read(struct snd_soc_codec *codec,
unsigned int reg) unsigned int reg)
{ {
u16 *reg_cache = codec->reg_cache; unsigned int val;
int ret;
BUG_ON(reg > WM8994_MAX_REGISTER); BUG_ON(reg > WM8994_MAX_REGISTER);
if (wm8994_volatile(reg)) if (!wm8994_volatile(reg) && wm8994_readable(reg) &&
return wm8994_reg_read(codec->control_data, reg); reg < codec->driver->reg_cache_size) {
else ret = snd_soc_cache_read(codec, reg, &val);
return reg_cache[reg]; if (ret >= 0)
return val;
else
dev_err(codec->dev, "Cache read from %x failed: %d\n",
reg, ret);
}
return wm8994_reg_read(codec->control_data, reg);
} }
static int configure_aif_clock(struct snd_soc_codec *codec, int aif) static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
...@@ -2370,26 +2379,12 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) ...@@ -2370,26 +2379,12 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8994_resume(struct snd_soc_codec *codec) static int wm8994_resume(struct snd_soc_codec *codec)
{ {
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 *reg_cache = codec->reg_cache;
int i, ret; int i, ret;
/* Restore the registers */ /* Restore the registers */
for (i = 1; i < ARRAY_SIZE(wm8994->reg_cache); i++) { ret = snd_soc_cache_sync(codec);
switch (i) { if (ret != 0)
case WM8994_LDO_1: dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
case WM8994_LDO_2:
case WM8994_SOFTWARE_RESET:
/* Handled by other MFD drivers */
continue;
default:
break;
}
if (!wm8994_access_masks[i].writable)
continue;
wm8994_reg_write(codec->control_data, i, reg_cache[i]);
}
wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
...@@ -2782,27 +2777,27 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) ...@@ -2782,27 +2777,27 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
return -ENOMEM; return -ENOMEM;
snd_soc_codec_set_drvdata(codec, wm8994); snd_soc_codec_set_drvdata(codec, wm8994);
codec->reg_cache = &wm8994->reg_cache;
wm8994->pdata = dev_get_platdata(codec->dev->parent); wm8994->pdata = dev_get_platdata(codec->dev->parent);
wm8994->codec = codec; wm8994->codec = codec;
/* Fill the cache with physical values we inherited; don't reset */ /* Read our current status back from the chip - we don't want to
ret = wm8994_bulk_read(codec->control_data, 0, * reset as this may interfere with the GPIO or LDO operation. */
ARRAY_SIZE(wm8994->reg_cache) - 1, for (i = 0; i < WM8994_CACHE_SIZE; i++) {
codec->reg_cache); if (!wm8994_readable(i) || wm8994_volatile(i))
if (ret < 0) { continue;
dev_err(codec->dev, "Failed to fill register cache: %d\n",
ret);
goto err;
}
/* Clear the cached values for unreadable/volatile registers to ret = wm8994_reg_read(codec->control_data, i);
* avoid potential confusion. if (ret <= 0)
*/ continue;
for (i = 0; i < ARRAY_SIZE(wm8994->reg_cache); i++)
if (wm8994_volatile(i) || !wm8994_readable(i)) ret = snd_soc_cache_write(codec, i, ret);
wm8994->reg_cache[i] = 0; if (ret != 0) {
dev_err(codec->dev,
"Failed to initialise cache for 0x%x: %d\n",
i, ret);
goto err;
}
}
/* Set revision-specific configuration */ /* Set revision-specific configuration */
wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION); wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION);
...@@ -3029,11 +3024,15 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { ...@@ -3029,11 +3024,15 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.remove = wm8994_codec_remove, .remove = wm8994_codec_remove,
.suspend = wm8994_suspend, .suspend = wm8994_suspend,
.resume = wm8994_resume, .resume = wm8994_resume,
.read = wm8994_read, .read = wm8994_read,
.write = wm8994_write, .write = wm8994_write,
.readable_register = wm8994_readable, .readable_register = wm8994_readable,
.volatile_register = wm8994_volatile, .volatile_register = wm8994_volatile,
.set_bias_level = wm8994_set_bias_level, .set_bias_level = wm8994_set_bias_level,
.reg_cache_size = WM8994_CACHE_SIZE,
.reg_cache_default = wm8994_reg_defaults,
.reg_word_size = 2,
}; };
static int __devinit wm8994_probe(struct platform_device *pdev) static int __devinit wm8994_probe(struct platform_device *pdev)
......
...@@ -43,5 +43,6 @@ struct wm8994_access_mask { ...@@ -43,5 +43,6 @@ struct wm8994_access_mask {
}; };
extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE]; extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE];
extern const __devinitdata u16 wm8994_reg_defaults[WM8994_CACHE_SIZE];
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment