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