ASoC: Use regmap update bits operation for drivers using regmap
If a driver is using regmap directly ensure that we're coherent with non-ASoC register updates by using the regmap API directly to do our read/modify/write cycles. This will bypass the ASoC cache but drivers using regmap directly should not be using the ASoC cache. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
278047fd65
commit
8a713da8d1
|
@ -560,6 +560,7 @@ struct snd_soc_codec {
|
||||||
unsigned int ac97_created:1; /* Codec has been created by SoC */
|
unsigned int ac97_created:1; /* Codec has been created by SoC */
|
||||||
unsigned int sysfs_registered:1; /* codec has been sysfs registered */
|
unsigned int sysfs_registered:1; /* codec has been sysfs registered */
|
||||||
unsigned int cache_init:1; /* codec cache has been initialized */
|
unsigned int cache_init:1; /* codec cache has been initialized */
|
||||||
|
unsigned int using_regmap:1; /* using regmap access */
|
||||||
u32 cache_only; /* Suppress writes to hardware */
|
u32 cache_only; /* Suppress writes to hardware */
|
||||||
u32 cache_sync; /* Cache needs to be synced to hardware */
|
u32 cache_sync; /* Cache needs to be synced to hardware */
|
||||||
|
|
||||||
|
|
|
@ -1869,23 +1869,28 @@ EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
|
||||||
int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
|
int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
|
||||||
unsigned int mask, unsigned int value)
|
unsigned int mask, unsigned int value)
|
||||||
{
|
{
|
||||||
int change;
|
bool change;
|
||||||
unsigned int old, new;
|
unsigned int old, new;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = snd_soc_read(codec, reg);
|
if (codec->using_regmap) {
|
||||||
if (ret < 0)
|
ret = regmap_update_bits_check(codec->control_data, reg,
|
||||||
return ret;
|
mask, value, &change);
|
||||||
|
} else {
|
||||||
old = ret;
|
ret = snd_soc_read(codec, reg);
|
||||||
new = (old & ~mask) | (value & mask);
|
|
||||||
change = old != new;
|
|
||||||
if (change) {
|
|
||||||
ret = snd_soc_write(codec, reg, new);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
old = ret;
|
||||||
|
new = (old & ~mask) | (value & mask);
|
||||||
|
change = old != new;
|
||||||
|
if (change)
|
||||||
|
ret = snd_soc_write(codec, reg, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_soc_update_bits);
|
EXPORT_SYMBOL_GPL(snd_soc_update_bits);
|
||||||
|
|
|
@ -197,21 +197,28 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
|
||||||
static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
|
static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
|
||||||
unsigned short reg, unsigned int mask, unsigned int value)
|
unsigned short reg, unsigned int mask, unsigned int value)
|
||||||
{
|
{
|
||||||
int change;
|
bool change;
|
||||||
unsigned int old, new;
|
unsigned int old, new;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = soc_widget_read(w, reg);
|
if (w->codec && w->codec->using_regmap) {
|
||||||
if (ret < 0)
|
ret = regmap_update_bits_check(w->codec->control_data,
|
||||||
return ret;
|
reg, mask, value, &change);
|
||||||
|
if (ret != 0)
|
||||||
old = ret;
|
return ret;
|
||||||
new = (old & ~mask) | (value & mask);
|
} else {
|
||||||
change = old != new;
|
ret = soc_widget_read(w, reg);
|
||||||
if (change) {
|
|
||||||
ret = soc_widget_write(w, reg, new);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
old = ret;
|
||||||
|
new = (old & ~mask) | (value & mask);
|
||||||
|
change = old != new;
|
||||||
|
if (change) {
|
||||||
|
ret = soc_widget_write(w, reg, new);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return change;
|
return change;
|
||||||
|
|
|
@ -140,6 +140,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
|
||||||
|
|
||||||
case SND_SOC_REGMAP:
|
case SND_SOC_REGMAP:
|
||||||
/* Device has made its own regmap arrangements */
|
/* Device has made its own regmap arrangements */
|
||||||
|
codec->using_regmap = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue