1*9e14035cSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0+ 2*9e14035cSKuninori Morimoto // 3*9e14035cSKuninori Morimoto // soc-devres.c -- ALSA SoC Audio Layer devres functions 4*9e14035cSKuninori Morimoto // 5*9e14035cSKuninori 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 12a0b03a61SMark Brown static void devm_component_release(struct device *dev, void *res) 13a0b03a61SMark Brown { 14a0b03a61SMark Brown snd_soc_unregister_component(*(struct device **)res); 15a0b03a61SMark Brown } 16a0b03a61SMark Brown 17a0b03a61SMark Brown /** 18a0b03a61SMark Brown * devm_snd_soc_register_component - resource managed component registration 19a0b03a61SMark Brown * @dev: Device used to manage component 20a0b03a61SMark Brown * @cmpnt_drv: Component driver 21a0b03a61SMark Brown * @dai_drv: DAI driver 22a0b03a61SMark Brown * @num_dai: Number of DAIs to register 23a0b03a61SMark Brown * 24a0b03a61SMark Brown * Register a component with automatic unregistration when the device is 25a0b03a61SMark Brown * unregistered. 26a0b03a61SMark Brown */ 27a0b03a61SMark Brown int devm_snd_soc_register_component(struct device *dev, 28a0b03a61SMark Brown const struct snd_soc_component_driver *cmpnt_drv, 29a0b03a61SMark Brown struct snd_soc_dai_driver *dai_drv, int num_dai) 30a0b03a61SMark Brown { 31a0b03a61SMark Brown struct device **ptr; 32a0b03a61SMark Brown int ret; 33a0b03a61SMark Brown 34a0b03a61SMark Brown ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL); 35a0b03a61SMark Brown if (!ptr) 36a0b03a61SMark Brown return -ENOMEM; 37a0b03a61SMark Brown 38a0b03a61SMark Brown ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai); 39a0b03a61SMark Brown if (ret == 0) { 40a0b03a61SMark Brown *ptr = dev; 41a0b03a61SMark Brown devres_add(dev, ptr); 42a0b03a61SMark Brown } else { 43a0b03a61SMark Brown devres_free(ptr); 44a0b03a61SMark Brown } 45a0b03a61SMark Brown 46a0b03a61SMark Brown return ret; 47a0b03a61SMark Brown } 48a0b03a61SMark Brown EXPORT_SYMBOL_GPL(devm_snd_soc_register_component); 490e4ff5c8SMark Brown 500e4ff5c8SMark Brown static void devm_card_release(struct device *dev, void *res) 510e4ff5c8SMark Brown { 520e4ff5c8SMark Brown snd_soc_unregister_card(*(struct snd_soc_card **)res); 530e4ff5c8SMark Brown } 540e4ff5c8SMark Brown 550e4ff5c8SMark Brown /** 560e4ff5c8SMark Brown * devm_snd_soc_register_card - resource managed card registration 570e4ff5c8SMark Brown * @dev: Device used to manage card 580e4ff5c8SMark Brown * @card: Card to register 590e4ff5c8SMark Brown * 600e4ff5c8SMark Brown * Register a card with automatic unregistration when the device is 610e4ff5c8SMark Brown * unregistered. 620e4ff5c8SMark Brown */ 630e4ff5c8SMark Brown int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) 640e4ff5c8SMark Brown { 65ebff6547SShawn Guo struct snd_soc_card **ptr; 660e4ff5c8SMark Brown int ret; 670e4ff5c8SMark Brown 680e4ff5c8SMark Brown ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL); 690e4ff5c8SMark Brown if (!ptr) 700e4ff5c8SMark Brown return -ENOMEM; 710e4ff5c8SMark Brown 720e4ff5c8SMark Brown ret = snd_soc_register_card(card); 730e4ff5c8SMark Brown if (ret == 0) { 74ebff6547SShawn Guo *ptr = card; 750e4ff5c8SMark Brown devres_add(dev, ptr); 760e4ff5c8SMark Brown } else { 770e4ff5c8SMark Brown devres_free(ptr); 780e4ff5c8SMark Brown } 790e4ff5c8SMark Brown 800e4ff5c8SMark Brown return ret; 810e4ff5c8SMark Brown } 820e4ff5c8SMark Brown EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); 8321585ee8SLars-Peter Clausen 8421585ee8SLars-Peter Clausen #ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM 8521585ee8SLars-Peter Clausen 8621585ee8SLars-Peter Clausen static void devm_dmaengine_pcm_release(struct device *dev, void *res) 8721585ee8SLars-Peter Clausen { 8821585ee8SLars-Peter Clausen snd_dmaengine_pcm_unregister(*(struct device **)res); 8921585ee8SLars-Peter Clausen } 9021585ee8SLars-Peter Clausen 9121585ee8SLars-Peter Clausen /** 9221585ee8SLars-Peter Clausen * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration 9321585ee8SLars-Peter Clausen * @dev: The parent device for the PCM device 9421585ee8SLars-Peter Clausen * @config: Platform specific PCM configuration 9521585ee8SLars-Peter Clausen * @flags: Platform specific quirks 9621585ee8SLars-Peter Clausen * 9721585ee8SLars-Peter Clausen * Register a dmaengine based PCM device with automatic unregistration when the 9821585ee8SLars-Peter Clausen * device is unregistered. 9921585ee8SLars-Peter Clausen */ 10021585ee8SLars-Peter Clausen int devm_snd_dmaengine_pcm_register(struct device *dev, 10121585ee8SLars-Peter Clausen const struct snd_dmaengine_pcm_config *config, unsigned int flags) 10221585ee8SLars-Peter Clausen { 10321585ee8SLars-Peter Clausen struct device **ptr; 10421585ee8SLars-Peter Clausen int ret; 10521585ee8SLars-Peter Clausen 10621585ee8SLars-Peter Clausen ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL); 10721585ee8SLars-Peter Clausen if (!ptr) 10821585ee8SLars-Peter Clausen return -ENOMEM; 10921585ee8SLars-Peter Clausen 11021585ee8SLars-Peter Clausen ret = snd_dmaengine_pcm_register(dev, config, flags); 11121585ee8SLars-Peter Clausen if (ret == 0) { 11221585ee8SLars-Peter Clausen *ptr = dev; 11321585ee8SLars-Peter Clausen devres_add(dev, ptr); 11421585ee8SLars-Peter Clausen } else { 11521585ee8SLars-Peter Clausen devres_free(ptr); 11621585ee8SLars-Peter Clausen } 11721585ee8SLars-Peter Clausen 11821585ee8SLars-Peter Clausen return ret; 11921585ee8SLars-Peter Clausen } 12021585ee8SLars-Peter Clausen EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register); 12121585ee8SLars-Peter Clausen 12221585ee8SLars-Peter Clausen #endif 123