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