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 37*1da0b989SSrinivas Kandagatla static inline int soc_component_field_shift(struct snd_soc_component *component, 38*1da0b989SSrinivas Kandagatla unsigned int mask) 39*1da0b989SSrinivas Kandagatla { 40*1da0b989SSrinivas Kandagatla if (!mask) { 41*1da0b989SSrinivas Kandagatla dev_err(component->dev, "ASoC: error field mask is zero for %s\n", 42*1da0b989SSrinivas Kandagatla component->name); 43*1da0b989SSrinivas Kandagatla return 0; 44*1da0b989SSrinivas Kandagatla } 45*1da0b989SSrinivas Kandagatla 46*1da0b989SSrinivas Kandagatla return (__builtin_ffs(mask) - 1); 47*1da0b989SSrinivas Kandagatla } 48*1da0b989SSrinivas Kandagatla 4951aff91aSKuninori Morimoto /* 5051aff91aSKuninori Morimoto * We might want to check substream by using list. 5151aff91aSKuninori Morimoto * In such case, we can update these macros. 5251aff91aSKuninori Morimoto */ 5351aff91aSKuninori Morimoto #define soc_component_mark_push(component, substream, tgt) ((component)->mark_##tgt = substream) 5451aff91aSKuninori Morimoto #define soc_component_mark_pop(component, substream, tgt) ((component)->mark_##tgt = NULL) 5551aff91aSKuninori Morimoto #define soc_component_mark_match(component, substream, tgt) ((component)->mark_##tgt == substream) 5651aff91aSKuninori Morimoto 57257c4dacSKuninori Morimoto void snd_soc_component_set_aux(struct snd_soc_component *component, 58257c4dacSKuninori Morimoto struct snd_soc_aux_dev *aux) 59257c4dacSKuninori Morimoto { 60257c4dacSKuninori Morimoto component->init = (aux) ? aux->init : NULL; 61257c4dacSKuninori Morimoto } 62257c4dacSKuninori Morimoto 63257c4dacSKuninori Morimoto int snd_soc_component_init(struct snd_soc_component *component) 64257c4dacSKuninori Morimoto { 65257c4dacSKuninori Morimoto int ret = 0; 66257c4dacSKuninori Morimoto 67257c4dacSKuninori Morimoto if (component->init) 68257c4dacSKuninori Morimoto ret = component->init(component); 69257c4dacSKuninori Morimoto 70257c4dacSKuninori Morimoto return soc_component_ret(component, ret); 71257c4dacSKuninori Morimoto } 72257c4dacSKuninori Morimoto 734ff1fef1SKuninori Morimoto /** 744ff1fef1SKuninori Morimoto * snd_soc_component_set_sysclk - configure COMPONENT system or master clock. 754ff1fef1SKuninori Morimoto * @component: COMPONENT 764ff1fef1SKuninori Morimoto * @clk_id: DAI specific clock ID 774ff1fef1SKuninori Morimoto * @source: Source for the clock 784ff1fef1SKuninori Morimoto * @freq: new clock frequency in Hz 794ff1fef1SKuninori Morimoto * @dir: new clock direction - input/output. 804ff1fef1SKuninori Morimoto * 814ff1fef1SKuninori Morimoto * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. 824ff1fef1SKuninori Morimoto */ 834ff1fef1SKuninori Morimoto int snd_soc_component_set_sysclk(struct snd_soc_component *component, 844ff1fef1SKuninori Morimoto int clk_id, int source, unsigned int freq, 854ff1fef1SKuninori Morimoto int dir) 864ff1fef1SKuninori Morimoto { 87e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 88e2329eebSKuninori Morimoto 894ff1fef1SKuninori Morimoto if (component->driver->set_sysclk) 90e2329eebSKuninori Morimoto ret = component->driver->set_sysclk(component, clk_id, source, 914ff1fef1SKuninori Morimoto freq, dir); 924ff1fef1SKuninori Morimoto 93e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 944ff1fef1SKuninori Morimoto } 954ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk); 964ff1fef1SKuninori Morimoto 974ff1fef1SKuninori Morimoto /* 984ff1fef1SKuninori Morimoto * snd_soc_component_set_pll - configure component PLL. 994ff1fef1SKuninori Morimoto * @component: COMPONENT 1004ff1fef1SKuninori Morimoto * @pll_id: DAI specific PLL ID 1014ff1fef1SKuninori Morimoto * @source: DAI specific source for the PLL 1024ff1fef1SKuninori Morimoto * @freq_in: PLL input clock frequency in Hz 1034ff1fef1SKuninori Morimoto * @freq_out: requested PLL output clock frequency in Hz 1044ff1fef1SKuninori Morimoto * 1054ff1fef1SKuninori Morimoto * Configures and enables PLL to generate output clock based on input clock. 1064ff1fef1SKuninori Morimoto */ 1074ff1fef1SKuninori Morimoto int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id, 1084ff1fef1SKuninori Morimoto int source, unsigned int freq_in, 1094ff1fef1SKuninori Morimoto unsigned int freq_out) 1104ff1fef1SKuninori Morimoto { 111e2329eebSKuninori Morimoto int ret = -EINVAL; 112e2329eebSKuninori Morimoto 1134ff1fef1SKuninori Morimoto if (component->driver->set_pll) 114e2329eebSKuninori Morimoto ret = component->driver->set_pll(component, pll_id, source, 1154ff1fef1SKuninori Morimoto freq_in, freq_out); 1164ff1fef1SKuninori Morimoto 117e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1184ff1fef1SKuninori Morimoto } 1194ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_pll); 1204ff1fef1SKuninori Morimoto 1219d415fbfSKuninori Morimoto void snd_soc_component_seq_notifier(struct snd_soc_component *component, 1229d415fbfSKuninori Morimoto enum snd_soc_dapm_type type, int subseq) 1239d415fbfSKuninori Morimoto { 1249d415fbfSKuninori Morimoto if (component->driver->seq_notifier) 1259d415fbfSKuninori Morimoto component->driver->seq_notifier(component, type, subseq); 1269d415fbfSKuninori Morimoto } 1279d415fbfSKuninori Morimoto 1288e2a990dSKuninori Morimoto int snd_soc_component_stream_event(struct snd_soc_component *component, 1298e2a990dSKuninori Morimoto int event) 1308e2a990dSKuninori Morimoto { 131e2329eebSKuninori Morimoto int ret = 0; 1328e2a990dSKuninori Morimoto 133e2329eebSKuninori Morimoto if (component->driver->stream_event) 134e2329eebSKuninori Morimoto ret = component->driver->stream_event(component, event); 135e2329eebSKuninori Morimoto 136e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1378e2a990dSKuninori Morimoto } 1388e2a990dSKuninori Morimoto 1397951b146SKuninori Morimoto int snd_soc_component_set_bias_level(struct snd_soc_component *component, 1407951b146SKuninori Morimoto enum snd_soc_bias_level level) 1417951b146SKuninori Morimoto { 142e2329eebSKuninori Morimoto int ret = 0; 1437951b146SKuninori Morimoto 144e2329eebSKuninori Morimoto if (component->driver->set_bias_level) 145e2329eebSKuninori Morimoto ret = component->driver->set_bias_level(component, level); 146e2329eebSKuninori Morimoto 147e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1487951b146SKuninori Morimoto } 1497951b146SKuninori Morimoto 1504ca8701eSKuninori Morimoto static int soc_component_pin(struct snd_soc_component *component, 1514ca8701eSKuninori Morimoto const char *pin, 1524ca8701eSKuninori Morimoto int (*pin_func)(struct snd_soc_dapm_context *dapm, 1534ca8701eSKuninori Morimoto const char *pin)) 1544ff1fef1SKuninori Morimoto { 1554ff1fef1SKuninori Morimoto struct snd_soc_dapm_context *dapm = 1564ff1fef1SKuninori Morimoto snd_soc_component_get_dapm(component); 1574ff1fef1SKuninori Morimoto char *full_name; 1584ff1fef1SKuninori Morimoto int ret; 1594ff1fef1SKuninori Morimoto 160e2329eebSKuninori Morimoto if (!component->name_prefix) { 161e2329eebSKuninori Morimoto ret = pin_func(dapm, pin); 162e2329eebSKuninori Morimoto goto end; 163e2329eebSKuninori Morimoto } 1644ff1fef1SKuninori Morimoto 1654ff1fef1SKuninori Morimoto full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin); 166e2329eebSKuninori Morimoto if (!full_name) { 167e2329eebSKuninori Morimoto ret = -ENOMEM; 168e2329eebSKuninori Morimoto goto end; 169e2329eebSKuninori Morimoto } 1704ff1fef1SKuninori Morimoto 1714ca8701eSKuninori Morimoto ret = pin_func(dapm, full_name); 1724ff1fef1SKuninori Morimoto kfree(full_name); 173e2329eebSKuninori Morimoto end: 174e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 1754ff1fef1SKuninori Morimoto } 1764ca8701eSKuninori Morimoto 1774ca8701eSKuninori Morimoto int snd_soc_component_enable_pin(struct snd_soc_component *component, 1784ca8701eSKuninori Morimoto const char *pin) 1794ca8701eSKuninori Morimoto { 1804ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_enable_pin); 1814ca8701eSKuninori Morimoto } 1824ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin); 1834ff1fef1SKuninori Morimoto 1844ff1fef1SKuninori Morimoto int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component, 1854ff1fef1SKuninori Morimoto const char *pin) 1864ff1fef1SKuninori Morimoto { 1874ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked); 1884ff1fef1SKuninori Morimoto } 1894ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked); 1904ff1fef1SKuninori Morimoto 1914ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin(struct snd_soc_component *component, 1924ff1fef1SKuninori Morimoto const char *pin) 1934ff1fef1SKuninori Morimoto { 1944ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_disable_pin); 1954ff1fef1SKuninori Morimoto } 1964ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin); 1974ff1fef1SKuninori Morimoto 1984ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component, 1994ff1fef1SKuninori Morimoto const char *pin) 2004ff1fef1SKuninori Morimoto { 2014ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked); 2024ff1fef1SKuninori Morimoto } 2034ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked); 2044ff1fef1SKuninori Morimoto 2054ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin(struct snd_soc_component *component, 2064ff1fef1SKuninori Morimoto const char *pin) 2074ff1fef1SKuninori Morimoto { 2084ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_nc_pin); 2094ff1fef1SKuninori Morimoto } 2104ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin); 2114ff1fef1SKuninori Morimoto 2124ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component, 2134ff1fef1SKuninori Morimoto const char *pin) 2144ff1fef1SKuninori Morimoto { 2154ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked); 2164ff1fef1SKuninori Morimoto } 2174ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked); 2184ff1fef1SKuninori Morimoto 2194ff1fef1SKuninori Morimoto int snd_soc_component_get_pin_status(struct snd_soc_component *component, 2204ff1fef1SKuninori Morimoto const char *pin) 2214ff1fef1SKuninori Morimoto { 2224ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status); 2234ff1fef1SKuninori Morimoto } 2244ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status); 2254ff1fef1SKuninori Morimoto 2264ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin(struct snd_soc_component *component, 2274ff1fef1SKuninori Morimoto const char *pin) 2284ff1fef1SKuninori Morimoto { 2294ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin); 2304ff1fef1SKuninori Morimoto } 2314ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin); 2324ff1fef1SKuninori Morimoto 2334ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin_unlocked( 2344ff1fef1SKuninori Morimoto struct snd_soc_component *component, 2354ff1fef1SKuninori Morimoto const char *pin) 2364ff1fef1SKuninori Morimoto { 2374ca8701eSKuninori Morimoto return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked); 2384ff1fef1SKuninori Morimoto } 2394ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked); 2404ff1fef1SKuninori Morimoto 2414ff1fef1SKuninori Morimoto /** 2424ff1fef1SKuninori Morimoto * snd_soc_component_set_jack - configure component jack. 2434ff1fef1SKuninori Morimoto * @component: COMPONENTs 2444ff1fef1SKuninori Morimoto * @jack: structure to use for the jack 2454ff1fef1SKuninori Morimoto * @data: can be used if codec driver need extra data for configuring jack 2464ff1fef1SKuninori Morimoto * 2474ff1fef1SKuninori Morimoto * Configures and enables jack detection function. 2484ff1fef1SKuninori Morimoto */ 2494ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component, 2504ff1fef1SKuninori Morimoto struct snd_soc_jack *jack, void *data) 2514ff1fef1SKuninori Morimoto { 252e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 2534ff1fef1SKuninori Morimoto 254e2329eebSKuninori Morimoto if (component->driver->set_jack) 255e2329eebSKuninori Morimoto ret = component->driver->set_jack(component, jack, data); 256e2329eebSKuninori Morimoto 257e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2584ff1fef1SKuninori Morimoto } 2594ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); 2604a81e8f3SKuninori Morimoto 2614a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component, 26251aff91aSKuninori Morimoto struct snd_pcm_substream *substream, 2634a81e8f3SKuninori Morimoto int upon_open) 2644a81e8f3SKuninori Morimoto { 265e2329eebSKuninori Morimoto int ret = 0; 266e2329eebSKuninori Morimoto 2674a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open && 2684a81e8f3SKuninori Morimoto !try_module_get(component->dev->driver->owner)) 269e2329eebSKuninori Morimoto ret = -ENODEV; 2704a81e8f3SKuninori Morimoto 27151aff91aSKuninori Morimoto /* mark substream if succeeded */ 27251aff91aSKuninori Morimoto if (ret == 0) 27351aff91aSKuninori Morimoto soc_component_mark_push(component, substream, module); 27451aff91aSKuninori Morimoto 275e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 2764a81e8f3SKuninori Morimoto } 2774a81e8f3SKuninori Morimoto 2784a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component, 27951aff91aSKuninori Morimoto struct snd_pcm_substream *substream, 28051aff91aSKuninori Morimoto int upon_open, int rollback) 2814a81e8f3SKuninori Morimoto { 28251aff91aSKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, module)) 28351aff91aSKuninori Morimoto return; 28451aff91aSKuninori Morimoto 2854a81e8f3SKuninori Morimoto if (component->driver->module_get_upon_open == !!upon_open) 2864a81e8f3SKuninori Morimoto module_put(component->dev->driver->owner); 28751aff91aSKuninori Morimoto 28851aff91aSKuninori Morimoto /* remove marked substream */ 28951aff91aSKuninori Morimoto soc_component_mark_pop(component, substream, module); 2904a81e8f3SKuninori Morimoto } 291ae2f4849SKuninori Morimoto 292ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component, 293ae2f4849SKuninori Morimoto struct snd_pcm_substream *substream) 294ae2f4849SKuninori Morimoto { 295e2329eebSKuninori Morimoto int ret = 0; 296e2329eebSKuninori Morimoto 297e2cb4a14SKuninori Morimoto if (component->driver->open) 298e2329eebSKuninori Morimoto ret = component->driver->open(component, substream); 299e2329eebSKuninori Morimoto 30051aff91aSKuninori Morimoto /* mark substream if succeeded */ 30151aff91aSKuninori Morimoto if (ret == 0) 30251aff91aSKuninori Morimoto soc_component_mark_push(component, substream, open); 30351aff91aSKuninori Morimoto 304e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 305ae2f4849SKuninori Morimoto } 3063672beb8SKuninori Morimoto 3073672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component, 30851aff91aSKuninori Morimoto struct snd_pcm_substream *substream, 30951aff91aSKuninori Morimoto int rollback) 3103672beb8SKuninori Morimoto { 311e2329eebSKuninori Morimoto int ret = 0; 312e2329eebSKuninori Morimoto 31351aff91aSKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, open)) 31451aff91aSKuninori Morimoto return 0; 31551aff91aSKuninori Morimoto 316e2cb4a14SKuninori Morimoto if (component->driver->close) 317e2329eebSKuninori Morimoto ret = component->driver->close(component, substream); 318e2329eebSKuninori Morimoto 31951aff91aSKuninori Morimoto /* remove marked substream */ 32051aff91aSKuninori Morimoto soc_component_mark_pop(component, substream, open); 32151aff91aSKuninori Morimoto 322e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 3233672beb8SKuninori Morimoto } 3246d537233SKuninori Morimoto 32566c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component) 32666c51573SKuninori Morimoto { 32766c51573SKuninori Morimoto if (component->driver->suspend) 32866c51573SKuninori Morimoto component->driver->suspend(component); 32966c51573SKuninori Morimoto component->suspended = 1; 33066c51573SKuninori Morimoto } 3319a840cbaSKuninori Morimoto 3329a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component) 3339a840cbaSKuninori Morimoto { 3349a840cbaSKuninori Morimoto if (component->driver->resume) 3359a840cbaSKuninori Morimoto component->driver->resume(component); 3369a840cbaSKuninori Morimoto component->suspended = 0; 3379a840cbaSKuninori Morimoto } 338e40fadbcSKuninori Morimoto 339e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component) 340e40fadbcSKuninori Morimoto { 341e40fadbcSKuninori Morimoto return component->suspended; 342e40fadbcSKuninori Morimoto } 34308e837ddSKuninori Morimoto 34408e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component) 34508e837ddSKuninori Morimoto { 346e2329eebSKuninori Morimoto int ret = 0; 34708e837ddSKuninori Morimoto 348e2329eebSKuninori Morimoto if (component->driver->probe) 349e2329eebSKuninori Morimoto ret = component->driver->probe(component); 350e2329eebSKuninori Morimoto 351e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 35208e837ddSKuninori Morimoto } 35303b34dd7SKuninori Morimoto 35403b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component) 35503b34dd7SKuninori Morimoto { 35603b34dd7SKuninori Morimoto if (component->driver->remove) 35703b34dd7SKuninori Morimoto component->driver->remove(component); 35803b34dd7SKuninori Morimoto } 3592c7b1704SKuninori Morimoto 3602c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, 3612c7b1704SKuninori Morimoto struct device_node *ep) 3622c7b1704SKuninori Morimoto { 363e2329eebSKuninori Morimoto int ret = -ENOTSUPP; 3642c7b1704SKuninori Morimoto 365e2329eebSKuninori Morimoto if (component->driver->of_xlate_dai_id) 366e2329eebSKuninori Morimoto ret = component->driver->of_xlate_dai_id(component, ep); 367e2329eebSKuninori Morimoto 368e2329eebSKuninori Morimoto return soc_component_ret(component, ret); 3692c7b1704SKuninori Morimoto } 370a2a34175SKuninori Morimoto 371a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, 372a2a34175SKuninori Morimoto struct of_phandle_args *args, 373a2a34175SKuninori Morimoto const char **dai_name) 374a2a34175SKuninori Morimoto { 375a2a34175SKuninori Morimoto if (component->driver->of_xlate_dai_name) 376cc4d8cebSJerome Brunet return component->driver->of_xlate_dai_name(component, 377a2a34175SKuninori Morimoto args, dai_name); 378cc4d8cebSJerome Brunet /* 379cc4d8cebSJerome Brunet * Don't use soc_component_ret here because we may not want to report 380cc4d8cebSJerome Brunet * the error just yet. If a device has more than one component, the 381cc4d8cebSJerome Brunet * first may not match and we don't want spam the log with this. 382cc4d8cebSJerome Brunet */ 383cc4d8cebSJerome Brunet return -ENOTSUPP; 384a2a34175SKuninori Morimoto } 3850035e256SKuninori Morimoto 386c7d75b59SKuninori Morimoto void snd_soc_component_setup_regmap(struct snd_soc_component *component) 387c7d75b59SKuninori Morimoto { 388c7d75b59SKuninori Morimoto int val_bytes = regmap_get_val_bytes(component->regmap); 389c7d75b59SKuninori Morimoto 390c7d75b59SKuninori Morimoto /* Errors are legitimate for non-integer byte multiples */ 391c7d75b59SKuninori Morimoto if (val_bytes > 0) 392c7d75b59SKuninori Morimoto component->val_bytes = val_bytes; 393c7d75b59SKuninori Morimoto } 394c7d75b59SKuninori Morimoto 395c7d75b59SKuninori Morimoto #ifdef CONFIG_REGMAP 396c7d75b59SKuninori Morimoto 397c7d75b59SKuninori Morimoto /** 398c7d75b59SKuninori Morimoto * snd_soc_component_init_regmap() - Initialize regmap instance for the 399c7d75b59SKuninori Morimoto * component 400c7d75b59SKuninori Morimoto * @component: The component for which to initialize the regmap instance 401c7d75b59SKuninori Morimoto * @regmap: The regmap instance that should be used by the component 402c7d75b59SKuninori Morimoto * 403c7d75b59SKuninori Morimoto * This function allows deferred assignment of the regmap instance that is 404c7d75b59SKuninori Morimoto * associated with the component. Only use this if the regmap instance is not 405c7d75b59SKuninori Morimoto * yet ready when the component is registered. The function must also be called 406c7d75b59SKuninori Morimoto * before the first IO attempt of the component. 407c7d75b59SKuninori Morimoto */ 408c7d75b59SKuninori Morimoto void snd_soc_component_init_regmap(struct snd_soc_component *component, 409c7d75b59SKuninori Morimoto struct regmap *regmap) 410c7d75b59SKuninori Morimoto { 411c7d75b59SKuninori Morimoto component->regmap = regmap; 412c7d75b59SKuninori Morimoto snd_soc_component_setup_regmap(component); 413c7d75b59SKuninori Morimoto } 414c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); 415c7d75b59SKuninori Morimoto 416c7d75b59SKuninori Morimoto /** 417c7d75b59SKuninori Morimoto * snd_soc_component_exit_regmap() - De-initialize regmap instance for the 418c7d75b59SKuninori Morimoto * component 419c7d75b59SKuninori Morimoto * @component: The component for which to de-initialize the regmap instance 420c7d75b59SKuninori Morimoto * 421c7d75b59SKuninori Morimoto * Calls regmap_exit() on the regmap instance associated to the component and 422c7d75b59SKuninori Morimoto * removes the regmap instance from the component. 423c7d75b59SKuninori Morimoto * 424c7d75b59SKuninori Morimoto * This function should only be used if snd_soc_component_init_regmap() was used 425c7d75b59SKuninori Morimoto * to initialize the regmap instance. 426c7d75b59SKuninori Morimoto */ 427c7d75b59SKuninori Morimoto void snd_soc_component_exit_regmap(struct snd_soc_component *component) 428c7d75b59SKuninori Morimoto { 429c7d75b59SKuninori Morimoto regmap_exit(component->regmap); 430c7d75b59SKuninori Morimoto component->regmap = NULL; 431c7d75b59SKuninori Morimoto } 432c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); 433c7d75b59SKuninori Morimoto 434c7d75b59SKuninori Morimoto #endif 435c7d75b59SKuninori Morimoto 436f94ba9acSKuninori Morimoto int snd_soc_component_compr_open(struct snd_compr_stream *cstream) 437a4e427c5SKuninori Morimoto { 438a4e427c5SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 439a4e427c5SKuninori Morimoto struct snd_soc_component *component; 440a4e427c5SKuninori Morimoto int i, ret; 441a4e427c5SKuninori Morimoto 442a4e427c5SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 443a4e427c5SKuninori Morimoto if (component->driver->compress_ops && 444a4e427c5SKuninori Morimoto component->driver->compress_ops->open) { 445a4e427c5SKuninori Morimoto ret = component->driver->compress_ops->open(component, cstream); 446f94ba9acSKuninori Morimoto if (ret < 0) 447a4e427c5SKuninori Morimoto return soc_component_ret(component, ret); 448a4e427c5SKuninori Morimoto } 449f94ba9acSKuninori Morimoto soc_component_mark_push(component, cstream, compr_open); 450a4e427c5SKuninori Morimoto } 451a4e427c5SKuninori Morimoto 452a4e427c5SKuninori Morimoto return 0; 453a4e427c5SKuninori Morimoto } 454a4e427c5SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_open); 455a4e427c5SKuninori Morimoto 456dbde5e21SKuninori Morimoto void snd_soc_component_compr_free(struct snd_compr_stream *cstream, 457f94ba9acSKuninori Morimoto int rollback) 458dbde5e21SKuninori Morimoto { 459dbde5e21SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 460dbde5e21SKuninori Morimoto struct snd_soc_component *component; 461dbde5e21SKuninori Morimoto int i; 462dbde5e21SKuninori Morimoto 463dbde5e21SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 464f94ba9acSKuninori Morimoto if (rollback && !soc_component_mark_match(component, cstream, compr_open)) 465f94ba9acSKuninori Morimoto continue; 466dbde5e21SKuninori Morimoto 467dbde5e21SKuninori Morimoto if (component->driver->compress_ops && 468dbde5e21SKuninori Morimoto component->driver->compress_ops->free) 469dbde5e21SKuninori Morimoto component->driver->compress_ops->free(component, cstream); 470f94ba9acSKuninori Morimoto 471f94ba9acSKuninori Morimoto soc_component_mark_pop(component, cstream, compr_open); 472dbde5e21SKuninori Morimoto } 473dbde5e21SKuninori Morimoto } 474dbde5e21SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_free); 475dbde5e21SKuninori Morimoto 47608aee251SKuninori Morimoto int snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd) 47708aee251SKuninori Morimoto { 47808aee251SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 47908aee251SKuninori Morimoto struct snd_soc_component *component; 48008aee251SKuninori Morimoto int i, ret; 48108aee251SKuninori Morimoto 48208aee251SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 48308aee251SKuninori Morimoto if (component->driver->compress_ops && 48408aee251SKuninori Morimoto component->driver->compress_ops->trigger) { 48508aee251SKuninori Morimoto ret = component->driver->compress_ops->trigger( 48608aee251SKuninori Morimoto component, cstream, cmd); 48708aee251SKuninori Morimoto if (ret < 0) 48808aee251SKuninori Morimoto return soc_component_ret(component, ret); 48908aee251SKuninori Morimoto } 49008aee251SKuninori Morimoto } 49108aee251SKuninori Morimoto 49208aee251SKuninori Morimoto return 0; 49308aee251SKuninori Morimoto } 49408aee251SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_trigger); 49508aee251SKuninori Morimoto 496ff08cf80SKuninori Morimoto int snd_soc_component_compr_set_params(struct snd_compr_stream *cstream, 497ff08cf80SKuninori Morimoto struct snd_compr_params *params) 498ff08cf80SKuninori Morimoto { 499ff08cf80SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 500ff08cf80SKuninori Morimoto struct snd_soc_component *component; 501ff08cf80SKuninori Morimoto int i, ret; 502ff08cf80SKuninori Morimoto 503ff08cf80SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 504ff08cf80SKuninori Morimoto if (component->driver->compress_ops && 505ff08cf80SKuninori Morimoto component->driver->compress_ops->set_params) { 506ff08cf80SKuninori Morimoto ret = component->driver->compress_ops->set_params( 507ff08cf80SKuninori Morimoto component, cstream, params); 508ff08cf80SKuninori Morimoto if (ret < 0) 509ff08cf80SKuninori Morimoto return soc_component_ret(component, ret); 510ff08cf80SKuninori Morimoto } 511ff08cf80SKuninori Morimoto } 512ff08cf80SKuninori Morimoto 513ff08cf80SKuninori Morimoto return 0; 514ff08cf80SKuninori Morimoto } 515ff08cf80SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_params); 516ff08cf80SKuninori Morimoto 51777c221ecSKuninori Morimoto int snd_soc_component_compr_get_params(struct snd_compr_stream *cstream, 51877c221ecSKuninori Morimoto struct snd_codec *params) 51977c221ecSKuninori Morimoto { 52077c221ecSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 52177c221ecSKuninori Morimoto struct snd_soc_component *component; 52277c221ecSKuninori Morimoto int i, ret; 52377c221ecSKuninori Morimoto 52477c221ecSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 52577c221ecSKuninori Morimoto if (component->driver->compress_ops && 52677c221ecSKuninori Morimoto component->driver->compress_ops->get_params) { 52777c221ecSKuninori Morimoto ret = component->driver->compress_ops->get_params( 52877c221ecSKuninori Morimoto component, cstream, params); 52977c221ecSKuninori Morimoto return soc_component_ret(component, ret); 53077c221ecSKuninori Morimoto } 53177c221ecSKuninori Morimoto } 53277c221ecSKuninori Morimoto 53377c221ecSKuninori Morimoto return 0; 53477c221ecSKuninori Morimoto } 53577c221ecSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_params); 53677c221ecSKuninori Morimoto 537d67fcb2dSKuninori Morimoto int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream, 538d67fcb2dSKuninori Morimoto struct snd_compr_caps *caps) 539d67fcb2dSKuninori Morimoto { 540d67fcb2dSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 541d67fcb2dSKuninori Morimoto struct snd_soc_component *component; 542d67fcb2dSKuninori Morimoto int i, ret = 0; 543d67fcb2dSKuninori Morimoto 544d67fcb2dSKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 545d67fcb2dSKuninori Morimoto 546d67fcb2dSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 547d67fcb2dSKuninori Morimoto if (component->driver->compress_ops && 548d67fcb2dSKuninori Morimoto component->driver->compress_ops->get_caps) { 549d67fcb2dSKuninori Morimoto ret = component->driver->compress_ops->get_caps( 550d67fcb2dSKuninori Morimoto component, cstream, caps); 551d67fcb2dSKuninori Morimoto break; 552d67fcb2dSKuninori Morimoto } 553d67fcb2dSKuninori Morimoto } 554d67fcb2dSKuninori Morimoto 555d67fcb2dSKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 556d67fcb2dSKuninori Morimoto 557d67fcb2dSKuninori Morimoto return soc_component_ret(component, ret); 558d67fcb2dSKuninori Morimoto } 559d67fcb2dSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_caps); 560d67fcb2dSKuninori Morimoto 5610f6fe097SKuninori Morimoto int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, 5620f6fe097SKuninori Morimoto struct snd_compr_codec_caps *codec) 5630f6fe097SKuninori Morimoto { 5640f6fe097SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5650f6fe097SKuninori Morimoto struct snd_soc_component *component; 5660f6fe097SKuninori Morimoto int i, ret = 0; 5670f6fe097SKuninori Morimoto 5680f6fe097SKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 5690f6fe097SKuninori Morimoto 5700f6fe097SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 5710f6fe097SKuninori Morimoto if (component->driver->compress_ops && 5720f6fe097SKuninori Morimoto component->driver->compress_ops->get_codec_caps) { 5730f6fe097SKuninori Morimoto ret = component->driver->compress_ops->get_codec_caps( 5740f6fe097SKuninori Morimoto component, cstream, codec); 5750f6fe097SKuninori Morimoto break; 5760f6fe097SKuninori Morimoto } 5770f6fe097SKuninori Morimoto } 5780f6fe097SKuninori Morimoto 5790f6fe097SKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 5800f6fe097SKuninori Morimoto 5810f6fe097SKuninori Morimoto return soc_component_ret(component, ret); 5820f6fe097SKuninori Morimoto } 5830f6fe097SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_codec_caps); 5840f6fe097SKuninori Morimoto 5850506b885SKuninori Morimoto int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 5860506b885SKuninori Morimoto { 5870506b885SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 5880506b885SKuninori Morimoto struct snd_soc_component *component; 5890506b885SKuninori Morimoto int i, ret; 5900506b885SKuninori Morimoto 5910506b885SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 5920506b885SKuninori Morimoto if (component->driver->compress_ops && 5930506b885SKuninori Morimoto component->driver->compress_ops->ack) { 5940506b885SKuninori Morimoto ret = component->driver->compress_ops->ack( 5950506b885SKuninori Morimoto component, cstream, bytes); 5960506b885SKuninori Morimoto if (ret < 0) 5970506b885SKuninori Morimoto return soc_component_ret(component, ret); 5980506b885SKuninori Morimoto } 5990506b885SKuninori Morimoto } 6000506b885SKuninori Morimoto 6010506b885SKuninori Morimoto return 0; 6020506b885SKuninori Morimoto } 6030506b885SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack); 6040506b885SKuninori Morimoto 60503ecea64SKuninori Morimoto int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream, 60603ecea64SKuninori Morimoto struct snd_compr_tstamp *tstamp) 60703ecea64SKuninori Morimoto { 60803ecea64SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 60903ecea64SKuninori Morimoto struct snd_soc_component *component; 61003ecea64SKuninori Morimoto int i, ret; 61103ecea64SKuninori Morimoto 61203ecea64SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 61303ecea64SKuninori Morimoto if (component->driver->compress_ops && 61403ecea64SKuninori Morimoto component->driver->compress_ops->pointer) { 61503ecea64SKuninori Morimoto ret = component->driver->compress_ops->pointer( 61603ecea64SKuninori Morimoto component, cstream, tstamp); 61703ecea64SKuninori Morimoto return soc_component_ret(component, ret); 61803ecea64SKuninori Morimoto } 61903ecea64SKuninori Morimoto } 62003ecea64SKuninori Morimoto 62103ecea64SKuninori Morimoto return 0; 62203ecea64SKuninori Morimoto } 62303ecea64SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_pointer); 62403ecea64SKuninori Morimoto 625b5852e66SKuninori Morimoto int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, 626b5852e66SKuninori Morimoto char __user *buf, size_t count) 627b5852e66SKuninori Morimoto { 628b5852e66SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 629b5852e66SKuninori Morimoto struct snd_soc_component *component; 630b5852e66SKuninori Morimoto int i, ret = 0; 631b5852e66SKuninori Morimoto 632b5852e66SKuninori Morimoto mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 633b5852e66SKuninori Morimoto 634b5852e66SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 635b5852e66SKuninori Morimoto if (component->driver->compress_ops && 636b5852e66SKuninori Morimoto component->driver->compress_ops->copy) { 637b5852e66SKuninori Morimoto ret = component->driver->compress_ops->copy( 638b5852e66SKuninori Morimoto component, cstream, buf, count); 639b5852e66SKuninori Morimoto break; 640b5852e66SKuninori Morimoto } 641b5852e66SKuninori Morimoto } 642b5852e66SKuninori Morimoto 643b5852e66SKuninori Morimoto mutex_unlock(&rtd->card->pcm_mutex); 644b5852e66SKuninori Morimoto 645b5852e66SKuninori Morimoto return soc_component_ret(component, ret); 646b5852e66SKuninori Morimoto } 647b5852e66SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_copy); 648b5852e66SKuninori Morimoto 6491b308fb1SKuninori Morimoto int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream, 6501b308fb1SKuninori Morimoto struct snd_compr_metadata *metadata) 6511b308fb1SKuninori Morimoto { 6521b308fb1SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 6531b308fb1SKuninori Morimoto struct snd_soc_component *component; 6541b308fb1SKuninori Morimoto int i, ret; 6551b308fb1SKuninori Morimoto 6561b308fb1SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 6571b308fb1SKuninori Morimoto if (component->driver->compress_ops && 6581b308fb1SKuninori Morimoto component->driver->compress_ops->set_metadata) { 6591b308fb1SKuninori Morimoto ret = component->driver->compress_ops->set_metadata( 6601b308fb1SKuninori Morimoto component, cstream, metadata); 6611b308fb1SKuninori Morimoto if (ret < 0) 6621b308fb1SKuninori Morimoto return soc_component_ret(component, ret); 6631b308fb1SKuninori Morimoto } 6641b308fb1SKuninori Morimoto } 6651b308fb1SKuninori Morimoto 6661b308fb1SKuninori Morimoto return 0; 6671b308fb1SKuninori Morimoto } 6681b308fb1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_metadata); 6691b308fb1SKuninori Morimoto 670bab78c23SKuninori Morimoto int snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream, 671bab78c23SKuninori Morimoto struct snd_compr_metadata *metadata) 672bab78c23SKuninori Morimoto { 673bab78c23SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = cstream->private_data; 674bab78c23SKuninori Morimoto struct snd_soc_component *component; 675bab78c23SKuninori Morimoto int i, ret; 676bab78c23SKuninori Morimoto 677bab78c23SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 678bab78c23SKuninori Morimoto if (component->driver->compress_ops && 679bab78c23SKuninori Morimoto component->driver->compress_ops->get_metadata) { 680bab78c23SKuninori Morimoto ret = component->driver->compress_ops->get_metadata( 681bab78c23SKuninori Morimoto component, cstream, metadata); 682bab78c23SKuninori Morimoto return soc_component_ret(component, ret); 683bab78c23SKuninori Morimoto } 684bab78c23SKuninori Morimoto } 685bab78c23SKuninori Morimoto 686bab78c23SKuninori Morimoto return 0; 687bab78c23SKuninori Morimoto } 688bab78c23SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_metadata); 689bab78c23SKuninori Morimoto 690e8712315SKuninori Morimoto static unsigned int soc_component_read_no_lock( 691e8712315SKuninori Morimoto struct snd_soc_component *component, 692cf6e26c7SKuninori Morimoto unsigned int reg) 693460b42d1SKuninori Morimoto { 694460b42d1SKuninori Morimoto int ret; 695cf6e26c7SKuninori Morimoto unsigned int val = 0; 696460b42d1SKuninori Morimoto 697460b42d1SKuninori Morimoto if (component->regmap) 698cf6e26c7SKuninori Morimoto ret = regmap_read(component->regmap, reg, &val); 699460b42d1SKuninori Morimoto else if (component->driver->read) { 700460b42d1SKuninori Morimoto ret = 0; 701cf6e26c7SKuninori Morimoto val = component->driver->read(component, reg); 702460b42d1SKuninori Morimoto } 703460b42d1SKuninori Morimoto else 704460b42d1SKuninori Morimoto ret = -EIO; 705460b42d1SKuninori Morimoto 706460b42d1SKuninori Morimoto if (ret < 0) 707efc913c8STakashi Iwai return soc_component_ret(component, ret); 708460b42d1SKuninori Morimoto 709460b42d1SKuninori Morimoto return val; 710460b42d1SKuninori Morimoto } 711e8712315SKuninori Morimoto 712e8712315SKuninori Morimoto /** 713e8712315SKuninori Morimoto * snd_soc_component_read() - Read register value 714e8712315SKuninori Morimoto * @component: Component to read from 715e8712315SKuninori Morimoto * @reg: Register to read 716e8712315SKuninori Morimoto * 717e8712315SKuninori Morimoto * Return: read value 718e8712315SKuninori Morimoto */ 719e8712315SKuninori Morimoto unsigned int snd_soc_component_read(struct snd_soc_component *component, 720e8712315SKuninori Morimoto unsigned int reg) 721e8712315SKuninori Morimoto { 722e8712315SKuninori Morimoto unsigned int val; 723e8712315SKuninori Morimoto 724e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 725e8712315SKuninori Morimoto val = soc_component_read_no_lock(component, reg); 726e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 727e8712315SKuninori Morimoto 728e8712315SKuninori Morimoto return val; 729e8712315SKuninori Morimoto } 730cf6e26c7SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_read); 731460b42d1SKuninori Morimoto 732e8712315SKuninori Morimoto static int soc_component_write_no_lock( 733e8712315SKuninori Morimoto struct snd_soc_component *component, 734e8712315SKuninori Morimoto unsigned int reg, unsigned int val) 735e8712315SKuninori Morimoto { 736e8712315SKuninori Morimoto int ret = -EIO; 737e8712315SKuninori Morimoto 738e8712315SKuninori Morimoto if (component->regmap) 739e8712315SKuninori Morimoto ret = regmap_write(component->regmap, reg, val); 740e8712315SKuninori Morimoto else if (component->driver->write) 741e8712315SKuninori Morimoto ret = component->driver->write(component, reg, val); 742e8712315SKuninori Morimoto 743e8712315SKuninori Morimoto return soc_component_ret(component, ret); 744e8712315SKuninori Morimoto } 745e8712315SKuninori Morimoto 746460b42d1SKuninori Morimoto /** 747460b42d1SKuninori Morimoto * snd_soc_component_write() - Write register value 748460b42d1SKuninori Morimoto * @component: Component to write to 749460b42d1SKuninori Morimoto * @reg: Register to write 750460b42d1SKuninori Morimoto * @val: Value to write to the register 751460b42d1SKuninori Morimoto * 752460b42d1SKuninori Morimoto * Return: 0 on success, a negative error code otherwise. 753460b42d1SKuninori Morimoto */ 754460b42d1SKuninori Morimoto int snd_soc_component_write(struct snd_soc_component *component, 755460b42d1SKuninori Morimoto unsigned int reg, unsigned int val) 756460b42d1SKuninori Morimoto { 757e8712315SKuninori Morimoto int ret; 758460b42d1SKuninori Morimoto 759e8712315SKuninori Morimoto mutex_lock(&component->io_mutex); 760e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, val); 761e8712315SKuninori Morimoto mutex_unlock(&component->io_mutex); 762460b42d1SKuninori Morimoto 763e8712315SKuninori Morimoto return ret; 764460b42d1SKuninori Morimoto } 765460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_write); 766460b42d1SKuninori Morimoto 767460b42d1SKuninori Morimoto static int snd_soc_component_update_bits_legacy( 768460b42d1SKuninori Morimoto struct snd_soc_component *component, unsigned int reg, 769460b42d1SKuninori Morimoto unsigned int mask, unsigned int val, bool *change) 770460b42d1SKuninori Morimoto { 771460b42d1SKuninori Morimoto unsigned int old, new; 772cf6e26c7SKuninori Morimoto int ret = 0; 773460b42d1SKuninori Morimoto 774460b42d1SKuninori Morimoto mutex_lock(&component->io_mutex); 775460b42d1SKuninori Morimoto 776e8712315SKuninori Morimoto old = soc_component_read_no_lock(component, reg); 777460b42d1SKuninori Morimoto 778460b42d1SKuninori Morimoto new = (old & ~mask) | (val & mask); 779460b42d1SKuninori Morimoto *change = old != new; 780460b42d1SKuninori Morimoto if (*change) 781e8712315SKuninori Morimoto ret = soc_component_write_no_lock(component, reg, new); 782cf6e26c7SKuninori Morimoto 783460b42d1SKuninori Morimoto mutex_unlock(&component->io_mutex); 784460b42d1SKuninori Morimoto 785460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 786460b42d1SKuninori Morimoto } 787460b42d1SKuninori Morimoto 788460b42d1SKuninori Morimoto /** 789460b42d1SKuninori Morimoto * snd_soc_component_update_bits() - Perform read/modify/write cycle 790460b42d1SKuninori Morimoto * @component: Component to update 791460b42d1SKuninori Morimoto * @reg: Register to update 792460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 793460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 794460b42d1SKuninori Morimoto * 795460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 796460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 797460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 798460b42d1SKuninori Morimoto */ 799460b42d1SKuninori Morimoto int snd_soc_component_update_bits(struct snd_soc_component *component, 800460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 801460b42d1SKuninori Morimoto { 802460b42d1SKuninori Morimoto bool change; 803460b42d1SKuninori Morimoto int ret; 804460b42d1SKuninori Morimoto 805460b42d1SKuninori Morimoto if (component->regmap) 806460b42d1SKuninori Morimoto ret = regmap_update_bits_check(component->regmap, reg, mask, 807460b42d1SKuninori Morimoto val, &change); 808460b42d1SKuninori Morimoto else 809460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 810460b42d1SKuninori Morimoto mask, val, &change); 811460b42d1SKuninori Morimoto 812460b42d1SKuninori Morimoto if (ret < 0) 813460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 814460b42d1SKuninori Morimoto return change; 815460b42d1SKuninori Morimoto } 816460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits); 817460b42d1SKuninori Morimoto 818460b42d1SKuninori Morimoto /** 819460b42d1SKuninori Morimoto * snd_soc_component_update_bits_async() - Perform asynchronous 820460b42d1SKuninori Morimoto * read/modify/write cycle 821460b42d1SKuninori Morimoto * @component: Component to update 822460b42d1SKuninori Morimoto * @reg: Register to update 823460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to update 824460b42d1SKuninori Morimoto * @val: New value for the bits specified by mask 825460b42d1SKuninori Morimoto * 826460b42d1SKuninori Morimoto * This function is similar to snd_soc_component_update_bits(), but the update 827460b42d1SKuninori Morimoto * operation is scheduled asynchronously. This means it may not be completed 828460b42d1SKuninori Morimoto * when the function returns. To make sure that all scheduled updates have been 829460b42d1SKuninori Morimoto * completed snd_soc_component_async_complete() must be called. 830460b42d1SKuninori Morimoto * 831460b42d1SKuninori Morimoto * Return: 1 if the operation was successful and the value of the register 832460b42d1SKuninori Morimoto * changed, 0 if the operation was successful, but the value did not change. 833460b42d1SKuninori Morimoto * Returns a negative error code otherwise. 834460b42d1SKuninori Morimoto */ 835460b42d1SKuninori Morimoto int snd_soc_component_update_bits_async(struct snd_soc_component *component, 836460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int val) 837460b42d1SKuninori Morimoto { 838460b42d1SKuninori Morimoto bool change; 839460b42d1SKuninori Morimoto int ret; 840460b42d1SKuninori Morimoto 841460b42d1SKuninori Morimoto if (component->regmap) 842460b42d1SKuninori Morimoto ret = regmap_update_bits_check_async(component->regmap, reg, 843460b42d1SKuninori Morimoto mask, val, &change); 844460b42d1SKuninori Morimoto else 845460b42d1SKuninori Morimoto ret = snd_soc_component_update_bits_legacy(component, reg, 846460b42d1SKuninori Morimoto mask, val, &change); 847460b42d1SKuninori Morimoto 848460b42d1SKuninori Morimoto if (ret < 0) 849460b42d1SKuninori Morimoto return soc_component_ret(component, ret); 850460b42d1SKuninori Morimoto return change; 851460b42d1SKuninori Morimoto } 852460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async); 853460b42d1SKuninori Morimoto 854460b42d1SKuninori Morimoto /** 855*1da0b989SSrinivas Kandagatla * snd_soc_component_read_field() - Read register field value 856*1da0b989SSrinivas Kandagatla * @component: Component to read from 857*1da0b989SSrinivas Kandagatla * @reg: Register to read 858*1da0b989SSrinivas Kandagatla * @mask: mask of the register field 859*1da0b989SSrinivas Kandagatla * 860*1da0b989SSrinivas Kandagatla * Return: read value of register field. 861*1da0b989SSrinivas Kandagatla */ 862*1da0b989SSrinivas Kandagatla unsigned int snd_soc_component_read_field(struct snd_soc_component *component, 863*1da0b989SSrinivas Kandagatla unsigned int reg, unsigned int mask) 864*1da0b989SSrinivas Kandagatla { 865*1da0b989SSrinivas Kandagatla unsigned int val; 866*1da0b989SSrinivas Kandagatla 867*1da0b989SSrinivas Kandagatla val = snd_soc_component_read(component, reg); 868*1da0b989SSrinivas Kandagatla 869*1da0b989SSrinivas Kandagatla val = (val & mask) >> soc_component_field_shift(component, mask); 870*1da0b989SSrinivas Kandagatla 871*1da0b989SSrinivas Kandagatla return val; 872*1da0b989SSrinivas Kandagatla } 873*1da0b989SSrinivas Kandagatla EXPORT_SYMBOL_GPL(snd_soc_component_read_field); 874*1da0b989SSrinivas Kandagatla 875*1da0b989SSrinivas Kandagatla /** 876*1da0b989SSrinivas Kandagatla * snd_soc_component_write_field() - write to register field 877*1da0b989SSrinivas Kandagatla * @component: Component to write to 878*1da0b989SSrinivas Kandagatla * @reg: Register to write 879*1da0b989SSrinivas Kandagatla * @mask: mask of the register field to update 880*1da0b989SSrinivas Kandagatla * @val: value of the field to write 881*1da0b989SSrinivas Kandagatla * 882*1da0b989SSrinivas Kandagatla * Return: 1 for change, otherwise 0. 883*1da0b989SSrinivas Kandagatla */ 884*1da0b989SSrinivas Kandagatla int snd_soc_component_write_field(struct snd_soc_component *component, 885*1da0b989SSrinivas Kandagatla unsigned int reg, unsigned int mask, 886*1da0b989SSrinivas Kandagatla unsigned int val) 887*1da0b989SSrinivas Kandagatla { 888*1da0b989SSrinivas Kandagatla 889*1da0b989SSrinivas Kandagatla val = (val << soc_component_field_shift(component, mask)) & mask; 890*1da0b989SSrinivas Kandagatla 891*1da0b989SSrinivas Kandagatla return snd_soc_component_update_bits(component, reg, mask, val); 892*1da0b989SSrinivas Kandagatla } 893*1da0b989SSrinivas Kandagatla EXPORT_SYMBOL_GPL(snd_soc_component_write_field); 894*1da0b989SSrinivas Kandagatla 895*1da0b989SSrinivas Kandagatla /** 896460b42d1SKuninori Morimoto * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed 897460b42d1SKuninori Morimoto * @component: Component for which to wait 898460b42d1SKuninori Morimoto * 899460b42d1SKuninori Morimoto * This function blocks until all asynchronous I/O which has previously been 900460b42d1SKuninori Morimoto * scheduled using snd_soc_component_update_bits_async() has completed. 901460b42d1SKuninori Morimoto */ 902460b42d1SKuninori Morimoto void snd_soc_component_async_complete(struct snd_soc_component *component) 903460b42d1SKuninori Morimoto { 904460b42d1SKuninori Morimoto if (component->regmap) 905460b42d1SKuninori Morimoto regmap_async_complete(component->regmap); 906460b42d1SKuninori Morimoto } 907460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_async_complete); 908460b42d1SKuninori Morimoto 909460b42d1SKuninori Morimoto /** 910460b42d1SKuninori Morimoto * snd_soc_component_test_bits - Test register for change 911460b42d1SKuninori Morimoto * @component: component 912460b42d1SKuninori Morimoto * @reg: Register to test 913460b42d1SKuninori Morimoto * @mask: Mask that specifies which bits to test 914460b42d1SKuninori Morimoto * @value: Value to test against 915460b42d1SKuninori Morimoto * 916460b42d1SKuninori Morimoto * Tests a register with a new value and checks if the new value is 917460b42d1SKuninori Morimoto * different from the old value. 918460b42d1SKuninori Morimoto * 919460b42d1SKuninori Morimoto * Return: 1 for change, otherwise 0. 920460b42d1SKuninori Morimoto */ 921460b42d1SKuninori Morimoto int snd_soc_component_test_bits(struct snd_soc_component *component, 922460b42d1SKuninori Morimoto unsigned int reg, unsigned int mask, unsigned int value) 923460b42d1SKuninori Morimoto { 924460b42d1SKuninori Morimoto unsigned int old, new; 925460b42d1SKuninori Morimoto 926cf6e26c7SKuninori Morimoto old = snd_soc_component_read(component, reg); 927460b42d1SKuninori Morimoto new = (old & ~mask) | value; 928460b42d1SKuninori Morimoto return old != new; 929460b42d1SKuninori Morimoto } 930460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_test_bits); 931460b42d1SKuninori Morimoto 9320035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream) 9330035e256SKuninori Morimoto { 9340ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 9350035e256SKuninori Morimoto struct snd_soc_component *component; 936613fb500SKuninori Morimoto int i; 9370035e256SKuninori Morimoto 9380035e256SKuninori Morimoto /* FIXME: use 1st pointer */ 939613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 940e2cb4a14SKuninori Morimoto if (component->driver->pointer) 941e2cb4a14SKuninori Morimoto return component->driver->pointer(component, substream); 9420035e256SKuninori Morimoto 9430035e256SKuninori Morimoto return 0; 9440035e256SKuninori Morimoto } 94596a47908SKuninori Morimoto 94696a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, 94796a47908SKuninori Morimoto unsigned int cmd, void *arg) 94896a47908SKuninori Morimoto { 9490ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 95096a47908SKuninori Morimoto struct snd_soc_component *component; 951613fb500SKuninori Morimoto int i; 95296a47908SKuninori Morimoto 95396a47908SKuninori Morimoto /* FIXME: use 1st ioctl */ 954613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 955e2cb4a14SKuninori Morimoto if (component->driver->ioctl) 956e2329eebSKuninori Morimoto return soc_component_ret( 957e2329eebSKuninori Morimoto component, 958e2329eebSKuninori Morimoto component->driver->ioctl(component, 959e2329eebSKuninori Morimoto substream, cmd, arg)); 96096a47908SKuninori Morimoto 96196a47908SKuninori Morimoto return snd_pcm_lib_ioctl(substream, cmd, arg); 96296a47908SKuninori Morimoto } 96382d81f5cSKuninori Morimoto 9641e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream) 9651e5ddb6bSTakashi Iwai { 9660ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 9671e5ddb6bSTakashi Iwai struct snd_soc_component *component; 968613fb500SKuninori Morimoto int i, ret; 9691e5ddb6bSTakashi Iwai 970613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 971f1861a7cSKuninori Morimoto if (component->driver->sync_stop) { 9721e5ddb6bSTakashi Iwai ret = component->driver->sync_stop(component, 9731e5ddb6bSTakashi Iwai substream); 9741e5ddb6bSTakashi Iwai if (ret < 0) 975be75db57SShengjiu Wang return soc_component_ret(component, ret); 9761e5ddb6bSTakashi Iwai } 9771e5ddb6bSTakashi Iwai } 9781e5ddb6bSTakashi Iwai 9791e5ddb6bSTakashi Iwai return 0; 9801e5ddb6bSTakashi Iwai } 9811e5ddb6bSTakashi Iwai 98282d81f5cSKuninori Morimoto int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, 98382d81f5cSKuninori Morimoto int channel, unsigned long pos, 98482d81f5cSKuninori Morimoto void __user *buf, unsigned long bytes) 98582d81f5cSKuninori Morimoto { 9860ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 98782d81f5cSKuninori Morimoto struct snd_soc_component *component; 988613fb500SKuninori Morimoto int i; 98982d81f5cSKuninori Morimoto 99082d81f5cSKuninori Morimoto /* FIXME. it returns 1st copy now */ 991613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 992e2cb4a14SKuninori Morimoto if (component->driver->copy_user) 993e2329eebSKuninori Morimoto return soc_component_ret( 994e2329eebSKuninori Morimoto component, 995e2329eebSKuninori Morimoto component->driver->copy_user( 996e2329eebSKuninori Morimoto component, substream, channel, 997e2329eebSKuninori Morimoto pos, buf, bytes)); 99882d81f5cSKuninori Morimoto 99982d81f5cSKuninori Morimoto return -EINVAL; 100082d81f5cSKuninori Morimoto } 10019c712e4fSKuninori Morimoto 10029c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, 10039c712e4fSKuninori Morimoto unsigned long offset) 10049c712e4fSKuninori Morimoto { 10050ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 10069c712e4fSKuninori Morimoto struct snd_soc_component *component; 10079c712e4fSKuninori Morimoto struct page *page; 1008613fb500SKuninori Morimoto int i; 10099c712e4fSKuninori Morimoto 10109c712e4fSKuninori Morimoto /* FIXME. it returns 1st page now */ 1011613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1012e2cb4a14SKuninori Morimoto if (component->driver->page) { 1013e2cb4a14SKuninori Morimoto page = component->driver->page(component, 1014e2cb4a14SKuninori Morimoto substream, offset); 1015e2cb4a14SKuninori Morimoto if (page) 1016e2cb4a14SKuninori Morimoto return page; 1017e2cb4a14SKuninori Morimoto } 10189c712e4fSKuninori Morimoto } 10199c712e4fSKuninori Morimoto 10209c712e4fSKuninori Morimoto return NULL; 10219c712e4fSKuninori Morimoto } 1022205875e1SKuninori Morimoto 1023205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, 1024205875e1SKuninori Morimoto struct vm_area_struct *vma) 1025205875e1SKuninori Morimoto { 10260ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1027205875e1SKuninori Morimoto struct snd_soc_component *component; 1028613fb500SKuninori Morimoto int i; 1029205875e1SKuninori Morimoto 1030205875e1SKuninori Morimoto /* FIXME. it returns 1st mmap now */ 1031613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 1032e2cb4a14SKuninori Morimoto if (component->driver->mmap) 1033be75db57SShengjiu Wang return soc_component_ret( 1034e2329eebSKuninori Morimoto component, 1035e2329eebSKuninori Morimoto component->driver->mmap(component, 1036e2329eebSKuninori Morimoto substream, vma)); 1037205875e1SKuninori Morimoto 1038205875e1SKuninori Morimoto return -EINVAL; 1039205875e1SKuninori Morimoto } 10407484291eSKuninori Morimoto 1041b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd) 10427484291eSKuninori Morimoto { 10437484291eSKuninori Morimoto struct snd_soc_component *component; 10447484291eSKuninori Morimoto int ret; 1045613fb500SKuninori Morimoto int i; 10467484291eSKuninori Morimoto 1047613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1048c64bfc90SKuninori Morimoto if (component->driver->pcm_construct) { 1049c64bfc90SKuninori Morimoto ret = component->driver->pcm_construct(component, rtd); 1050c64bfc90SKuninori Morimoto if (ret < 0) 1051be75db57SShengjiu Wang return soc_component_ret(component, ret); 1052c64bfc90SKuninori Morimoto } 10537484291eSKuninori Morimoto } 10547484291eSKuninori Morimoto 10557484291eSKuninori Morimoto return 0; 10567484291eSKuninori Morimoto } 105779776da0SKuninori Morimoto 1058b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd) 105979776da0SKuninori Morimoto { 106079776da0SKuninori Morimoto struct snd_soc_component *component; 1061613fb500SKuninori Morimoto int i; 106279776da0SKuninori Morimoto 10638e3366caSTakashi Iwai if (!rtd->pcm) 10648e3366caSTakashi Iwai return; 10658e3366caSTakashi Iwai 1066613fb500SKuninori Morimoto for_each_rtd_components(rtd, i, component) 1067c64bfc90SKuninori Morimoto if (component->driver->pcm_destruct) 1068b2b2afbbSKuninori Morimoto component->driver->pcm_destruct(component, rtd->pcm); 106979776da0SKuninori Morimoto } 10704f39514fSKuninori Morimoto 10714f39514fSKuninori Morimoto int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream) 10724f39514fSKuninori Morimoto { 10730ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 10744f39514fSKuninori Morimoto struct snd_soc_component *component; 10754f39514fSKuninori Morimoto int i, ret; 10764f39514fSKuninori Morimoto 10774f39514fSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 10784f39514fSKuninori Morimoto if (component->driver->prepare) { 10794f39514fSKuninori Morimoto ret = component->driver->prepare(component, substream); 10804f39514fSKuninori Morimoto if (ret < 0) 10814f39514fSKuninori Morimoto return soc_component_ret(component, ret); 10824f39514fSKuninori Morimoto } 10834f39514fSKuninori Morimoto } 10844f39514fSKuninori Morimoto 10854f39514fSKuninori Morimoto return 0; 10864f39514fSKuninori Morimoto } 1087e1bafa82SKuninori Morimoto 1088e1bafa82SKuninori Morimoto int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, 10893a36a64aSKuninori Morimoto struct snd_pcm_hw_params *params) 1090e1bafa82SKuninori Morimoto { 10910ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 1092e1bafa82SKuninori Morimoto struct snd_soc_component *component; 1093e1bafa82SKuninori Morimoto int i, ret; 1094e1bafa82SKuninori Morimoto 1095e1bafa82SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1096e1bafa82SKuninori Morimoto if (component->driver->hw_params) { 1097e1bafa82SKuninori Morimoto ret = component->driver->hw_params(component, 1098e1bafa82SKuninori Morimoto substream, params); 10993a36a64aSKuninori Morimoto if (ret < 0) 1100e1bafa82SKuninori Morimoto return soc_component_ret(component, ret); 1101e1bafa82SKuninori Morimoto } 11023a36a64aSKuninori Morimoto /* mark substream if succeeded */ 11033a36a64aSKuninori Morimoto soc_component_mark_push(component, substream, hw_params); 1104e1bafa82SKuninori Morimoto } 1105e1bafa82SKuninori Morimoto 1106e1bafa82SKuninori Morimoto return 0; 1107e1bafa82SKuninori Morimoto } 110804751119SKuninori Morimoto 110904751119SKuninori Morimoto void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, 11103a36a64aSKuninori Morimoto int rollback) 111104751119SKuninori Morimoto { 11120ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 111304751119SKuninori Morimoto struct snd_soc_component *component; 111404751119SKuninori Morimoto int i, ret; 111504751119SKuninori Morimoto 111604751119SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 11173a36a64aSKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, hw_params)) 11183a36a64aSKuninori Morimoto continue; 111904751119SKuninori Morimoto 112004751119SKuninori Morimoto if (component->driver->hw_free) { 112104751119SKuninori Morimoto ret = component->driver->hw_free(component, substream); 112204751119SKuninori Morimoto if (ret < 0) 112304751119SKuninori Morimoto soc_component_ret(component, ret); 112404751119SKuninori Morimoto } 11253a36a64aSKuninori Morimoto 11263a36a64aSKuninori Morimoto /* remove marked substream */ 11273a36a64aSKuninori Morimoto soc_component_mark_pop(component, substream, hw_params); 112804751119SKuninori Morimoto } 112904751119SKuninori Morimoto } 113032fd1204SKuninori Morimoto 11316374f493SKuninori Morimoto static int soc_component_trigger(struct snd_soc_component *component, 11326374f493SKuninori Morimoto struct snd_pcm_substream *substream, 113332fd1204SKuninori Morimoto int cmd) 113432fd1204SKuninori Morimoto { 11356374f493SKuninori Morimoto int ret = 0; 11366374f493SKuninori Morimoto 11376374f493SKuninori Morimoto if (component->driver->trigger) 11386374f493SKuninori Morimoto ret = component->driver->trigger(component, substream, cmd); 11396374f493SKuninori Morimoto 11406374f493SKuninori Morimoto return soc_component_ret(component, ret); 11416374f493SKuninori Morimoto } 11426374f493SKuninori Morimoto 11436374f493SKuninori Morimoto int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, 11446374f493SKuninori Morimoto int cmd, int rollback) 11456374f493SKuninori Morimoto { 11460ceef681SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 114732fd1204SKuninori Morimoto struct snd_soc_component *component; 11486374f493SKuninori Morimoto int i, r, ret = 0; 114932fd1204SKuninori Morimoto 11506374f493SKuninori Morimoto switch (cmd) { 11516374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_START: 11526374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_RESUME: 11536374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 115432fd1204SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 11556374f493SKuninori Morimoto ret = soc_component_trigger(component, substream, cmd); 115632fd1204SKuninori Morimoto if (ret < 0) 11576374f493SKuninori Morimoto break; 11586374f493SKuninori Morimoto soc_component_mark_push(component, substream, trigger); 11596374f493SKuninori Morimoto } 11606374f493SKuninori Morimoto break; 11616374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_STOP: 11626374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_SUSPEND: 11636374f493SKuninori Morimoto case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 11646374f493SKuninori Morimoto for_each_rtd_components(rtd, i, component) { 11656374f493SKuninori Morimoto if (rollback && !soc_component_mark_match(component, substream, trigger)) 11666374f493SKuninori Morimoto continue; 11676374f493SKuninori Morimoto 11686374f493SKuninori Morimoto r = soc_component_trigger(component, substream, cmd); 11696374f493SKuninori Morimoto if (r < 0) 11706374f493SKuninori Morimoto ret = r; /* use last ret */ 11716374f493SKuninori Morimoto soc_component_mark_pop(component, substream, trigger); 117232fd1204SKuninori Morimoto } 117332fd1204SKuninori Morimoto } 117432fd1204SKuninori Morimoto 11756374f493SKuninori Morimoto return ret; 117632fd1204SKuninori Morimoto } 1177939a5cfbSKuninori Morimoto 1178939a5cfbSKuninori Morimoto int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd, 1179939a5cfbSKuninori Morimoto void *stream) 1180939a5cfbSKuninori Morimoto { 1181939a5cfbSKuninori Morimoto struct snd_soc_component *component; 1182939a5cfbSKuninori Morimoto int i, ret; 1183939a5cfbSKuninori Morimoto 1184939a5cfbSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1185939a5cfbSKuninori Morimoto ret = pm_runtime_get_sync(component->dev); 1186939a5cfbSKuninori Morimoto if (ret < 0 && ret != -EACCES) { 1187939a5cfbSKuninori Morimoto pm_runtime_put_noidle(component->dev); 1188939a5cfbSKuninori Morimoto return soc_component_ret(component, ret); 1189939a5cfbSKuninori Morimoto } 1190939a5cfbSKuninori Morimoto /* mark stream if succeeded */ 1191939a5cfbSKuninori Morimoto soc_component_mark_push(component, stream, pm); 1192939a5cfbSKuninori Morimoto } 1193939a5cfbSKuninori Morimoto 1194939a5cfbSKuninori Morimoto return 0; 1195939a5cfbSKuninori Morimoto } 1196939a5cfbSKuninori Morimoto 1197939a5cfbSKuninori Morimoto void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd, 1198939a5cfbSKuninori Morimoto void *stream, int rollback) 1199939a5cfbSKuninori Morimoto { 1200939a5cfbSKuninori Morimoto struct snd_soc_component *component; 1201939a5cfbSKuninori Morimoto int i; 1202939a5cfbSKuninori Morimoto 1203939a5cfbSKuninori Morimoto for_each_rtd_components(rtd, i, component) { 1204939a5cfbSKuninori Morimoto if (rollback && !soc_component_mark_match(component, stream, pm)) 1205939a5cfbSKuninori Morimoto continue; 1206939a5cfbSKuninori Morimoto 1207939a5cfbSKuninori Morimoto pm_runtime_mark_last_busy(component->dev); 1208939a5cfbSKuninori Morimoto pm_runtime_put_autosuspend(component->dev); 1209939a5cfbSKuninori Morimoto 1210939a5cfbSKuninori Morimoto /* remove marked stream */ 1211939a5cfbSKuninori Morimoto soc_component_mark_pop(component, stream, pm); 1212939a5cfbSKuninori Morimoto } 1213939a5cfbSKuninori Morimoto } 1214