xref: /openbmc/linux/sound/soc/soc-component.c (revision 4ca8701e)
14ff1fef1SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
24ff1fef1SKuninori Morimoto //
34ff1fef1SKuninori Morimoto // soc-component.c
44ff1fef1SKuninori Morimoto //
54ff1fef1SKuninori Morimoto // Copyright (C) 2019 Renesas Electronics Corp.
64ff1fef1SKuninori Morimoto // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
74ff1fef1SKuninori Morimoto //
84a81e8f3SKuninori Morimoto #include <linux/module.h>
94ff1fef1SKuninori Morimoto #include <sound/soc.h>
104ff1fef1SKuninori Morimoto 
114ff1fef1SKuninori Morimoto /**
124ff1fef1SKuninori Morimoto  * snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
134ff1fef1SKuninori Morimoto  * @component: COMPONENT
144ff1fef1SKuninori Morimoto  * @clk_id: DAI specific clock ID
154ff1fef1SKuninori Morimoto  * @source: Source for the clock
164ff1fef1SKuninori Morimoto  * @freq: new clock frequency in Hz
174ff1fef1SKuninori Morimoto  * @dir: new clock direction - input/output.
184ff1fef1SKuninori Morimoto  *
194ff1fef1SKuninori Morimoto  * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
204ff1fef1SKuninori Morimoto  */
214ff1fef1SKuninori Morimoto int snd_soc_component_set_sysclk(struct snd_soc_component *component,
224ff1fef1SKuninori Morimoto 				 int clk_id, int source, unsigned int freq,
234ff1fef1SKuninori Morimoto 				 int dir)
244ff1fef1SKuninori Morimoto {
254ff1fef1SKuninori Morimoto 	if (component->driver->set_sysclk)
264ff1fef1SKuninori Morimoto 		return component->driver->set_sysclk(component, clk_id, source,
274ff1fef1SKuninori Morimoto 						     freq, dir);
284ff1fef1SKuninori Morimoto 
294ff1fef1SKuninori Morimoto 	return -ENOTSUPP;
304ff1fef1SKuninori Morimoto }
314ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
324ff1fef1SKuninori Morimoto 
334ff1fef1SKuninori Morimoto /*
344ff1fef1SKuninori Morimoto  * snd_soc_component_set_pll - configure component PLL.
354ff1fef1SKuninori Morimoto  * @component: COMPONENT
364ff1fef1SKuninori Morimoto  * @pll_id: DAI specific PLL ID
374ff1fef1SKuninori Morimoto  * @source: DAI specific source for the PLL
384ff1fef1SKuninori Morimoto  * @freq_in: PLL input clock frequency in Hz
394ff1fef1SKuninori Morimoto  * @freq_out: requested PLL output clock frequency in Hz
404ff1fef1SKuninori Morimoto  *
414ff1fef1SKuninori Morimoto  * Configures and enables PLL to generate output clock based on input clock.
424ff1fef1SKuninori Morimoto  */
434ff1fef1SKuninori Morimoto int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
444ff1fef1SKuninori Morimoto 			      int source, unsigned int freq_in,
454ff1fef1SKuninori Morimoto 			      unsigned int freq_out)
464ff1fef1SKuninori Morimoto {
474ff1fef1SKuninori Morimoto 	if (component->driver->set_pll)
484ff1fef1SKuninori Morimoto 		return component->driver->set_pll(component, pll_id, source,
494ff1fef1SKuninori Morimoto 						  freq_in, freq_out);
504ff1fef1SKuninori Morimoto 
514ff1fef1SKuninori Morimoto 	return -EINVAL;
524ff1fef1SKuninori Morimoto }
534ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_pll);
544ff1fef1SKuninori Morimoto 
559d415fbfSKuninori Morimoto void snd_soc_component_seq_notifier(struct snd_soc_component *component,
569d415fbfSKuninori Morimoto 				    enum snd_soc_dapm_type type, int subseq)
579d415fbfSKuninori Morimoto {
589d415fbfSKuninori Morimoto 	if (component->driver->seq_notifier)
599d415fbfSKuninori Morimoto 		component->driver->seq_notifier(component, type, subseq);
609d415fbfSKuninori Morimoto }
619d415fbfSKuninori Morimoto 
628e2a990dSKuninori Morimoto int snd_soc_component_stream_event(struct snd_soc_component *component,
638e2a990dSKuninori Morimoto 				   int event)
648e2a990dSKuninori Morimoto {
658e2a990dSKuninori Morimoto 	if (component->driver->stream_event)
668e2a990dSKuninori Morimoto 		return component->driver->stream_event(component, event);
678e2a990dSKuninori Morimoto 
688e2a990dSKuninori Morimoto 	return 0;
698e2a990dSKuninori Morimoto }
708e2a990dSKuninori Morimoto 
717951b146SKuninori Morimoto int snd_soc_component_set_bias_level(struct snd_soc_component *component,
727951b146SKuninori Morimoto 				     enum snd_soc_bias_level level)
737951b146SKuninori Morimoto {
747951b146SKuninori Morimoto 	if (component->driver->set_bias_level)
757951b146SKuninori Morimoto 		return component->driver->set_bias_level(component, level);
767951b146SKuninori Morimoto 
777951b146SKuninori Morimoto 	return 0;
787951b146SKuninori Morimoto }
797951b146SKuninori Morimoto 
804ca8701eSKuninori Morimoto static int soc_component_pin(struct snd_soc_component *component,
814ca8701eSKuninori Morimoto 			     const char *pin,
824ca8701eSKuninori Morimoto 			     int (*pin_func)(struct snd_soc_dapm_context *dapm,
834ca8701eSKuninori Morimoto 					     const char *pin))
844ff1fef1SKuninori Morimoto {
854ff1fef1SKuninori Morimoto 	struct snd_soc_dapm_context *dapm =
864ff1fef1SKuninori Morimoto 		snd_soc_component_get_dapm(component);
874ff1fef1SKuninori Morimoto 	char *full_name;
884ff1fef1SKuninori Morimoto 	int ret;
894ff1fef1SKuninori Morimoto 
904ff1fef1SKuninori Morimoto 	if (!component->name_prefix)
914ca8701eSKuninori Morimoto 		return pin_func(dapm, pin);
924ff1fef1SKuninori Morimoto 
934ff1fef1SKuninori Morimoto 	full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
944ff1fef1SKuninori Morimoto 	if (!full_name)
954ff1fef1SKuninori Morimoto 		return -ENOMEM;
964ff1fef1SKuninori Morimoto 
974ca8701eSKuninori Morimoto 	ret = pin_func(dapm, full_name);
984ff1fef1SKuninori Morimoto 	kfree(full_name);
994ff1fef1SKuninori Morimoto 
1004ff1fef1SKuninori Morimoto 	return ret;
1014ff1fef1SKuninori Morimoto }
1024ca8701eSKuninori Morimoto 
1034ca8701eSKuninori Morimoto int snd_soc_component_enable_pin(struct snd_soc_component *component,
1044ca8701eSKuninori Morimoto 				 const char *pin)
1054ca8701eSKuninori Morimoto {
1064ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_enable_pin);
1074ca8701eSKuninori Morimoto }
1084ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
1094ff1fef1SKuninori Morimoto 
1104ff1fef1SKuninori Morimoto int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
1114ff1fef1SKuninori Morimoto 					  const char *pin)
1124ff1fef1SKuninori Morimoto {
1134ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked);
1144ff1fef1SKuninori Morimoto }
1154ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
1164ff1fef1SKuninori Morimoto 
1174ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin(struct snd_soc_component *component,
1184ff1fef1SKuninori Morimoto 				  const char *pin)
1194ff1fef1SKuninori Morimoto {
1204ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_disable_pin);
1214ff1fef1SKuninori Morimoto }
1224ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
1234ff1fef1SKuninori Morimoto 
1244ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
1254ff1fef1SKuninori Morimoto 					   const char *pin)
1264ff1fef1SKuninori Morimoto {
1274ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked);
1284ff1fef1SKuninori Morimoto }
1294ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
1304ff1fef1SKuninori Morimoto 
1314ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin(struct snd_soc_component *component,
1324ff1fef1SKuninori Morimoto 			     const char *pin)
1334ff1fef1SKuninori Morimoto {
1344ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_nc_pin);
1354ff1fef1SKuninori Morimoto }
1364ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
1374ff1fef1SKuninori Morimoto 
1384ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
1394ff1fef1SKuninori Morimoto 				      const char *pin)
1404ff1fef1SKuninori Morimoto {
1414ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked);
1424ff1fef1SKuninori Morimoto }
1434ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
1444ff1fef1SKuninori Morimoto 
1454ff1fef1SKuninori Morimoto int snd_soc_component_get_pin_status(struct snd_soc_component *component,
1464ff1fef1SKuninori Morimoto 				     const char *pin)
1474ff1fef1SKuninori Morimoto {
1484ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status);
1494ff1fef1SKuninori Morimoto }
1504ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
1514ff1fef1SKuninori Morimoto 
1524ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
1534ff1fef1SKuninori Morimoto 				       const char *pin)
1544ff1fef1SKuninori Morimoto {
1554ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin);
1564ff1fef1SKuninori Morimoto }
1574ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
1584ff1fef1SKuninori Morimoto 
1594ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin_unlocked(
1604ff1fef1SKuninori Morimoto 	struct snd_soc_component *component,
1614ff1fef1SKuninori Morimoto 	const char *pin)
1624ff1fef1SKuninori Morimoto {
1634ca8701eSKuninori Morimoto 	return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked);
1644ff1fef1SKuninori Morimoto }
1654ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
1664ff1fef1SKuninori Morimoto 
1674ff1fef1SKuninori Morimoto /**
1684ff1fef1SKuninori Morimoto  * snd_soc_component_set_jack - configure component jack.
1694ff1fef1SKuninori Morimoto  * @component: COMPONENTs
1704ff1fef1SKuninori Morimoto  * @jack: structure to use for the jack
1714ff1fef1SKuninori Morimoto  * @data: can be used if codec driver need extra data for configuring jack
1724ff1fef1SKuninori Morimoto  *
1734ff1fef1SKuninori Morimoto  * Configures and enables jack detection function.
1744ff1fef1SKuninori Morimoto  */
1754ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component,
1764ff1fef1SKuninori Morimoto 			       struct snd_soc_jack *jack, void *data)
1774ff1fef1SKuninori Morimoto {
1784ff1fef1SKuninori Morimoto 	if (component->driver->set_jack)
1794ff1fef1SKuninori Morimoto 		return component->driver->set_jack(component, jack, data);
1804ff1fef1SKuninori Morimoto 
1814ff1fef1SKuninori Morimoto 	return -ENOTSUPP;
1824ff1fef1SKuninori Morimoto }
1834ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
1844a81e8f3SKuninori Morimoto 
1854a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component,
1864a81e8f3SKuninori Morimoto 				 int upon_open)
1874a81e8f3SKuninori Morimoto {
1884a81e8f3SKuninori Morimoto 	if (component->driver->module_get_upon_open == !!upon_open &&
1894a81e8f3SKuninori Morimoto 	    !try_module_get(component->dev->driver->owner))
1904a81e8f3SKuninori Morimoto 		return -ENODEV;
1914a81e8f3SKuninori Morimoto 
1924a81e8f3SKuninori Morimoto 	return 0;
1934a81e8f3SKuninori Morimoto }
1944a81e8f3SKuninori Morimoto 
1954a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component,
1964a81e8f3SKuninori Morimoto 				  int upon_open)
1974a81e8f3SKuninori Morimoto {
1984a81e8f3SKuninori Morimoto 	if (component->driver->module_get_upon_open == !!upon_open)
1994a81e8f3SKuninori Morimoto 		module_put(component->dev->driver->owner);
2004a81e8f3SKuninori Morimoto }
201ae2f4849SKuninori Morimoto 
202ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component,
203ae2f4849SKuninori Morimoto 			   struct snd_pcm_substream *substream)
204ae2f4849SKuninori Morimoto {
205e2cb4a14SKuninori Morimoto 	if (component->driver->open)
206e2cb4a14SKuninori Morimoto 		return component->driver->open(component, substream);
207ae2f4849SKuninori Morimoto 	return 0;
208ae2f4849SKuninori Morimoto }
2093672beb8SKuninori Morimoto 
2103672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component,
2113672beb8SKuninori Morimoto 			    struct snd_pcm_substream *substream)
2123672beb8SKuninori Morimoto {
213e2cb4a14SKuninori Morimoto 	if (component->driver->close)
214e2cb4a14SKuninori Morimoto 		return component->driver->close(component, substream);
2153672beb8SKuninori Morimoto 	return 0;
2163672beb8SKuninori Morimoto }
2176d537233SKuninori Morimoto 
2186d537233SKuninori Morimoto int snd_soc_component_prepare(struct snd_soc_component *component,
2196d537233SKuninori Morimoto 			      struct snd_pcm_substream *substream)
2206d537233SKuninori Morimoto {
221e2cb4a14SKuninori Morimoto 	if (component->driver->prepare)
222e2cb4a14SKuninori Morimoto 		return component->driver->prepare(component, substream);
2236d537233SKuninori Morimoto 	return 0;
2246d537233SKuninori Morimoto }
225245c539aSKuninori Morimoto 
226245c539aSKuninori Morimoto int snd_soc_component_hw_params(struct snd_soc_component *component,
227245c539aSKuninori Morimoto 				struct snd_pcm_substream *substream,
228245c539aSKuninori Morimoto 				struct snd_pcm_hw_params *params)
229245c539aSKuninori Morimoto {
230e2cb4a14SKuninori Morimoto 	if (component->driver->hw_params)
231e2cb4a14SKuninori Morimoto 		return component->driver->hw_params(component,
232e2cb4a14SKuninori Morimoto 						    substream, params);
233245c539aSKuninori Morimoto 	return 0;
234245c539aSKuninori Morimoto }
235eae7136aSKuninori Morimoto 
236eae7136aSKuninori Morimoto int snd_soc_component_hw_free(struct snd_soc_component *component,
237eae7136aSKuninori Morimoto 			       struct snd_pcm_substream *substream)
238eae7136aSKuninori Morimoto {
239e2cb4a14SKuninori Morimoto 	if (component->driver->hw_free)
240e2cb4a14SKuninori Morimoto 		return component->driver->hw_free(component, substream);
241eae7136aSKuninori Morimoto 	return 0;
242eae7136aSKuninori Morimoto }
2435693d50cSKuninori Morimoto 
2445693d50cSKuninori Morimoto int snd_soc_component_trigger(struct snd_soc_component *component,
2455693d50cSKuninori Morimoto 			      struct snd_pcm_substream *substream,
2465693d50cSKuninori Morimoto 			      int cmd)
2475693d50cSKuninori Morimoto {
248e2cb4a14SKuninori Morimoto 	if (component->driver->trigger)
249e2cb4a14SKuninori Morimoto 		return component->driver->trigger(component, substream, cmd);
2505693d50cSKuninori Morimoto 	return 0;
2515693d50cSKuninori Morimoto }
25266c51573SKuninori Morimoto 
25366c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component)
25466c51573SKuninori Morimoto {
25566c51573SKuninori Morimoto 	if (component->driver->suspend)
25666c51573SKuninori Morimoto 		component->driver->suspend(component);
25766c51573SKuninori Morimoto 	component->suspended = 1;
25866c51573SKuninori Morimoto }
2599a840cbaSKuninori Morimoto 
2609a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component)
2619a840cbaSKuninori Morimoto {
2629a840cbaSKuninori Morimoto 	if (component->driver->resume)
2639a840cbaSKuninori Morimoto 		component->driver->resume(component);
2649a840cbaSKuninori Morimoto 	component->suspended = 0;
2659a840cbaSKuninori Morimoto }
266e40fadbcSKuninori Morimoto 
267e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component)
268e40fadbcSKuninori Morimoto {
269e40fadbcSKuninori Morimoto 	return component->suspended;
270e40fadbcSKuninori Morimoto }
27108e837ddSKuninori Morimoto 
27208e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component)
27308e837ddSKuninori Morimoto {
27408e837ddSKuninori Morimoto 	if (component->driver->probe)
27508e837ddSKuninori Morimoto 		return component->driver->probe(component);
27608e837ddSKuninori Morimoto 
27708e837ddSKuninori Morimoto 	return 0;
27808e837ddSKuninori Morimoto }
27903b34dd7SKuninori Morimoto 
28003b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component)
28103b34dd7SKuninori Morimoto {
28203b34dd7SKuninori Morimoto 	if (component->driver->remove)
28303b34dd7SKuninori Morimoto 		component->driver->remove(component);
28403b34dd7SKuninori Morimoto }
2852c7b1704SKuninori Morimoto 
2862c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
2872c7b1704SKuninori Morimoto 				      struct device_node *ep)
2882c7b1704SKuninori Morimoto {
2892c7b1704SKuninori Morimoto 	if (component->driver->of_xlate_dai_id)
2902c7b1704SKuninori Morimoto 		return component->driver->of_xlate_dai_id(component, ep);
2912c7b1704SKuninori Morimoto 
2922c7b1704SKuninori Morimoto 	return -ENOTSUPP;
2932c7b1704SKuninori Morimoto }
294a2a34175SKuninori Morimoto 
295a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
296a2a34175SKuninori Morimoto 					struct of_phandle_args *args,
297a2a34175SKuninori Morimoto 					const char **dai_name)
298a2a34175SKuninori Morimoto {
299a2a34175SKuninori Morimoto 	if (component->driver->of_xlate_dai_name)
300a2a34175SKuninori Morimoto 		return component->driver->of_xlate_dai_name(component,
301a2a34175SKuninori Morimoto 						     args, dai_name);
302a2a34175SKuninori Morimoto 	return -ENOTSUPP;
303a2a34175SKuninori Morimoto }
3040035e256SKuninori Morimoto 
3050035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
3060035e256SKuninori Morimoto {
3070035e256SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
3080035e256SKuninori Morimoto 	struct snd_soc_component *component;
309613fb500SKuninori Morimoto 	int i;
3100035e256SKuninori Morimoto 
3110035e256SKuninori Morimoto 	/* FIXME: use 1st pointer */
312613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
313e2cb4a14SKuninori Morimoto 		if (component->driver->pointer)
314e2cb4a14SKuninori Morimoto 			return component->driver->pointer(component, substream);
3150035e256SKuninori Morimoto 
3160035e256SKuninori Morimoto 	return 0;
3170035e256SKuninori Morimoto }
31896a47908SKuninori Morimoto 
31996a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
32096a47908SKuninori Morimoto 				unsigned int cmd, void *arg)
32196a47908SKuninori Morimoto {
32296a47908SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
32396a47908SKuninori Morimoto 	struct snd_soc_component *component;
324613fb500SKuninori Morimoto 	int i;
32596a47908SKuninori Morimoto 
32696a47908SKuninori Morimoto 	/* FIXME: use 1st ioctl */
327613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
328e2cb4a14SKuninori Morimoto 		if (component->driver->ioctl)
329e2cb4a14SKuninori Morimoto 			return component->driver->ioctl(component, substream,
330e2cb4a14SKuninori Morimoto 							cmd, arg);
33196a47908SKuninori Morimoto 
33296a47908SKuninori Morimoto 	return snd_pcm_lib_ioctl(substream, cmd, arg);
33396a47908SKuninori Morimoto }
33482d81f5cSKuninori Morimoto 
3351e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream)
3361e5ddb6bSTakashi Iwai {
3371e5ddb6bSTakashi Iwai 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
3381e5ddb6bSTakashi Iwai 	struct snd_soc_component *component;
339613fb500SKuninori Morimoto 	int i, ret;
3401e5ddb6bSTakashi Iwai 
341613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
342f1861a7cSKuninori Morimoto 		if (component->driver->sync_stop) {
3431e5ddb6bSTakashi Iwai 			ret = component->driver->sync_stop(component,
3441e5ddb6bSTakashi Iwai 							   substream);
3451e5ddb6bSTakashi Iwai 			if (ret < 0)
3461e5ddb6bSTakashi Iwai 				return ret;
3471e5ddb6bSTakashi Iwai 		}
3481e5ddb6bSTakashi Iwai 	}
3491e5ddb6bSTakashi Iwai 
3501e5ddb6bSTakashi Iwai 	return 0;
3511e5ddb6bSTakashi Iwai }
3521e5ddb6bSTakashi Iwai 
35382d81f5cSKuninori Morimoto int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream,
35482d81f5cSKuninori Morimoto 				    int channel, unsigned long pos,
35582d81f5cSKuninori Morimoto 				    void __user *buf, unsigned long bytes)
35682d81f5cSKuninori Morimoto {
35782d81f5cSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
35882d81f5cSKuninori Morimoto 	struct snd_soc_component *component;
359613fb500SKuninori Morimoto 	int i;
36082d81f5cSKuninori Morimoto 
36182d81f5cSKuninori Morimoto 	/* FIXME. it returns 1st copy now */
362613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
363e2cb4a14SKuninori Morimoto 		if (component->driver->copy_user)
364e2cb4a14SKuninori Morimoto 			return component->driver->copy_user(
365e2cb4a14SKuninori Morimoto 				component, substream, channel, pos, buf, bytes);
36682d81f5cSKuninori Morimoto 
36782d81f5cSKuninori Morimoto 	return -EINVAL;
36882d81f5cSKuninori Morimoto }
3699c712e4fSKuninori Morimoto 
3709c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
3719c712e4fSKuninori Morimoto 					unsigned long offset)
3729c712e4fSKuninori Morimoto {
3739c712e4fSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
3749c712e4fSKuninori Morimoto 	struct snd_soc_component *component;
3759c712e4fSKuninori Morimoto 	struct page *page;
376613fb500SKuninori Morimoto 	int i;
3779c712e4fSKuninori Morimoto 
3789c712e4fSKuninori Morimoto 	/* FIXME. it returns 1st page now */
379613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
380e2cb4a14SKuninori Morimoto 		if (component->driver->page) {
381e2cb4a14SKuninori Morimoto 			page = component->driver->page(component,
382e2cb4a14SKuninori Morimoto 						       substream, offset);
383e2cb4a14SKuninori Morimoto 			if (page)
384e2cb4a14SKuninori Morimoto 				return page;
385e2cb4a14SKuninori Morimoto 		}
3869c712e4fSKuninori Morimoto 	}
3879c712e4fSKuninori Morimoto 
3889c712e4fSKuninori Morimoto 	return NULL;
3899c712e4fSKuninori Morimoto }
390205875e1SKuninori Morimoto 
391205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
392205875e1SKuninori Morimoto 			       struct vm_area_struct *vma)
393205875e1SKuninori Morimoto {
394205875e1SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
395205875e1SKuninori Morimoto 	struct snd_soc_component *component;
396613fb500SKuninori Morimoto 	int i;
397205875e1SKuninori Morimoto 
398205875e1SKuninori Morimoto 	/* FIXME. it returns 1st mmap now */
399613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
400e2cb4a14SKuninori Morimoto 		if (component->driver->mmap)
401e2cb4a14SKuninori Morimoto 			return component->driver->mmap(component,
402e2cb4a14SKuninori Morimoto 						       substream, vma);
403205875e1SKuninori Morimoto 
404205875e1SKuninori Morimoto 	return -EINVAL;
405205875e1SKuninori Morimoto }
4067484291eSKuninori Morimoto 
407b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd)
4087484291eSKuninori Morimoto {
4097484291eSKuninori Morimoto 	struct snd_soc_component *component;
4107484291eSKuninori Morimoto 	int ret;
411613fb500SKuninori Morimoto 	int i;
4127484291eSKuninori Morimoto 
413613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
414c64bfc90SKuninori Morimoto 		if (component->driver->pcm_construct) {
415c64bfc90SKuninori Morimoto 			ret = component->driver->pcm_construct(component, rtd);
416c64bfc90SKuninori Morimoto 			if (ret < 0)
417c64bfc90SKuninori Morimoto 				return ret;
418c64bfc90SKuninori Morimoto 		}
4197484291eSKuninori Morimoto 	}
4207484291eSKuninori Morimoto 
4217484291eSKuninori Morimoto 	return 0;
4227484291eSKuninori Morimoto }
42379776da0SKuninori Morimoto 
424b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd)
42579776da0SKuninori Morimoto {
42679776da0SKuninori Morimoto 	struct snd_soc_component *component;
427613fb500SKuninori Morimoto 	int i;
42879776da0SKuninori Morimoto 
4298e3366caSTakashi Iwai 	if (!rtd->pcm)
4308e3366caSTakashi Iwai 		return;
4318e3366caSTakashi Iwai 
432613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
433c64bfc90SKuninori Morimoto 		if (component->driver->pcm_destruct)
434b2b2afbbSKuninori Morimoto 			component->driver->pcm_destruct(component, rtd->pcm);
43579776da0SKuninori Morimoto }
436