1a0b03a61SMark Brown /* 2a0b03a61SMark Brown * soc-devres.c -- ALSA SoC Audio Layer devres functions 3a0b03a61SMark Brown * 4a0b03a61SMark Brown * Copyright (C) 2013 Linaro Ltd 5a0b03a61SMark Brown * 6a0b03a61SMark Brown * This program is free software; you can redistribute it and/or modify it 7a0b03a61SMark Brown * under the terms of the GNU General Public License as published by the 8a0b03a61SMark Brown * Free Software Foundation; either version 2 of the License, or (at your 9a0b03a61SMark Brown * option) any later version. 10a0b03a61SMark Brown */ 11a0b03a61SMark Brown 12a0b03a61SMark Brown #include <linux/module.h> 13a0b03a61SMark Brown #include <linux/moduleparam.h> 14a0b03a61SMark Brown #include <sound/soc.h> 15a0b03a61SMark Brown 16a0b03a61SMark Brown static void devm_component_release(struct device *dev, void *res) 17a0b03a61SMark Brown { 18a0b03a61SMark Brown snd_soc_unregister_component(*(struct device **)res); 19a0b03a61SMark Brown } 20a0b03a61SMark Brown 21a0b03a61SMark Brown /** 22a0b03a61SMark Brown * devm_snd_soc_register_component - resource managed component registration 23a0b03a61SMark Brown * @dev: Device used to manage component 24a0b03a61SMark Brown * @cmpnt_drv: Component driver 25a0b03a61SMark Brown * @dai_drv: DAI driver 26a0b03a61SMark Brown * @num_dai: Number of DAIs to register 27a0b03a61SMark Brown * 28a0b03a61SMark Brown * Register a component with automatic unregistration when the device is 29a0b03a61SMark Brown * unregistered. 30a0b03a61SMark Brown */ 31a0b03a61SMark Brown int devm_snd_soc_register_component(struct device *dev, 32a0b03a61SMark Brown const struct snd_soc_component_driver *cmpnt_drv, 33a0b03a61SMark Brown struct snd_soc_dai_driver *dai_drv, int num_dai) 34a0b03a61SMark Brown { 35a0b03a61SMark Brown struct device **ptr; 36a0b03a61SMark Brown int ret; 37a0b03a61SMark Brown 38a0b03a61SMark Brown ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL); 39a0b03a61SMark Brown if (!ptr) 40a0b03a61SMark Brown return -ENOMEM; 41a0b03a61SMark Brown 42a0b03a61SMark Brown ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai); 43a0b03a61SMark Brown if (ret == 0) { 44a0b03a61SMark Brown *ptr = dev; 45a0b03a61SMark Brown devres_add(dev, ptr); 46a0b03a61SMark Brown } else { 47a0b03a61SMark Brown devres_free(ptr); 48a0b03a61SMark Brown } 49a0b03a61SMark Brown 50a0b03a61SMark Brown return ret; 51a0b03a61SMark Brown } 52a0b03a61SMark Brown EXPORT_SYMBOL_GPL(devm_snd_soc_register_component); 530e4ff5c8SMark Brown 540e4ff5c8SMark Brown static void devm_card_release(struct device *dev, void *res) 550e4ff5c8SMark Brown { 560e4ff5c8SMark Brown snd_soc_unregister_card(*(struct snd_soc_card **)res); 570e4ff5c8SMark Brown } 580e4ff5c8SMark Brown 590e4ff5c8SMark Brown /** 600e4ff5c8SMark Brown * devm_snd_soc_register_card - resource managed card registration 610e4ff5c8SMark Brown * @dev: Device used to manage card 620e4ff5c8SMark Brown * @card: Card to register 630e4ff5c8SMark Brown * 640e4ff5c8SMark Brown * Register a card with automatic unregistration when the device is 650e4ff5c8SMark Brown * unregistered. 660e4ff5c8SMark Brown */ 670e4ff5c8SMark Brown int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) 680e4ff5c8SMark Brown { 69*ebff6547SShawn Guo struct snd_soc_card **ptr; 700e4ff5c8SMark Brown int ret; 710e4ff5c8SMark Brown 720e4ff5c8SMark Brown ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL); 730e4ff5c8SMark Brown if (!ptr) 740e4ff5c8SMark Brown return -ENOMEM; 750e4ff5c8SMark Brown 760e4ff5c8SMark Brown ret = snd_soc_register_card(card); 770e4ff5c8SMark Brown if (ret == 0) { 78*ebff6547SShawn Guo *ptr = card; 790e4ff5c8SMark Brown devres_add(dev, ptr); 800e4ff5c8SMark Brown } else { 810e4ff5c8SMark Brown devres_free(ptr); 820e4ff5c8SMark Brown } 830e4ff5c8SMark Brown 840e4ff5c8SMark Brown return ret; 850e4ff5c8SMark Brown } 860e4ff5c8SMark Brown EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); 87