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