diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2014-11-18 13:45:52 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-11-19 05:46:03 -0500 |
commit | 20feb881988cdf5f53304c355ae8ee3bf82e80ec (patch) | |
tree | 195f81489bd8935cd1103d469b068c5181562bba | |
parent | f114040e3ea6e07372334ade75d1ee0775c355e1 (diff) |
ASoC: Add helper functions for deferred regmap setup
Some drivers (most notably the AC'97 drivers) do not have access to their
regmap struct when the component/codec is registered. For those drivers the
automatic regmap setup will not work and needs to be done manually,
typically from the component/CODEC drivers probe callback.
This patch adds a set of helper function to handle deferred regmap
initialization as well as early regmap tear-down.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | include/sound/soc.h | 35 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 58 |
2 files changed, 82 insertions, 11 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index 7ba7130037a0..342b43b3799e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -1277,6 +1277,41 @@ void snd_soc_component_async_complete(struct snd_soc_component *component); | |||
1277 | int snd_soc_component_test_bits(struct snd_soc_component *component, | 1277 | int snd_soc_component_test_bits(struct snd_soc_component *component, |
1278 | unsigned int reg, unsigned int mask, unsigned int value); | 1278 | unsigned int reg, unsigned int mask, unsigned int value); |
1279 | 1279 | ||
1280 | void snd_soc_component_init_regmap(struct snd_soc_component *component, | ||
1281 | struct regmap *regmap); | ||
1282 | void snd_soc_component_exit_regmap(struct snd_soc_component *component); | ||
1283 | |||
1284 | /** | ||
1285 | * snd_soc_codec_init_regmap() - Initialize regmap instance for the CODEC | ||
1286 | * @codec: The CODEC for which to initialize the regmap instance | ||
1287 | * @regmap: The regmap instance that should be used by the CODEC | ||
1288 | * | ||
1289 | * This function allows deferred assignment of the regmap instance that is | ||
1290 | * associated with the CODEC. Only use this if the regmap instance is not yet | ||
1291 | * ready when the CODEC is registered. The function must also be called before | ||
1292 | * the first IO attempt of the CODEC. | ||
1293 | */ | ||
1294 | static inline void snd_soc_codec_init_regmap(struct snd_soc_codec *codec, | ||
1295 | struct regmap *regmap) | ||
1296 | { | ||
1297 | snd_soc_component_init_regmap(&codec->component, regmap); | ||
1298 | } | ||
1299 | |||
1300 | /** | ||
1301 | * snd_soc_codec_exit_regmap() - De-initialize regmap instance for the CODEC | ||
1302 | * @codec: The CODEC for which to de-initialize the regmap instance | ||
1303 | * | ||
1304 | * Calls regmap_exit() on the regmap instance associated to the CODEC and | ||
1305 | * removes the regmap instance from the CODEC. | ||
1306 | * | ||
1307 | * This function should only be used if snd_soc_codec_init_regmap() was used to | ||
1308 | * initialize the regmap instance. | ||
1309 | */ | ||
1310 | static inline void snd_soc_codec_exit_regmap(struct snd_soc_codec *codec) | ||
1311 | { | ||
1312 | snd_soc_component_exit_regmap(&codec->component); | ||
1313 | } | ||
1314 | |||
1280 | /* device driver data */ | 1315 | /* device driver data */ |
1281 | 1316 | ||
1282 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, | 1317 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4c8f8a23a0e9..5fd5f08ce24e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -3996,22 +3996,58 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, | |||
3996 | return 0; | 3996 | return 0; |
3997 | } | 3997 | } |
3998 | 3998 | ||
3999 | static void snd_soc_component_init_regmap(struct snd_soc_component *component) | 3999 | static void snd_soc_component_setup_regmap(struct snd_soc_component *component) |
4000 | { | 4000 | { |
4001 | if (!component->regmap) | 4001 | int val_bytes = regmap_get_val_bytes(component->regmap); |
4002 | component->regmap = dev_get_regmap(component->dev, NULL); | 4002 | |
4003 | if (component->regmap) { | 4003 | /* Errors are legitimate for non-integer byte multiples */ |
4004 | int val_bytes = regmap_get_val_bytes(component->regmap); | 4004 | if (val_bytes > 0) |
4005 | /* Errors are legitimate for non-integer byte multiples */ | 4005 | component->val_bytes = val_bytes; |
4006 | if (val_bytes > 0) | 4006 | } |
4007 | component->val_bytes = val_bytes; | 4007 | |
4008 | } | 4008 | /** |
4009 | * snd_soc_component_init_regmap() - Initialize regmap instance for the component | ||
4010 | * @component: The component for which to initialize the regmap instance | ||
4011 | * @regmap: The regmap instance that should be used by the component | ||
4012 | * | ||
4013 | * This function allows deferred assignment of the regmap instance that is | ||
4014 | * associated with the component. Only use this if the regmap instance is not | ||
4015 | * yet ready when the component is registered. The function must also be called | ||
4016 | * before the first IO attempt of the component. | ||
4017 | */ | ||
4018 | void snd_soc_component_init_regmap(struct snd_soc_component *component, | ||
4019 | struct regmap *regmap) | ||
4020 | { | ||
4021 | component->regmap = regmap; | ||
4022 | snd_soc_component_setup_regmap(component); | ||
4009 | } | 4023 | } |
4024 | EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); | ||
4025 | |||
4026 | /** | ||
4027 | * snd_soc_component_exit_regmap() - De-initialize regmap instance for the component | ||
4028 | * @component: The component for which to de-initialize the regmap instance | ||
4029 | * | ||
4030 | * Calls regmap_exit() on the regmap instance associated to the component and | ||
4031 | * removes the regmap instance from the component. | ||
4032 | * | ||
4033 | * This function should only be used if snd_soc_component_init_regmap() was used | ||
4034 | * to initialize the regmap instance. | ||
4035 | */ | ||
4036 | void snd_soc_component_exit_regmap(struct snd_soc_component *component) | ||
4037 | { | ||
4038 | regmap_exit(component->regmap); | ||
4039 | component->regmap = NULL; | ||
4040 | } | ||
4041 | EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); | ||
4010 | 4042 | ||
4011 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) | 4043 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) |
4012 | { | 4044 | { |
4013 | if (!component->write && !component->read) | 4045 | if (!component->write && !component->read) { |
4014 | snd_soc_component_init_regmap(component); | 4046 | if (!component->regmap) |
4047 | component->regmap = dev_get_regmap(component->dev, NULL); | ||
4048 | if (component->regmap) | ||
4049 | snd_soc_component_setup_regmap(component); | ||
4050 | } | ||
4015 | 4051 | ||
4016 | list_add(&component->list, &component_list); | 4052 | list_add(&component->list, &component_list); |
4017 | } | 4053 | } |