1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // soc-devres.c -- ALSA SoC Audio Layer devres functions 4 // 5 // Copyright (C) 2013 Linaro Ltd 6 7 #include <linux/module.h> 8 #include <linux/moduleparam.h> 9 #include <sound/soc.h> 10 #include <sound/dmaengine_pcm.h> 11 12 static void devm_component_release(struct device *dev, void *res) 13 { 14 const struct snd_soc_component_driver **cmpnt_drv = res; 15 16 snd_soc_unregister_component_by_driver(dev, *cmpnt_drv); 17 } 18 19 /** 20 * devm_snd_soc_register_component - resource managed component registration 21 * @dev: Device used to manage component 22 * @cmpnt_drv: Component driver 23 * @dai_drv: DAI driver 24 * @num_dai: Number of DAIs to register 25 * 26 * Register a component with automatic unregistration when the device is 27 * unregistered. 28 */ 29 int devm_snd_soc_register_component(struct device *dev, 30 const struct snd_soc_component_driver *cmpnt_drv, 31 struct snd_soc_dai_driver *dai_drv, int num_dai) 32 { 33 const struct snd_soc_component_driver **ptr; 34 int ret; 35 36 ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL); 37 if (!ptr) 38 return -ENOMEM; 39 40 ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai); 41 if (ret == 0) { 42 *ptr = cmpnt_drv; 43 devres_add(dev, ptr); 44 } else { 45 devres_free(ptr); 46 } 47 48 return ret; 49 } 50 EXPORT_SYMBOL_GPL(devm_snd_soc_register_component); 51 52 static void devm_card_release(struct device *dev, void *res) 53 { 54 snd_soc_unregister_card(*(struct snd_soc_card **)res); 55 } 56 57 /** 58 * devm_snd_soc_register_card - resource managed card registration 59 * @dev: Device used to manage card 60 * @card: Card to register 61 * 62 * Register a card with automatic unregistration when the device is 63 * unregistered. 64 */ 65 int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) 66 { 67 struct snd_soc_card **ptr; 68 int ret; 69 70 ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL); 71 if (!ptr) 72 return -ENOMEM; 73 74 ret = snd_soc_register_card(card); 75 if (ret == 0) { 76 *ptr = card; 77 devres_add(dev, ptr); 78 } else { 79 devres_free(ptr); 80 } 81 82 return ret; 83 } 84 EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); 85 86 #ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM 87 88 static void devm_dmaengine_pcm_release(struct device *dev, void *res) 89 { 90 snd_dmaengine_pcm_unregister(*(struct device **)res); 91 } 92 93 /** 94 * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration 95 * @dev: The parent device for the PCM device 96 * @config: Platform specific PCM configuration 97 * @flags: Platform specific quirks 98 * 99 * Register a dmaengine based PCM device with automatic unregistration when the 100 * device is unregistered. 101 */ 102 int devm_snd_dmaengine_pcm_register(struct device *dev, 103 const struct snd_dmaengine_pcm_config *config, unsigned int flags) 104 { 105 struct device **ptr; 106 int ret; 107 108 ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL); 109 if (!ptr) 110 return -ENOMEM; 111 112 ret = snd_dmaengine_pcm_register(dev, config, flags); 113 if (ret == 0) { 114 *ptr = dev; 115 devres_add(dev, ptr); 116 } else { 117 devres_free(ptr); 118 } 119 120 return ret; 121 } 122 EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register); 123 124 #endif 125