xref: /linux/sound/soc/soc-devres.c (revision 0fae253af563cf5d1f5dc651d520c3eafd74f183)
19e14035cSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0+
29e14035cSKuninori Morimoto //
39e14035cSKuninori Morimoto // soc-devres.c  --  ALSA SoC Audio Layer devres functions
49e14035cSKuninori Morimoto //
59e14035cSKuninori Morimoto // Copyright (C) 2013 Linaro Ltd
6a0b03a61SMark Brown 
7a0b03a61SMark Brown #include <linux/module.h>
8a0b03a61SMark Brown #include <linux/moduleparam.h>
9a0b03a61SMark Brown #include <sound/soc.h>
1021585ee8SLars-Peter Clausen #include <sound/dmaengine_pcm.h>
11a0b03a61SMark Brown 
12*0fae253aSPierre-Louis Bossart static void devm_dai_release(struct device *dev, void *res)
13*0fae253aSPierre-Louis Bossart {
14*0fae253aSPierre-Louis Bossart 	snd_soc_unregister_dai(*(struct snd_soc_dai **)res);
15*0fae253aSPierre-Louis Bossart }
16*0fae253aSPierre-Louis Bossart 
17*0fae253aSPierre-Louis Bossart /**
18*0fae253aSPierre-Louis Bossart  * devm_snd_soc_register_dai - resource-managed dai registration
19*0fae253aSPierre-Louis Bossart  * @dev: Device used to manage component
20*0fae253aSPierre-Louis Bossart  * @component: The component the DAIs are registered for
21*0fae253aSPierre-Louis Bossart  * @dai_drv: DAI driver to use for the DAI
22*0fae253aSPierre-Louis Bossart  * @legacy_dai_naming: if %true, use legacy single-name format;
23*0fae253aSPierre-Louis Bossart  *	if %false, use multiple-name format;
24*0fae253aSPierre-Louis Bossart  */
25*0fae253aSPierre-Louis Bossart struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
26*0fae253aSPierre-Louis Bossart 					      struct snd_soc_component *component,
27*0fae253aSPierre-Louis Bossart 					      struct snd_soc_dai_driver *dai_drv,
28*0fae253aSPierre-Louis Bossart 					      bool legacy_dai_naming)
29*0fae253aSPierre-Louis Bossart {
30*0fae253aSPierre-Louis Bossart 	struct snd_soc_dai **ptr;
31*0fae253aSPierre-Louis Bossart 	struct snd_soc_dai *dai;
32*0fae253aSPierre-Louis Bossart 
33*0fae253aSPierre-Louis Bossart 	ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL);
34*0fae253aSPierre-Louis Bossart 	if (!ptr)
35*0fae253aSPierre-Louis Bossart 		return NULL;
36*0fae253aSPierre-Louis Bossart 
37*0fae253aSPierre-Louis Bossart 	dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming);
38*0fae253aSPierre-Louis Bossart 	if (dai) {
39*0fae253aSPierre-Louis Bossart 		*ptr = dai;
40*0fae253aSPierre-Louis Bossart 		devres_add(dev, ptr);
41*0fae253aSPierre-Louis Bossart 	} else {
42*0fae253aSPierre-Louis Bossart 		devres_free(ptr);
43*0fae253aSPierre-Louis Bossart 	}
44*0fae253aSPierre-Louis Bossart 
45*0fae253aSPierre-Louis Bossart 	return dai;
46*0fae253aSPierre-Louis Bossart }
47*0fae253aSPierre-Louis Bossart EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai);
48*0fae253aSPierre-Louis Bossart 
49a0b03a61SMark Brown static void devm_component_release(struct device *dev, void *res)
50a0b03a61SMark Brown {
51a0b03a61SMark Brown 	snd_soc_unregister_component(*(struct device **)res);
52a0b03a61SMark Brown }
53a0b03a61SMark Brown 
54a0b03a61SMark Brown /**
55a0b03a61SMark Brown  * devm_snd_soc_register_component - resource managed component registration
56a0b03a61SMark Brown  * @dev: Device used to manage component
57a0b03a61SMark Brown  * @cmpnt_drv: Component driver
58a0b03a61SMark Brown  * @dai_drv: DAI driver
59a0b03a61SMark Brown  * @num_dai: Number of DAIs to register
60a0b03a61SMark Brown  *
61a0b03a61SMark Brown  * Register a component with automatic unregistration when the device is
62a0b03a61SMark Brown  * unregistered.
63a0b03a61SMark Brown  */
64a0b03a61SMark Brown int devm_snd_soc_register_component(struct device *dev,
65a0b03a61SMark Brown 			 const struct snd_soc_component_driver *cmpnt_drv,
66a0b03a61SMark Brown 			 struct snd_soc_dai_driver *dai_drv, int num_dai)
67a0b03a61SMark Brown {
68a0b03a61SMark Brown 	struct device **ptr;
69a0b03a61SMark Brown 	int ret;
70a0b03a61SMark Brown 
71a0b03a61SMark Brown 	ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
72a0b03a61SMark Brown 	if (!ptr)
73a0b03a61SMark Brown 		return -ENOMEM;
74a0b03a61SMark Brown 
75a0b03a61SMark Brown 	ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
76a0b03a61SMark Brown 	if (ret == 0) {
77a0b03a61SMark Brown 		*ptr = dev;
78a0b03a61SMark Brown 		devres_add(dev, ptr);
79a0b03a61SMark Brown 	} else {
80a0b03a61SMark Brown 		devres_free(ptr);
81a0b03a61SMark Brown 	}
82a0b03a61SMark Brown 
83a0b03a61SMark Brown 	return ret;
84a0b03a61SMark Brown }
85a0b03a61SMark Brown EXPORT_SYMBOL_GPL(devm_snd_soc_register_component);
860e4ff5c8SMark Brown 
870e4ff5c8SMark Brown static void devm_card_release(struct device *dev, void *res)
880e4ff5c8SMark Brown {
890e4ff5c8SMark Brown 	snd_soc_unregister_card(*(struct snd_soc_card **)res);
900e4ff5c8SMark Brown }
910e4ff5c8SMark Brown 
920e4ff5c8SMark Brown /**
930e4ff5c8SMark Brown  * devm_snd_soc_register_card - resource managed card registration
940e4ff5c8SMark Brown  * @dev: Device used to manage card
950e4ff5c8SMark Brown  * @card: Card to register
960e4ff5c8SMark Brown  *
970e4ff5c8SMark Brown  * Register a card with automatic unregistration when the device is
980e4ff5c8SMark Brown  * unregistered.
990e4ff5c8SMark Brown  */
1000e4ff5c8SMark Brown int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
1010e4ff5c8SMark Brown {
102ebff6547SShawn Guo 	struct snd_soc_card **ptr;
1030e4ff5c8SMark Brown 	int ret;
1040e4ff5c8SMark Brown 
1050e4ff5c8SMark Brown 	ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
1060e4ff5c8SMark Brown 	if (!ptr)
1070e4ff5c8SMark Brown 		return -ENOMEM;
1080e4ff5c8SMark Brown 
1090e4ff5c8SMark Brown 	ret = snd_soc_register_card(card);
1100e4ff5c8SMark Brown 	if (ret == 0) {
111ebff6547SShawn Guo 		*ptr = card;
1120e4ff5c8SMark Brown 		devres_add(dev, ptr);
1130e4ff5c8SMark Brown 	} else {
1140e4ff5c8SMark Brown 		devres_free(ptr);
1150e4ff5c8SMark Brown 	}
1160e4ff5c8SMark Brown 
1170e4ff5c8SMark Brown 	return ret;
1180e4ff5c8SMark Brown }
1190e4ff5c8SMark Brown EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
12021585ee8SLars-Peter Clausen 
12121585ee8SLars-Peter Clausen #ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM
12221585ee8SLars-Peter Clausen 
12321585ee8SLars-Peter Clausen static void devm_dmaengine_pcm_release(struct device *dev, void *res)
12421585ee8SLars-Peter Clausen {
12521585ee8SLars-Peter Clausen 	snd_dmaengine_pcm_unregister(*(struct device **)res);
12621585ee8SLars-Peter Clausen }
12721585ee8SLars-Peter Clausen 
12821585ee8SLars-Peter Clausen /**
12921585ee8SLars-Peter Clausen  * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration
13021585ee8SLars-Peter Clausen  * @dev: The parent device for the PCM device
13121585ee8SLars-Peter Clausen  * @config: Platform specific PCM configuration
13221585ee8SLars-Peter Clausen  * @flags: Platform specific quirks
13321585ee8SLars-Peter Clausen  *
13421585ee8SLars-Peter Clausen  * Register a dmaengine based PCM device with automatic unregistration when the
13521585ee8SLars-Peter Clausen  * device is unregistered.
13621585ee8SLars-Peter Clausen  */
13721585ee8SLars-Peter Clausen int devm_snd_dmaengine_pcm_register(struct device *dev,
13821585ee8SLars-Peter Clausen 	const struct snd_dmaengine_pcm_config *config, unsigned int flags)
13921585ee8SLars-Peter Clausen {
14021585ee8SLars-Peter Clausen 	struct device **ptr;
14121585ee8SLars-Peter Clausen 	int ret;
14221585ee8SLars-Peter Clausen 
14321585ee8SLars-Peter Clausen 	ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL);
14421585ee8SLars-Peter Clausen 	if (!ptr)
14521585ee8SLars-Peter Clausen 		return -ENOMEM;
14621585ee8SLars-Peter Clausen 
14721585ee8SLars-Peter Clausen 	ret = snd_dmaengine_pcm_register(dev, config, flags);
14821585ee8SLars-Peter Clausen 	if (ret == 0) {
14921585ee8SLars-Peter Clausen 		*ptr = dev;
15021585ee8SLars-Peter Clausen 		devres_add(dev, ptr);
15121585ee8SLars-Peter Clausen 	} else {
15221585ee8SLars-Peter Clausen 		devres_free(ptr);
15321585ee8SLars-Peter Clausen 	}
15421585ee8SLars-Peter Clausen 
15521585ee8SLars-Peter Clausen 	return ret;
15621585ee8SLars-Peter Clausen }
15721585ee8SLars-Peter Clausen EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register);
15821585ee8SLars-Peter Clausen 
15921585ee8SLars-Peter Clausen #endif
160