14ff1fef1SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0 24ff1fef1SKuninori Morimoto // 34ff1fef1SKuninori Morimoto // soc-component.c 44ff1fef1SKuninori Morimoto // 5460b42d1SKuninori Morimoto // Copyright 2009-2011 Wolfson Microelectronics PLC. 64ff1fef1SKuninori Morimoto // Copyright (C) 2019 Renesas Electronics Corp. 7460b42d1SKuninori Morimoto // 8460b42d1SKuninori Morimoto // Mark Brown <broonie@opensource.wolfsonmicro.com> 94ff1fef1SKuninori Morimoto // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 104ff1fef1SKuninori Morimoto // 114a81e8f3SKuninori Morimoto #include <linux/module.h> 124ff1fef1SKuninori Morimoto #include <sound/soc.h> 134ff1fef1SKuninori Morimoto 14e2329eebSKuninori Morimoto #define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret) 15e2329eebSKuninori Morimoto static inline int _soc_component_ret(struct snd_soc_component *component, 16e2329eebSKuninori Morimoto const char *func, int ret) 17e2329eebSKuninori Morimoto { 18e2329eebSKuninori Morimoto /* Positive/Zero values are not errors */ 19e2329eebSKuninori Morimoto if (ret >= 0) 20e2329eebSKuninori Morimoto return ret; 21e2329eebSKuninori Morimoto 22e2329eebSKuninori Morimoto /* Negative values might be errors */ 23e2329eebSKuninori Morimoto switch (ret) { 24e2329eebSKuninori Morimoto case -EPROBE_DEFER: 25e2329eebSKuninori Morimoto case -ENOTSUPP: 26e2329eebSKuninori Morimoto break; 27e2329eebSKuninori Morimoto default: 28e2329eebSKuninori Morimoto dev_err(component->dev, 29e2329eebSKuninori Morimoto "ASoC: error at %s on %s: %d\n", 30e2329eebSKuninori Morimoto func, component->name, ret); 31e2329eebSKuninori Morimoto } 32e2329eebSKuninori Morimoto 33e2329eebSKuninori Morimoto return ret; 34e2329eebSKuninori Morimoto } 35e2329eebSKuninori Morimoto 36536aba1dSKuninori Morimoto int snd_soc_component_initialize(struct snd_soc_component *component, 37536aba1dSKuninori Morimoto const struct snd_soc_component_driver *driver, 38536aba1dSKuninori Morimoto struct device *dev, const char *name) 39536aba1dSKuninori Morimoto { 40536aba1dSKuninori Morimoto INIT_LIST_HEAD(&component->dai_list); 41536aba1dSKuninori Morimoto INIT_LIST_HEAD(&component->dobj_list); 42536aba1dSKuninori Morimoto INIT_LIST_HEAD(&component->card_list); 43536aba1dSKuninori Morimoto mutex_init(&component->io_mutex); 44536aba1dSKuninori Morimoto 45536aba1dSKuninori Morimoto component->name = name; 46536aba1dSKuninori Morimoto component->dev = dev; 47536aba1dSKuninori Morimoto component->driver = driver; 48536aba1dSKuninori Morimoto 49536aba1dSKuninori Morimoto return 0; 50536aba1dSKuninori Morimoto } 51536aba1dSKuninori Morimoto 52257c4dacSKuninori Morimoto void snd_soc_component_set_aux(struct snd_soc_component *component, 53257c4dacSKuninori Morimoto struct snd_soc_aux_dev *aux) 54257c4dacSKuninori Morimoto { 55257c4dacSKuninori Morimoto component->init = (aux) ? aux->init : NULL; 56257c4dacSKuninori Morimoto } 57257c4dacSKuninori Morimoto 58257c4dacSKuninori Morimoto int snd_soc_component_init(struct snd_soc_component *component) 59257c4dacSKuninori Morimoto { 60257c4dacSKuninori Morimoto int ret = 0; 61257c4dacSKuninori Morimoto 62257c4dacSKuninori Morimoto if (component->init) 63257c4dacSKuninori Morimoto ret = component->init(component); 64257c4dacSKuninori Morimoto 65257c4dacSKuninori Morimoto return soc_component_ret(component, ret); 66257c4dacSKuninori Morimoto } 67257c4dacSKuninori Morimoto 684ff1fef1SKuninori Morimoto /** 694ff1fef1SKuninori Morimoto * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. 704ff1fef1SKuninori Morimoto * @component: COMPONENT 714ff1fef1SKuninori Morimoto * @clk_id: DAI specific clock ID 724ff1fef1SKuninori Morimoto * @source: Source for the clock 734ff1fef1SKuninori Morimoto * @freq: new clock frequency in Hz 744ff1fef1SKuninori Morimoto * @dir: new clock direction - input/output. 754ff1fef1SKuninori Morimoto * 764ff1fef1SKuninori Morimoto * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. 774ff1fef1SKuninori Morimoto */ 784ff1fef1SKuninori Morimoto int snd_soc_component_set_sysclk(struct snd_soc_component *component, 794ff1fef1SKuninori Morimoto int clk_id, int source, unsigned int freq, 804ff1fef1SKuninori Morimoto int dir) 814ff1fef1SKuninori Morimoto { 82e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 83e2329eebSKuninori Morimoto 844ff1fef1SKuninori Morimoto if (component->driver->set_sysclk) 85e2329eebSKuninori Morimoto ret = component->driver->set_sysclk(component, clk_id, source, 864ff1fef1SKuninori Morimoto freq, dir); 874ff1fef1SKuninori Morimoto 88e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 894ff1fef1SKuninori Morimoto } 904ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); 914ff1fef1SKuninori Morimoto 924ff1fef1SKuninori Morimoto /* 934ff1fef1SKuninori Morimoto * snd_soc_component_set_pll - configure component PLL. 944ff1fef1SKuninori Morimoto * @component: COMPONENT 954ff1fef1SKuninori Morimoto * @pll_id: DAI specific PLL ID 964ff1fef1SKuninori Morimoto * @source: DAI specific source for the PLL 974ff1fef1SKuninori Morimoto * @freq_in: PLL input clock frequency in Hz 984ff1fef1SKuninori Morimoto * @freq_out: requested PLL output clock frequency in Hz 994ff1fef1SKuninori Morimoto * 1004ff1fef1SKuninori Morimoto * Configures and enables PLL to generate output clock based on input clock. 1014ff1fef1SKuninori Morimoto */ 1024ff1fef1SKuninori Morimoto int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, 1034ff1fef1SKuninori Morimoto int source, unsigned int freq_in, 1044ff1fef1SKuninori Morimoto unsigned int freq_out) 1054ff1fef1SKuninori Morimoto { 106e2329eebSKuninori Morimoto int ret = -EINVAL; 107e2329eebSKuninori Morimoto 1084ff1fef1SKuninori Morimoto if (component->driver->set_pll) 109e2329eebSKuninori Morimoto ret = component->driver->set_pll(component, pll_id, source, 1104ff1fef1SKuninori Morimoto freq_in, freq_out); 1114ff1fef1SKuninori Morimoto 112e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1134ff1fef1SKuninori Morimoto } 1144ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); 1154ff1fef1SKuninori Morimoto 1169d415fbfSKuninori Morimoto void snd_soc_component_seq_notifier(struct snd_soc_component *component, 1179d415fbfSKuninori Morimoto enum snd_soc_dapm_type type, int subseq) 1189d415fbfSKuninori Morimoto { 1199d415fbfSKuninori Morimoto if (component->driver->seq_notifier) 1209d415fbfSKuninori Morimoto component->driver->seq_notifier(component, type, subseq); 1219d415fbfSKuninori Morimoto } 1229d415fbfSKuninori Morimoto 1238e2a990dSKuninori Morimoto int snd_soc_component_stream_event(struct snd_soc_component *component, 1248e2a990dSKuninori Morimoto int event) 1258e2a990dSKuninori Morimoto { 126e2329eebSKuninori Morimoto int ret = 0; 1278e2a990dSKuninori Morimoto 128e2329eebSKuninori Morimoto if (component->driver->stream_event) 129e2329eebSKuninori Morimoto ret = component->driver->stream_event(component, event); 130e2329eebSKuninori Morimoto 131e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1328e2a990dSKuninori Morimoto } 1338e2a990dSKuninori Morimoto 1347951b146SKuninori Morimoto int snd_soc_component_set_bias_level(struct snd_soc_component *component, 1357951b146SKuninori Morimoto enum snd_soc_bias_level level) 1367951b146SKuninori Morimoto { 137e2329eebSKuninori Morimoto int ret = 0; 1387951b146SKuninori Morimoto 139e2329eebSKuninori Morimoto if (component->driver->set_bias_level) 140e2329eebSKuninori Morimoto ret = component->driver->set_bias_level(component, level); 141e2329eebSKuninori Morimoto 142e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1437951b146SKuninori Morimoto } 1447951b146SKuninori Morimoto 1454ca8701eSKuninori Morimoto static int soc_component_pin(struct snd_soc_component *component, 1464ca8701eSKuninori Morimoto const char *pin, 1474ca8701eSKuninori Morimoto int (*pin_func)(struct snd_soc_dapm_context *dapm, 1484ca8701eSKuninori Morimoto const char *pin)) 1494ff1fef1SKuninori Morimoto { 1504ff1fef1SKuninori Morimoto struct snd_soc_dapm_context *dapm = 1514ff1fef1SKuninori Morimoto snd_soc_component_get_dapm(component); 1524ff1fef1SKuninori Morimoto char *full_name; 1534ff1fef1SKuninori Morimoto int ret; 1544ff1fef1SKuninori Morimoto 155e2329eebSKuninori Morimoto if (!component->name_prefix) { 156e2329eebSKuninori Morimoto ret = pin_func(dapm, pin); 157e2329eebSKuninori Morimoto goto end; 158e2329eebSKuninori Morimoto } 1594ff1fef1SKuninori Morimoto 1604ff1fef1SKuninori Morimoto full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); 161e2329eebSKuninori Morimoto if (!full_name) { 162e2329eebSKuninori Morimoto ret = -ENOMEM; 163e2329eebSKuninori Morimoto goto end; 164e2329eebSKuninori Morimoto } 1654ff1fef1SKuninori Morimoto 1664ca8701eSKuninori Morimoto ret = pin_func(dapm, full_name); 1674ff1fef1SKuninori Morimoto kfree(full_name); 168e2329eebSKuninori Morimoto end: 169e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1704ff1fef1SKuninori Morimoto } 1714ca8701eSKuninori Morimoto 1724ca8701eSKuninori Morimoto int snd_soc_component_enable_pin(struct snd_soc_component *component, 1734ca8701eSKuninori Morimoto const char *pin) 1744ca8701eSKuninori Morimoto { 1754ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_enable_pin); 1764ca8701eSKuninori Morimoto } 1774ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); 1784ff1fef1SKuninori Morimoto 1794ff1fef1SKuninori Morimoto int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, 1804ff1fef1SKuninori Morimoto const char *pin) 1814ff1fef1SKuninori Morimoto { 1824ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked); 1834ff1fef1SKuninori Morimoto } 1844ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); 1854ff1fef1SKuninori Morimoto 1864ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin(struct snd_soc_component *component, 1874ff1fef1SKuninori Morimoto const char *pin) 1884ff1fef1SKuninori Morimoto { 1894ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_disable_pin); 1904ff1fef1SKuninori Morimoto } 1914ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); 1924ff1fef1SKuninori Morimoto 1934ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, 1944ff1fef1SKuninori Morimoto const char *pin) 1954ff1fef1SKuninori Morimoto { 1964ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked); 1974ff1fef1SKuninori Morimoto } 1984ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); 1994ff1fef1SKuninori Morimoto 2004ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin(struct snd_soc_component *component, 2014ff1fef1SKuninori Morimoto const char *pin) 2024ff1fef1SKuninori Morimoto { 2034ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_nc_pin); 2044ff1fef1SKuninori Morimoto } 2054ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); 2064ff1fef1SKuninori Morimoto 2074ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, 2084ff1fef1SKuninori Morimoto const char *pin) 2094ff1fef1SKuninori Morimoto { 2104ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked); 2114ff1fef1SKuninori Morimoto } 2124ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); 2134ff1fef1SKuninori Morimoto 2144ff1fef1SKuninori Morimoto int snd_soc_component_get_pin_status(struct snd_soc_component *component, 2154ff1fef1SKuninori Morimoto const char *pin) 2164ff1fef1SKuninori Morimoto { 2174ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status); 2184ff1fef1SKuninori Morimoto } 2194ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); 2204ff1fef1SKuninori Morimoto 2214ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin(struct snd_soc_component *component, 2224ff1fef1SKuninori Morimoto const char *pin) 2234ff1fef1SKuninori Morimoto { 2244ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin); 2254ff1fef1SKuninori Morimoto } 2264ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); 2274ff1fef1SKuninori Morimoto 2284ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin_unlocked( 2294ff1fef1SKuninori Morimoto struct snd_soc_component *component, 2304ff1fef1SKuninori Morimoto const char *pin) 2314ff1fef1SKuninori Morimoto { 2324ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked); 2334ff1fef1SKuninori Morimoto } 2344ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); 2354ff1fef1SKuninori Morimoto 2364ff1fef1SKuninori Morimoto /** 2374ff1fef1SKuninori Morimoto * snd_soc_component_set_jack - configure component jack. 2384ff1fef1SKuninori Morimoto * @component: COMPONENTs 2394ff1fef1SKuninori Morimoto * @jack: structure to use for the jack 2404ff1fef1SKuninori Morimoto * @data: can be used if codec driver need extra data for configuring jack 2414ff1fef1SKuninori Morimoto * 2424ff1fef1SKuninori Morimoto * Configures and enables jack detection function. 2434ff1fef1SKuninori Morimoto */ 2444ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component, 2454ff1fef1SKuninori Morimoto struct snd_soc_jack *jack, void *data) 2464ff1fef1SKuninori Morimoto { 247e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 2484ff1fef1SKuninori Morimoto 249e2329eebSKuninori Morimoto if (component->driver->set_jack) 250e2329eebSKuninori Morimoto ret = component->driver->set_jack(component, jack, data); 251e2329eebSKuninori Morimoto 252e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2534ff1fef1SKuninori Morimoto } 2544ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); 2554a81e8f3SKuninori Morimoto 2564a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component, 2574a81e8f3SKuninori Morimoto int upon_open) 2584a81e8f3SKuninori Morimoto { 259e2329eebSKuninori Morimoto int ret = 0; 260e2329eebSKuninori Morimoto 2614a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open && 2624a81e8f3SKuninori Morimoto !try_module_get(component->dev->driver->owner)) 263e2329eebSKuninori Morimoto ret = -ENODEV; 2644a81e8f3SKuninori Morimoto 265e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2664a81e8f3SKuninori Morimoto } 2674a81e8f3SKuninori Morimoto 2684a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component, 2694a81e8f3SKuninori Morimoto int upon_open) 2704a81e8f3SKuninori Morimoto { 2714a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open) 2724a81e8f3SKuninori Morimoto module_put(component->dev->driver->owner); 2734a81e8f3SKuninori Morimoto } 274ae2f4849SKuninori Morimoto 275ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component, 276ae2f4849SKuninori Morimoto struct snd_pcm_substream *substream) 277ae2f4849SKuninori Morimoto { 278e2329eebSKuninori Morimoto int ret = 0; 279e2329eebSKuninori Morimoto 280e2cb4a14SKuninori Morimoto if (component->driver->open) 281e2329eebSKuninori Morimoto ret = component->driver->open(component, substream); 282e2329eebSKuninori Morimoto 283e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 284ae2f4849SKuninori Morimoto } 2853672beb8SKuninori Morimoto 2863672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component, 2873672beb8SKuninori Morimoto struct snd_pcm_substream *substream) 2883672beb8SKuninori Morimoto { 289e2329eebSKuninori Morimoto int ret = 0; 290e2329eebSKuninori Morimoto 291e2cb4a14SKuninori Morimoto if (component->driver->close) 292e2329eebSKuninori Morimoto ret = component->driver->close(component, substream); 293e2329eebSKuninori Morimoto 294e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2953672beb8SKuninori Morimoto } 2966d537233SKuninori Morimoto 29766c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component) 29866c51573SKuninori Morimoto { 29966c51573SKuninori Morimoto if (component->driver->suspend) 30066c51573SKuninori Morimoto component->driver->suspend(component); 30166c51573SKuninori Morimoto component->suspended = 1; 30266c51573SKuninori Morimoto } 3039a840cbaSKuninori Morimoto 3049a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component) 3059a840cbaSKuninori Morimoto { 3069a840cbaSKuninori Morimoto if (component->driver->resume) 3079a840cbaSKuninori Morimoto component->driver->resume(component); 3089a840cbaSKuninori Morimoto component->suspended = 0; 3099a840cbaSKuninori Morimoto } 310e40fadbcSKuninori Morimoto 311e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component) 312e40fadbcSKuninori Morimoto { 313e40fadbcSKuninori Morimoto return component->suspended; 314e40fadbcSKuninori Morimoto } 31508e837ddSKuninori Morimoto 31608e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component) 31708e837ddSKuninori Morimoto { 318e2329eebSKuninori Morimoto int ret = 0; 31908e837ddSKuninori Morimoto 320e2329eebSKuninori Morimoto if (component->driver->probe) 321e2329eebSKuninori Morimoto ret = component->driver->probe(component); 322e2329eebSKuninori Morimoto 323e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 32408e837ddSKuninori Morimoto } 32503b34dd7SKuninori Morimoto 32603b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component) 32703b34dd7SKuninori Morimoto { 32803b34dd7SKuninori Morimoto if (component->driver->remove) 32903b34dd7SKuninori Morimoto component->driver->remove(component); 33003b34dd7SKuninori Morimoto } 3312c7b1704SKuninori Morimoto 3322c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, 3332c7b1704SKuninori Morimoto struct device_node *ep) 3342c7b1704SKuninori Morimoto { 335e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 3362c7b1704SKuninori Morimoto 337e2329eebSKuninori Morimoto if (component->driver->of_xlate_dai_id) 338e2329eebSKuninori Morimoto ret = component->driver->of_xlate_dai_id(component, ep); 339e2329eebSKuninori Morimoto 340e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 3412c7b1704SKuninori Morimoto } 342a2a34175SKuninori Morimoto 343a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, 344a2a34175SKuninori Morimoto struct of_phandle_args *args, 345a2a34175SKuninori Morimoto const char **dai_name) 346a2a34175SKuninori Morimoto { 347a2a34175SKuninori Morimoto if (component->driver->of_xlate_dai_name) 348cc4d8cebSJerome Brunet return component->driver->of_xlate_dai_name(component, 349a2a34175SKuninori Morimoto args, dai_name); 350cc4d8cebSJerome Brunet /* 351cc4d8cebSJerome Brunet * Don't use soc_component_ret here because we may not want to report 352cc4d8cebSJerome Brunet * the error just yet. If a device has more than one component, the 353cc4d8cebSJerome Brunet * first may not match and we don't want spam the log with this. 354cc4d8cebSJerome Brunet */ 355cc4d8cebSJerome Brunet return -ENOTSUPP; 356a2a34175SKuninori Morimoto } 3570035e256SKuninori Morimoto 358c7d75b59SKuninori Morimoto void snd_soc_component_setup_regmap(struct snd_soc_component *component) 359c7d75b59SKuninori Morimoto { 360c7d75b59SKuninori Morimoto int val_bytes = regmap_get_val_bytes(component->regmap); 361c7d75b59SKuninori Morimoto 362c7d75b59SKuninori Morimoto /* Errors are legitimate for non-integer byte multiples */ 363c7d75b59SKuninori Morimoto if (val_bytes > 0) 364c7d75b59SKuninori Morimoto component->val_bytes = val_bytes; 365c7d75b59SKuninori Morimoto } 366c7d75b59SKuninori Morimoto 367c7d75b59SKuninori Morimoto #ifdef CONFIG_REGMAP 368c7d75b59SKuninori Morimoto 369c7d75b59SKuninori Morimoto /** 370c7d75b59SKuninori Morimoto * snd_soc_component_init_regmap() - Initialize regmap instance for the 371c7d75b59SKuninori Morimoto * component 372c7d75b59SKuninori Morimoto * @component: The component for which to initialize the regmap instance 373c7d75b59SKuninori Morimoto * @regmap: The regmap instance that should be used by the component 374c7d75b59SKuninori Morimoto * 375c7d75b59SKuninori Morimoto * This function allows deferred assignment of the regmap instance that is 376c7d75b59SKuninori Morimoto * associated with the component. Only use this if the regmap instance is not 377c7d75b59SKuninori Morimoto * yet ready when the component is registered. The function must also be called 378c7d75b59SKuninori Morimoto * before the first IO attempt of the component. 379c7d75b59SKuninori Morimoto */ 380c7d75b59SKuninori Morimoto void snd_soc_component_init_regmap(struct snd_soc_component *component, 381c7d75b59SKuninori Morimoto struct regmap *regmap) 382c7d75b59SKuninori Morimoto { 383c7d75b59SKuninori Morimoto component->regmap = regmap; 384c7d75b59SKuninori Morimoto snd_soc_component_setup_regmap(component); 385c7d75b59SKuninori Morimoto } 386c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); 387c7d75b59SKuninori Morimoto 388c7d75b59SKuninori Morimoto /** 389c7d75b59SKuninori Morimoto * snd_soc_component_exit_regmap() - De-initialize regmap instance for the 390c7d75b59SKuninori Morimoto * component 391c7d75b59SKuninori Morimoto * @component: The component for which to de-initialize the regmap instance 392c7d75b59SKuninori Morimoto * 393c7d75b59SKuninori Morimoto * Calls regmap_exit() on the regmap instance associated to the component and 394c7d75b59SKuninori Morimoto * removes the regmap instance from the component. 395c7d75b59SKuninori Morimoto * 396c7d75b59SKuninori Morimoto * This function should only be used if snd_soc_component_init_regmap() was used 397c7d75b59SKuninori Morimoto * to initialize the regmap instance. 398c7d75b59SKuninori Morimoto */ 399c7d75b59SKuninori Morimoto void snd_soc_component_exit_regmap(struct snd_soc_component *component) 400c7d75b59SKuninori Morimoto { 401c7d75b59SKuninori Morimoto regmap_exit(component->regmap); 402c7d75b59SKuninori Morimoto component->regmap = NULL; 403c7d75b59SKuninori Morimoto } 404c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); 405c7d75b59SKuninori Morimoto 406c7d75b59SKuninori Morimoto #endif 407c7d75b59SKuninori Morimoto 408e8712315SKuninori Morimoto static unsigned int soc_component_read_no_lock( 409e8712315SKuninori Morimoto struct snd_soc_component *component, 410cf6e26c7SKuninori Morimoto unsigned int reg) 411460b42d1SKuninori Morimoto { 412460b42d1SKuninori Morimoto int ret; 413cf6e26c7SKuninori Morimoto unsigned int val = 0; 414460b42d1SKuninori Morimoto 415460b42d1SKuninori Morimoto if (component->regmap) 416cf6e26c7SKuninori Morimoto ret = regmap_read(component->regmap, reg, &val); 417460b42d1SKuninori Morimoto else if (component->driver->read) { 418460b42d1SKuninori Morimoto ret = 0; 419cf6e26c7SKuninori Morimoto val = component->driver->read(component, reg); 420460b42d1SKuninori Morimoto } 421460b42d1SKuninori Morimoto else 422460b42d1SKuninori Morimoto ret = -EIO; 423460b42d1SKuninori Morimoto 424460b42d1SKuninori Morimoto if (ret < 0) 425cf6e26c7SKuninori Morimoto soc_component_ret(component, ret); 426460b42d1SKuninori Morimoto 427460b42d1SKuninori Morimoto return val; 428460b42d1SKuninori Morimoto } 429e8712315SKuninori Morimoto 430e8712315SKuninori Morimoto /** 431e8712315SKuninori Morimoto * snd_soc_component_read() - Read register value 432e8712315SKuninori Morimoto * @component: Component to read from 433e8712315SKuninori Morimoto * @reg: Register to read 434e8712315SKuninori Morimoto * 435e8712315SKuninori Morimoto * Return: read value 436e8712315SKuninori Morimoto */ 437e8712315SKuninori Morimoto unsigned int snd_soc_component_read(struct snd_soc_component *component, 438e8712315SKuninori Morimoto unsigned int reg) 439e8712315SKuninori Morimoto { 440e8712315SKuninori Morimoto unsigned int val; 441e8712315SKuninori Morimoto 442e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 443e8712315SKuninori Morimoto val = soc_component_read_no_lock(component, reg); 444e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 445e8712315SKuninori Morimoto 446e8712315SKuninori Morimoto return val; 447e8712315SKuninori Morimoto } 448cf6e26c7SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_read); 449460b42d1SKuninori Morimoto 450e8712315SKuninori Morimoto static int soc_component_write_no_lock( 451e8712315SKuninori Morimoto struct snd_soc_component *component, 452e8712315SKuninori Morimoto unsigned int reg, unsigned int val) 453e8712315SKuninori Morimoto { 454e8712315SKuninori Morimoto int ret = -EIO; 455e8712315SKuninori Morimoto 456e8712315SKuninori Morimoto if (component->regmap) 457e8712315SKuninori Morimoto ret = regmap_write(component->regmap, reg, val); 458e8712315SKuninori Morimoto else if (component->driver->write) 459e8712315SKuninori Morimoto ret = component->driver->write(component, reg, val); 460e8712315SKuninori Morimoto 461e8712315SKuninori Morimoto return soc_component_ret(component, ret); 462e8712315SKuninori Morimoto } 463e8712315SKuninori Morimoto 464460b42d1SKuninori Morimoto /** 465460b42d1SKuninori Morimoto * snd_soc_component_write() - Write register value 466460b42d1SKuninori Morimoto * @component: Component to write to 467460b42d1SKuninori Morimoto * @reg: Register to write 468460b42d1SKuninori Morimoto * @val: Value to write to the register 469460b42d1SKuninori Morimoto * 470460b42d1SKuninori Morimoto * Return: 0 on success, a negative error code otherwise. 471460b42d1SKuninori Morimoto */ 472460b42d1SKuninori Morimoto int snd_soc_component_write(struct snd_soc_component *component, 473460b42d1SKuninori Morimoto unsigned int reg, unsigned int val) 474460b42d1SKuninori Morimoto { 475e8712315SKuninori Morimoto int ret; 476460b42d1SKuninori Morimoto 477e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 478e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, val); 479e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 480460b42d1SKuninori Morimoto 481e8712315SKuninori Morimoto return ret; 482460b42d1SKuninori Morimoto } 483460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_write); 484460b42d1SKuninori Morimoto 485460b42d1SKuninori Morimoto static int snd_soc_component_update_bits_legacy( 486460b42d1SKuninori Morimoto struct snd_soc_component *component, unsigned int reg, 487460b42d1SKuninori Morimoto unsigned int mask, unsigned int val, bool *change) 488460b42d1SKuninori Morimoto { 489460b42d1SKuninori Morimoto unsigned int old, new; 490cf6e26c7SKuninori Morimoto int ret = 0; 491460b42d1SKuninori Morimoto 492460b42d1SKuninori Morimoto mutex_lock(&component->io_mutex); 493460b42d1SKuninori Morimoto 494e8712315SKuninori Morimoto old = soc_component_read_no_lock(component, reg); 495460b42d1SKuninori Morimoto 496460b42d1SKuninori Morimoto new = (old & ~mask) | (val & mask); 497460b42d1SKuninori Morimoto *change = old != new; 498460b42d1SKuninori Morimoto if (*change) 499e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, new); 500cf6e26c7SKuninori Morimoto 501460b42d1SKuninori Morimoto mutex_unlock(&component->io_mutex); 502460b42d1SKuninori Morimoto 503460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 504460b42d1SKuninori Morimoto } 505460b42d1SKuninori Morimoto 506460b42d1SKuninori Morimoto /** 507460b42d1SKuninori Morimoto * snd_soc_component_update_bits() - Perform read/modify/write cycle 508460b42d1SKuninori Morimoto * @component: Component to update 509460b42d1SKuninori Morimoto * @reg: Register to update 510460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 511460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 512460b42d1SKuninori Morimoto * 513460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 514460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 515460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 516460b42d1SKuninori Morimoto */ 517460b42d1SKuninori Morimoto int snd_soc_component_update_bits(struct snd_soc_component *component, 518460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 519460b42d1SKuninori Morimoto { 520460b42d1SKuninori Morimoto bool change; 521460b42d1SKuninori Morimoto int ret; 522460b42d1SKuninori Morimoto 523460b42d1SKuninori Morimoto if (component->regmap) 524460b42d1SKuninori Morimoto ret = regmap_update_bits_check(component->regmap, reg, mask, 525460b42d1SKuninori Morimoto val, &change); 526460b42d1SKuninori Morimoto else 527460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 528460b42d1SKuninori Morimoto mask, val, &change); 529460b42d1SKuninori Morimoto 530460b42d1SKuninori Morimoto if (ret < 0) 531460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 532460b42d1SKuninori Morimoto return change; 533460b42d1SKuninori Morimoto } 534460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); 535460b42d1SKuninori Morimoto 536460b42d1SKuninori Morimoto /** 537460b42d1SKuninori Morimoto * snd_soc_component_update_bits_async() - Perform asynchronous 538460b42d1SKuninori Morimoto * read/modify/write cycle 539460b42d1SKuninori Morimoto * @component: Component to update 540460b42d1SKuninori Morimoto * @reg: Register to update 541460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 542460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 543460b42d1SKuninori Morimoto * 544460b42d1SKuninori Morimoto * This function is similar to snd_soc_component_update_bits(), but the update 545460b42d1SKuninori Morimoto * operation is scheduled asynchronously. This means it may not be completed 546460b42d1SKuninori Morimoto * when the function returns. To make sure that all scheduled updates have been 547460b42d1SKuninori Morimoto * completed snd_soc_component_async_complete() must be called. 548460b42d1SKuninori Morimoto * 549460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 550460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 551460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 552460b42d1SKuninori Morimoto */ 553460b42d1SKuninori Morimoto int snd_soc_component_update_bits_async(struct snd_soc_component *component, 554460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 555460b42d1SKuninori Morimoto { 556460b42d1SKuninori Morimoto bool change; 557460b42d1SKuninori Morimoto int ret; 558460b42d1SKuninori Morimoto 559460b42d1SKuninori Morimoto if (component->regmap) 560460b42d1SKuninori Morimoto ret = regmap_update_bits_check_async(component->regmap, reg, 561460b42d1SKuninori Morimoto mask, val, &change); 562460b42d1SKuninori Morimoto else 563460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 564460b42d1SKuninori Morimoto mask, val, &change); 565460b42d1SKuninori Morimoto 566460b42d1SKuninori Morimoto if (ret < 0) 567460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 568460b42d1SKuninori Morimoto return change; 569460b42d1SKuninori Morimoto } 570460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); 571460b42d1SKuninori Morimoto 572460b42d1SKuninori Morimoto /** 573460b42d1SKuninori Morimoto * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed 574460b42d1SKuninori Morimoto * @component: Component for which to wait 575460b42d1SKuninori Morimoto * 576460b42d1SKuninori Morimoto * This function blocks until all asynchronous I/O which has previously been 577460b42d1SKuninori Morimoto * scheduled using snd_soc_component_update_bits_async() has completed. 578460b42d1SKuninori Morimoto */ 579460b42d1SKuninori Morimoto void snd_soc_component_async_complete(struct snd_soc_component *component) 580460b42d1SKuninori Morimoto { 581460b42d1SKuninori Morimoto if (component->regmap) 582460b42d1SKuninori Morimoto regmap_async_complete(component->regmap); 583460b42d1SKuninori Morimoto } 584460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); 585460b42d1SKuninori Morimoto 586460b42d1SKuninori Morimoto /** 587460b42d1SKuninori Morimoto * snd_soc_component_test_bits - Test register for change 588460b42d1SKuninori Morimoto * @component: component 589460b42d1SKuninori Morimoto * @reg: Register to test 590460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to test 591460b42d1SKuninori Morimoto * @value: Value to test against 592460b42d1SKuninori Morimoto * 593460b42d1SKuninori Morimoto * Tests a register with a new value and checks if the new value is 594460b42d1SKuninori Morimoto * different from the old value. 595460b42d1SKuninori Morimoto * 596460b42d1SKuninori Morimoto * Return: 1 for change, otherwise 0. 597460b42d1SKuninori Morimoto */ 598460b42d1SKuninori Morimoto int snd_soc_component_test_bits(struct snd_soc_component *component, 599460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int value) 600460b42d1SKuninori Morimoto { 601460b42d1SKuninori Morimoto unsigned int old, new; 602460b42d1SKuninori Morimoto 603cf6e26c7SKuninori Morimoto old = snd_soc_component_read(component, reg); 604460b42d1SKuninori Morimoto new = (old & ~mask) | value; 605460b42d1SKuninori Morimoto return old != new; 606460b42d1SKuninori Morimoto } 607460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); 608460b42d1SKuninori Morimoto 6090035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) 6100035e256SKuninori Morimoto { 6110ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 6120035e256SKuninori Morimoto struct snd_soc_component *component; 613613fb500SKuninori Morimoto int i; 6140035e256SKuninori Morimoto 6150035e256SKuninori Morimoto /* FIXME: use 1st pointer */ 616613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 617e2cb4a14SKuninori Morimoto if (component->driver->pointer) 618e2cb4a14SKuninori Morimoto return component->driver->pointer(component, substream); 6190035e256SKuninori Morimoto 6200035e256SKuninori Morimoto return 0; 6210035e256SKuninori Morimoto } 62296a47908SKuninori Morimoto 62396a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, 62496a47908SKuninori Morimoto unsigned int cmd, void *arg) 62596a47908SKuninori Morimoto { 6260ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 62796a47908SKuninori Morimoto struct snd_soc_component *component; 628613fb500SKuninori Morimoto int i; 62996a47908SKuninori Morimoto 63096a47908SKuninori Morimoto /* FIXME: use 1st ioctl */ 631613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 632e2cb4a14SKuninori Morimoto if (component->driver->ioctl) 633e2329eebSKuninori Morimoto return soc_component_ret( 634e2329eebSKuninori Morimoto component, 635e2329eebSKuninori Morimoto component->driver->ioctl(component, 636e2329eebSKuninori Morimoto substream, cmd, arg)); 63796a47908SKuninori Morimoto 63896a47908SKuninori Morimoto return snd_pcm_lib_ioctl(substream, cmd, arg); 63996a47908SKuninori Morimoto } 64082d81f5cSKuninori Morimoto 6411e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) 6421e5ddb6bSTakashi Iwai { 6430ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 6441e5ddb6bSTakashi Iwai struct snd_soc_component *component; 645613fb500SKuninori Morimoto int i, ret; 6461e5ddb6bSTakashi Iwai 647613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 648f1861a7cSKuninori Morimoto if (component->driver->sync_stop) { 6491e5ddb6bSTakashi Iwai ret = component->driver->sync_stop(component, 6501e5ddb6bSTakashi Iwai substream); 6511e5ddb6bSTakashi Iwai if (ret < 0) 652be75db57SShengjiu Wang return soc_component_ret(component, ret); 6531e5ddb6bSTakashi Iwai } 6541e5ddb6bSTakashi Iwai } 6551e5ddb6bSTakashi Iwai 6561e5ddb6bSTakashi Iwai return 0; 6571e5ddb6bSTakashi Iwai } 6581e5ddb6bSTakashi Iwai 65982d81f5cSKuninori Morimoto int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, 66082d81f5cSKuninori Morimoto int channel, unsigned long pos, 66182d81f5cSKuninori Morimoto void __user *buf, unsigned long bytes) 66282d81f5cSKuninori Morimoto { 6630ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 66482d81f5cSKuninori Morimoto struct snd_soc_component *component; 665613fb500SKuninori Morimoto int i; 66682d81f5cSKuninori Morimoto 66782d81f5cSKuninori Morimoto /* FIXME. it returns 1st copy now */ 668613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 669e2cb4a14SKuninori Morimoto if (component->driver->copy_user) 670e2329eebSKuninori Morimoto return soc_component_ret( 671e2329eebSKuninori Morimoto component, 672e2329eebSKuninori Morimoto component->driver->copy_user( 673e2329eebSKuninori Morimoto component, substream, channel, 674e2329eebSKuninori Morimoto pos, buf, bytes)); 67582d81f5cSKuninori Morimoto 67682d81f5cSKuninori Morimoto return -EINVAL; 67782d81f5cSKuninori Morimoto } 6789c712e4fSKuninori Morimoto 6799c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, 6809c712e4fSKuninori Morimoto unsigned long offset) 6819c712e4fSKuninori Morimoto { 6820ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 6839c712e4fSKuninori Morimoto struct snd_soc_component *component; 6849c712e4fSKuninori Morimoto struct page *page; 685613fb500SKuninori Morimoto int i; 6869c712e4fSKuninori Morimoto 6879c712e4fSKuninori Morimoto /* FIXME. it returns 1st page now */ 688613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 689e2cb4a14SKuninori Morimoto if (component->driver->page) { 690e2cb4a14SKuninori Morimoto page = component->driver->page(component, 691e2cb4a14SKuninori Morimoto substream, offset); 692e2cb4a14SKuninori Morimoto if (page) 693e2cb4a14SKuninori Morimoto return page; 694e2cb4a14SKuninori Morimoto } 6959c712e4fSKuninori Morimoto } 6969c712e4fSKuninori Morimoto 6979c712e4fSKuninori Morimoto return NULL; 6989c712e4fSKuninori Morimoto } 699205875e1SKuninori Morimoto 700205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, 701205875e1SKuninori Morimoto struct vm_area_struct *vma) 702205875e1SKuninori Morimoto { 7030ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 704205875e1SKuninori Morimoto struct snd_soc_component *component; 705613fb500SKuninori Morimoto int i; 706205875e1SKuninori Morimoto 707205875e1SKuninori Morimoto /* FIXME. it returns 1st mmap now */ 708613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 709e2cb4a14SKuninori Morimoto if (component->driver->mmap) 710be75db57SShengjiu Wang return soc_component_ret( 711e2329eebSKuninori Morimoto component, 712e2329eebSKuninori Morimoto component->driver->mmap(component, 713e2329eebSKuninori Morimoto substream, vma)); 714205875e1SKuninori Morimoto 715205875e1SKuninori Morimoto return -EINVAL; 716205875e1SKuninori Morimoto } 7177484291eSKuninori Morimoto 718b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd) 7197484291eSKuninori Morimoto { 7207484291eSKuninori Morimoto struct snd_soc_component *component; 7217484291eSKuninori Morimoto int ret; 722613fb500SKuninori Morimoto int i; 7237484291eSKuninori Morimoto 724613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 725c64bfc90SKuninori Morimoto if (component->driver->pcm_construct) { 726c64bfc90SKuninori Morimoto ret = component->driver->pcm_construct(component, rtd); 727c64bfc90SKuninori Morimoto if (ret < 0) 728be75db57SShengjiu Wang return soc_component_ret(component, ret); 729c64bfc90SKuninori Morimoto } 7307484291eSKuninori Morimoto } 7317484291eSKuninori Morimoto 7327484291eSKuninori Morimoto return 0; 7337484291eSKuninori Morimoto } 73479776da0SKuninori Morimoto 735b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd) 73679776da0SKuninori Morimoto { 73779776da0SKuninori Morimoto struct snd_soc_component *component; 738613fb500SKuninori Morimoto int i; 73979776da0SKuninori Morimoto 7408e3366caSTakashi Iwai if (!rtd->pcm) 7418e3366caSTakashi Iwai return; 7428e3366caSTakashi Iwai 743613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 744c64bfc90SKuninori Morimoto if (component->driver->pcm_destruct) 745b2b2afbbSKuninori Morimoto component->driver->pcm_destruct(component, rtd->pcm); 74679776da0SKuninori Morimoto } 7474f39514fSKuninori Morimoto 7484f39514fSKuninori Morimoto int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream) 7494f39514fSKuninori Morimoto { 7500ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 7514f39514fSKuninori Morimoto struct snd_soc_component *component; 7524f39514fSKuninori Morimoto int i, ret; 7534f39514fSKuninori Morimoto 7544f39514fSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 7554f39514fSKuninori Morimoto if (component->driver->prepare) { 7564f39514fSKuninori Morimoto ret = component->driver->prepare(component, substream); 7574f39514fSKuninori Morimoto if (ret < 0) 7584f39514fSKuninori Morimoto return soc_component_ret(component, ret); 7594f39514fSKuninori Morimoto } 7604f39514fSKuninori Morimoto } 7614f39514fSKuninori Morimoto 7624f39514fSKuninori Morimoto return 0; 7634f39514fSKuninori Morimoto } 764e1bafa82SKuninori Morimoto 765e1bafa82SKuninori Morimoto int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, 766e1bafa82SKuninori Morimoto struct snd_pcm_hw_params *params, 767e1bafa82SKuninori Morimoto struct snd_soc_component **last) 768e1bafa82SKuninori Morimoto { 7690ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 770e1bafa82SKuninori Morimoto struct snd_soc_component *component; 771e1bafa82SKuninori Morimoto int i, ret; 772e1bafa82SKuninori Morimoto 773e1bafa82SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 774e1bafa82SKuninori Morimoto if (component->driver->hw_params) { 775e1bafa82SKuninori Morimoto ret = component->driver->hw_params(component, 776e1bafa82SKuninori Morimoto substream, params); 777e1bafa82SKuninori Morimoto if (ret < 0) { 778e1bafa82SKuninori Morimoto *last = component; 779e1bafa82SKuninori Morimoto return soc_component_ret(component, ret); 780e1bafa82SKuninori Morimoto } 781e1bafa82SKuninori Morimoto } 782e1bafa82SKuninori Morimoto } 783e1bafa82SKuninori Morimoto 784e1bafa82SKuninori Morimoto *last = NULL; 785e1bafa82SKuninori Morimoto return 0; 786e1bafa82SKuninori Morimoto } 78704751119SKuninori Morimoto 78804751119SKuninori Morimoto void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, 78904751119SKuninori Morimoto struct snd_soc_component *last) 79004751119SKuninori Morimoto { 7910ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 79204751119SKuninori Morimoto struct snd_soc_component *component; 79304751119SKuninori Morimoto int i, ret; 79404751119SKuninori Morimoto 79504751119SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 79604751119SKuninori Morimoto if (component == last) 79704751119SKuninori Morimoto break; 79804751119SKuninori Morimoto 79904751119SKuninori Morimoto if (component->driver->hw_free) { 80004751119SKuninori Morimoto ret = component->driver->hw_free(component, substream); 80104751119SKuninori Morimoto if (ret < 0) 80204751119SKuninori Morimoto soc_component_ret(component, ret); 80304751119SKuninori Morimoto } 80404751119SKuninori Morimoto } 80504751119SKuninori Morimoto } 80632fd1204SKuninori Morimoto 80732fd1204SKuninori Morimoto int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, 80832fd1204SKuninori Morimoto int cmd) 80932fd1204SKuninori Morimoto { 8100ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 81132fd1204SKuninori Morimoto struct snd_soc_component *component; 81232fd1204SKuninori Morimoto int i, ret; 81332fd1204SKuninori Morimoto 81432fd1204SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 81532fd1204SKuninori Morimoto if (component->driver->trigger) { 81632fd1204SKuninori Morimoto ret = component->driver->trigger(component, substream, cmd); 81732fd1204SKuninori Morimoto if (ret < 0) 81832fd1204SKuninori Morimoto return soc_component_ret(component, ret); 81932fd1204SKuninori Morimoto } 82032fd1204SKuninori Morimoto } 82132fd1204SKuninori Morimoto 82232fd1204SKuninori Morimoto return 0; 82332fd1204SKuninori Morimoto } 824