xref: /linux/sound/soc/soc-devres.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
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 
devm_dai_release(struct device * dev,void * res)120fae253aSPierre-Louis Bossart static void devm_dai_release(struct device *dev, void *res)
130fae253aSPierre-Louis Bossart {
140fae253aSPierre-Louis Bossart 	snd_soc_unregister_dai(*(struct snd_soc_dai **)res);
150fae253aSPierre-Louis Bossart }
160fae253aSPierre-Louis Bossart 
170fae253aSPierre-Louis Bossart /**
180fae253aSPierre-Louis Bossart  * devm_snd_soc_register_dai - resource-managed dai registration
190fae253aSPierre-Louis Bossart  * @dev: Device used to manage component
200fae253aSPierre-Louis Bossart  * @component: The component the DAIs are registered for
210fae253aSPierre-Louis Bossart  * @dai_drv: DAI driver to use for the DAI
220fae253aSPierre-Louis Bossart  * @legacy_dai_naming: if %true, use legacy single-name format;
230fae253aSPierre-Louis Bossart  *	if %false, use multiple-name format;
240fae253aSPierre-Louis Bossart  */
devm_snd_soc_register_dai(struct device * dev,struct snd_soc_component * component,struct snd_soc_dai_driver * dai_drv,bool legacy_dai_naming)250fae253aSPierre-Louis Bossart struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
260fae253aSPierre-Louis Bossart 					      struct snd_soc_component *component,
270fae253aSPierre-Louis Bossart 					      struct snd_soc_dai_driver *dai_drv,
280fae253aSPierre-Louis Bossart 					      bool legacy_dai_naming)
290fae253aSPierre-Louis Bossart {
300fae253aSPierre-Louis Bossart 	struct snd_soc_dai **ptr;
310fae253aSPierre-Louis Bossart 	struct snd_soc_dai *dai;
320fae253aSPierre-Louis Bossart 
330fae253aSPierre-Louis Bossart 	ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL);
340fae253aSPierre-Louis Bossart 	if (!ptr)
350fae253aSPierre-Louis Bossart 		return NULL;
360fae253aSPierre-Louis Bossart 
370fae253aSPierre-Louis Bossart 	dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming);
380fae253aSPierre-Louis Bossart 	if (dai) {
390fae253aSPierre-Louis Bossart 		*ptr = dai;
400fae253aSPierre-Louis Bossart 		devres_add(dev, ptr);
410fae253aSPierre-Louis Bossart 	} else {
420fae253aSPierre-Louis Bossart 		devres_free(ptr);
430fae253aSPierre-Louis Bossart 	}
440fae253aSPierre-Louis Bossart 
450fae253aSPierre-Louis Bossart 	return dai;
460fae253aSPierre-Louis Bossart }
470fae253aSPierre-Louis Bossart EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai);
480fae253aSPierre-Louis Bossart 
devm_component_release(struct device * dev,void * res)49a0b03a61SMark Brown static void devm_component_release(struct device *dev, void *res)
50a0b03a61SMark Brown {
51*58f30150SMaxime Ripard 	const struct snd_soc_component_driver **cmpnt_drv = res;
52*58f30150SMaxime Ripard 
53*58f30150SMaxime Ripard 	snd_soc_unregister_component_by_driver(dev, *cmpnt_drv);
54a0b03a61SMark Brown }
55a0b03a61SMark Brown 
56a0b03a61SMark Brown /**
57a0b03a61SMark Brown  * devm_snd_soc_register_component - resource managed component registration
58a0b03a61SMark Brown  * @dev: Device used to manage component
59a0b03a61SMark Brown  * @cmpnt_drv: Component driver
60a0b03a61SMark Brown  * @dai_drv: DAI driver
61a0b03a61SMark Brown  * @num_dai: Number of DAIs to register
62a0b03a61SMark Brown  *
63a0b03a61SMark Brown  * Register a component with automatic unregistration when the device is
64a0b03a61SMark Brown  * unregistered.
65a0b03a61SMark Brown  */
devm_snd_soc_register_component(struct device * dev,const struct snd_soc_component_driver * cmpnt_drv,struct snd_soc_dai_driver * dai_drv,int num_dai)66a0b03a61SMark Brown int devm_snd_soc_register_component(struct device *dev,
67a0b03a61SMark Brown 			 const struct snd_soc_component_driver *cmpnt_drv,
68a0b03a61SMark Brown 			 struct snd_soc_dai_driver *dai_drv, int num_dai)
69a0b03a61SMark Brown {
70*58f30150SMaxime Ripard 	const struct snd_soc_component_driver **ptr;
71a0b03a61SMark Brown 	int ret;
72a0b03a61SMark Brown 
73a0b03a61SMark Brown 	ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
74a0b03a61SMark Brown 	if (!ptr)
75a0b03a61SMark Brown 		return -ENOMEM;
76a0b03a61SMark Brown 
77a0b03a61SMark Brown 	ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
78a0b03a61SMark Brown 	if (ret == 0) {
79*58f30150SMaxime Ripard 		*ptr = cmpnt_drv;
80a0b03a61SMark Brown 		devres_add(dev, ptr);
81a0b03a61SMark Brown 	} else {
82a0b03a61SMark Brown 		devres_free(ptr);
83a0b03a61SMark Brown 	}
84a0b03a61SMark Brown 
85a0b03a61SMark Brown 	return ret;
86a0b03a61SMark Brown }
87a0b03a61SMark Brown EXPORT_SYMBOL_GPL(devm_snd_soc_register_component);
880e4ff5c8SMark Brown 
devm_card_release(struct device * dev,void * res)890e4ff5c8SMark Brown static void devm_card_release(struct device *dev, void *res)
900e4ff5c8SMark Brown {
910e4ff5c8SMark Brown 	snd_soc_unregister_card(*(struct snd_soc_card **)res);
920e4ff5c8SMark Brown }
930e4ff5c8SMark Brown 
940e4ff5c8SMark Brown /**
950e4ff5c8SMark Brown  * devm_snd_soc_register_card - resource managed card registration
960e4ff5c8SMark Brown  * @dev: Device used to manage card
970e4ff5c8SMark Brown  * @card: Card to register
980e4ff5c8SMark Brown  *
990e4ff5c8SMark Brown  * Register a card with automatic unregistration when the device is
1000e4ff5c8SMark Brown  * unregistered.
1010e4ff5c8SMark Brown  */
devm_snd_soc_register_card(struct device * dev,struct snd_soc_card * card)1020e4ff5c8SMark Brown int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
1030e4ff5c8SMark Brown {
104ebff6547SShawn Guo 	struct snd_soc_card **ptr;
1050e4ff5c8SMark Brown 	int ret;
1060e4ff5c8SMark Brown 
1070e4ff5c8SMark Brown 	ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
1080e4ff5c8SMark Brown 	if (!ptr)
1090e4ff5c8SMark Brown 		return -ENOMEM;
1100e4ff5c8SMark Brown 
1110e4ff5c8SMark Brown 	ret = snd_soc_register_card(card);
1120e4ff5c8SMark Brown 	if (ret == 0) {
113ebff6547SShawn Guo 		*ptr = card;
1140e4ff5c8SMark Brown 		devres_add(dev, ptr);
1150e4ff5c8SMark Brown 	} else {
1160e4ff5c8SMark Brown 		devres_free(ptr);
1170e4ff5c8SMark Brown 	}
1180e4ff5c8SMark Brown 
1190e4ff5c8SMark Brown 	return ret;
1200e4ff5c8SMark Brown }
1210e4ff5c8SMark Brown EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
12221585ee8SLars-Peter Clausen 
12321585ee8SLars-Peter Clausen #ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM
12421585ee8SLars-Peter Clausen 
devm_dmaengine_pcm_release(struct device * dev,void * res)12521585ee8SLars-Peter Clausen static void devm_dmaengine_pcm_release(struct device *dev, void *res)
12621585ee8SLars-Peter Clausen {
12721585ee8SLars-Peter Clausen 	snd_dmaengine_pcm_unregister(*(struct device **)res);
12821585ee8SLars-Peter Clausen }
12921585ee8SLars-Peter Clausen 
13021585ee8SLars-Peter Clausen /**
13121585ee8SLars-Peter Clausen  * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration
13221585ee8SLars-Peter Clausen  * @dev: The parent device for the PCM device
13321585ee8SLars-Peter Clausen  * @config: Platform specific PCM configuration
13421585ee8SLars-Peter Clausen  * @flags: Platform specific quirks
13521585ee8SLars-Peter Clausen  *
13621585ee8SLars-Peter Clausen  * Register a dmaengine based PCM device with automatic unregistration when the
13721585ee8SLars-Peter Clausen  * device is unregistered.
13821585ee8SLars-Peter Clausen  */
devm_snd_dmaengine_pcm_register(struct device * dev,const struct snd_dmaengine_pcm_config * config,unsigned int flags)13921585ee8SLars-Peter Clausen int devm_snd_dmaengine_pcm_register(struct device *dev,
14021585ee8SLars-Peter Clausen 	const struct snd_dmaengine_pcm_config *config, unsigned int flags)
14121585ee8SLars-Peter Clausen {
14221585ee8SLars-Peter Clausen 	struct device **ptr;
14321585ee8SLars-Peter Clausen 	int ret;
14421585ee8SLars-Peter Clausen 
14521585ee8SLars-Peter Clausen 	ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL);
14621585ee8SLars-Peter Clausen 	if (!ptr)
14721585ee8SLars-Peter Clausen 		return -ENOMEM;
14821585ee8SLars-Peter Clausen 
14921585ee8SLars-Peter Clausen 	ret = snd_dmaengine_pcm_register(dev, config, flags);
15021585ee8SLars-Peter Clausen 	if (ret == 0) {
15121585ee8SLars-Peter Clausen 		*ptr = dev;
15221585ee8SLars-Peter Clausen 		devres_add(dev, ptr);
15321585ee8SLars-Peter Clausen 	} else {
15421585ee8SLars-Peter Clausen 		devres_free(ptr);
15521585ee8SLars-Peter Clausen 	}
15621585ee8SLars-Peter Clausen 
15721585ee8SLars-Peter Clausen 	return ret;
15821585ee8SLars-Peter Clausen }
15921585ee8SLars-Peter Clausen EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register);
16021585ee8SLars-Peter Clausen 
16121585ee8SLars-Peter Clausen #endif
162