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 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 */ 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 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 */ 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 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 */ 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 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 */ 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