xref: /openbmc/linux/sound/soc/soc-component.c (revision 6374f493)
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