[alsa-devel] [PATCH 1/3] ASoC: Add default snd_soc_default_writable_register() callback
By using struct snd_soc_reg_access for the read/write/vol attributes of the registers, we provide callbacks that automatically determine whether a given register is readable/writable or volatile.
Signed-off-by: Dimitris Papastamos dp@opensource.wolfsonmicro.com --- include/sound/soc.h | 4 ++++ sound/soc/soc-cache.c | 14 ++++++++++++++ sound/soc/soc-core.c | 3 +++ 3 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index bfa4836..982e63e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -292,6 +292,8 @@ int snd_soc_default_volatile_register(struct snd_soc_codec *codec, unsigned int reg); int snd_soc_default_readable_register(struct snd_soc_codec *codec, unsigned int reg); +int snd_soc_default_writable_register(struct snd_soc_codec *codec, + unsigned int reg);
/* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); @@ -523,6 +525,7 @@ struct snd_soc_codec { size_t reg_size; /* reg_cache_size * reg_word_size */ int (*volatile_register)(struct snd_soc_codec *, unsigned int); int (*readable_register)(struct snd_soc_codec *, unsigned int); + int (*writable_register)(struct snd_soc_codec *, unsigned int);
/* runtime */ struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ @@ -587,6 +590,7 @@ struct snd_soc_codec_driver { size_t, unsigned int); int (*volatile_register)(struct snd_soc_codec *, unsigned int); int (*readable_register)(struct snd_soc_codec *, unsigned int); + int (*writable_register)(struct snd_soc_codec *, unsigned int); short reg_cache_size; short reg_cache_step; short reg_word_size; diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 5d76da4..657889d 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -1677,3 +1677,17 @@ int snd_soc_default_readable_register(struct snd_soc_codec *codec, return codec->driver->reg_access_default[index].read; } EXPORT_SYMBOL_GPL(snd_soc_default_readable_register); + +int snd_soc_default_writable_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + int index; + + if (reg >= codec->driver->reg_cache_size) + return 1; + index = snd_soc_get_reg_access_index(codec, reg); + if (index < 0) + return 0; + return codec->driver->reg_access_default[index].write; +} +EXPORT_SYMBOL_GPL(snd_soc_default_writable_register); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4dda589..1cb1446 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3666,6 +3666,7 @@ int snd_soc_register_codec(struct device *dev, codec->read = codec_drv->read; codec->volatile_register = codec_drv->volatile_register; codec->readable_register = codec_drv->readable_register; + codec->writable_register = codec_drv->writable_register; codec->dapm.bias_level = SND_SOC_BIAS_OFF; codec->dapm.dev = dev; codec->dapm.codec = codec; @@ -3700,6 +3701,8 @@ int snd_soc_register_codec(struct device *dev, codec->volatile_register = snd_soc_default_volatile_register; if (!codec->readable_register) codec->readable_register = snd_soc_default_readable_register; + if (!codec->writable_register) + codec->writable_register = snd_soc_default_writable_register; }
for (i = 0; i < num_dai; i++) {
Provide the top level ASoC core functions for indicating whether a given register is readable or writable.
Signed-off-by: Dimitris Papastamos dp@opensource.wolfsonmicro.com --- include/sound/soc.h | 4 ++++ sound/soc/soc-core.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 982e63e..e8447be 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -278,6 +278,10 @@ int snd_soc_register_codec(struct device *dev, void snd_soc_unregister_codec(struct device *dev); int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, unsigned int reg); +int snd_soc_codec_readable_register(struct snd_soc_codec *codec, + unsigned int reg); +int snd_soc_codec_writable_register(struct snd_soc_codec *codec, + unsigned int reg); int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, int addr_bits, int data_bits, enum snd_soc_control_type control); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1cb1446..60a22a6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2147,6 +2147,42 @@ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
/** + * snd_soc_codec_readable_register: Report if a register is readable. + * + * @codec: CODEC to query. + * @reg: Register to query. + * + * Boolean function indicating if a CODEC register is readable. + */ +int snd_soc_codec_readable_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + if (codec->readable_register) + return codec->readable_register(codec, reg); + else + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_codec_readable_register); + +/** + * snd_soc_codec_writable_register: Report if a register is writable. + * + * @codec: CODEC to query. + * @reg: Register to query. + * + * Boolean function indicating if a CODEC register is writable. + */ +int snd_soc_codec_writable_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + if (codec->writable_register) + return codec->writable_register(codec, reg); + else + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register); + +/** * snd_soc_new_ac97_codec - initailise AC97 device * @codec: audio codec * @ops: AC97 bus operations
When syncing the cache, if the driver has given us a writable_register() callback, use it to not sync any non-writable registers.
Signed-off-by: Dimitris Papastamos dp@opensource.wolfsonmicro.com --- sound/soc/soc-cache.c | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 657889d..0ec8e13 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -889,6 +889,9 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec) rbnode = rb_entry(node, struct snd_soc_rbtree_node, node); if (rbnode->value == rbnode->defval) continue; + if (codec->writable_register && + !codec->writable_register(codec, rbnode->reg)) + continue; ret = snd_soc_cache_read(codec, rbnode->reg, &val); if (ret) return ret; @@ -1149,6 +1152,8 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
lzo_blocks = codec->reg_cache; for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) { + if (codec->writable_register && !codec->writable_register(codec, i)) + continue; ret = snd_soc_cache_read(codec, i, &val); if (ret) return ret; @@ -1407,6 +1412,8 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
codec_drv = codec->driver; for (i = 0; i < codec_drv->reg_cache_size; ++i) { + if (codec->writable_register && !codec->writable_register(codec, i)) + continue; ret = snd_soc_cache_read(codec, i, &val); if (ret) return ret;
On Thu, Mar 24, 2011 at 01:45:19PM +0000, Dimitris Papastamos wrote:
When syncing the cache, if the driver has given us a writable_register() callback, use it to not sync any non-writable registers.
Signed-off-by: Dimitris Papastamos dp@opensource.wolfsonmicro.com
Thinking about this again I'm actually thinking we should really be warning if we ever find a need to sync a non-writable register - given that we suppress writes of the default value this'd mean that we'd have had to have written to the register at some point in the past which means that something messed up somewhere.
On Sat, Mar 26, 2011 at 05:29:41PM +0000, Mark Brown wrote:
On Thu, Mar 24, 2011 at 01:45:19PM +0000, Dimitris Papastamos wrote:
When syncing the cache, if the driver has given us a writable_register() callback, use it to not sync any non-writable registers.
Signed-off-by: Dimitris Papastamos dp@opensource.wolfsonmicro.com
Thinking about this again I'm actually thinking we should really be warning if we ever find a need to sync a non-writable register - given that we suppress writes of the default value this'd mean that we'd have had to have written to the register at some point in the past which means that something messed up somewhere.
Yea that makes sense. I will send in a patch.
Thanks, Dimitris
On Thu, 2011-03-24 at 13:45 +0000, Dimitris Papastamos wrote:
By using struct snd_soc_reg_access for the read/write/vol attributes of the registers, we provide callbacks that automatically determine whether a given register is readable/writable or volatile.
Signed-off-by: Dimitris Papastamos dp@opensource.wolfsonmicro.com
All
Acked-by: Liam Girdwood lrg@ti.com
On Thu, Mar 24, 2011 at 01:45:17PM +0000, Dimitris Papastamos wrote:
By using struct snd_soc_reg_access for the read/write/vol attributes of the registers, we provide callbacks that automatically determine whether a given register is readable/writable or volatile.
Signed-off-by: Dimitris Papastamos dp@opensource.wolfsonmicro.com
Applied this and patch 2, thanks.
participants (3)
-
Dimitris Papastamos
-
Liam Girdwood
-
Mark Brown