diff options
author | Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | 2011-01-13 07:20:36 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-01-13 09:17:32 -0500 |
commit | 066d16c3e8194677a9aaeb06a45e4014387d16f1 (patch) | |
tree | fbdd51ab4478d56fdba8d3c30a381c248a5a3718 | |
parent | 3e8e2cc45c9d6b5c1265838a8cff701815321dbc (diff) |
ASoC: soc-cache: Add support for default readable()/volatile() functions
For common scenarios, device drivers can provide a table of all the
registers that are at least either readable/writable/volatile. The idea
is that if a register lookup fails, all of its read/write/vol members
will be zero and will be treated as default. This also reduces the
size of the register access array.
Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | include/sound/soc.h | 22 | ||||
-rw-r--r-- | sound/soc/soc-cache.c | 49 |
2 files changed, 71 insertions, 0 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index d609232da82a..b8acf99ac89d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -276,6 +276,10 @@ int snd_soc_cache_write(struct snd_soc_codec *codec, | |||
276 | unsigned int reg, unsigned int value); | 276 | unsigned int reg, unsigned int value); |
277 | int snd_soc_cache_read(struct snd_soc_codec *codec, | 277 | int snd_soc_cache_read(struct snd_soc_codec *codec, |
278 | unsigned int reg, unsigned int *value); | 278 | unsigned int reg, unsigned int *value); |
279 | int snd_soc_default_volatile_register(struct snd_soc_codec *codec, | ||
280 | unsigned int reg); | ||
281 | int snd_soc_default_readable_register(struct snd_soc_codec *codec, | ||
282 | unsigned int reg); | ||
279 | 283 | ||
280 | /* Utility functions to get clock rates from various things */ | 284 | /* Utility functions to get clock rates from various things */ |
281 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); | 285 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); |
@@ -367,6 +371,22 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol, | |||
367 | struct snd_ctl_elem_value *ucontrol); | 371 | struct snd_ctl_elem_value *ucontrol); |
368 | 372 | ||
369 | /** | 373 | /** |
374 | * struct snd_soc_reg_access - Describes whether a given register is | ||
375 | * readable, writable or volatile. | ||
376 | * | ||
377 | * @reg: the register number | ||
378 | * @read: whether this register is readable | ||
379 | * @write: whether this register is writable | ||
380 | * @vol: whether this register is volatile | ||
381 | */ | ||
382 | struct snd_soc_reg_access { | ||
383 | u16 reg; | ||
384 | u16 read; | ||
385 | u16 write; | ||
386 | u16 vol; | ||
387 | }; | ||
388 | |||
389 | /** | ||
370 | * struct snd_soc_jack_pin - Describes a pin to update based on jack detection | 390 | * struct snd_soc_jack_pin - Describes a pin to update based on jack detection |
371 | * | 391 | * |
372 | * @pin: name of the pin to update | 392 | * @pin: name of the pin to update |
@@ -515,6 +535,8 @@ struct snd_soc_codec_driver { | |||
515 | short reg_cache_step; | 535 | short reg_cache_step; |
516 | short reg_word_size; | 536 | short reg_word_size; |
517 | const void *reg_cache_default; | 537 | const void *reg_cache_default; |
538 | short reg_access_size; | ||
539 | const struct snd_soc_reg_access *reg_access_default; | ||
518 | enum snd_soc_compress_type compress_type; | 540 | enum snd_soc_compress_type compress_type; |
519 | 541 | ||
520 | /* codec bias level */ | 542 | /* codec bias level */ |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 1a36b36c5baa..d97a59f6a249 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -1603,3 +1603,52 @@ int snd_soc_cache_sync(struct snd_soc_codec *codec) | |||
1603 | return -EINVAL; | 1603 | return -EINVAL; |
1604 | } | 1604 | } |
1605 | EXPORT_SYMBOL_GPL(snd_soc_cache_sync); | 1605 | EXPORT_SYMBOL_GPL(snd_soc_cache_sync); |
1606 | |||
1607 | static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec, | ||
1608 | unsigned int reg) | ||
1609 | { | ||
1610 | const struct snd_soc_codec_driver *codec_drv; | ||
1611 | unsigned int min, max, index; | ||
1612 | |||
1613 | codec_drv = codec->driver; | ||
1614 | min = 0; | ||
1615 | max = codec_drv->reg_access_size - 1; | ||
1616 | do { | ||
1617 | index = (min + max) / 2; | ||
1618 | if (codec_drv->reg_access_default[index].reg == reg) | ||
1619 | return index; | ||
1620 | if (codec_drv->reg_access_default[index].reg < reg) | ||
1621 | min = index + 1; | ||
1622 | else | ||
1623 | max = index; | ||
1624 | } while (min <= max); | ||
1625 | return -1; | ||
1626 | } | ||
1627 | |||
1628 | int snd_soc_default_volatile_register(struct snd_soc_codec *codec, | ||
1629 | unsigned int reg) | ||
1630 | { | ||
1631 | int index; | ||
1632 | |||
1633 | if (reg >= codec->driver->reg_cache_size) | ||
1634 | return 1; | ||
1635 | index = snd_soc_get_reg_access_index(codec, reg); | ||
1636 | if (index < 0) | ||
1637 | return 0; | ||
1638 | return codec->driver->reg_access_default[index].vol; | ||
1639 | } | ||
1640 | EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register); | ||
1641 | |||
1642 | int snd_soc_default_readable_register(struct snd_soc_codec *codec, | ||
1643 | unsigned int reg) | ||
1644 | { | ||
1645 | int index; | ||
1646 | |||
1647 | if (reg >= codec->driver->reg_cache_size) | ||
1648 | return 1; | ||
1649 | index = snd_soc_get_reg_access_index(codec, reg); | ||
1650 | if (index < 0) | ||
1651 | return 0; | ||
1652 | return codec->driver->reg_access_default[index].read; | ||
1653 | } | ||
1654 | EXPORT_SYMBOL_GPL(snd_soc_default_readable_register); | ||