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 36257c4dacSKuninori Morimoto void snd_soc_component_set_aux(struct snd_soc_component *component, 37257c4dacSKuninori Morimoto struct snd_soc_aux_dev *aux) 38257c4dacSKuninori Morimoto { 39257c4dacSKuninori Morimoto component->init = (aux) ? aux->init : NULL; 40257c4dacSKuninori Morimoto } 41257c4dacSKuninori Morimoto 42257c4dacSKuninori Morimoto int snd_soc_component_init(struct snd_soc_component *component) 43257c4dacSKuninori Morimoto { 44257c4dacSKuninori Morimoto int ret = 0; 45257c4dacSKuninori Morimoto 46257c4dacSKuninori Morimoto if (component->init) 47257c4dacSKuninori Morimoto ret = component->init(component); 48257c4dacSKuninori Morimoto 49257c4dacSKuninori Morimoto return soc_component_ret(component, ret); 50257c4dacSKuninori Morimoto } 51257c4dacSKuninori Morimoto 524ff1fef1SKuninori Morimoto /** 534ff1fef1SKuninori Morimoto * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. 544ff1fef1SKuninori Morimoto * @component: COMPONENT 554ff1fef1SKuninori Morimoto * @clk_id: DAI specific clock ID 564ff1fef1SKuninori Morimoto * @source: Source for the clock 574ff1fef1SKuninori Morimoto * @freq: new clock frequency in Hz 584ff1fef1SKuninori Morimoto * @dir: new clock direction - input/output. 594ff1fef1SKuninori Morimoto * 604ff1fef1SKuninori Morimoto * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. 614ff1fef1SKuninori Morimoto */ 624ff1fef1SKuninori Morimoto int snd_soc_component_set_sysclk(struct snd_soc_component *component, 634ff1fef1SKuninori Morimoto int clk_id, int source, unsigned int freq, 644ff1fef1SKuninori Morimoto int dir) 654ff1fef1SKuninori Morimoto { 66e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 67e2329eebSKuninori Morimoto 684ff1fef1SKuninori Morimoto if (component->driver->set_sysclk) 69e2329eebSKuninori Morimoto ret = component->driver->set_sysclk(component, clk_id, source, 704ff1fef1SKuninori Morimoto freq, dir); 714ff1fef1SKuninori Morimoto 72e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 734ff1fef1SKuninori Morimoto } 744ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); 754ff1fef1SKuninori Morimoto 764ff1fef1SKuninori Morimoto /* 774ff1fef1SKuninori Morimoto * snd_soc_component_set_pll - configure component PLL. 784ff1fef1SKuninori Morimoto * @component: COMPONENT 794ff1fef1SKuninori Morimoto * @pll_id: DAI specific PLL ID 804ff1fef1SKuninori Morimoto * @source: DAI specific source for the PLL 814ff1fef1SKuninori Morimoto * @freq_in: PLL input clock frequency in Hz 824ff1fef1SKuninori Morimoto * @freq_out: requested PLL output clock frequency in Hz 834ff1fef1SKuninori Morimoto * 844ff1fef1SKuninori Morimoto * Configures and enables PLL to generate output clock based on input clock. 854ff1fef1SKuninori Morimoto */ 864ff1fef1SKuninori Morimoto int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, 874ff1fef1SKuninori Morimoto int source, unsigned int freq_in, 884ff1fef1SKuninori Morimoto unsigned int freq_out) 894ff1fef1SKuninori Morimoto { 90e2329eebSKuninori Morimoto int ret = -EINVAL; 91e2329eebSKuninori Morimoto 924ff1fef1SKuninori Morimoto if (component->driver->set_pll) 93e2329eebSKuninori Morimoto ret = component->driver->set_pll(component, pll_id, source, 944ff1fef1SKuninori Morimoto freq_in, freq_out); 954ff1fef1SKuninori Morimoto 96e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 974ff1fef1SKuninori Morimoto } 984ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); 994ff1fef1SKuninori Morimoto 1009d415fbfSKuninori Morimoto void snd_soc_component_seq_notifier(struct snd_soc_component *component, 1019d415fbfSKuninori Morimoto enum snd_soc_dapm_type type, int subseq) 1029d415fbfSKuninori Morimoto { 1039d415fbfSKuninori Morimoto if (component->driver->seq_notifier) 1049d415fbfSKuninori Morimoto component->driver->seq_notifier(component, type, subseq); 1059d415fbfSKuninori Morimoto } 1069d415fbfSKuninori Morimoto 1078e2a990dSKuninori Morimoto int snd_soc_component_stream_event(struct snd_soc_component *component, 1088e2a990dSKuninori Morimoto int event) 1098e2a990dSKuninori Morimoto { 110e2329eebSKuninori Morimoto int ret = 0; 1118e2a990dSKuninori Morimoto 112e2329eebSKuninori Morimoto if (component->driver->stream_event) 113e2329eebSKuninori Morimoto ret = component->driver->stream_event(component, event); 114e2329eebSKuninori Morimoto 115e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1168e2a990dSKuninori Morimoto } 1178e2a990dSKuninori Morimoto 1187951b146SKuninori Morimoto int snd_soc_component_set_bias_level(struct snd_soc_component *component, 1197951b146SKuninori Morimoto enum snd_soc_bias_level level) 1207951b146SKuninori Morimoto { 121e2329eebSKuninori Morimoto int ret = 0; 1227951b146SKuninori Morimoto 123e2329eebSKuninori Morimoto if (component->driver->set_bias_level) 124e2329eebSKuninori Morimoto ret = component->driver->set_bias_level(component, level); 125e2329eebSKuninori Morimoto 126e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1277951b146SKuninori Morimoto } 1287951b146SKuninori Morimoto 1294ca8701eSKuninori Morimoto static int soc_component_pin(struct snd_soc_component *component, 1304ca8701eSKuninori Morimoto const char *pin, 1314ca8701eSKuninori Morimoto int (*pin_func)(struct snd_soc_dapm_context *dapm, 1324ca8701eSKuninori Morimoto const char *pin)) 1334ff1fef1SKuninori Morimoto { 1344ff1fef1SKuninori Morimoto struct snd_soc_dapm_context *dapm = 1354ff1fef1SKuninori Morimoto snd_soc_component_get_dapm(component); 1364ff1fef1SKuninori Morimoto char *full_name; 1374ff1fef1SKuninori Morimoto int ret; 1384ff1fef1SKuninori Morimoto 139e2329eebSKuninori Morimoto if (!component->name_prefix) { 140e2329eebSKuninori Morimoto ret = pin_func(dapm, pin); 141e2329eebSKuninori Morimoto goto end; 142e2329eebSKuninori Morimoto } 1434ff1fef1SKuninori Morimoto 1444ff1fef1SKuninori Morimoto full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); 145e2329eebSKuninori Morimoto if (!full_name) { 146e2329eebSKuninori Morimoto ret = -ENOMEM; 147e2329eebSKuninori Morimoto goto end; 148e2329eebSKuninori Morimoto } 1494ff1fef1SKuninori Morimoto 1504ca8701eSKuninori Morimoto ret = pin_func(dapm, full_name); 1514ff1fef1SKuninori Morimoto kfree(full_name); 152e2329eebSKuninori Morimoto end: 153e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1544ff1fef1SKuninori Morimoto } 1554ca8701eSKuninori Morimoto 1564ca8701eSKuninori Morimoto int snd_soc_component_enable_pin(struct snd_soc_component *component, 1574ca8701eSKuninori Morimoto const char *pin) 1584ca8701eSKuninori Morimoto { 1594ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_enable_pin); 1604ca8701eSKuninori Morimoto } 1614ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); 1624ff1fef1SKuninori Morimoto 1634ff1fef1SKuninori Morimoto int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, 1644ff1fef1SKuninori Morimoto const char *pin) 1654ff1fef1SKuninori Morimoto { 1664ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked); 1674ff1fef1SKuninori Morimoto } 1684ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); 1694ff1fef1SKuninori Morimoto 1704ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin(struct snd_soc_component *component, 1714ff1fef1SKuninori Morimoto const char *pin) 1724ff1fef1SKuninori Morimoto { 1734ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_disable_pin); 1744ff1fef1SKuninori Morimoto } 1754ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); 1764ff1fef1SKuninori Morimoto 1774ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, 1784ff1fef1SKuninori Morimoto const char *pin) 1794ff1fef1SKuninori Morimoto { 1804ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked); 1814ff1fef1SKuninori Morimoto } 1824ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); 1834ff1fef1SKuninori Morimoto 1844ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin(struct snd_soc_component *component, 1854ff1fef1SKuninori Morimoto const char *pin) 1864ff1fef1SKuninori Morimoto { 1874ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_nc_pin); 1884ff1fef1SKuninori Morimoto } 1894ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); 1904ff1fef1SKuninori Morimoto 1914ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, 1924ff1fef1SKuninori Morimoto const char *pin) 1934ff1fef1SKuninori Morimoto { 1944ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked); 1954ff1fef1SKuninori Morimoto } 1964ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); 1974ff1fef1SKuninori Morimoto 1984ff1fef1SKuninori Morimoto int snd_soc_component_get_pin_status(struct snd_soc_component *component, 1994ff1fef1SKuninori Morimoto const char *pin) 2004ff1fef1SKuninori Morimoto { 2014ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status); 2024ff1fef1SKuninori Morimoto } 2034ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); 2044ff1fef1SKuninori Morimoto 2054ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin(struct snd_soc_component *component, 2064ff1fef1SKuninori Morimoto const char *pin) 2074ff1fef1SKuninori Morimoto { 2084ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin); 2094ff1fef1SKuninori Morimoto } 2104ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); 2114ff1fef1SKuninori Morimoto 2124ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin_unlocked( 2134ff1fef1SKuninori Morimoto struct snd_soc_component *component, 2144ff1fef1SKuninori Morimoto const char *pin) 2154ff1fef1SKuninori Morimoto { 2164ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked); 2174ff1fef1SKuninori Morimoto } 2184ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); 2194ff1fef1SKuninori Morimoto 2204ff1fef1SKuninori Morimoto /** 2214ff1fef1SKuninori Morimoto * snd_soc_component_set_jack - configure component jack. 2224ff1fef1SKuninori Morimoto * @component: COMPONENTs 2234ff1fef1SKuninori Morimoto * @jack: structure to use for the jack 2244ff1fef1SKuninori Morimoto * @data: can be used if codec driver need extra data for configuring jack 2254ff1fef1SKuninori Morimoto * 2264ff1fef1SKuninori Morimoto * Configures and enables jack detection function. 2274ff1fef1SKuninori Morimoto */ 2284ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component, 2294ff1fef1SKuninori Morimoto struct snd_soc_jack *jack, void *data) 2304ff1fef1SKuninori Morimoto { 231e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 2324ff1fef1SKuninori Morimoto 233e2329eebSKuninori Morimoto if (component->driver->set_jack) 234e2329eebSKuninori Morimoto ret = component->driver->set_jack(component, jack, data); 235e2329eebSKuninori Morimoto 236e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2374ff1fef1SKuninori Morimoto } 2384ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); 2394a81e8f3SKuninori Morimoto 2404a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component, 2414a81e8f3SKuninori Morimoto int upon_open) 2424a81e8f3SKuninori Morimoto { 243e2329eebSKuninori Morimoto int ret = 0; 244e2329eebSKuninori Morimoto 2454a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open && 2464a81e8f3SKuninori Morimoto !try_module_get(component->dev->driver->owner)) 247e2329eebSKuninori Morimoto ret = -ENODEV; 2484a81e8f3SKuninori Morimoto 249e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2504a81e8f3SKuninori Morimoto } 2514a81e8f3SKuninori Morimoto 2524a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component, 2534a81e8f3SKuninori Morimoto int upon_open) 2544a81e8f3SKuninori Morimoto { 2554a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open) 2564a81e8f3SKuninori Morimoto module_put(component->dev->driver->owner); 2574a81e8f3SKuninori Morimoto } 258ae2f4849SKuninori Morimoto 259ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component, 260ae2f4849SKuninori Morimoto struct snd_pcm_substream *substream) 261ae2f4849SKuninori Morimoto { 262e2329eebSKuninori Morimoto int ret = 0; 263e2329eebSKuninori Morimoto 264e2cb4a14SKuninori Morimoto if (component->driver->open) 265e2329eebSKuninori Morimoto ret = component->driver->open(component, substream); 266e2329eebSKuninori Morimoto 267e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 268ae2f4849SKuninori Morimoto } 2693672beb8SKuninori Morimoto 2703672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component, 2713672beb8SKuninori Morimoto struct snd_pcm_substream *substream) 2723672beb8SKuninori Morimoto { 273e2329eebSKuninori Morimoto int ret = 0; 274e2329eebSKuninori Morimoto 275e2cb4a14SKuninori Morimoto if (component->driver->close) 276e2329eebSKuninori Morimoto ret = component->driver->close(component, substream); 277e2329eebSKuninori Morimoto 278e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2793672beb8SKuninori Morimoto } 2806d537233SKuninori Morimoto 28166c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component) 28266c51573SKuninori Morimoto { 28366c51573SKuninori Morimoto if (component->driver->suspend) 28466c51573SKuninori Morimoto component->driver->suspend(component); 28566c51573SKuninori Morimoto component->suspended = 1; 28666c51573SKuninori Morimoto } 2879a840cbaSKuninori Morimoto 2889a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component) 2899a840cbaSKuninori Morimoto { 2909a840cbaSKuninori Morimoto if (component->driver->resume) 2919a840cbaSKuninori Morimoto component->driver->resume(component); 2929a840cbaSKuninori Morimoto component->suspended = 0; 2939a840cbaSKuninori Morimoto } 294e40fadbcSKuninori Morimoto 295e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component) 296e40fadbcSKuninori Morimoto { 297e40fadbcSKuninori Morimoto return component->suspended; 298e40fadbcSKuninori Morimoto } 29908e837ddSKuninori Morimoto 30008e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component) 30108e837ddSKuninori Morimoto { 302e2329eebSKuninori Morimoto int ret = 0; 30308e837ddSKuninori Morimoto 304e2329eebSKuninori Morimoto if (component->driver->probe) 305e2329eebSKuninori Morimoto ret = component->driver->probe(component); 306e2329eebSKuninori Morimoto 307e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 30808e837ddSKuninori Morimoto } 30903b34dd7SKuninori Morimoto 31003b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component) 31103b34dd7SKuninori Morimoto { 31203b34dd7SKuninori Morimoto if (component->driver->remove) 31303b34dd7SKuninori Morimoto component->driver->remove(component); 31403b34dd7SKuninori Morimoto } 3152c7b1704SKuninori Morimoto 3162c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, 3172c7b1704SKuninori Morimoto struct device_node *ep) 3182c7b1704SKuninori Morimoto { 319e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 3202c7b1704SKuninori Morimoto 321e2329eebSKuninori Morimoto if (component->driver->of_xlate_dai_id) 322e2329eebSKuninori Morimoto ret = component->driver->of_xlate_dai_id(component, ep); 323e2329eebSKuninori Morimoto 324e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 3252c7b1704SKuninori Morimoto } 326a2a34175SKuninori Morimoto 327a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, 328a2a34175SKuninori Morimoto struct of_phandle_args *args, 329a2a34175SKuninori Morimoto const char **dai_name) 330a2a34175SKuninori Morimoto { 331a2a34175SKuninori Morimoto if (component->driver->of_xlate_dai_name) 332cc4d8cebSJerome Brunet return component->driver->of_xlate_dai_name(component, 333a2a34175SKuninori Morimoto args, dai_name); 334cc4d8cebSJerome Brunet /* 335cc4d8cebSJerome Brunet * Don't use soc_component_ret here because we may not want to report 336cc4d8cebSJerome Brunet * the error just yet. If a device has more than one component, the 337cc4d8cebSJerome Brunet * first may not match and we don't want spam the log with this. 338cc4d8cebSJerome Brunet */ 339cc4d8cebSJerome Brunet return -ENOTSUPP; 340a2a34175SKuninori Morimoto } 3410035e256SKuninori Morimoto 342c7d75b59SKuninori Morimoto void snd_soc_component_setup_regmap(struct snd_soc_component *component) 343c7d75b59SKuninori Morimoto { 344c7d75b59SKuninori Morimoto int val_bytes = regmap_get_val_bytes(component->regmap); 345c7d75b59SKuninori Morimoto 346c7d75b59SKuninori Morimoto /* Errors are legitimate for non-integer byte multiples */ 347c7d75b59SKuninori Morimoto if (val_bytes > 0) 348c7d75b59SKuninori Morimoto component->val_bytes = val_bytes; 349c7d75b59SKuninori Morimoto } 350c7d75b59SKuninori Morimoto 351c7d75b59SKuninori Morimoto #ifdef CONFIG_REGMAP 352c7d75b59SKuninori Morimoto 353c7d75b59SKuninori Morimoto /** 354c7d75b59SKuninori Morimoto * snd_soc_component_init_regmap() - Initialize regmap instance for the 355c7d75b59SKuninori Morimoto * component 356c7d75b59SKuninori Morimoto * @component: The component for which to initialize the regmap instance 357c7d75b59SKuninori Morimoto * @regmap: The regmap instance that should be used by the component 358c7d75b59SKuninori Morimoto * 359c7d75b59SKuninori Morimoto * This function allows deferred assignment of the regmap instance that is 360c7d75b59SKuninori Morimoto * associated with the component. Only use this if the regmap instance is not 361c7d75b59SKuninori Morimoto * yet ready when the component is registered. The function must also be called 362c7d75b59SKuninori Morimoto * before the first IO attempt of the component. 363c7d75b59SKuninori Morimoto */ 364c7d75b59SKuninori Morimoto void snd_soc_component_init_regmap(struct snd_soc_component *component, 365c7d75b59SKuninori Morimoto struct regmap *regmap) 366c7d75b59SKuninori Morimoto { 367c7d75b59SKuninori Morimoto component->regmap = regmap; 368c7d75b59SKuninori Morimoto snd_soc_component_setup_regmap(component); 369c7d75b59SKuninori Morimoto } 370c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); 371c7d75b59SKuninori Morimoto 372c7d75b59SKuninori Morimoto /** 373c7d75b59SKuninori Morimoto * snd_soc_component_exit_regmap() - De-initialize regmap instance for the 374c7d75b59SKuninori Morimoto * component 375c7d75b59SKuninori Morimoto * @component: The component for which to de-initialize the regmap instance 376c7d75b59SKuninori Morimoto * 377c7d75b59SKuninori Morimoto * Calls regmap_exit() on the regmap instance associated to the component and 378c7d75b59SKuninori Morimoto * removes the regmap instance from the component. 379c7d75b59SKuninori Morimoto * 380c7d75b59SKuninori Morimoto * This function should only be used if snd_soc_component_init_regmap() was used 381c7d75b59SKuninori Morimoto * to initialize the regmap instance. 382c7d75b59SKuninori Morimoto */ 383c7d75b59SKuninori Morimoto void snd_soc_component_exit_regmap(struct snd_soc_component *component) 384c7d75b59SKuninori Morimoto { 385c7d75b59SKuninori Morimoto regmap_exit(component->regmap); 386c7d75b59SKuninori Morimoto component->regmap = NULL; 387c7d75b59SKuninori Morimoto } 388c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); 389c7d75b59SKuninori Morimoto 390c7d75b59SKuninori Morimoto #endif 391c7d75b59SKuninori Morimoto 392e8712315SKuninori Morimoto static unsigned int soc_component_read_no_lock( 393e8712315SKuninori Morimoto struct snd_soc_component *component, 394cf6e26c7SKuninori Morimoto unsigned int reg) 395460b42d1SKuninori Morimoto { 396460b42d1SKuninori Morimoto int ret; 397cf6e26c7SKuninori Morimoto unsigned int val = 0; 398460b42d1SKuninori Morimoto 399460b42d1SKuninori Morimoto if (component->regmap) 400cf6e26c7SKuninori Morimoto ret = regmap_read(component->regmap, reg, &val); 401460b42d1SKuninori Morimoto else if (component->driver->read) { 402460b42d1SKuninori Morimoto ret = 0; 403cf6e26c7SKuninori Morimoto val = component->driver->read(component, reg); 404460b42d1SKuninori Morimoto } 405460b42d1SKuninori Morimoto else 406460b42d1SKuninori Morimoto ret = -EIO; 407460b42d1SKuninori Morimoto 408460b42d1SKuninori Morimoto if (ret < 0) 409efc913c8STakashi Iwai return soc_component_ret(component, ret); 410460b42d1SKuninori Morimoto 411460b42d1SKuninori Morimoto return val; 412460b42d1SKuninori Morimoto } 413e8712315SKuninori Morimoto 414e8712315SKuninori Morimoto /** 415e8712315SKuninori Morimoto * snd_soc_component_read() - Read register value 416e8712315SKuninori Morimoto * @component: Component to read from 417e8712315SKuninori Morimoto * @reg: Register to read 418e8712315SKuninori Morimoto * 419e8712315SKuninori Morimoto * Return: read value 420e8712315SKuninori Morimoto */ 421e8712315SKuninori Morimoto unsigned int snd_soc_component_read(struct snd_soc_component *component, 422e8712315SKuninori Morimoto unsigned int reg) 423e8712315SKuninori Morimoto { 424e8712315SKuninori Morimoto unsigned int val; 425e8712315SKuninori Morimoto 426e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 427e8712315SKuninori Morimoto val = soc_component_read_no_lock(component, reg); 428e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 429e8712315SKuninori Morimoto 430e8712315SKuninori Morimoto return val; 431e8712315SKuninori Morimoto } 432cf6e26c7SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_read); 433460b42d1SKuninori Morimoto 434e8712315SKuninori Morimoto static int soc_component_write_no_lock( 435e8712315SKuninori Morimoto struct snd_soc_component *component, 436e8712315SKuninori Morimoto unsigned int reg, unsigned int val) 437e8712315SKuninori Morimoto { 438e8712315SKuninori Morimoto int ret = -EIO; 439e8712315SKuninori Morimoto 440e8712315SKuninori Morimoto if (component->regmap) 441e8712315SKuninori Morimoto ret = regmap_write(component->regmap, reg, val); 442e8712315SKuninori Morimoto else if (component->driver->write) 443e8712315SKuninori Morimoto ret = component->driver->write(component, reg, val); 444e8712315SKuninori Morimoto 445e8712315SKuninori Morimoto return soc_component_ret(component, ret); 446e8712315SKuninori Morimoto } 447e8712315SKuninori Morimoto 448460b42d1SKuninori Morimoto /** 449460b42d1SKuninori Morimoto * snd_soc_component_write() - Write register value 450460b42d1SKuninori Morimoto * @component: Component to write to 451460b42d1SKuninori Morimoto * @reg: Register to write 452460b42d1SKuninori Morimoto * @val: Value to write to the register 453460b42d1SKuninori Morimoto * 454460b42d1SKuninori Morimoto * Return: 0 on success, a negative error code otherwise. 455460b42d1SKuninori Morimoto */ 456460b42d1SKuninori Morimoto int snd_soc_component_write(struct snd_soc_component *component, 457460b42d1SKuninori Morimoto unsigned int reg, unsigned int val) 458460b42d1SKuninori Morimoto { 459e8712315SKuninori Morimoto int ret; 460460b42d1SKuninori Morimoto 461e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 462e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, val); 463e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 464460b42d1SKuninori Morimoto 465e8712315SKuninori Morimoto return ret; 466460b42d1SKuninori Morimoto } 467460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_write); 468460b42d1SKuninori Morimoto 469460b42d1SKuninori Morimoto static int snd_soc_component_update_bits_legacy( 470460b42d1SKuninori Morimoto struct snd_soc_component *component, unsigned int reg, 471460b42d1SKuninori Morimoto unsigned int mask, unsigned int val, bool *change) 472460b42d1SKuninori Morimoto { 473460b42d1SKuninori Morimoto unsigned int old, new; 474cf6e26c7SKuninori Morimoto int ret = 0; 475460b42d1SKuninori Morimoto 476460b42d1SKuninori Morimoto mutex_lock(&component->io_mutex); 477460b42d1SKuninori Morimoto 478e8712315SKuninori Morimoto old = soc_component_read_no_lock(component, reg); 479460b42d1SKuninori Morimoto 480460b42d1SKuninori Morimoto new = (old & ~mask) | (val & mask); 481460b42d1SKuninori Morimoto *change = old != new; 482460b42d1SKuninori Morimoto if (*change) 483e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, new); 484cf6e26c7SKuninori Morimoto 485460b42d1SKuninori Morimoto mutex_unlock(&component->io_mutex); 486460b42d1SKuninori Morimoto 487460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 488460b42d1SKuninori Morimoto } 489460b42d1SKuninori Morimoto 490460b42d1SKuninori Morimoto /** 491460b42d1SKuninori Morimoto * snd_soc_component_update_bits() - Perform read/modify/write cycle 492460b42d1SKuninori Morimoto * @component: Component to update 493460b42d1SKuninori Morimoto * @reg: Register to update 494460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 495460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 496460b42d1SKuninori Morimoto * 497460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 498460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 499460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 500460b42d1SKuninori Morimoto */ 501460b42d1SKuninori Morimoto int snd_soc_component_update_bits(struct snd_soc_component *component, 502460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 503460b42d1SKuninori Morimoto { 504460b42d1SKuninori Morimoto bool change; 505460b42d1SKuninori Morimoto int ret; 506460b42d1SKuninori Morimoto 507460b42d1SKuninori Morimoto if (component->regmap) 508460b42d1SKuninori Morimoto ret = regmap_update_bits_check(component->regmap, reg, mask, 509460b42d1SKuninori Morimoto val, &change); 510460b42d1SKuninori Morimoto else 511460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 512460b42d1SKuninori Morimoto mask, val, &change); 513460b42d1SKuninori Morimoto 514460b42d1SKuninori Morimoto if (ret < 0) 515460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 516460b42d1SKuninori Morimoto return change; 517460b42d1SKuninori Morimoto } 518460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); 519460b42d1SKuninori Morimoto 520460b42d1SKuninori Morimoto /** 521460b42d1SKuninori Morimoto * snd_soc_component_update_bits_async() - Perform asynchronous 522460b42d1SKuninori Morimoto * read/modify/write cycle 523460b42d1SKuninori Morimoto * @component: Component to update 524460b42d1SKuninori Morimoto * @reg: Register to update 525460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 526460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 527460b42d1SKuninori Morimoto * 528460b42d1SKuninori Morimoto * This function is similar to snd_soc_component_update_bits(), but the update 529460b42d1SKuninori Morimoto * operation is scheduled asynchronously. This means it may not be completed 530460b42d1SKuninori Morimoto * when the function returns. To make sure that all scheduled updates have been 531460b42d1SKuninori Morimoto * completed snd_soc_component_async_complete() must be called. 532460b42d1SKuninori Morimoto * 533460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 534460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 535460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 536460b42d1SKuninori Morimoto */ 537460b42d1SKuninori Morimoto int snd_soc_component_update_bits_async(struct snd_soc_component *component, 538460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 539460b42d1SKuninori Morimoto { 540460b42d1SKuninori Morimoto bool change; 541460b42d1SKuninori Morimoto int ret; 542460b42d1SKuninori Morimoto 543460b42d1SKuninori Morimoto if (component->regmap) 544460b42d1SKuninori Morimoto ret = regmap_update_bits_check_async(component->regmap, reg, 545460b42d1SKuninori Morimoto mask, val, &change); 546460b42d1SKuninori Morimoto else 547460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 548460b42d1SKuninori Morimoto mask, val, &change); 549460b42d1SKuninori Morimoto 550460b42d1SKuninori Morimoto if (ret < 0) 551460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 552460b42d1SKuninori Morimoto return change; 553460b42d1SKuninori Morimoto } 554460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); 555460b42d1SKuninori Morimoto 556460b42d1SKuninori Morimoto /** 557460b42d1SKuninori Morimoto * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed 558460b42d1SKuninori Morimoto * @component: Component for which to wait 559460b42d1SKuninori Morimoto * 560460b42d1SKuninori Morimoto * This function blocks until all asynchronous I/O which has previously been 561460b42d1SKuninori Morimoto * scheduled using snd_soc_component_update_bits_async() has completed. 562460b42d1SKuninori Morimoto */ 563460b42d1SKuninori Morimoto void snd_soc_component_async_complete(struct snd_soc_component *component) 564460b42d1SKuninori Morimoto { 565460b42d1SKuninori Morimoto if (component->regmap) 566460b42d1SKuninori Morimoto regmap_async_complete(component->regmap); 567460b42d1SKuninori Morimoto } 568460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); 569460b42d1SKuninori Morimoto 570460b42d1SKuninori Morimoto /** 571460b42d1SKuninori Morimoto * snd_soc_component_test_bits - Test register for change 572460b42d1SKuninori Morimoto * @component: component 573460b42d1SKuninori Morimoto * @reg: Register to test 574460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to test 575460b42d1SKuninori Morimoto * @value: Value to test against 576460b42d1SKuninori Morimoto * 577460b42d1SKuninori Morimoto * Tests a register with a new value and checks if the new value is 578460b42d1SKuninori Morimoto * different from the old value. 579460b42d1SKuninori Morimoto * 580460b42d1SKuninori Morimoto * Return: 1 for change, otherwise 0. 581460b42d1SKuninori Morimoto */ 582460b42d1SKuninori Morimoto int snd_soc_component_test_bits(struct snd_soc_component *component, 583460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int value) 584460b42d1SKuninori Morimoto { 585460b42d1SKuninori Morimoto unsigned int old, new; 586460b42d1SKuninori Morimoto 587cf6e26c7SKuninori Morimoto old = snd_soc_component_read(component, reg); 588460b42d1SKuninori Morimoto new = (old & ~mask) | value; 589460b42d1SKuninori Morimoto return old != new; 590460b42d1SKuninori Morimoto } 591460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); 592460b42d1SKuninori Morimoto 5930035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) 5940035e256SKuninori Morimoto { 5950ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 5960035e256SKuninori Morimoto struct snd_soc_component *component; 597613fb500SKuninori Morimoto int i; 5980035e256SKuninori Morimoto 5990035e256SKuninori Morimoto /* FIXME: use 1st pointer */ 600613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 601e2cb4a14SKuninori Morimoto if (component->driver->pointer) 602e2cb4a14SKuninori Morimoto return component->driver->pointer(component, substream); 6030035e256SKuninori Morimoto 6040035e256SKuninori Morimoto return 0; 6050035e256SKuninori Morimoto } 60696a47908SKuninori Morimoto 60796a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, 60896a47908SKuninori Morimoto unsigned int cmd, void *arg) 60996a47908SKuninori Morimoto { 6100ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 61196a47908SKuninori Morimoto struct snd_soc_component *component; 612613fb500SKuninori Morimoto int i; 61396a47908SKuninori Morimoto 61496a47908SKuninori Morimoto /* FIXME: use 1st ioctl */ 615613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 616e2cb4a14SKuninori Morimoto if (component->driver->ioctl) 617e2329eebSKuninori Morimoto return soc_component_ret( 618e2329eebSKuninori Morimoto component, 619e2329eebSKuninori Morimoto component->driver->ioctl(component, 620e2329eebSKuninori Morimoto substream, cmd, arg)); 62196a47908SKuninori Morimoto 62296a47908SKuninori Morimoto return snd_pcm_lib_ioctl(substream, cmd, arg); 62396a47908SKuninori Morimoto } 62482d81f5cSKuninori Morimoto 6251e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) 6261e5ddb6bSTakashi Iwai { 6270ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 6281e5ddb6bSTakashi Iwai struct snd_soc_component *component; 629613fb500SKuninori Morimoto int i, ret; 6301e5ddb6bSTakashi Iwai 631613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 632f1861a7cSKuninori Morimoto if (component->driver->sync_stop) { 6331e5ddb6bSTakashi Iwai ret = component->driver->sync_stop(component, 6341e5ddb6bSTakashi Iwai substream); 6351e5ddb6bSTakashi Iwai if (ret < 0) 636be75db57SShengjiu Wang return soc_component_ret(component, ret); 6371e5ddb6bSTakashi Iwai } 6381e5ddb6bSTakashi Iwai } 6391e5ddb6bSTakashi Iwai 6401e5ddb6bSTakashi Iwai return 0; 6411e5ddb6bSTakashi Iwai } 6421e5ddb6bSTakashi Iwai 64382d81f5cSKuninori Morimoto int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, 64482d81f5cSKuninori Morimoto int channel, unsigned long pos, 64582d81f5cSKuninori Morimoto void __user *buf, unsigned long bytes) 64682d81f5cSKuninori Morimoto { 6470ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 64882d81f5cSKuninori Morimoto struct snd_soc_component *component; 649613fb500SKuninori Morimoto int i; 65082d81f5cSKuninori Morimoto 65182d81f5cSKuninori Morimoto /* FIXME. it returns 1st copy now */ 652613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 653e2cb4a14SKuninori Morimoto if (component->driver->copy_user) 654e2329eebSKuninori Morimoto return soc_component_ret( 655e2329eebSKuninori Morimoto component, 656e2329eebSKuninori Morimoto component->driver->copy_user( 657e2329eebSKuninori Morimoto component, substream, channel, 658e2329eebSKuninori Morimoto pos, buf, bytes)); 65982d81f5cSKuninori Morimoto 66082d81f5cSKuninori Morimoto return -EINVAL; 66182d81f5cSKuninori Morimoto } 6629c712e4fSKuninori Morimoto 6639c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, 6649c712e4fSKuninori Morimoto unsigned long offset) 6659c712e4fSKuninori Morimoto { 6660ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 6679c712e4fSKuninori Morimoto struct snd_soc_component *component; 6689c712e4fSKuninori Morimoto struct page *page; 669613fb500SKuninori Morimoto int i; 6709c712e4fSKuninori Morimoto 6719c712e4fSKuninori Morimoto /* FIXME. it returns 1st page now */ 672613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 673e2cb4a14SKuninori Morimoto if (component->driver->page) { 674e2cb4a14SKuninori Morimoto page = component->driver->page(component, 675e2cb4a14SKuninori Morimoto substream, offset); 676e2cb4a14SKuninori Morimoto if (page) 677e2cb4a14SKuninori Morimoto return page; 678e2cb4a14SKuninori Morimoto } 6799c712e4fSKuninori Morimoto } 6809c712e4fSKuninori Morimoto 6819c712e4fSKuninori Morimoto return NULL; 6829c712e4fSKuninori Morimoto } 683205875e1SKuninori Morimoto 684205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, 685205875e1SKuninori Morimoto struct vm_area_struct *vma) 686205875e1SKuninori Morimoto { 6870ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 688205875e1SKuninori Morimoto struct snd_soc_component *component; 689613fb500SKuninori Morimoto int i; 690205875e1SKuninori Morimoto 691205875e1SKuninori Morimoto /* FIXME. it returns 1st mmap now */ 692613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 693e2cb4a14SKuninori Morimoto if (component->driver->mmap) 694be75db57SShengjiu Wang return soc_component_ret( 695e2329eebSKuninori Morimoto component, 696e2329eebSKuninori Morimoto component->driver->mmap(component, 697e2329eebSKuninori Morimoto substream, vma)); 698205875e1SKuninori Morimoto 699205875e1SKuninori Morimoto return -EINVAL; 700205875e1SKuninori Morimoto } 7017484291eSKuninori Morimoto 702b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd) 7037484291eSKuninori Morimoto { 7047484291eSKuninori Morimoto struct snd_soc_component *component; 7057484291eSKuninori Morimoto int ret; 706613fb500SKuninori Morimoto int i; 7077484291eSKuninori Morimoto 708613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 709c64bfc90SKuninori Morimoto if (component->driver->pcm_construct) { 710c64bfc90SKuninori Morimoto ret = component->driver->pcm_construct(component, rtd); 711c64bfc90SKuninori Morimoto if (ret < 0) 712be75db57SShengjiu Wang return soc_component_ret(component, ret); 713c64bfc90SKuninori Morimoto } 7147484291eSKuninori Morimoto } 7157484291eSKuninori Morimoto 7167484291eSKuninori Morimoto return 0; 7177484291eSKuninori Morimoto } 71879776da0SKuninori Morimoto 719b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd) 72079776da0SKuninori Morimoto { 72179776da0SKuninori Morimoto struct snd_soc_component *component; 722613fb500SKuninori Morimoto int i; 72379776da0SKuninori Morimoto 7248e3366caSTakashi Iwai if (!rtd->pcm) 7258e3366caSTakashi Iwai return; 7268e3366caSTakashi Iwai 727613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 728c64bfc90SKuninori Morimoto if (component->driver->pcm_destruct) 729b2b2afbbSKuninori Morimoto component->driver->pcm_destruct(component, rtd->pcm); 73079776da0SKuninori Morimoto } 7314f39514fSKuninori Morimoto 7324f39514fSKuninori Morimoto int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream) 7334f39514fSKuninori Morimoto { 7340ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 7354f39514fSKuninori Morimoto struct snd_soc_component *component; 7364f39514fSKuninori Morimoto int i, ret; 7374f39514fSKuninori Morimoto 7384f39514fSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 7394f39514fSKuninori Morimoto if (component->driver->prepare) { 7404f39514fSKuninori Morimoto ret = component->driver->prepare(component, substream); 7414f39514fSKuninori Morimoto if (ret < 0) 7424f39514fSKuninori Morimoto return soc_component_ret(component, ret); 7434f39514fSKuninori Morimoto } 7444f39514fSKuninori Morimoto } 7454f39514fSKuninori Morimoto 7464f39514fSKuninori Morimoto return 0; 7474f39514fSKuninori Morimoto } 748e1bafa82SKuninori Morimoto 749e1bafa82SKuninori Morimoto int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, 750e1bafa82SKuninori Morimoto struct snd_pcm_hw_params *params, 751e1bafa82SKuninori Morimoto struct snd_soc_component **last) 752e1bafa82SKuninori Morimoto { 7530ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 754e1bafa82SKuninori Morimoto struct snd_soc_component *component; 755e1bafa82SKuninori Morimoto int i, ret; 756e1bafa82SKuninori Morimoto 757e1bafa82SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 758e1bafa82SKuninori Morimoto if (component->driver->hw_params) { 759e1bafa82SKuninori Morimoto ret = component->driver->hw_params(component, 760e1bafa82SKuninori Morimoto substream, params); 761e1bafa82SKuninori Morimoto if (ret < 0) { 762e1bafa82SKuninori Morimoto *last = component; 763e1bafa82SKuninori Morimoto return soc_component_ret(component, ret); 764e1bafa82SKuninori Morimoto } 765e1bafa82SKuninori Morimoto } 766e1bafa82SKuninori Morimoto } 767e1bafa82SKuninori Morimoto 768e1bafa82SKuninori Morimoto *last = NULL; 769e1bafa82SKuninori Morimoto return 0; 770e1bafa82SKuninori Morimoto } 77104751119SKuninori Morimoto 77204751119SKuninori Morimoto void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, 77304751119SKuninori Morimoto struct snd_soc_component *last) 77404751119SKuninori Morimoto { 7750ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 77604751119SKuninori Morimoto struct snd_soc_component *component; 77704751119SKuninori Morimoto int i, ret; 77804751119SKuninori Morimoto 77904751119SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 78004751119SKuninori Morimoto if (component == last) 78104751119SKuninori Morimoto break; 78204751119SKuninori Morimoto 78304751119SKuninori Morimoto if (component->driver->hw_free) { 78404751119SKuninori Morimoto ret = component->driver->hw_free(component, substream); 78504751119SKuninori Morimoto if (ret < 0) 78604751119SKuninori Morimoto soc_component_ret(component, ret); 78704751119SKuninori Morimoto } 78804751119SKuninori Morimoto } 78904751119SKuninori Morimoto } 79032fd1204SKuninori Morimoto 79132fd1204SKuninori Morimoto int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, 79232fd1204SKuninori Morimoto int cmd) 79332fd1204SKuninori Morimoto { 7940ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 79532fd1204SKuninori Morimoto struct snd_soc_component *component; 79632fd1204SKuninori Morimoto int i, ret; 79732fd1204SKuninori Morimoto 79832fd1204SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 79932fd1204SKuninori Morimoto if (component->driver->trigger) { 80032fd1204SKuninori Morimoto ret = component->driver->trigger(component, substream, cmd); 80132fd1204SKuninori Morimoto if (ret < 0) 80232fd1204SKuninori Morimoto return soc_component_ret(component, ret); 80332fd1204SKuninori Morimoto } 80432fd1204SKuninori Morimoto } 80532fd1204SKuninori Morimoto 80632fd1204SKuninori Morimoto return 0; 80732fd1204SKuninori Morimoto } 808