162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// soc-devres.c -- ALSA SoC Audio Layer devres functions 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (C) 2013 Linaro Ltd 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/module.h> 862306a36Sopenharmony_ci#include <linux/moduleparam.h> 962306a36Sopenharmony_ci#include <sound/soc.h> 1062306a36Sopenharmony_ci#include <sound/dmaengine_pcm.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistatic void devm_dai_release(struct device *dev, void *res) 1362306a36Sopenharmony_ci{ 1462306a36Sopenharmony_ci snd_soc_unregister_dai(*(struct snd_soc_dai **)res); 1562306a36Sopenharmony_ci} 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/** 1862306a36Sopenharmony_ci * devm_snd_soc_register_dai - resource-managed dai registration 1962306a36Sopenharmony_ci * @dev: Device used to manage component 2062306a36Sopenharmony_ci * @component: The component the DAIs are registered for 2162306a36Sopenharmony_ci * @dai_drv: DAI driver to use for the DAI 2262306a36Sopenharmony_ci * @legacy_dai_naming: if %true, use legacy single-name format; 2362306a36Sopenharmony_ci * if %false, use multiple-name format; 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_cistruct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev, 2662306a36Sopenharmony_ci struct snd_soc_component *component, 2762306a36Sopenharmony_ci struct snd_soc_dai_driver *dai_drv, 2862306a36Sopenharmony_ci bool legacy_dai_naming) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci struct snd_soc_dai **ptr; 3162306a36Sopenharmony_ci struct snd_soc_dai *dai; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL); 3462306a36Sopenharmony_ci if (!ptr) 3562306a36Sopenharmony_ci return NULL; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming); 3862306a36Sopenharmony_ci if (dai) { 3962306a36Sopenharmony_ci *ptr = dai; 4062306a36Sopenharmony_ci devres_add(dev, ptr); 4162306a36Sopenharmony_ci } else { 4262306a36Sopenharmony_ci devres_free(ptr); 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci return dai; 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_snd_soc_register_dai); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic void devm_component_release(struct device *dev, void *res) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci const struct snd_soc_component_driver **cmpnt_drv = res; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci snd_soc_unregister_component_by_driver(dev, *cmpnt_drv); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/** 5762306a36Sopenharmony_ci * devm_snd_soc_register_component - resource managed component registration 5862306a36Sopenharmony_ci * @dev: Device used to manage component 5962306a36Sopenharmony_ci * @cmpnt_drv: Component driver 6062306a36Sopenharmony_ci * @dai_drv: DAI driver 6162306a36Sopenharmony_ci * @num_dai: Number of DAIs to register 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * Register a component with automatic unregistration when the device is 6462306a36Sopenharmony_ci * unregistered. 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_ciint devm_snd_soc_register_component(struct device *dev, 6762306a36Sopenharmony_ci const struct snd_soc_component_driver *cmpnt_drv, 6862306a36Sopenharmony_ci struct snd_soc_dai_driver *dai_drv, int num_dai) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci const struct snd_soc_component_driver **ptr; 7162306a36Sopenharmony_ci int ret; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL); 7462306a36Sopenharmony_ci if (!ptr) 7562306a36Sopenharmony_ci return -ENOMEM; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai); 7862306a36Sopenharmony_ci if (ret == 0) { 7962306a36Sopenharmony_ci *ptr = cmpnt_drv; 8062306a36Sopenharmony_ci devres_add(dev, ptr); 8162306a36Sopenharmony_ci } else { 8262306a36Sopenharmony_ci devres_free(ptr); 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci return ret; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_snd_soc_register_component); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic void devm_card_release(struct device *dev, void *res) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci snd_soc_unregister_card(*(struct snd_soc_card **)res); 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/** 9562306a36Sopenharmony_ci * devm_snd_soc_register_card - resource managed card registration 9662306a36Sopenharmony_ci * @dev: Device used to manage card 9762306a36Sopenharmony_ci * @card: Card to register 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * Register a card with automatic unregistration when the device is 10062306a36Sopenharmony_ci * unregistered. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ciint devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci struct snd_soc_card **ptr; 10562306a36Sopenharmony_ci int ret; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL); 10862306a36Sopenharmony_ci if (!ptr) 10962306a36Sopenharmony_ci return -ENOMEM; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci ret = snd_soc_register_card(card); 11262306a36Sopenharmony_ci if (ret == 0) { 11362306a36Sopenharmony_ci *ptr = card; 11462306a36Sopenharmony_ci devres_add(dev, ptr); 11562306a36Sopenharmony_ci } else { 11662306a36Sopenharmony_ci devres_free(ptr); 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci return ret; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_snd_soc_register_card); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic void devm_dmaengine_pcm_release(struct device *dev, void *res) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci snd_dmaengine_pcm_unregister(*(struct device **)res); 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/** 13162306a36Sopenharmony_ci * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration 13262306a36Sopenharmony_ci * @dev: The parent device for the PCM device 13362306a36Sopenharmony_ci * @config: Platform specific PCM configuration 13462306a36Sopenharmony_ci * @flags: Platform specific quirks 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * Register a dmaengine based PCM device with automatic unregistration when the 13762306a36Sopenharmony_ci * device is unregistered. 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_ciint devm_snd_dmaengine_pcm_register(struct device *dev, 14062306a36Sopenharmony_ci const struct snd_dmaengine_pcm_config *config, unsigned int flags) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci struct device **ptr; 14362306a36Sopenharmony_ci int ret; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL); 14662306a36Sopenharmony_ci if (!ptr) 14762306a36Sopenharmony_ci return -ENOMEM; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci ret = snd_dmaengine_pcm_register(dev, config, flags); 15062306a36Sopenharmony_ci if (ret == 0) { 15162306a36Sopenharmony_ci *ptr = dev; 15262306a36Sopenharmony_ci devres_add(dev, ptr); 15362306a36Sopenharmony_ci } else { 15462306a36Sopenharmony_ci devres_free(ptr); 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci return ret; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci#endif 162