xref: /openbmc/linux/sound/soc/soc-component.c (revision be75db57)
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 
36536aba1dSKuninori Morimoto int snd_soc_component_initialize(struct snd_soc_component *component,
37536aba1dSKuninori Morimoto 				 const struct snd_soc_component_driver *driver,
38536aba1dSKuninori Morimoto 				 struct device *dev, const char *name)
39536aba1dSKuninori Morimoto {
40536aba1dSKuninori Morimoto 	INIT_LIST_HEAD(&component->dai_list);
41536aba1dSKuninori Morimoto 	INIT_LIST_HEAD(&component->dobj_list);
42536aba1dSKuninori Morimoto 	INIT_LIST_HEAD(&component->card_list);
43536aba1dSKuninori Morimoto 	mutex_init(&component->io_mutex);
44536aba1dSKuninori Morimoto 
45536aba1dSKuninori Morimoto 	component->name		= name;
46536aba1dSKuninori Morimoto 	component->dev		= dev;
47536aba1dSKuninori Morimoto 	component->driver	= driver;
48536aba1dSKuninori Morimoto 
49536aba1dSKuninori Morimoto 	return 0;
50536aba1dSKuninori Morimoto }
51536aba1dSKuninori Morimoto 
52257c4dacSKuninori Morimoto void snd_soc_component_set_aux(struct snd_soc_component *component,
53257c4dacSKuninori Morimoto 			       struct snd_soc_aux_dev *aux)
54257c4dacSKuninori Morimoto {
55257c4dacSKuninori Morimoto 	component->init = (aux) ? aux->init : NULL;
56257c4dacSKuninori Morimoto }
57257c4dacSKuninori Morimoto 
58257c4dacSKuninori Morimoto int snd_soc_component_init(struct snd_soc_component *component)
59257c4dacSKuninori Morimoto {
60257c4dacSKuninori Morimoto 	int ret = 0;
61257c4dacSKuninori Morimoto 
62257c4dacSKuninori Morimoto 	if (component->init)
63257c4dacSKuninori Morimoto 		ret = component->init(component);
64257c4dacSKuninori Morimoto 
65257c4dacSKuninori Morimoto 	return soc_component_ret(component, ret);
66257c4dacSKuninori Morimoto }
67257c4dacSKuninori Morimoto 
684ff1fef1SKuninori Morimoto /**
694ff1fef1SKuninori Morimoto  * snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
704ff1fef1SKuninori Morimoto  * @component: COMPONENT
714ff1fef1SKuninori Morimoto  * @clk_id: DAI specific clock ID
724ff1fef1SKuninori Morimoto  * @source: Source for the clock
734ff1fef1SKuninori Morimoto  * @freq: new clock frequency in Hz
744ff1fef1SKuninori Morimoto  * @dir: new clock direction - input/output.
754ff1fef1SKuninori Morimoto  *
764ff1fef1SKuninori Morimoto  * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
774ff1fef1SKuninori Morimoto  */
784ff1fef1SKuninori Morimoto int snd_soc_component_set_sysclk(struct snd_soc_component *component,
794ff1fef1SKuninori Morimoto 				 int clk_id, int source, unsigned int freq,
804ff1fef1SKuninori Morimoto 				 int dir)
814ff1fef1SKuninori Morimoto {
82e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
83e2329eebSKuninori Morimoto 
844ff1fef1SKuninori Morimoto 	if (component->driver->set_sysclk)
85e2329eebSKuninori Morimoto 		ret = component->driver->set_sysclk(component, clk_id, source,
864ff1fef1SKuninori Morimoto 						     freq, dir);
874ff1fef1SKuninori Morimoto 
88e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
894ff1fef1SKuninori Morimoto }
904ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
914ff1fef1SKuninori Morimoto 
924ff1fef1SKuninori Morimoto /*
934ff1fef1SKuninori Morimoto  * snd_soc_component_set_pll - configure component PLL.
944ff1fef1SKuninori Morimoto  * @component: COMPONENT
954ff1fef1SKuninori Morimoto  * @pll_id: DAI specific PLL ID
964ff1fef1SKuninori Morimoto  * @source: DAI specific source for the PLL
974ff1fef1SKuninori Morimoto  * @freq_in: PLL input clock frequency in Hz
984ff1fef1SKuninori Morimoto  * @freq_out: requested PLL output clock frequency in Hz
994ff1fef1SKuninori Morimoto  *
1004ff1fef1SKuninori Morimoto  * Configures and enables PLL to generate output clock based on input clock.
1014ff1fef1SKuninori Morimoto  */
1024ff1fef1SKuninori Morimoto int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
1034ff1fef1SKuninori Morimoto 			      int source, unsigned int freq_in,
1044ff1fef1SKuninori Morimoto 			      unsigned int freq_out)
1054ff1fef1SKuninori Morimoto {
106e2329eebSKuninori Morimoto 	int ret = -EINVAL;
107e2329eebSKuninori Morimoto 
1084ff1fef1SKuninori Morimoto 	if (component->driver->set_pll)
109e2329eebSKuninori Morimoto 		ret = component->driver->set_pll(component, pll_id, source,
1104ff1fef1SKuninori Morimoto 						  freq_in, freq_out);
1114ff1fef1SKuninori Morimoto 
112e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
1134ff1fef1SKuninori Morimoto }
1144ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_pll);
1154ff1fef1SKuninori Morimoto 
1169d415fbfSKuninori Morimoto void snd_soc_component_seq_notifier(struct snd_soc_component *component,
1179d415fbfSKuninori Morimoto 				    enum snd_soc_dapm_type type, int subseq)
1189d415fbfSKuninori Morimoto {
1199d415fbfSKuninori Morimoto 	if (component->driver->seq_notifier)
1209d415fbfSKuninori Morimoto 		component->driver->seq_notifier(component, type, subseq);
1219d415fbfSKuninori Morimoto }
1229d415fbfSKuninori Morimoto 
1238e2a990dSKuninori Morimoto int snd_soc_component_stream_event(struct snd_soc_component *component,
1248e2a990dSKuninori Morimoto 				   int event)
1258e2a990dSKuninori Morimoto {
126e2329eebSKuninori Morimoto 	int ret = 0;
1278e2a990dSKuninori Morimoto 
128e2329eebSKuninori Morimoto 	if (component->driver->stream_event)
129e2329eebSKuninori Morimoto 		ret = component->driver->stream_event(component, event);
130e2329eebSKuninori Morimoto 
131e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
1328e2a990dSKuninori Morimoto }
1338e2a990dSKuninori Morimoto 
1347951b146SKuninori Morimoto int snd_soc_component_set_bias_level(struct snd_soc_component *component,
1357951b146SKuninori Morimoto 				     enum snd_soc_bias_level level)
1367951b146SKuninori Morimoto {
137e2329eebSKuninori Morimoto 	int ret = 0;
1387951b146SKuninori Morimoto 
139e2329eebSKuninori Morimoto 	if (component->driver->set_bias_level)
140e2329eebSKuninori Morimoto 		ret = component->driver->set_bias_level(component, level);
141e2329eebSKuninori Morimoto 
142e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
1437951b146SKuninori Morimoto }
1447951b146SKuninori Morimoto 
1454ca8701eSKuninori Morimoto static int soc_component_pin(struct snd_soc_component *component,
1464ca8701eSKuninori Morimoto 			     const char *pin,
1474ca8701eSKuninori Morimoto 			     int (*pin_func)(struct snd_soc_dapm_context *dapm,
1484ca8701eSKuninori Morimoto 					     const char *pin))
1494ff1fef1SKuninori Morimoto {
1504ff1fef1SKuninori Morimoto 	struct snd_soc_dapm_context *dapm =
1514ff1fef1SKuninori Morimoto 		snd_soc_component_get_dapm(component);
1524ff1fef1SKuninori Morimoto 	char *full_name;
1534ff1fef1SKuninori Morimoto 	int ret;
1544ff1fef1SKuninori Morimoto 
155e2329eebSKuninori Morimoto 	if (!component->name_prefix) {
156e2329eebSKuninori Morimoto 		ret = pin_func(dapm, pin);
157e2329eebSKuninori Morimoto 		goto end;
158e2329eebSKuninori Morimoto 	}
1594ff1fef1SKuninori Morimoto 
1604ff1fef1SKuninori Morimoto 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
161e2329eebSKuninori Morimoto 	if (!full_name) {
162e2329eebSKuninori Morimoto 		ret = -ENOMEM;
163e2329eebSKuninori Morimoto 		goto end;
164e2329eebSKuninori Morimoto 	}
1654ff1fef1SKuninori Morimoto 
1664ca8701eSKuninori Morimoto 	ret = pin_func(dapm, full_name);
1674ff1fef1SKuninori Morimoto 	kfree(full_name);
168e2329eebSKuninori Morimoto end:
169e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
1704ff1fef1SKuninori Morimoto }
1714ca8701eSKuninori Morimoto 
1724ca8701eSKuninori Morimoto int snd_soc_component_enable_pin(struct snd_soc_component *component,
1734ca8701eSKuninori Morimoto 				 const char *pin)
1744ca8701eSKuninori Morimoto {
1754ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_enable_pin);
1764ca8701eSKuninori Morimoto }
1774ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
1784ff1fef1SKuninori Morimoto 
1794ff1fef1SKuninori Morimoto int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
1804ff1fef1SKuninori Morimoto 					  const char *pin)
1814ff1fef1SKuninori Morimoto {
1824ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked);
1834ff1fef1SKuninori Morimoto }
1844ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
1854ff1fef1SKuninori Morimoto 
1864ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin(struct snd_soc_component *component,
1874ff1fef1SKuninori Morimoto 				  const char *pin)
1884ff1fef1SKuninori Morimoto {
1894ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_disable_pin);
1904ff1fef1SKuninori Morimoto }
1914ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
1924ff1fef1SKuninori Morimoto 
1934ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
1944ff1fef1SKuninori Morimoto 					   const char *pin)
1954ff1fef1SKuninori Morimoto {
1964ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked);
1974ff1fef1SKuninori Morimoto }
1984ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
1994ff1fef1SKuninori Morimoto 
2004ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin(struct snd_soc_component *component,
2014ff1fef1SKuninori Morimoto 			     const char *pin)
2024ff1fef1SKuninori Morimoto {
2034ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_nc_pin);
2044ff1fef1SKuninori Morimoto }
2054ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
2064ff1fef1SKuninori Morimoto 
2074ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
2084ff1fef1SKuninori Morimoto 				      const char *pin)
2094ff1fef1SKuninori Morimoto {
2104ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked);
2114ff1fef1SKuninori Morimoto }
2124ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
2134ff1fef1SKuninori Morimoto 
2144ff1fef1SKuninori Morimoto int snd_soc_component_get_pin_status(struct snd_soc_component *component,
2154ff1fef1SKuninori Morimoto 				     const char *pin)
2164ff1fef1SKuninori Morimoto {
2174ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status);
2184ff1fef1SKuninori Morimoto }
2194ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
2204ff1fef1SKuninori Morimoto 
2214ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
2224ff1fef1SKuninori Morimoto 				       const char *pin)
2234ff1fef1SKuninori Morimoto {
2244ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin);
2254ff1fef1SKuninori Morimoto }
2264ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
2274ff1fef1SKuninori Morimoto 
2284ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin_unlocked(
2294ff1fef1SKuninori Morimoto 	struct snd_soc_component *component,
2304ff1fef1SKuninori Morimoto 	const char *pin)
2314ff1fef1SKuninori Morimoto {
2324ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked);
2334ff1fef1SKuninori Morimoto }
2344ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
2354ff1fef1SKuninori Morimoto 
2364ff1fef1SKuninori Morimoto /**
2374ff1fef1SKuninori Morimoto  * snd_soc_component_set_jack - configure component jack.
2384ff1fef1SKuninori Morimoto  * @component: COMPONENTs
2394ff1fef1SKuninori Morimoto  * @jack: structure to use for the jack
2404ff1fef1SKuninori Morimoto  * @data: can be used if codec driver need extra data for configuring jack
2414ff1fef1SKuninori Morimoto  *
2424ff1fef1SKuninori Morimoto  * Configures and enables jack detection function.
2434ff1fef1SKuninori Morimoto  */
2444ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component,
2454ff1fef1SKuninori Morimoto 			       struct snd_soc_jack *jack, void *data)
2464ff1fef1SKuninori Morimoto {
247e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
2484ff1fef1SKuninori Morimoto 
249e2329eebSKuninori Morimoto 	if (component->driver->set_jack)
250e2329eebSKuninori Morimoto 		ret = component->driver->set_jack(component, jack, data);
251e2329eebSKuninori Morimoto 
252e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
2534ff1fef1SKuninori Morimoto }
2544ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
2554a81e8f3SKuninori Morimoto 
2564a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component,
2574a81e8f3SKuninori Morimoto 				 int upon_open)
2584a81e8f3SKuninori Morimoto {
259e2329eebSKuninori Morimoto 	int ret = 0;
260e2329eebSKuninori Morimoto 
2614a81e8f3SKuninori Morimoto 	if (component->driver->module_get_upon_open == !!upon_open &&
2624a81e8f3SKuninori Morimoto 	    !try_module_get(component->dev->driver->owner))
263e2329eebSKuninori Morimoto 		ret = -ENODEV;
2644a81e8f3SKuninori Morimoto 
265e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
2664a81e8f3SKuninori Morimoto }
2674a81e8f3SKuninori Morimoto 
2684a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component,
2694a81e8f3SKuninori Morimoto 				  int upon_open)
2704a81e8f3SKuninori Morimoto {
2714a81e8f3SKuninori Morimoto 	if (component->driver->module_get_upon_open == !!upon_open)
2724a81e8f3SKuninori Morimoto 		module_put(component->dev->driver->owner);
2734a81e8f3SKuninori Morimoto }
274ae2f4849SKuninori Morimoto 
275ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component,
276ae2f4849SKuninori Morimoto 			   struct snd_pcm_substream *substream)
277ae2f4849SKuninori Morimoto {
278e2329eebSKuninori Morimoto 	int ret = 0;
279e2329eebSKuninori Morimoto 
280e2cb4a14SKuninori Morimoto 	if (component->driver->open)
281e2329eebSKuninori Morimoto 		ret = component->driver->open(component, substream);
282e2329eebSKuninori Morimoto 
283e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
284ae2f4849SKuninori Morimoto }
2853672beb8SKuninori Morimoto 
2863672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component,
2873672beb8SKuninori Morimoto 			    struct snd_pcm_substream *substream)
2883672beb8SKuninori Morimoto {
289e2329eebSKuninori Morimoto 	int ret = 0;
290e2329eebSKuninori Morimoto 
291e2cb4a14SKuninori Morimoto 	if (component->driver->close)
292e2329eebSKuninori Morimoto 		ret = component->driver->close(component, substream);
293e2329eebSKuninori Morimoto 
294e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
2953672beb8SKuninori Morimoto }
2966d537233SKuninori Morimoto 
29766c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component)
29866c51573SKuninori Morimoto {
29966c51573SKuninori Morimoto 	if (component->driver->suspend)
30066c51573SKuninori Morimoto 		component->driver->suspend(component);
30166c51573SKuninori Morimoto 	component->suspended = 1;
30266c51573SKuninori Morimoto }
3039a840cbaSKuninori Morimoto 
3049a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component)
3059a840cbaSKuninori Morimoto {
3069a840cbaSKuninori Morimoto 	if (component->driver->resume)
3079a840cbaSKuninori Morimoto 		component->driver->resume(component);
3089a840cbaSKuninori Morimoto 	component->suspended = 0;
3099a840cbaSKuninori Morimoto }
310e40fadbcSKuninori Morimoto 
311e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component)
312e40fadbcSKuninori Morimoto {
313e40fadbcSKuninori Morimoto 	return component->suspended;
314e40fadbcSKuninori Morimoto }
31508e837ddSKuninori Morimoto 
31608e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component)
31708e837ddSKuninori Morimoto {
318e2329eebSKuninori Morimoto 	int ret = 0;
31908e837ddSKuninori Morimoto 
320e2329eebSKuninori Morimoto 	if (component->driver->probe)
321e2329eebSKuninori Morimoto 		ret = component->driver->probe(component);
322e2329eebSKuninori Morimoto 
323e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
32408e837ddSKuninori Morimoto }
32503b34dd7SKuninori Morimoto 
32603b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component)
32703b34dd7SKuninori Morimoto {
32803b34dd7SKuninori Morimoto 	if (component->driver->remove)
32903b34dd7SKuninori Morimoto 		component->driver->remove(component);
33003b34dd7SKuninori Morimoto }
3312c7b1704SKuninori Morimoto 
3322c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
3332c7b1704SKuninori Morimoto 				      struct device_node *ep)
3342c7b1704SKuninori Morimoto {
335e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
3362c7b1704SKuninori Morimoto 
337e2329eebSKuninori Morimoto 	if (component->driver->of_xlate_dai_id)
338e2329eebSKuninori Morimoto 		ret = component->driver->of_xlate_dai_id(component, ep);
339e2329eebSKuninori Morimoto 
340e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
3412c7b1704SKuninori Morimoto }
342a2a34175SKuninori Morimoto 
343a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
344a2a34175SKuninori Morimoto 					struct of_phandle_args *args,
345a2a34175SKuninori Morimoto 					const char **dai_name)
346a2a34175SKuninori Morimoto {
347e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
348e2329eebSKuninori Morimoto 
349a2a34175SKuninori Morimoto 	if (component->driver->of_xlate_dai_name)
350e2329eebSKuninori Morimoto 		ret = component->driver->of_xlate_dai_name(component,
351a2a34175SKuninori Morimoto 							   args, dai_name);
352e2329eebSKuninori Morimoto 
353e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
354a2a34175SKuninori Morimoto }
3550035e256SKuninori Morimoto 
356c7d75b59SKuninori Morimoto void snd_soc_component_setup_regmap(struct snd_soc_component *component)
357c7d75b59SKuninori Morimoto {
358c7d75b59SKuninori Morimoto 	int val_bytes = regmap_get_val_bytes(component->regmap);
359c7d75b59SKuninori Morimoto 
360c7d75b59SKuninori Morimoto 	/* Errors are legitimate for non-integer byte multiples */
361c7d75b59SKuninori Morimoto 	if (val_bytes > 0)
362c7d75b59SKuninori Morimoto 		component->val_bytes = val_bytes;
363c7d75b59SKuninori Morimoto }
364c7d75b59SKuninori Morimoto 
365c7d75b59SKuninori Morimoto #ifdef CONFIG_REGMAP
366c7d75b59SKuninori Morimoto 
367c7d75b59SKuninori Morimoto /**
368c7d75b59SKuninori Morimoto  * snd_soc_component_init_regmap() - Initialize regmap instance for the
369c7d75b59SKuninori Morimoto  *                                   component
370c7d75b59SKuninori Morimoto  * @component: The component for which to initialize the regmap instance
371c7d75b59SKuninori Morimoto  * @regmap: The regmap instance that should be used by the component
372c7d75b59SKuninori Morimoto  *
373c7d75b59SKuninori Morimoto  * This function allows deferred assignment of the regmap instance that is
374c7d75b59SKuninori Morimoto  * associated with the component. Only use this if the regmap instance is not
375c7d75b59SKuninori Morimoto  * yet ready when the component is registered. The function must also be called
376c7d75b59SKuninori Morimoto  * before the first IO attempt of the component.
377c7d75b59SKuninori Morimoto  */
378c7d75b59SKuninori Morimoto void snd_soc_component_init_regmap(struct snd_soc_component *component,
379c7d75b59SKuninori Morimoto 				   struct regmap *regmap)
380c7d75b59SKuninori Morimoto {
381c7d75b59SKuninori Morimoto 	component->regmap = regmap;
382c7d75b59SKuninori Morimoto 	snd_soc_component_setup_regmap(component);
383c7d75b59SKuninori Morimoto }
384c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);
385c7d75b59SKuninori Morimoto 
386c7d75b59SKuninori Morimoto /**
387c7d75b59SKuninori Morimoto  * snd_soc_component_exit_regmap() - De-initialize regmap instance for the
388c7d75b59SKuninori Morimoto  *                                   component
389c7d75b59SKuninori Morimoto  * @component: The component for which to de-initialize the regmap instance
390c7d75b59SKuninori Morimoto  *
391c7d75b59SKuninori Morimoto  * Calls regmap_exit() on the regmap instance associated to the component and
392c7d75b59SKuninori Morimoto  * removes the regmap instance from the component.
393c7d75b59SKuninori Morimoto  *
394c7d75b59SKuninori Morimoto  * This function should only be used if snd_soc_component_init_regmap() was used
395c7d75b59SKuninori Morimoto  * to initialize the regmap instance.
396c7d75b59SKuninori Morimoto  */
397c7d75b59SKuninori Morimoto void snd_soc_component_exit_regmap(struct snd_soc_component *component)
398c7d75b59SKuninori Morimoto {
399c7d75b59SKuninori Morimoto 	regmap_exit(component->regmap);
400c7d75b59SKuninori Morimoto 	component->regmap = NULL;
401c7d75b59SKuninori Morimoto }
402c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
403c7d75b59SKuninori Morimoto 
404c7d75b59SKuninori Morimoto #endif
405c7d75b59SKuninori Morimoto 
406e8712315SKuninori Morimoto static unsigned int soc_component_read_no_lock(
407e8712315SKuninori Morimoto 	struct snd_soc_component *component,
408cf6e26c7SKuninori Morimoto 	unsigned int reg)
409460b42d1SKuninori Morimoto {
410460b42d1SKuninori Morimoto 	int ret;
411cf6e26c7SKuninori Morimoto 	unsigned int val = 0;
412460b42d1SKuninori Morimoto 
413460b42d1SKuninori Morimoto 	if (component->regmap)
414cf6e26c7SKuninori Morimoto 		ret = regmap_read(component->regmap, reg, &val);
415460b42d1SKuninori Morimoto 	else if (component->driver->read) {
416460b42d1SKuninori Morimoto 		ret = 0;
417cf6e26c7SKuninori Morimoto 		val = component->driver->read(component, reg);
418460b42d1SKuninori Morimoto 	}
419460b42d1SKuninori Morimoto 	else
420460b42d1SKuninori Morimoto 		ret = -EIO;
421460b42d1SKuninori Morimoto 
422460b42d1SKuninori Morimoto 	if (ret < 0)
423cf6e26c7SKuninori Morimoto 		soc_component_ret(component, ret);
424460b42d1SKuninori Morimoto 
425460b42d1SKuninori Morimoto 	return val;
426460b42d1SKuninori Morimoto }
427e8712315SKuninori Morimoto 
428e8712315SKuninori Morimoto /**
429e8712315SKuninori Morimoto  * snd_soc_component_read() - Read register value
430e8712315SKuninori Morimoto  * @component: Component to read from
431e8712315SKuninori Morimoto  * @reg: Register to read
432e8712315SKuninori Morimoto  *
433e8712315SKuninori Morimoto  * Return: read value
434e8712315SKuninori Morimoto  */
435e8712315SKuninori Morimoto unsigned int snd_soc_component_read(struct snd_soc_component *component,
436e8712315SKuninori Morimoto 				    unsigned int reg)
437e8712315SKuninori Morimoto {
438e8712315SKuninori Morimoto 	unsigned int val;
439e8712315SKuninori Morimoto 
440e8712315SKuninori Morimoto 	mutex_lock(&component->io_mutex);
441e8712315SKuninori Morimoto 	val = soc_component_read_no_lock(component, reg);
442e8712315SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
443e8712315SKuninori Morimoto 
444e8712315SKuninori Morimoto 	return val;
445e8712315SKuninori Morimoto }
446cf6e26c7SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_read);
447460b42d1SKuninori Morimoto 
448e8712315SKuninori Morimoto static int soc_component_write_no_lock(
449e8712315SKuninori Morimoto 	struct snd_soc_component *component,
450e8712315SKuninori Morimoto 	unsigned int reg, unsigned int val)
451e8712315SKuninori Morimoto {
452e8712315SKuninori Morimoto 	int ret = -EIO;
453e8712315SKuninori Morimoto 
454e8712315SKuninori Morimoto 	if (component->regmap)
455e8712315SKuninori Morimoto 		ret = regmap_write(component->regmap, reg, val);
456e8712315SKuninori Morimoto 	else if (component->driver->write)
457e8712315SKuninori Morimoto 		ret = component->driver->write(component, reg, val);
458e8712315SKuninori Morimoto 
459e8712315SKuninori Morimoto 	return soc_component_ret(component, ret);
460e8712315SKuninori Morimoto }
461e8712315SKuninori Morimoto 
462460b42d1SKuninori Morimoto /**
463460b42d1SKuninori Morimoto  * snd_soc_component_write() - Write register value
464460b42d1SKuninori Morimoto  * @component: Component to write to
465460b42d1SKuninori Morimoto  * @reg: Register to write
466460b42d1SKuninori Morimoto  * @val: Value to write to the register
467460b42d1SKuninori Morimoto  *
468460b42d1SKuninori Morimoto  * Return: 0 on success, a negative error code otherwise.
469460b42d1SKuninori Morimoto  */
470460b42d1SKuninori Morimoto int snd_soc_component_write(struct snd_soc_component *component,
471460b42d1SKuninori Morimoto 			    unsigned int reg, unsigned int val)
472460b42d1SKuninori Morimoto {
473e8712315SKuninori Morimoto 	int ret;
474460b42d1SKuninori Morimoto 
475e8712315SKuninori Morimoto 	mutex_lock(&component->io_mutex);
476e8712315SKuninori Morimoto 	ret = soc_component_write_no_lock(component, reg, val);
477e8712315SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
478460b42d1SKuninori Morimoto 
479e8712315SKuninori Morimoto 	return ret;
480460b42d1SKuninori Morimoto }
481460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_write);
482460b42d1SKuninori Morimoto 
483460b42d1SKuninori Morimoto static int snd_soc_component_update_bits_legacy(
484460b42d1SKuninori Morimoto 	struct snd_soc_component *component, unsigned int reg,
485460b42d1SKuninori Morimoto 	unsigned int mask, unsigned int val, bool *change)
486460b42d1SKuninori Morimoto {
487460b42d1SKuninori Morimoto 	unsigned int old, new;
488cf6e26c7SKuninori Morimoto 	int ret = 0;
489460b42d1SKuninori Morimoto 
490460b42d1SKuninori Morimoto 	mutex_lock(&component->io_mutex);
491460b42d1SKuninori Morimoto 
492e8712315SKuninori Morimoto 	old = soc_component_read_no_lock(component, reg);
493460b42d1SKuninori Morimoto 
494460b42d1SKuninori Morimoto 	new = (old & ~mask) | (val & mask);
495460b42d1SKuninori Morimoto 	*change = old != new;
496460b42d1SKuninori Morimoto 	if (*change)
497e8712315SKuninori Morimoto 		ret = soc_component_write_no_lock(component, reg, new);
498cf6e26c7SKuninori Morimoto 
499460b42d1SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
500460b42d1SKuninori Morimoto 
501460b42d1SKuninori Morimoto 	return soc_component_ret(component, ret);
502460b42d1SKuninori Morimoto }
503460b42d1SKuninori Morimoto 
504460b42d1SKuninori Morimoto /**
505460b42d1SKuninori Morimoto  * snd_soc_component_update_bits() - Perform read/modify/write cycle
506460b42d1SKuninori Morimoto  * @component: Component to update
507460b42d1SKuninori Morimoto  * @reg: Register to update
508460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to update
509460b42d1SKuninori Morimoto  * @val: New value for the bits specified by mask
510460b42d1SKuninori Morimoto  *
511460b42d1SKuninori Morimoto  * Return: 1 if the operation was successful and the value of the register
512460b42d1SKuninori Morimoto  * changed, 0 if the operation was successful, but the value did not change.
513460b42d1SKuninori Morimoto  * Returns a negative error code otherwise.
514460b42d1SKuninori Morimoto  */
515460b42d1SKuninori Morimoto int snd_soc_component_update_bits(struct snd_soc_component *component,
516460b42d1SKuninori Morimoto 				  unsigned int reg, unsigned int mask, unsigned int val)
517460b42d1SKuninori Morimoto {
518460b42d1SKuninori Morimoto 	bool change;
519460b42d1SKuninori Morimoto 	int ret;
520460b42d1SKuninori Morimoto 
521460b42d1SKuninori Morimoto 	if (component->regmap)
522460b42d1SKuninori Morimoto 		ret = regmap_update_bits_check(component->regmap, reg, mask,
523460b42d1SKuninori Morimoto 					       val, &change);
524460b42d1SKuninori Morimoto 	else
525460b42d1SKuninori Morimoto 		ret = snd_soc_component_update_bits_legacy(component, reg,
526460b42d1SKuninori Morimoto 							   mask, val, &change);
527460b42d1SKuninori Morimoto 
528460b42d1SKuninori Morimoto 	if (ret < 0)
529460b42d1SKuninori Morimoto 		return soc_component_ret(component, ret);
530460b42d1SKuninori Morimoto 	return change;
531460b42d1SKuninori Morimoto }
532460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
533460b42d1SKuninori Morimoto 
534460b42d1SKuninori Morimoto /**
535460b42d1SKuninori Morimoto  * snd_soc_component_update_bits_async() - Perform asynchronous
536460b42d1SKuninori Morimoto  *  read/modify/write cycle
537460b42d1SKuninori Morimoto  * @component: Component to update
538460b42d1SKuninori Morimoto  * @reg: Register to update
539460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to update
540460b42d1SKuninori Morimoto  * @val: New value for the bits specified by mask
541460b42d1SKuninori Morimoto  *
542460b42d1SKuninori Morimoto  * This function is similar to snd_soc_component_update_bits(), but the update
543460b42d1SKuninori Morimoto  * operation is scheduled asynchronously. This means it may not be completed
544460b42d1SKuninori Morimoto  * when the function returns. To make sure that all scheduled updates have been
545460b42d1SKuninori Morimoto  * completed snd_soc_component_async_complete() must be called.
546460b42d1SKuninori Morimoto  *
547460b42d1SKuninori Morimoto  * Return: 1 if the operation was successful and the value of the register
548460b42d1SKuninori Morimoto  * changed, 0 if the operation was successful, but the value did not change.
549460b42d1SKuninori Morimoto  * Returns a negative error code otherwise.
550460b42d1SKuninori Morimoto  */
551460b42d1SKuninori Morimoto int snd_soc_component_update_bits_async(struct snd_soc_component *component,
552460b42d1SKuninori Morimoto 					unsigned int reg, unsigned int mask, unsigned int val)
553460b42d1SKuninori Morimoto {
554460b42d1SKuninori Morimoto 	bool change;
555460b42d1SKuninori Morimoto 	int ret;
556460b42d1SKuninori Morimoto 
557460b42d1SKuninori Morimoto 	if (component->regmap)
558460b42d1SKuninori Morimoto 		ret = regmap_update_bits_check_async(component->regmap, reg,
559460b42d1SKuninori Morimoto 						     mask, val, &change);
560460b42d1SKuninori Morimoto 	else
561460b42d1SKuninori Morimoto 		ret = snd_soc_component_update_bits_legacy(component, reg,
562460b42d1SKuninori Morimoto 							   mask, val, &change);
563460b42d1SKuninori Morimoto 
564460b42d1SKuninori Morimoto 	if (ret < 0)
565460b42d1SKuninori Morimoto 		return soc_component_ret(component, ret);
566460b42d1SKuninori Morimoto 	return change;
567460b42d1SKuninori Morimoto }
568460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
569460b42d1SKuninori Morimoto 
570460b42d1SKuninori Morimoto /**
571460b42d1SKuninori Morimoto  * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
572460b42d1SKuninori Morimoto  * @component: Component for which to wait
573460b42d1SKuninori Morimoto  *
574460b42d1SKuninori Morimoto  * This function blocks until all asynchronous I/O which has previously been
575460b42d1SKuninori Morimoto  * scheduled using snd_soc_component_update_bits_async() has completed.
576460b42d1SKuninori Morimoto  */
577460b42d1SKuninori Morimoto void snd_soc_component_async_complete(struct snd_soc_component *component)
578460b42d1SKuninori Morimoto {
579460b42d1SKuninori Morimoto 	if (component->regmap)
580460b42d1SKuninori Morimoto 		regmap_async_complete(component->regmap);
581460b42d1SKuninori Morimoto }
582460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
583460b42d1SKuninori Morimoto 
584460b42d1SKuninori Morimoto /**
585460b42d1SKuninori Morimoto  * snd_soc_component_test_bits - Test register for change
586460b42d1SKuninori Morimoto  * @component: component
587460b42d1SKuninori Morimoto  * @reg: Register to test
588460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to test
589460b42d1SKuninori Morimoto  * @value: Value to test against
590460b42d1SKuninori Morimoto  *
591460b42d1SKuninori Morimoto  * Tests a register with a new value and checks if the new value is
592460b42d1SKuninori Morimoto  * different from the old value.
593460b42d1SKuninori Morimoto  *
594460b42d1SKuninori Morimoto  * Return: 1 for change, otherwise 0.
595460b42d1SKuninori Morimoto  */
596460b42d1SKuninori Morimoto int snd_soc_component_test_bits(struct snd_soc_component *component,
597460b42d1SKuninori Morimoto 				unsigned int reg, unsigned int mask, unsigned int value)
598460b42d1SKuninori Morimoto {
599460b42d1SKuninori Morimoto 	unsigned int old, new;
600460b42d1SKuninori Morimoto 
601cf6e26c7SKuninori Morimoto 	old = snd_soc_component_read(component, reg);
602460b42d1SKuninori Morimoto 	new = (old & ~mask) | value;
603460b42d1SKuninori Morimoto 	return old != new;
604460b42d1SKuninori Morimoto }
605460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
606460b42d1SKuninori Morimoto 
6070035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
6080035e256SKuninori Morimoto {
6090035e256SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
6100035e256SKuninori Morimoto 	struct snd_soc_component *component;
611613fb500SKuninori Morimoto 	int i;
6120035e256SKuninori Morimoto 
6130035e256SKuninori Morimoto 	/* FIXME: use 1st pointer */
614613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
615e2cb4a14SKuninori Morimoto 		if (component->driver->pointer)
616e2cb4a14SKuninori Morimoto 			return component->driver->pointer(component, substream);
6170035e256SKuninori Morimoto 
6180035e256SKuninori Morimoto 	return 0;
6190035e256SKuninori Morimoto }
62096a47908SKuninori Morimoto 
62196a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
62296a47908SKuninori Morimoto 				unsigned int cmd, void *arg)
62396a47908SKuninori Morimoto {
62496a47908SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
62596a47908SKuninori Morimoto 	struct snd_soc_component *component;
626613fb500SKuninori Morimoto 	int i;
62796a47908SKuninori Morimoto 
62896a47908SKuninori Morimoto 	/* FIXME: use 1st ioctl */
629613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
630e2cb4a14SKuninori Morimoto 		if (component->driver->ioctl)
631e2329eebSKuninori Morimoto 			return soc_component_ret(
632e2329eebSKuninori Morimoto 				component,
633e2329eebSKuninori Morimoto 				component->driver->ioctl(component,
634e2329eebSKuninori Morimoto 							 substream, cmd, arg));
63596a47908SKuninori Morimoto 
63696a47908SKuninori Morimoto 	return snd_pcm_lib_ioctl(substream, cmd, arg);
63796a47908SKuninori Morimoto }
63882d81f5cSKuninori Morimoto 
6391e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream)
6401e5ddb6bSTakashi Iwai {
6411e5ddb6bSTakashi Iwai 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
6421e5ddb6bSTakashi Iwai 	struct snd_soc_component *component;
643613fb500SKuninori Morimoto 	int i, ret;
6441e5ddb6bSTakashi Iwai 
645613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
646f1861a7cSKuninori Morimoto 		if (component->driver->sync_stop) {
6471e5ddb6bSTakashi Iwai 			ret = component->driver->sync_stop(component,
6481e5ddb6bSTakashi Iwai 							   substream);
6491e5ddb6bSTakashi Iwai 			if (ret < 0)
650be75db57SShengjiu Wang 				return soc_component_ret(component, ret);
6511e5ddb6bSTakashi Iwai 		}
6521e5ddb6bSTakashi Iwai 	}
6531e5ddb6bSTakashi Iwai 
6541e5ddb6bSTakashi Iwai 	return 0;
6551e5ddb6bSTakashi Iwai }
6561e5ddb6bSTakashi Iwai 
65782d81f5cSKuninori Morimoto int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream,
65882d81f5cSKuninori Morimoto 				    int channel, unsigned long pos,
65982d81f5cSKuninori Morimoto 				    void __user *buf, unsigned long bytes)
66082d81f5cSKuninori Morimoto {
66182d81f5cSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
66282d81f5cSKuninori Morimoto 	struct snd_soc_component *component;
663613fb500SKuninori Morimoto 	int i;
66482d81f5cSKuninori Morimoto 
66582d81f5cSKuninori Morimoto 	/* FIXME. it returns 1st copy now */
666613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
667e2cb4a14SKuninori Morimoto 		if (component->driver->copy_user)
668e2329eebSKuninori Morimoto 			return soc_component_ret(
669e2329eebSKuninori Morimoto 				component,
670e2329eebSKuninori Morimoto 				component->driver->copy_user(
671e2329eebSKuninori Morimoto 					component, substream, channel,
672e2329eebSKuninori Morimoto 					pos, buf, bytes));
67382d81f5cSKuninori Morimoto 
67482d81f5cSKuninori Morimoto 	return -EINVAL;
67582d81f5cSKuninori Morimoto }
6769c712e4fSKuninori Morimoto 
6779c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
6789c712e4fSKuninori Morimoto 					unsigned long offset)
6799c712e4fSKuninori Morimoto {
6809c712e4fSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
6819c712e4fSKuninori Morimoto 	struct snd_soc_component *component;
6829c712e4fSKuninori Morimoto 	struct page *page;
683613fb500SKuninori Morimoto 	int i;
6849c712e4fSKuninori Morimoto 
6859c712e4fSKuninori Morimoto 	/* FIXME. it returns 1st page now */
686613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
687e2cb4a14SKuninori Morimoto 		if (component->driver->page) {
688e2cb4a14SKuninori Morimoto 			page = component->driver->page(component,
689e2cb4a14SKuninori Morimoto 						       substream, offset);
690e2cb4a14SKuninori Morimoto 			if (page)
691e2cb4a14SKuninori Morimoto 				return page;
692e2cb4a14SKuninori Morimoto 		}
6939c712e4fSKuninori Morimoto 	}
6949c712e4fSKuninori Morimoto 
6959c712e4fSKuninori Morimoto 	return NULL;
6969c712e4fSKuninori Morimoto }
697205875e1SKuninori Morimoto 
698205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
699205875e1SKuninori Morimoto 			       struct vm_area_struct *vma)
700205875e1SKuninori Morimoto {
701205875e1SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
702205875e1SKuninori Morimoto 	struct snd_soc_component *component;
703613fb500SKuninori Morimoto 	int i;
704205875e1SKuninori Morimoto 
705205875e1SKuninori Morimoto 	/* FIXME. it returns 1st mmap now */
706613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
707e2cb4a14SKuninori Morimoto 		if (component->driver->mmap)
708be75db57SShengjiu Wang 			return soc_component_ret(
709e2329eebSKuninori Morimoto 				component,
710e2329eebSKuninori Morimoto 				component->driver->mmap(component,
711e2329eebSKuninori Morimoto 							substream, vma));
712205875e1SKuninori Morimoto 
713205875e1SKuninori Morimoto 	return -EINVAL;
714205875e1SKuninori Morimoto }
7157484291eSKuninori Morimoto 
716b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd)
7177484291eSKuninori Morimoto {
7187484291eSKuninori Morimoto 	struct snd_soc_component *component;
7197484291eSKuninori Morimoto 	int ret;
720613fb500SKuninori Morimoto 	int i;
7217484291eSKuninori Morimoto 
722613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
723c64bfc90SKuninori Morimoto 		if (component->driver->pcm_construct) {
724c64bfc90SKuninori Morimoto 			ret = component->driver->pcm_construct(component, rtd);
725c64bfc90SKuninori Morimoto 			if (ret < 0)
726be75db57SShengjiu Wang 				return soc_component_ret(component, ret);
727c64bfc90SKuninori Morimoto 		}
7287484291eSKuninori Morimoto 	}
7297484291eSKuninori Morimoto 
7307484291eSKuninori Morimoto 	return 0;
7317484291eSKuninori Morimoto }
73279776da0SKuninori Morimoto 
733b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd)
73479776da0SKuninori Morimoto {
73579776da0SKuninori Morimoto 	struct snd_soc_component *component;
736613fb500SKuninori Morimoto 	int i;
73779776da0SKuninori Morimoto 
7388e3366caSTakashi Iwai 	if (!rtd->pcm)
7398e3366caSTakashi Iwai 		return;
7408e3366caSTakashi Iwai 
741613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
742c64bfc90SKuninori Morimoto 		if (component->driver->pcm_destruct)
743b2b2afbbSKuninori Morimoto 			component->driver->pcm_destruct(component, rtd->pcm);
74479776da0SKuninori Morimoto }
7454f39514fSKuninori Morimoto 
7464f39514fSKuninori Morimoto int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream)
7474f39514fSKuninori Morimoto {
7484f39514fSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
7494f39514fSKuninori Morimoto 	struct snd_soc_component *component;
7504f39514fSKuninori Morimoto 	int i, ret;
7514f39514fSKuninori Morimoto 
7524f39514fSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
7534f39514fSKuninori Morimoto 		if (component->driver->prepare) {
7544f39514fSKuninori Morimoto 			ret = component->driver->prepare(component, substream);
7554f39514fSKuninori Morimoto 			if (ret < 0)
7564f39514fSKuninori Morimoto 				return soc_component_ret(component, ret);
7574f39514fSKuninori Morimoto 		}
7584f39514fSKuninori Morimoto 	}
7594f39514fSKuninori Morimoto 
7604f39514fSKuninori Morimoto 	return 0;
7614f39514fSKuninori Morimoto }
762e1bafa82SKuninori Morimoto 
763e1bafa82SKuninori Morimoto int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
764e1bafa82SKuninori Morimoto 				    struct snd_pcm_hw_params *params,
765e1bafa82SKuninori Morimoto 				    struct snd_soc_component **last)
766e1bafa82SKuninori Morimoto {
767e1bafa82SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
768e1bafa82SKuninori Morimoto 	struct snd_soc_component *component;
769e1bafa82SKuninori Morimoto 	int i, ret;
770e1bafa82SKuninori Morimoto 
771e1bafa82SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
772e1bafa82SKuninori Morimoto 		if (component->driver->hw_params) {
773e1bafa82SKuninori Morimoto 			ret = component->driver->hw_params(component,
774e1bafa82SKuninori Morimoto 							   substream, params);
775e1bafa82SKuninori Morimoto 			if (ret < 0) {
776e1bafa82SKuninori Morimoto 				*last = component;
777e1bafa82SKuninori Morimoto 				return soc_component_ret(component, ret);
778e1bafa82SKuninori Morimoto 			}
779e1bafa82SKuninori Morimoto 		}
780e1bafa82SKuninori Morimoto 	}
781e1bafa82SKuninori Morimoto 
782e1bafa82SKuninori Morimoto 	*last = NULL;
783e1bafa82SKuninori Morimoto 	return 0;
784e1bafa82SKuninori Morimoto }
78504751119SKuninori Morimoto 
78604751119SKuninori Morimoto void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
78704751119SKuninori Morimoto 				   struct snd_soc_component *last)
78804751119SKuninori Morimoto {
78904751119SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
79004751119SKuninori Morimoto 	struct snd_soc_component *component;
79104751119SKuninori Morimoto 	int i, ret;
79204751119SKuninori Morimoto 
79304751119SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
79404751119SKuninori Morimoto 		if (component == last)
79504751119SKuninori Morimoto 			break;
79604751119SKuninori Morimoto 
79704751119SKuninori Morimoto 		if (component->driver->hw_free) {
79804751119SKuninori Morimoto 			ret = component->driver->hw_free(component, substream);
79904751119SKuninori Morimoto 			if (ret < 0)
80004751119SKuninori Morimoto 				soc_component_ret(component, ret);
80104751119SKuninori Morimoto 		}
80204751119SKuninori Morimoto 	}
80304751119SKuninori Morimoto }
80432fd1204SKuninori Morimoto 
80532fd1204SKuninori Morimoto int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
80632fd1204SKuninori Morimoto 				  int cmd)
80732fd1204SKuninori Morimoto {
80832fd1204SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
80932fd1204SKuninori Morimoto 	struct snd_soc_component *component;
81032fd1204SKuninori Morimoto 	int i, ret;
81132fd1204SKuninori Morimoto 
81232fd1204SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
81332fd1204SKuninori Morimoto 		if (component->driver->trigger) {
81432fd1204SKuninori Morimoto 			ret = component->driver->trigger(component, substream, cmd);
81532fd1204SKuninori Morimoto 			if (ret < 0)
81632fd1204SKuninori Morimoto 				return soc_component_ret(component, ret);
81732fd1204SKuninori Morimoto 		}
81832fd1204SKuninori Morimoto 	}
81932fd1204SKuninori Morimoto 
82032fd1204SKuninori Morimoto 	return 0;
82132fd1204SKuninori Morimoto }
822