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> 12939a5cfbSKuninori Morimoto #include <linux/pm_runtime.h> 134ff1fef1SKuninori Morimoto #include <sound/soc.h> 144ff1fef1SKuninori Morimoto 15e2329eebSKuninori Morimoto #define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret) 16e2329eebSKuninori Morimoto static inline int _soc_component_ret(struct snd_soc_component *component, 17e2329eebSKuninori Morimoto const char *func, int ret) 18e2329eebSKuninori Morimoto { 19e2329eebSKuninori Morimoto /* Positive/Zero values are not errors */ 20e2329eebSKuninori Morimoto if (ret >= 0) 21e2329eebSKuninori Morimoto return ret; 22e2329eebSKuninori Morimoto 23e2329eebSKuninori Morimoto /* Negative values might be errors */ 24e2329eebSKuninori Morimoto switch (ret) { 25e2329eebSKuninori Morimoto case -EPROBE_DEFER: 26e2329eebSKuninori Morimoto case -ENOTSUPP: 27e2329eebSKuninori Morimoto break; 28e2329eebSKuninori Morimoto default: 29e2329eebSKuninori Morimoto dev_err(component->dev, 30e2329eebSKuninori Morimoto "ASoC: error at %s on %s: %d\n", 31e2329eebSKuninori Morimoto func, component->name, ret); 32e2329eebSKuninori Morimoto } 33e2329eebSKuninori Morimoto 34e2329eebSKuninori Morimoto return ret; 35e2329eebSKuninori Morimoto } 36e2329eebSKuninori Morimoto 3751aff91aSKuninori Morimoto /* 3851aff91aSKuninori Morimoto * We might want to check substream by using list. 3951aff91aSKuninori Morimoto * In such case, we can update these macros. 4051aff91aSKuninori Morimoto */ 4151aff91aSKuninori Morimoto #define soc_component_mark_push(component, substream, tgt) ((component)->mark_##tgt = substream) 4251aff91aSKuninori Morimoto #define soc_component_mark_pop(component, substream, tgt) ((component)->mark_##tgt = NULL) 4351aff91aSKuninori Morimoto #define soc_component_mark_match(component, substream, tgt) ((component)->mark_##tgt == substream) 4451aff91aSKuninori Morimoto 45257c4dacSKuninori Morimoto void snd_soc_component_set_aux(struct snd_soc_component *component, 46257c4dacSKuninori Morimoto struct snd_soc_aux_dev *aux) 47257c4dacSKuninori Morimoto { 48257c4dacSKuninori Morimoto component->init = (aux) ? aux->init : NULL; 49257c4dacSKuninori Morimoto } 50257c4dacSKuninori Morimoto 51257c4dacSKuninori Morimoto int snd_soc_component_init(struct snd_soc_component *component) 52257c4dacSKuninori Morimoto { 53257c4dacSKuninori Morimoto int ret = 0; 54257c4dacSKuninori Morimoto 55257c4dacSKuninori Morimoto if (component->init) 56257c4dacSKuninori Morimoto ret = component->init(component); 57257c4dacSKuninori Morimoto 58257c4dacSKuninori Morimoto return soc_component_ret(component, ret); 59257c4dacSKuninori Morimoto } 60257c4dacSKuninori Morimoto 614ff1fef1SKuninori Morimoto /** 624ff1fef1SKuninori Morimoto * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. 634ff1fef1SKuninori Morimoto * @component: COMPONENT 644ff1fef1SKuninori Morimoto * @clk_id: DAI specific clock ID 654ff1fef1SKuninori Morimoto * @source: Source for the clock 664ff1fef1SKuninori Morimoto * @freq: new clock frequency in Hz 674ff1fef1SKuninori Morimoto * @dir: new clock direction - input/output. 684ff1fef1SKuninori Morimoto * 694ff1fef1SKuninori Morimoto * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. 704ff1fef1SKuninori Morimoto */ 714ff1fef1SKuninori Morimoto int snd_soc_component_set_sysclk(struct snd_soc_component *component, 724ff1fef1SKuninori Morimoto int clk_id, int source, unsigned int freq, 734ff1fef1SKuninori Morimoto int dir) 744ff1fef1SKuninori Morimoto { 75e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 76e2329eebSKuninori Morimoto 774ff1fef1SKuninori Morimoto if (component->driver->set_sysclk) 78e2329eebSKuninori Morimoto ret = component->driver->set_sysclk(component, clk_id, source, 794ff1fef1SKuninori Morimoto freq, dir); 804ff1fef1SKuninori Morimoto 81e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 824ff1fef1SKuninori Morimoto } 834ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); 844ff1fef1SKuninori Morimoto 854ff1fef1SKuninori Morimoto /* 864ff1fef1SKuninori Morimoto * snd_soc_component_set_pll - configure component PLL. 874ff1fef1SKuninori Morimoto * @component: COMPONENT 884ff1fef1SKuninori Morimoto * @pll_id: DAI specific PLL ID 894ff1fef1SKuninori Morimoto * @source: DAI specific source for the PLL 904ff1fef1SKuninori Morimoto * @freq_in: PLL input clock frequency in Hz 914ff1fef1SKuninori Morimoto * @freq_out: requested PLL output clock frequency in Hz 924ff1fef1SKuninori Morimoto * 934ff1fef1SKuninori Morimoto * Configures and enables PLL to generate output clock based on input clock. 944ff1fef1SKuninori Morimoto */ 954ff1fef1SKuninori Morimoto int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, 964ff1fef1SKuninori Morimoto int source, unsigned int freq_in, 974ff1fef1SKuninori Morimoto unsigned int freq_out) 984ff1fef1SKuninori Morimoto { 99e2329eebSKuninori Morimoto int ret = -EINVAL; 100e2329eebSKuninori Morimoto 1014ff1fef1SKuninori Morimoto if (component->driver->set_pll) 102e2329eebSKuninori Morimoto ret = component->driver->set_pll(component, pll_id, source, 1034ff1fef1SKuninori Morimoto freq_in, freq_out); 1044ff1fef1SKuninori Morimoto 105e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1064ff1fef1SKuninori Morimoto } 1074ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); 1084ff1fef1SKuninori Morimoto 1099d415fbfSKuninori Morimoto void snd_soc_component_seq_notifier(struct snd_soc_component *component, 1109d415fbfSKuninori Morimoto enum snd_soc_dapm_type type, int subseq) 1119d415fbfSKuninori Morimoto { 1129d415fbfSKuninori Morimoto if (component->driver->seq_notifier) 1139d415fbfSKuninori Morimoto component->driver->seq_notifier(component, type, subseq); 1149d415fbfSKuninori Morimoto } 1159d415fbfSKuninori Morimoto 1168e2a990dSKuninori Morimoto int snd_soc_component_stream_event(struct snd_soc_component *component, 1178e2a990dSKuninori Morimoto int event) 1188e2a990dSKuninori Morimoto { 119e2329eebSKuninori Morimoto int ret = 0; 1208e2a990dSKuninori Morimoto 121e2329eebSKuninori Morimoto if (component->driver->stream_event) 122e2329eebSKuninori Morimoto ret = component->driver->stream_event(component, event); 123e2329eebSKuninori Morimoto 124e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1258e2a990dSKuninori Morimoto } 1268e2a990dSKuninori Morimoto 1277951b146SKuninori Morimoto int snd_soc_component_set_bias_level(struct snd_soc_component *component, 1287951b146SKuninori Morimoto enum snd_soc_bias_level level) 1297951b146SKuninori Morimoto { 130e2329eebSKuninori Morimoto int ret = 0; 1317951b146SKuninori Morimoto 132e2329eebSKuninori Morimoto if (component->driver->set_bias_level) 133e2329eebSKuninori Morimoto ret = component->driver->set_bias_level(component, level); 134e2329eebSKuninori Morimoto 135e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1367951b146SKuninori Morimoto } 1377951b146SKuninori Morimoto 1384ca8701eSKuninori Morimoto static int soc_component_pin(struct snd_soc_component *component, 1394ca8701eSKuninori Morimoto const char *pin, 1404ca8701eSKuninori Morimoto int (*pin_func)(struct snd_soc_dapm_context *dapm, 1414ca8701eSKuninori Morimoto const char *pin)) 1424ff1fef1SKuninori Morimoto { 1434ff1fef1SKuninori Morimoto struct snd_soc_dapm_context *dapm = 1444ff1fef1SKuninori Morimoto snd_soc_component_get_dapm(component); 1454ff1fef1SKuninori Morimoto char *full_name; 1464ff1fef1SKuninori Morimoto int ret; 1474ff1fef1SKuninori Morimoto 148e2329eebSKuninori Morimoto if (!component->name_prefix) { 149e2329eebSKuninori Morimoto ret = pin_func(dapm, pin); 150e2329eebSKuninori Morimoto goto end; 151e2329eebSKuninori Morimoto } 1524ff1fef1SKuninori Morimoto 1534ff1fef1SKuninori Morimoto full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); 154e2329eebSKuninori Morimoto if (!full_name) { 155e2329eebSKuninori Morimoto ret = -ENOMEM; 156e2329eebSKuninori Morimoto goto end; 157e2329eebSKuninori Morimoto } 1584ff1fef1SKuninori Morimoto 1594ca8701eSKuninori Morimoto ret = pin_func(dapm, full_name); 1604ff1fef1SKuninori Morimoto kfree(full_name); 161e2329eebSKuninori Morimoto end: 162e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1634ff1fef1SKuninori Morimoto } 1644ca8701eSKuninori Morimoto 1654ca8701eSKuninori Morimoto int snd_soc_component_enable_pin(struct snd_soc_component *component, 1664ca8701eSKuninori Morimoto const char *pin) 1674ca8701eSKuninori Morimoto { 1684ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_enable_pin); 1694ca8701eSKuninori Morimoto } 1704ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); 1714ff1fef1SKuninori Morimoto 1724ff1fef1SKuninori Morimoto int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, 1734ff1fef1SKuninori Morimoto const char *pin) 1744ff1fef1SKuninori Morimoto { 1754ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked); 1764ff1fef1SKuninori Morimoto } 1774ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); 1784ff1fef1SKuninori Morimoto 1794ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin(struct snd_soc_component *component, 1804ff1fef1SKuninori Morimoto const char *pin) 1814ff1fef1SKuninori Morimoto { 1824ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_disable_pin); 1834ff1fef1SKuninori Morimoto } 1844ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); 1854ff1fef1SKuninori Morimoto 1864ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin_unlocked(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_unlocked); 1904ff1fef1SKuninori Morimoto } 1914ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); 1924ff1fef1SKuninori Morimoto 1934ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin(struct snd_soc_component *component, 1944ff1fef1SKuninori Morimoto const char *pin) 1954ff1fef1SKuninori Morimoto { 1964ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_nc_pin); 1974ff1fef1SKuninori Morimoto } 1984ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); 1994ff1fef1SKuninori Morimoto 2004ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin_unlocked(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_unlocked); 2044ff1fef1SKuninori Morimoto } 2054ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); 2064ff1fef1SKuninori Morimoto 2074ff1fef1SKuninori Morimoto int snd_soc_component_get_pin_status(struct snd_soc_component *component, 2084ff1fef1SKuninori Morimoto const char *pin) 2094ff1fef1SKuninori Morimoto { 2104ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status); 2114ff1fef1SKuninori Morimoto } 2124ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); 2134ff1fef1SKuninori Morimoto 2144ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin(struct snd_soc_component *component, 2154ff1fef1SKuninori Morimoto const char *pin) 2164ff1fef1SKuninori Morimoto { 2174ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin); 2184ff1fef1SKuninori Morimoto } 2194ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); 2204ff1fef1SKuninori Morimoto 2214ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin_unlocked( 2224ff1fef1SKuninori Morimoto struct snd_soc_component *component, 2234ff1fef1SKuninori Morimoto const char *pin) 2244ff1fef1SKuninori Morimoto { 2254ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked); 2264ff1fef1SKuninori Morimoto } 2274ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); 2284ff1fef1SKuninori Morimoto 2294ff1fef1SKuninori Morimoto /** 2304ff1fef1SKuninori Morimoto * snd_soc_component_set_jack - configure component jack. 2314ff1fef1SKuninori Morimoto * @component: COMPONENTs 2324ff1fef1SKuninori Morimoto * @jack: structure to use for the jack 2334ff1fef1SKuninori Morimoto * @data: can be used if codec driver need extra data for configuring jack 2344ff1fef1SKuninori Morimoto * 2354ff1fef1SKuninori Morimoto * Configures and enables jack detection function. 2364ff1fef1SKuninori Morimoto */ 2374ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component, 2384ff1fef1SKuninori Morimoto struct snd_soc_jack *jack, void *data) 2394ff1fef1SKuninori Morimoto { 240e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 2414ff1fef1SKuninori Morimoto 242e2329eebSKuninori Morimoto if (component->driver->set_jack) 243e2329eebSKuninori Morimoto ret = component->driver->set_jack(component, jack, data); 244e2329eebSKuninori Morimoto 245e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2464ff1fef1SKuninori Morimoto } 2474ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); 2484a81e8f3SKuninori Morimoto 2494a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component, 25051aff91aSKuninori Morimoto struct snd_pcm_substream *substream, 2514a81e8f3SKuninori Morimoto int upon_open) 2524a81e8f3SKuninori Morimoto { 253e2329eebSKuninori Morimoto int ret = 0; 254e2329eebSKuninori Morimoto 2554a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open && 2564a81e8f3SKuninori Morimoto !try_module_get(component->dev->driver->owner)) 257e2329eebSKuninori Morimoto ret = -ENODEV; 2584a81e8f3SKuninori Morimoto 25951aff91aSKuninori Morimoto /* mark substream if succeeded */ 26051aff91aSKuninori Morimoto if (ret == 0) 26151aff91aSKuninori Morimoto soc_component_mark_push(component, substream, module); 26251aff91aSKuninori Morimoto 263e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2644a81e8f3SKuninori Morimoto } 2654a81e8f3SKuninori Morimoto 2664a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component, 26751aff91aSKuninori Morimoto struct snd_pcm_substream *substream, 26851aff91aSKuninori Morimoto int upon_open, int rollback) 2694a81e8f3SKuninori Morimoto { 27051aff91aSKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, module)) 27151aff91aSKuninori Morimoto return; 27251aff91aSKuninori Morimoto 2734a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open) 2744a81e8f3SKuninori Morimoto module_put(component->dev->driver->owner); 27551aff91aSKuninori Morimoto 27651aff91aSKuninori Morimoto /* remove marked substream */ 27751aff91aSKuninori Morimoto soc_component_mark_pop(component, substream, module); 2784a81e8f3SKuninori Morimoto } 279ae2f4849SKuninori Morimoto 280ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component, 281ae2f4849SKuninori Morimoto struct snd_pcm_substream *substream) 282ae2f4849SKuninori Morimoto { 283e2329eebSKuninori Morimoto int ret = 0; 284e2329eebSKuninori Morimoto 285e2cb4a14SKuninori Morimoto if (component->driver->open) 286e2329eebSKuninori Morimoto ret = component->driver->open(component, substream); 287e2329eebSKuninori Morimoto 28851aff91aSKuninori Morimoto /* mark substream if succeeded */ 28951aff91aSKuninori Morimoto if (ret == 0) 29051aff91aSKuninori Morimoto soc_component_mark_push(component, substream, open); 29151aff91aSKuninori Morimoto 292e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 293ae2f4849SKuninori Morimoto } 2943672beb8SKuninori Morimoto 2953672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component, 29651aff91aSKuninori Morimoto struct snd_pcm_substream *substream, 29751aff91aSKuninori Morimoto int rollback) 2983672beb8SKuninori Morimoto { 299e2329eebSKuninori Morimoto int ret = 0; 300e2329eebSKuninori Morimoto 30151aff91aSKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, open)) 30251aff91aSKuninori Morimoto return 0; 30351aff91aSKuninori Morimoto 304e2cb4a14SKuninori Morimoto if (component->driver->close) 305e2329eebSKuninori Morimoto ret = component->driver->close(component, substream); 306e2329eebSKuninori Morimoto 30751aff91aSKuninori Morimoto /* remove marked substream */ 30851aff91aSKuninori Morimoto soc_component_mark_pop(component, substream, open); 30951aff91aSKuninori Morimoto 310e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 3113672beb8SKuninori Morimoto } 3126d537233SKuninori Morimoto 31366c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component) 31466c51573SKuninori Morimoto { 31566c51573SKuninori Morimoto if (component->driver->suspend) 31666c51573SKuninori Morimoto component->driver->suspend(component); 31766c51573SKuninori Morimoto component->suspended = 1; 31866c51573SKuninori Morimoto } 3199a840cbaSKuninori Morimoto 3209a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component) 3219a840cbaSKuninori Morimoto { 3229a840cbaSKuninori Morimoto if (component->driver->resume) 3239a840cbaSKuninori Morimoto component->driver->resume(component); 3249a840cbaSKuninori Morimoto component->suspended = 0; 3259a840cbaSKuninori Morimoto } 326e40fadbcSKuninori Morimoto 327e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component) 328e40fadbcSKuninori Morimoto { 329e40fadbcSKuninori Morimoto return component->suspended; 330e40fadbcSKuninori Morimoto } 33108e837ddSKuninori Morimoto 33208e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component) 33308e837ddSKuninori Morimoto { 334e2329eebSKuninori Morimoto int ret = 0; 33508e837ddSKuninori Morimoto 336e2329eebSKuninori Morimoto if (component->driver->probe) 337e2329eebSKuninori Morimoto ret = component->driver->probe(component); 338e2329eebSKuninori Morimoto 339e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 34008e837ddSKuninori Morimoto } 34103b34dd7SKuninori Morimoto 34203b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component) 34303b34dd7SKuninori Morimoto { 34403b34dd7SKuninori Morimoto if (component->driver->remove) 34503b34dd7SKuninori Morimoto component->driver->remove(component); 34603b34dd7SKuninori Morimoto } 3472c7b1704SKuninori Morimoto 3482c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, 3492c7b1704SKuninori Morimoto struct device_node *ep) 3502c7b1704SKuninori Morimoto { 351e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 3522c7b1704SKuninori Morimoto 353e2329eebSKuninori Morimoto if (component->driver->of_xlate_dai_id) 354e2329eebSKuninori Morimoto ret = component->driver->of_xlate_dai_id(component, ep); 355e2329eebSKuninori Morimoto 356e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 3572c7b1704SKuninori Morimoto } 358a2a34175SKuninori Morimoto 359a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, 360a2a34175SKuninori Morimoto struct of_phandle_args *args, 361a2a34175SKuninori Morimoto const char **dai_name) 362a2a34175SKuninori Morimoto { 363a2a34175SKuninori Morimoto if (component->driver->of_xlate_dai_name) 364cc4d8cebSJerome Brunet return component->driver->of_xlate_dai_name(component, 365a2a34175SKuninori Morimoto args, dai_name); 366cc4d8cebSJerome Brunet /* 367cc4d8cebSJerome Brunet * Don't use soc_component_ret here because we may not want to report 368cc4d8cebSJerome Brunet * the error just yet. If a device has more than one component, the 369cc4d8cebSJerome Brunet * first may not match and we don't want spam the log with this. 370cc4d8cebSJerome Brunet */ 371cc4d8cebSJerome Brunet return -ENOTSUPP; 372a2a34175SKuninori Morimoto } 3730035e256SKuninori Morimoto 374c7d75b59SKuninori Morimoto void snd_soc_component_setup_regmap(struct snd_soc_component *component) 375c7d75b59SKuninori Morimoto { 376c7d75b59SKuninori Morimoto int val_bytes = regmap_get_val_bytes(component->regmap); 377c7d75b59SKuninori Morimoto 378c7d75b59SKuninori Morimoto /* Errors are legitimate for non-integer byte multiples */ 379c7d75b59SKuninori Morimoto if (val_bytes > 0) 380c7d75b59SKuninori Morimoto component->val_bytes = val_bytes; 381c7d75b59SKuninori Morimoto } 382c7d75b59SKuninori Morimoto 383c7d75b59SKuninori Morimoto #ifdef CONFIG_REGMAP 384c7d75b59SKuninori Morimoto 385c7d75b59SKuninori Morimoto /** 386c7d75b59SKuninori Morimoto * snd_soc_component_init_regmap() - Initialize regmap instance for the 387c7d75b59SKuninori Morimoto * component 388c7d75b59SKuninori Morimoto * @component: The component for which to initialize the regmap instance 389c7d75b59SKuninori Morimoto * @regmap: The regmap instance that should be used by the component 390c7d75b59SKuninori Morimoto * 391c7d75b59SKuninori Morimoto * This function allows deferred assignment of the regmap instance that is 392c7d75b59SKuninori Morimoto * associated with the component. Only use this if the regmap instance is not 393c7d75b59SKuninori Morimoto * yet ready when the component is registered. The function must also be called 394c7d75b59SKuninori Morimoto * before the first IO attempt of the component. 395c7d75b59SKuninori Morimoto */ 396c7d75b59SKuninori Morimoto void snd_soc_component_init_regmap(struct snd_soc_component *component, 397c7d75b59SKuninori Morimoto struct regmap *regmap) 398c7d75b59SKuninori Morimoto { 399c7d75b59SKuninori Morimoto component->regmap = regmap; 400c7d75b59SKuninori Morimoto snd_soc_component_setup_regmap(component); 401c7d75b59SKuninori Morimoto } 402c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); 403c7d75b59SKuninori Morimoto 404c7d75b59SKuninori Morimoto /** 405c7d75b59SKuninori Morimoto * snd_soc_component_exit_regmap() - De-initialize regmap instance for the 406c7d75b59SKuninori Morimoto * component 407c7d75b59SKuninori Morimoto * @component: The component for which to de-initialize the regmap instance 408c7d75b59SKuninori Morimoto * 409c7d75b59SKuninori Morimoto * Calls regmap_exit() on the regmap instance associated to the component and 410c7d75b59SKuninori Morimoto * removes the regmap instance from the component. 411c7d75b59SKuninori Morimoto * 412c7d75b59SKuninori Morimoto * This function should only be used if snd_soc_component_init_regmap() was used 413c7d75b59SKuninori Morimoto * to initialize the regmap instance. 414c7d75b59SKuninori Morimoto */ 415c7d75b59SKuninori Morimoto void snd_soc_component_exit_regmap(struct snd_soc_component *component) 416c7d75b59SKuninori Morimoto { 417c7d75b59SKuninori Morimoto regmap_exit(component->regmap); 418c7d75b59SKuninori Morimoto component->regmap = NULL; 419c7d75b59SKuninori Morimoto } 420c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); 421c7d75b59SKuninori Morimoto 422c7d75b59SKuninori Morimoto #endif 423c7d75b59SKuninori Morimoto 424f94ba9acSKuninori Morimoto int snd_soc_component_compr_open(struct snd_compr_stream *cstream) 425a4e427c5SKuninori Morimoto { 426a4e427c5SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 427a4e427c5SKuninori Morimoto struct snd_soc_component *component; 428a4e427c5SKuninori Morimoto int i, ret; 429a4e427c5SKuninori Morimoto 430a4e427c5SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 431a4e427c5SKuninori Morimoto if (component->driver->compress_ops && 432a4e427c5SKuninori Morimoto component->driver->compress_ops->open) { 433a4e427c5SKuninori Morimoto ret = component->driver->compress_ops->open(component, cstream); 434f94ba9acSKuninori Morimoto if (ret < 0) 435a4e427c5SKuninori Morimoto return soc_component_ret(component, ret); 436a4e427c5SKuninori Morimoto } 437f94ba9acSKuninori Morimoto soc_component_mark_push(component, cstream, compr_open); 438a4e427c5SKuninori Morimoto } 439a4e427c5SKuninori Morimoto 440a4e427c5SKuninori Morimoto return 0; 441a4e427c5SKuninori Morimoto } 442a4e427c5SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_open); 443a4e427c5SKuninori Morimoto 444dbde5e21SKuninori Morimoto void snd_soc_component_compr_free(struct snd_compr_stream *cstream, 445f94ba9acSKuninori Morimoto int rollback) 446dbde5e21SKuninori Morimoto { 447dbde5e21SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 448dbde5e21SKuninori Morimoto struct snd_soc_component *component; 449dbde5e21SKuninori Morimoto int i; 450dbde5e21SKuninori Morimoto 451dbde5e21SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 452f94ba9acSKuninori Morimoto if (rollback && !soc_component_mark_match(component, cstream, compr_open)) 453f94ba9acSKuninori Morimoto continue; 454dbde5e21SKuninori Morimoto 455dbde5e21SKuninori Morimoto if (component->driver->compress_ops && 456dbde5e21SKuninori Morimoto component->driver->compress_ops->free) 457dbde5e21SKuninori Morimoto component->driver->compress_ops->free(component, cstream); 458f94ba9acSKuninori Morimoto 459f94ba9acSKuninori Morimoto soc_component_mark_pop(component, cstream, compr_open); 460dbde5e21SKuninori Morimoto } 461dbde5e21SKuninori Morimoto } 462dbde5e21SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_free); 463dbde5e21SKuninori Morimoto 46408aee251SKuninori Morimoto int snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd) 46508aee251SKuninori Morimoto { 46608aee251SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 46708aee251SKuninori Morimoto struct snd_soc_component *component; 46808aee251SKuninori Morimoto int i, ret; 46908aee251SKuninori Morimoto 47008aee251SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 47108aee251SKuninori Morimoto if (component->driver->compress_ops && 47208aee251SKuninori Morimoto component->driver->compress_ops->trigger) { 47308aee251SKuninori Morimoto ret = component->driver->compress_ops->trigger( 47408aee251SKuninori Morimoto component, cstream, cmd); 47508aee251SKuninori Morimoto if (ret < 0) 47608aee251SKuninori Morimoto return soc_component_ret(component, ret); 47708aee251SKuninori Morimoto } 47808aee251SKuninori Morimoto } 47908aee251SKuninori Morimoto 48008aee251SKuninori Morimoto return 0; 48108aee251SKuninori Morimoto } 48208aee251SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_trigger); 48308aee251SKuninori Morimoto 484ff08cf80SKuninori Morimoto int snd_soc_component_compr_set_params(struct snd_compr_stream *cstream, 485ff08cf80SKuninori Morimoto struct snd_compr_params *params) 486ff08cf80SKuninori Morimoto { 487ff08cf80SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 488ff08cf80SKuninori Morimoto struct snd_soc_component *component; 489ff08cf80SKuninori Morimoto int i, ret; 490ff08cf80SKuninori Morimoto 491ff08cf80SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 492ff08cf80SKuninori Morimoto if (component->driver->compress_ops && 493ff08cf80SKuninori Morimoto component->driver->compress_ops->set_params) { 494ff08cf80SKuninori Morimoto ret = component->driver->compress_ops->set_params( 495ff08cf80SKuninori Morimoto component, cstream, params); 496ff08cf80SKuninori Morimoto if (ret < 0) 497ff08cf80SKuninori Morimoto return soc_component_ret(component, ret); 498ff08cf80SKuninori Morimoto } 499ff08cf80SKuninori Morimoto } 500ff08cf80SKuninori Morimoto 501ff08cf80SKuninori Morimoto return 0; 502ff08cf80SKuninori Morimoto } 503ff08cf80SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_params); 504ff08cf80SKuninori Morimoto 50577c221ecSKuninori Morimoto int snd_soc_component_compr_get_params(struct snd_compr_stream *cstream, 50677c221ecSKuninori Morimoto struct snd_codec *params) 50777c221ecSKuninori Morimoto { 50877c221ecSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 50977c221ecSKuninori Morimoto struct snd_soc_component *component; 51077c221ecSKuninori Morimoto int i, ret; 51177c221ecSKuninori Morimoto 51277c221ecSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 51377c221ecSKuninori Morimoto if (component->driver->compress_ops && 51477c221ecSKuninori Morimoto component->driver->compress_ops->get_params) { 51577c221ecSKuninori Morimoto ret = component->driver->compress_ops->get_params( 51677c221ecSKuninori Morimoto component, cstream, params); 51777c221ecSKuninori Morimoto return soc_component_ret(component, ret); 51877c221ecSKuninori Morimoto } 51977c221ecSKuninori Morimoto } 52077c221ecSKuninori Morimoto 52177c221ecSKuninori Morimoto return 0; 52277c221ecSKuninori Morimoto } 52377c221ecSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_params); 52477c221ecSKuninori Morimoto 525d67fcb2dSKuninori Morimoto int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream, 526d67fcb2dSKuninori Morimoto struct snd_compr_caps *caps) 527d67fcb2dSKuninori Morimoto { 528d67fcb2dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 529d67fcb2dSKuninori Morimoto struct snd_soc_component *component; 530d67fcb2dSKuninori Morimoto int i, ret = 0; 531d67fcb2dSKuninori Morimoto 532d67fcb2dSKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 533d67fcb2dSKuninori Morimoto 534d67fcb2dSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 535d67fcb2dSKuninori Morimoto if (component->driver->compress_ops && 536d67fcb2dSKuninori Morimoto component->driver->compress_ops->get_caps) { 537d67fcb2dSKuninori Morimoto ret = component->driver->compress_ops->get_caps( 538d67fcb2dSKuninori Morimoto component, cstream, caps); 539d67fcb2dSKuninori Morimoto break; 540d67fcb2dSKuninori Morimoto } 541d67fcb2dSKuninori Morimoto } 542d67fcb2dSKuninori Morimoto 543d67fcb2dSKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 544d67fcb2dSKuninori Morimoto 545d67fcb2dSKuninori Morimoto return soc_component_ret(component, ret); 546d67fcb2dSKuninori Morimoto } 547d67fcb2dSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_caps); 548d67fcb2dSKuninori Morimoto 5490f6fe097SKuninori Morimoto int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, 5500f6fe097SKuninori Morimoto struct snd_compr_codec_caps *codec) 5510f6fe097SKuninori Morimoto { 5520f6fe097SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5530f6fe097SKuninori Morimoto struct snd_soc_component *component; 5540f6fe097SKuninori Morimoto int i, ret = 0; 5550f6fe097SKuninori Morimoto 5560f6fe097SKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 5570f6fe097SKuninori Morimoto 5580f6fe097SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 5590f6fe097SKuninori Morimoto if (component->driver->compress_ops && 5600f6fe097SKuninori Morimoto component->driver->compress_ops->get_codec_caps) { 5610f6fe097SKuninori Morimoto ret = component->driver->compress_ops->get_codec_caps( 5620f6fe097SKuninori Morimoto component, cstream, codec); 5630f6fe097SKuninori Morimoto break; 5640f6fe097SKuninori Morimoto } 5650f6fe097SKuninori Morimoto } 5660f6fe097SKuninori Morimoto 5670f6fe097SKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 5680f6fe097SKuninori Morimoto 5690f6fe097SKuninori Morimoto return soc_component_ret(component, ret); 5700f6fe097SKuninori Morimoto } 5710f6fe097SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_codec_caps); 5720f6fe097SKuninori Morimoto 5730506b885SKuninori Morimoto int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 5740506b885SKuninori Morimoto { 5750506b885SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5760506b885SKuninori Morimoto struct snd_soc_component *component; 5770506b885SKuninori Morimoto int i, ret; 5780506b885SKuninori Morimoto 5790506b885SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 5800506b885SKuninori Morimoto if (component->driver->compress_ops && 5810506b885SKuninori Morimoto component->driver->compress_ops->ack) { 5820506b885SKuninori Morimoto ret = component->driver->compress_ops->ack( 5830506b885SKuninori Morimoto component, cstream, bytes); 5840506b885SKuninori Morimoto if (ret < 0) 5850506b885SKuninori Morimoto return soc_component_ret(component, ret); 5860506b885SKuninori Morimoto } 5870506b885SKuninori Morimoto } 5880506b885SKuninori Morimoto 5890506b885SKuninori Morimoto return 0; 5900506b885SKuninori Morimoto } 5910506b885SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack); 5920506b885SKuninori Morimoto 59303ecea64SKuninori Morimoto int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream, 59403ecea64SKuninori Morimoto struct snd_compr_tstamp *tstamp) 59503ecea64SKuninori Morimoto { 59603ecea64SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 59703ecea64SKuninori Morimoto struct snd_soc_component *component; 59803ecea64SKuninori Morimoto int i, ret; 59903ecea64SKuninori Morimoto 60003ecea64SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 60103ecea64SKuninori Morimoto if (component->driver->compress_ops && 60203ecea64SKuninori Morimoto component->driver->compress_ops->pointer) { 60303ecea64SKuninori Morimoto ret = component->driver->compress_ops->pointer( 60403ecea64SKuninori Morimoto component, cstream, tstamp); 60503ecea64SKuninori Morimoto return soc_component_ret(component, ret); 60603ecea64SKuninori Morimoto } 60703ecea64SKuninori Morimoto } 60803ecea64SKuninori Morimoto 60903ecea64SKuninori Morimoto return 0; 61003ecea64SKuninori Morimoto } 61103ecea64SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_pointer); 61203ecea64SKuninori Morimoto 613b5852e66SKuninori Morimoto int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, 614b5852e66SKuninori Morimoto char __user *buf, size_t count) 615b5852e66SKuninori Morimoto { 616b5852e66SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 617b5852e66SKuninori Morimoto struct snd_soc_component *component; 618b5852e66SKuninori Morimoto int i, ret = 0; 619b5852e66SKuninori Morimoto 620b5852e66SKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 621b5852e66SKuninori Morimoto 622b5852e66SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 623b5852e66SKuninori Morimoto if (component->driver->compress_ops && 624b5852e66SKuninori Morimoto component->driver->compress_ops->copy) { 625b5852e66SKuninori Morimoto ret = component->driver->compress_ops->copy( 626b5852e66SKuninori Morimoto component, cstream, buf, count); 627b5852e66SKuninori Morimoto break; 628b5852e66SKuninori Morimoto } 629b5852e66SKuninori Morimoto } 630b5852e66SKuninori Morimoto 631b5852e66SKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 632b5852e66SKuninori Morimoto 633b5852e66SKuninori Morimoto return soc_component_ret(component, ret); 634b5852e66SKuninori Morimoto } 635b5852e66SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_copy); 636b5852e66SKuninori Morimoto 6371b308fb1SKuninori Morimoto int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream, 6381b308fb1SKuninori Morimoto struct snd_compr_metadata *metadata) 6391b308fb1SKuninori Morimoto { 6401b308fb1SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 6411b308fb1SKuninori Morimoto struct snd_soc_component *component; 6421b308fb1SKuninori Morimoto int i, ret; 6431b308fb1SKuninori Morimoto 6441b308fb1SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 6451b308fb1SKuninori Morimoto if (component->driver->compress_ops && 6461b308fb1SKuninori Morimoto component->driver->compress_ops->set_metadata) { 6471b308fb1SKuninori Morimoto ret = component->driver->compress_ops->set_metadata( 6481b308fb1SKuninori Morimoto component, cstream, metadata); 6491b308fb1SKuninori Morimoto if (ret < 0) 6501b308fb1SKuninori Morimoto return soc_component_ret(component, ret); 6511b308fb1SKuninori Morimoto } 6521b308fb1SKuninori Morimoto } 6531b308fb1SKuninori Morimoto 6541b308fb1SKuninori Morimoto return 0; 6551b308fb1SKuninori Morimoto } 6561b308fb1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_metadata); 6571b308fb1SKuninori Morimoto 658bab78c23SKuninori Morimoto int snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream, 659bab78c23SKuninori Morimoto struct snd_compr_metadata *metadata) 660bab78c23SKuninori Morimoto { 661bab78c23SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 662bab78c23SKuninori Morimoto struct snd_soc_component *component; 663bab78c23SKuninori Morimoto int i, ret; 664bab78c23SKuninori Morimoto 665bab78c23SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 666bab78c23SKuninori Morimoto if (component->driver->compress_ops && 667bab78c23SKuninori Morimoto component->driver->compress_ops->get_metadata) { 668bab78c23SKuninori Morimoto ret = component->driver->compress_ops->get_metadata( 669bab78c23SKuninori Morimoto component, cstream, metadata); 670bab78c23SKuninori Morimoto return soc_component_ret(component, ret); 671bab78c23SKuninori Morimoto } 672bab78c23SKuninori Morimoto } 673bab78c23SKuninori Morimoto 674bab78c23SKuninori Morimoto return 0; 675bab78c23SKuninori Morimoto } 676bab78c23SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_metadata); 677bab78c23SKuninori Morimoto 678e8712315SKuninori Morimoto static unsigned int soc_component_read_no_lock( 679e8712315SKuninori Morimoto struct snd_soc_component *component, 680cf6e26c7SKuninori Morimoto unsigned int reg) 681460b42d1SKuninori Morimoto { 682460b42d1SKuninori Morimoto int ret; 683cf6e26c7SKuninori Morimoto unsigned int val = 0; 684460b42d1SKuninori Morimoto 685460b42d1SKuninori Morimoto if (component->regmap) 686cf6e26c7SKuninori Morimoto ret = regmap_read(component->regmap, reg, &val); 687460b42d1SKuninori Morimoto else if (component->driver->read) { 688460b42d1SKuninori Morimoto ret = 0; 689cf6e26c7SKuninori Morimoto val = component->driver->read(component, reg); 690460b42d1SKuninori Morimoto } 691460b42d1SKuninori Morimoto else 692460b42d1SKuninori Morimoto ret = -EIO; 693460b42d1SKuninori Morimoto 694460b42d1SKuninori Morimoto if (ret < 0) 695efc913c8STakashi Iwai return soc_component_ret(component, ret); 696460b42d1SKuninori Morimoto 697460b42d1SKuninori Morimoto return val; 698460b42d1SKuninori Morimoto } 699e8712315SKuninori Morimoto 700e8712315SKuninori Morimoto /** 701e8712315SKuninori Morimoto * snd_soc_component_read() - Read register value 702e8712315SKuninori Morimoto * @component: Component to read from 703e8712315SKuninori Morimoto * @reg: Register to read 704e8712315SKuninori Morimoto * 705e8712315SKuninori Morimoto * Return: read value 706e8712315SKuninori Morimoto */ 707e8712315SKuninori Morimoto unsigned int snd_soc_component_read(struct snd_soc_component *component, 708e8712315SKuninori Morimoto unsigned int reg) 709e8712315SKuninori Morimoto { 710e8712315SKuninori Morimoto unsigned int val; 711e8712315SKuninori Morimoto 712e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 713e8712315SKuninori Morimoto val = soc_component_read_no_lock(component, reg); 714e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 715e8712315SKuninori Morimoto 716e8712315SKuninori Morimoto return val; 717e8712315SKuninori Morimoto } 718cf6e26c7SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_read); 719460b42d1SKuninori Morimoto 720e8712315SKuninori Morimoto static int soc_component_write_no_lock( 721e8712315SKuninori Morimoto struct snd_soc_component *component, 722e8712315SKuninori Morimoto unsigned int reg, unsigned int val) 723e8712315SKuninori Morimoto { 724e8712315SKuninori Morimoto int ret = -EIO; 725e8712315SKuninori Morimoto 726e8712315SKuninori Morimoto if (component->regmap) 727e8712315SKuninori Morimoto ret = regmap_write(component->regmap, reg, val); 728e8712315SKuninori Morimoto else if (component->driver->write) 729e8712315SKuninori Morimoto ret = component->driver->write(component, reg, val); 730e8712315SKuninori Morimoto 731e8712315SKuninori Morimoto return soc_component_ret(component, ret); 732e8712315SKuninori Morimoto } 733e8712315SKuninori Morimoto 734460b42d1SKuninori Morimoto /** 735460b42d1SKuninori Morimoto * snd_soc_component_write() - Write register value 736460b42d1SKuninori Morimoto * @component: Component to write to 737460b42d1SKuninori Morimoto * @reg: Register to write 738460b42d1SKuninori Morimoto * @val: Value to write to the register 739460b42d1SKuninori Morimoto * 740460b42d1SKuninori Morimoto * Return: 0 on success, a negative error code otherwise. 741460b42d1SKuninori Morimoto */ 742460b42d1SKuninori Morimoto int snd_soc_component_write(struct snd_soc_component *component, 743460b42d1SKuninori Morimoto unsigned int reg, unsigned int val) 744460b42d1SKuninori Morimoto { 745e8712315SKuninori Morimoto int ret; 746460b42d1SKuninori Morimoto 747e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 748e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, val); 749e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 750460b42d1SKuninori Morimoto 751e8712315SKuninori Morimoto return ret; 752460b42d1SKuninori Morimoto } 753460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_write); 754460b42d1SKuninori Morimoto 755460b42d1SKuninori Morimoto static int snd_soc_component_update_bits_legacy( 756460b42d1SKuninori Morimoto struct snd_soc_component *component, unsigned int reg, 757460b42d1SKuninori Morimoto unsigned int mask, unsigned int val, bool *change) 758460b42d1SKuninori Morimoto { 759460b42d1SKuninori Morimoto unsigned int old, new; 760cf6e26c7SKuninori Morimoto int ret = 0; 761460b42d1SKuninori Morimoto 762460b42d1SKuninori Morimoto mutex_lock(&component->io_mutex); 763460b42d1SKuninori Morimoto 764e8712315SKuninori Morimoto old = soc_component_read_no_lock(component, reg); 765460b42d1SKuninori Morimoto 766460b42d1SKuninori Morimoto new = (old & ~mask) | (val & mask); 767460b42d1SKuninori Morimoto *change = old != new; 768460b42d1SKuninori Morimoto if (*change) 769e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, new); 770cf6e26c7SKuninori Morimoto 771460b42d1SKuninori Morimoto mutex_unlock(&component->io_mutex); 772460b42d1SKuninori Morimoto 773460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 774460b42d1SKuninori Morimoto } 775460b42d1SKuninori Morimoto 776460b42d1SKuninori Morimoto /** 777460b42d1SKuninori Morimoto * snd_soc_component_update_bits() - Perform read/modify/write cycle 778460b42d1SKuninori Morimoto * @component: Component to update 779460b42d1SKuninori Morimoto * @reg: Register to update 780460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 781460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 782460b42d1SKuninori Morimoto * 783460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 784460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 785460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 786460b42d1SKuninori Morimoto */ 787460b42d1SKuninori Morimoto int snd_soc_component_update_bits(struct snd_soc_component *component, 788460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 789460b42d1SKuninori Morimoto { 790460b42d1SKuninori Morimoto bool change; 791460b42d1SKuninori Morimoto int ret; 792460b42d1SKuninori Morimoto 793460b42d1SKuninori Morimoto if (component->regmap) 794460b42d1SKuninori Morimoto ret = regmap_update_bits_check(component->regmap, reg, mask, 795460b42d1SKuninori Morimoto val, &change); 796460b42d1SKuninori Morimoto else 797460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 798460b42d1SKuninori Morimoto mask, val, &change); 799460b42d1SKuninori Morimoto 800460b42d1SKuninori Morimoto if (ret < 0) 801460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 802460b42d1SKuninori Morimoto return change; 803460b42d1SKuninori Morimoto } 804460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); 805460b42d1SKuninori Morimoto 806460b42d1SKuninori Morimoto /** 807460b42d1SKuninori Morimoto * snd_soc_component_update_bits_async() - Perform asynchronous 808460b42d1SKuninori Morimoto * read/modify/write cycle 809460b42d1SKuninori Morimoto * @component: Component to update 810460b42d1SKuninori Morimoto * @reg: Register to update 811460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 812460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 813460b42d1SKuninori Morimoto * 814460b42d1SKuninori Morimoto * This function is similar to snd_soc_component_update_bits(), but the update 815460b42d1SKuninori Morimoto * operation is scheduled asynchronously. This means it may not be completed 816460b42d1SKuninori Morimoto * when the function returns. To make sure that all scheduled updates have been 817460b42d1SKuninori Morimoto * completed snd_soc_component_async_complete() must be called. 818460b42d1SKuninori Morimoto * 819460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 820460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 821460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 822460b42d1SKuninori Morimoto */ 823460b42d1SKuninori Morimoto int snd_soc_component_update_bits_async(struct snd_soc_component *component, 824460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 825460b42d1SKuninori Morimoto { 826460b42d1SKuninori Morimoto bool change; 827460b42d1SKuninori Morimoto int ret; 828460b42d1SKuninori Morimoto 829460b42d1SKuninori Morimoto if (component->regmap) 830460b42d1SKuninori Morimoto ret = regmap_update_bits_check_async(component->regmap, reg, 831460b42d1SKuninori Morimoto mask, val, &change); 832460b42d1SKuninori Morimoto else 833460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 834460b42d1SKuninori Morimoto mask, val, &change); 835460b42d1SKuninori Morimoto 836460b42d1SKuninori Morimoto if (ret < 0) 837460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 838460b42d1SKuninori Morimoto return change; 839460b42d1SKuninori Morimoto } 840460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); 841460b42d1SKuninori Morimoto 842460b42d1SKuninori Morimoto /** 843460b42d1SKuninori Morimoto * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed 844460b42d1SKuninori Morimoto * @component: Component for which to wait 845460b42d1SKuninori Morimoto * 846460b42d1SKuninori Morimoto * This function blocks until all asynchronous I/O which has previously been 847460b42d1SKuninori Morimoto * scheduled using snd_soc_component_update_bits_async() has completed. 848460b42d1SKuninori Morimoto */ 849460b42d1SKuninori Morimoto void snd_soc_component_async_complete(struct snd_soc_component *component) 850460b42d1SKuninori Morimoto { 851460b42d1SKuninori Morimoto if (component->regmap) 852460b42d1SKuninori Morimoto regmap_async_complete(component->regmap); 853460b42d1SKuninori Morimoto } 854460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); 855460b42d1SKuninori Morimoto 856460b42d1SKuninori Morimoto /** 857460b42d1SKuninori Morimoto * snd_soc_component_test_bits - Test register for change 858460b42d1SKuninori Morimoto * @component: component 859460b42d1SKuninori Morimoto * @reg: Register to test 860460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to test 861460b42d1SKuninori Morimoto * @value: Value to test against 862460b42d1SKuninori Morimoto * 863460b42d1SKuninori Morimoto * Tests a register with a new value and checks if the new value is 864460b42d1SKuninori Morimoto * different from the old value. 865460b42d1SKuninori Morimoto * 866460b42d1SKuninori Morimoto * Return: 1 for change, otherwise 0. 867460b42d1SKuninori Morimoto */ 868460b42d1SKuninori Morimoto int snd_soc_component_test_bits(struct snd_soc_component *component, 869460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int value) 870460b42d1SKuninori Morimoto { 871460b42d1SKuninori Morimoto unsigned int old, new; 872460b42d1SKuninori Morimoto 873cf6e26c7SKuninori Morimoto old = snd_soc_component_read(component, reg); 874460b42d1SKuninori Morimoto new = (old & ~mask) | value; 875460b42d1SKuninori Morimoto return old != new; 876460b42d1SKuninori Morimoto } 877460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); 878460b42d1SKuninori Morimoto 8790035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) 8800035e256SKuninori Morimoto { 8810ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 8820035e256SKuninori Morimoto struct snd_soc_component *component; 883613fb500SKuninori Morimoto int i; 8840035e256SKuninori Morimoto 8850035e256SKuninori Morimoto /* FIXME: use 1st pointer */ 886613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 887e2cb4a14SKuninori Morimoto if (component->driver->pointer) 888e2cb4a14SKuninori Morimoto return component->driver->pointer(component, substream); 8890035e256SKuninori Morimoto 8900035e256SKuninori Morimoto return 0; 8910035e256SKuninori Morimoto } 89296a47908SKuninori Morimoto 89396a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, 89496a47908SKuninori Morimoto unsigned int cmd, void *arg) 89596a47908SKuninori Morimoto { 8960ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 89796a47908SKuninori Morimoto struct snd_soc_component *component; 898613fb500SKuninori Morimoto int i; 89996a47908SKuninori Morimoto 90096a47908SKuninori Morimoto /* FIXME: use 1st ioctl */ 901613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 902e2cb4a14SKuninori Morimoto if (component->driver->ioctl) 903e2329eebSKuninori Morimoto return soc_component_ret( 904e2329eebSKuninori Morimoto component, 905e2329eebSKuninori Morimoto component->driver->ioctl(component, 906e2329eebSKuninori Morimoto substream, cmd, arg)); 90796a47908SKuninori Morimoto 90896a47908SKuninori Morimoto return snd_pcm_lib_ioctl(substream, cmd, arg); 90996a47908SKuninori Morimoto } 91082d81f5cSKuninori Morimoto 9111e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) 9121e5ddb6bSTakashi Iwai { 9130ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 9141e5ddb6bSTakashi Iwai struct snd_soc_component *component; 915613fb500SKuninori Morimoto int i, ret; 9161e5ddb6bSTakashi Iwai 917613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 918f1861a7cSKuninori Morimoto if (component->driver->sync_stop) { 9191e5ddb6bSTakashi Iwai ret = component->driver->sync_stop(component, 9201e5ddb6bSTakashi Iwai substream); 9211e5ddb6bSTakashi Iwai if (ret < 0) 922be75db57SShengjiu Wang return soc_component_ret(component, ret); 9231e5ddb6bSTakashi Iwai } 9241e5ddb6bSTakashi Iwai } 9251e5ddb6bSTakashi Iwai 9261e5ddb6bSTakashi Iwai return 0; 9271e5ddb6bSTakashi Iwai } 9281e5ddb6bSTakashi Iwai 92982d81f5cSKuninori Morimoto int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, 93082d81f5cSKuninori Morimoto int channel, unsigned long pos, 93182d81f5cSKuninori Morimoto void __user *buf, unsigned long bytes) 93282d81f5cSKuninori Morimoto { 9330ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 93482d81f5cSKuninori Morimoto struct snd_soc_component *component; 935613fb500SKuninori Morimoto int i; 93682d81f5cSKuninori Morimoto 93782d81f5cSKuninori Morimoto /* FIXME. it returns 1st copy now */ 938613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 939e2cb4a14SKuninori Morimoto if (component->driver->copy_user) 940e2329eebSKuninori Morimoto return soc_component_ret( 941e2329eebSKuninori Morimoto component, 942e2329eebSKuninori Morimoto component->driver->copy_user( 943e2329eebSKuninori Morimoto component, substream, channel, 944e2329eebSKuninori Morimoto pos, buf, bytes)); 94582d81f5cSKuninori Morimoto 94682d81f5cSKuninori Morimoto return -EINVAL; 94782d81f5cSKuninori Morimoto } 9489c712e4fSKuninori Morimoto 9499c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, 9509c712e4fSKuninori Morimoto unsigned long offset) 9519c712e4fSKuninori Morimoto { 9520ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 9539c712e4fSKuninori Morimoto struct snd_soc_component *component; 9549c712e4fSKuninori Morimoto struct page *page; 955613fb500SKuninori Morimoto int i; 9569c712e4fSKuninori Morimoto 9579c712e4fSKuninori Morimoto /* FIXME. it returns 1st page now */ 958613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 959e2cb4a14SKuninori Morimoto if (component->driver->page) { 960e2cb4a14SKuninori Morimoto page = component->driver->page(component, 961e2cb4a14SKuninori Morimoto substream, offset); 962e2cb4a14SKuninori Morimoto if (page) 963e2cb4a14SKuninori Morimoto return page; 964e2cb4a14SKuninori Morimoto } 9659c712e4fSKuninori Morimoto } 9669c712e4fSKuninori Morimoto 9679c712e4fSKuninori Morimoto return NULL; 9689c712e4fSKuninori Morimoto } 969205875e1SKuninori Morimoto 970205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, 971205875e1SKuninori Morimoto struct vm_area_struct *vma) 972205875e1SKuninori Morimoto { 9730ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 974205875e1SKuninori Morimoto struct snd_soc_component *component; 975613fb500SKuninori Morimoto int i; 976205875e1SKuninori Morimoto 977205875e1SKuninori Morimoto /* FIXME. it returns 1st mmap now */ 978613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 979e2cb4a14SKuninori Morimoto if (component->driver->mmap) 980be75db57SShengjiu Wang return soc_component_ret( 981e2329eebSKuninori Morimoto component, 982e2329eebSKuninori Morimoto component->driver->mmap(component, 983e2329eebSKuninori Morimoto substream, vma)); 984205875e1SKuninori Morimoto 985205875e1SKuninori Morimoto return -EINVAL; 986205875e1SKuninori Morimoto } 9877484291eSKuninori Morimoto 988b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd) 9897484291eSKuninori Morimoto { 9907484291eSKuninori Morimoto struct snd_soc_component *component; 9917484291eSKuninori Morimoto int ret; 992613fb500SKuninori Morimoto int i; 9937484291eSKuninori Morimoto 994613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 995c64bfc90SKuninori Morimoto if (component->driver->pcm_construct) { 996c64bfc90SKuninori Morimoto ret = component->driver->pcm_construct(component, rtd); 997c64bfc90SKuninori Morimoto if (ret < 0) 998be75db57SShengjiu Wang return soc_component_ret(component, ret); 999c64bfc90SKuninori Morimoto } 10007484291eSKuninori Morimoto } 10017484291eSKuninori Morimoto 10027484291eSKuninori Morimoto return 0; 10037484291eSKuninori Morimoto } 100479776da0SKuninori Morimoto 1005b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd) 100679776da0SKuninori Morimoto { 100779776da0SKuninori Morimoto struct snd_soc_component *component; 1008613fb500SKuninori Morimoto int i; 100979776da0SKuninori Morimoto 10108e3366caSTakashi Iwai if (!rtd->pcm) 10118e3366caSTakashi Iwai return; 10128e3366caSTakashi Iwai 1013613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 1014c64bfc90SKuninori Morimoto if (component->driver->pcm_destruct) 1015b2b2afbbSKuninori Morimoto component->driver->pcm_destruct(component, rtd->pcm); 101679776da0SKuninori Morimoto } 10174f39514fSKuninori Morimoto 10184f39514fSKuninori Morimoto int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream) 10194f39514fSKuninori Morimoto { 10200ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 10214f39514fSKuninori Morimoto struct snd_soc_component *component; 10224f39514fSKuninori Morimoto int i, ret; 10234f39514fSKuninori Morimoto 10244f39514fSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 10254f39514fSKuninori Morimoto if (component->driver->prepare) { 10264f39514fSKuninori Morimoto ret = component->driver->prepare(component, substream); 10274f39514fSKuninori Morimoto if (ret < 0) 10284f39514fSKuninori Morimoto return soc_component_ret(component, ret); 10294f39514fSKuninori Morimoto } 10304f39514fSKuninori Morimoto } 10314f39514fSKuninori Morimoto 10324f39514fSKuninori Morimoto return 0; 10334f39514fSKuninori Morimoto } 1034e1bafa82SKuninori Morimoto 1035e1bafa82SKuninori Morimoto int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, 10363a36a64aSKuninori Morimoto struct snd_pcm_hw_params *params) 1037e1bafa82SKuninori Morimoto { 10380ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1039e1bafa82SKuninori Morimoto struct snd_soc_component *component; 1040e1bafa82SKuninori Morimoto int i, ret; 1041e1bafa82SKuninori Morimoto 1042e1bafa82SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1043e1bafa82SKuninori Morimoto if (component->driver->hw_params) { 1044e1bafa82SKuninori Morimoto ret = component->driver->hw_params(component, 1045e1bafa82SKuninori Morimoto substream, params); 10463a36a64aSKuninori Morimoto if (ret < 0) 1047e1bafa82SKuninori Morimoto return soc_component_ret(component, ret); 1048e1bafa82SKuninori Morimoto } 10493a36a64aSKuninori Morimoto /* mark substream if succeeded */ 10503a36a64aSKuninori Morimoto soc_component_mark_push(component, substream, hw_params); 1051e1bafa82SKuninori Morimoto } 1052e1bafa82SKuninori Morimoto 1053e1bafa82SKuninori Morimoto return 0; 1054e1bafa82SKuninori Morimoto } 105504751119SKuninori Morimoto 105604751119SKuninori Morimoto void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, 10573a36a64aSKuninori Morimoto int rollback) 105804751119SKuninori Morimoto { 10590ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 106004751119SKuninori Morimoto struct snd_soc_component *component; 106104751119SKuninori Morimoto int i, ret; 106204751119SKuninori Morimoto 106304751119SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 10643a36a64aSKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, hw_params)) 10653a36a64aSKuninori Morimoto continue; 106604751119SKuninori Morimoto 106704751119SKuninori Morimoto if (component->driver->hw_free) { 106804751119SKuninori Morimoto ret = component->driver->hw_free(component, substream); 106904751119SKuninori Morimoto if (ret < 0) 107004751119SKuninori Morimoto soc_component_ret(component, ret); 107104751119SKuninori Morimoto } 10723a36a64aSKuninori Morimoto 10733a36a64aSKuninori Morimoto /* remove marked substream */ 10743a36a64aSKuninori Morimoto soc_component_mark_pop(component, substream, hw_params); 107504751119SKuninori Morimoto } 107604751119SKuninori Morimoto } 107732fd1204SKuninori Morimoto 1078*6374f493SKuninori Morimoto static int soc_component_trigger(struct snd_soc_component *component, 1079*6374f493SKuninori Morimoto struct snd_pcm_substream *substream, 108032fd1204SKuninori Morimoto int cmd) 108132fd1204SKuninori Morimoto { 1082*6374f493SKuninori Morimoto int ret = 0; 1083*6374f493SKuninori Morimoto 1084*6374f493SKuninori Morimoto if (component->driver->trigger) 1085*6374f493SKuninori Morimoto ret = component->driver->trigger(component, substream, cmd); 1086*6374f493SKuninori Morimoto 1087*6374f493SKuninori Morimoto return soc_component_ret(component, ret); 1088*6374f493SKuninori Morimoto } 1089*6374f493SKuninori Morimoto 1090*6374f493SKuninori Morimoto int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, 1091*6374f493SKuninori Morimoto int cmd, int rollback) 1092*6374f493SKuninori Morimoto { 10930ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 109432fd1204SKuninori Morimoto struct snd_soc_component *component; 1095*6374f493SKuninori Morimoto int i, r, ret = 0; 109632fd1204SKuninori Morimoto 1097*6374f493SKuninori Morimoto switch (cmd) { 1098*6374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_START: 1099*6374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_RESUME: 1100*6374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 110132fd1204SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1102*6374f493SKuninori Morimoto ret = soc_component_trigger(component, substream, cmd); 110332fd1204SKuninori Morimoto if (ret < 0) 1104*6374f493SKuninori Morimoto break; 1105*6374f493SKuninori Morimoto soc_component_mark_push(component, substream, trigger); 1106*6374f493SKuninori Morimoto } 1107*6374f493SKuninori Morimoto break; 1108*6374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_STOP: 1109*6374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_SUSPEND: 1110*6374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1111*6374f493SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1112*6374f493SKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, trigger)) 1113*6374f493SKuninori Morimoto continue; 1114*6374f493SKuninori Morimoto 1115*6374f493SKuninori Morimoto r = soc_component_trigger(component, substream, cmd); 1116*6374f493SKuninori Morimoto if (r < 0) 1117*6374f493SKuninori Morimoto ret = r; /* use last ret */ 1118*6374f493SKuninori Morimoto soc_component_mark_pop(component, substream, trigger); 111932fd1204SKuninori Morimoto } 112032fd1204SKuninori Morimoto } 112132fd1204SKuninori Morimoto 1122*6374f493SKuninori Morimoto return ret; 112332fd1204SKuninori Morimoto } 1124939a5cfbSKuninori Morimoto 1125939a5cfbSKuninori Morimoto int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd, 1126939a5cfbSKuninori Morimoto void *stream) 1127939a5cfbSKuninori Morimoto { 1128939a5cfbSKuninori Morimoto struct snd_soc_component *component; 1129939a5cfbSKuninori Morimoto int i, ret; 1130939a5cfbSKuninori Morimoto 1131939a5cfbSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1132939a5cfbSKuninori Morimoto ret = pm_runtime_get_sync(component->dev); 1133939a5cfbSKuninori Morimoto if (ret < 0 && ret != -EACCES) { 1134939a5cfbSKuninori Morimoto pm_runtime_put_noidle(component->dev); 1135939a5cfbSKuninori Morimoto return soc_component_ret(component, ret); 1136939a5cfbSKuninori Morimoto } 1137939a5cfbSKuninori Morimoto /* mark stream if succeeded */ 1138939a5cfbSKuninori Morimoto soc_component_mark_push(component, stream, pm); 1139939a5cfbSKuninori Morimoto } 1140939a5cfbSKuninori Morimoto 1141939a5cfbSKuninori Morimoto return 0; 1142939a5cfbSKuninori Morimoto } 1143939a5cfbSKuninori Morimoto 1144939a5cfbSKuninori Morimoto void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd, 1145939a5cfbSKuninori Morimoto void *stream, int rollback) 1146939a5cfbSKuninori Morimoto { 1147939a5cfbSKuninori Morimoto struct snd_soc_component *component; 1148939a5cfbSKuninori Morimoto int i; 1149939a5cfbSKuninori Morimoto 1150939a5cfbSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1151939a5cfbSKuninori Morimoto if (rollback && !soc_component_mark_match(component, stream, pm)) 1152939a5cfbSKuninori Morimoto continue; 1153939a5cfbSKuninori Morimoto 1154939a5cfbSKuninori Morimoto pm_runtime_mark_last_busy(component->dev); 1155939a5cfbSKuninori Morimoto pm_runtime_put_autosuspend(component->dev); 1156939a5cfbSKuninori Morimoto 1157939a5cfbSKuninori Morimoto /* remove marked stream */ 1158939a5cfbSKuninori Morimoto soc_component_mark_pop(component, stream, pm); 1159939a5cfbSKuninori Morimoto } 1160939a5cfbSKuninori Morimoto } 1161