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>
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4c8f8a2..5fd5f08 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3996,22 +3996,58 @@
 	return 0;
 }
 
-static void snd_soc_component_init_regmap(struct snd_soc_component *component)
+static void snd_soc_component_setup_regmap(struct snd_soc_component *component)
 {
-	if (!component->regmap)
-		component->regmap = dev_get_regmap(component->dev, NULL);
-	if (component->regmap) {
-		int val_bytes = regmap_get_val_bytes(component->regmap);
-		/* Errors are legitimate for non-integer byte multiples */
-		if (val_bytes > 0)
-			component->val_bytes = val_bytes;
-	}
+	int val_bytes = regmap_get_val_bytes(component->regmap);
+
+	/* Errors are legitimate for non-integer byte multiples */
+	if (val_bytes > 0)
+		component->val_bytes = val_bytes;
 }
 
+/**
+ * snd_soc_component_init_regmap() - Initialize regmap instance for the component
+ * @component: The component for which to initialize the regmap instance
+ * @regmap: The regmap instance that should be used by the component
+ *
+ * This function allows deferred assignment of the regmap instance that is
+ * associated with the component. Only use this if the regmap instance is not
+ * yet ready when the component is registered. The function must also be called
+ * before the first IO attempt of the component.
+ */
+void snd_soc_component_init_regmap(struct snd_soc_component *component,
+	struct regmap *regmap)
+{
+	component->regmap = regmap;
+	snd_soc_component_setup_regmap(component);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);
+
+/**
+ * snd_soc_component_exit_regmap() - De-initialize regmap instance for the component
+ * @component: The component for which to de-initialize the regmap instance
+ *
+ * Calls regmap_exit() on the regmap instance associated to the component and
+ * removes the regmap instance from the component.
+ *
+ * This function should only be used if snd_soc_component_init_regmap() was used
+ * to initialize the regmap instance.
+ */
+void snd_soc_component_exit_regmap(struct snd_soc_component *component)
+{
+	regmap_exit(component->regmap);
+	component->regmap = NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
+
 static void snd_soc_component_add_unlocked(struct snd_soc_component *component)
 {
-	if (!component->write && !component->read)
-		snd_soc_component_init_regmap(component);
+	if (!component->write && !component->read) {
+		if (!component->regmap)
+			component->regmap = dev_get_regmap(component->dev, NULL);
+		if (component->regmap)
+			snd_soc_component_setup_regmap(component);
+	}
 
 	list_add(&component->list, &component_list);
 }