xref: /openbmc/linux/sound/soc/soc-component.c (revision df55122b)
14ff1fef1SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
24ff1fef1SKuninori Morimoto //
34ff1fef1SKuninori Morimoto // soc-component.c
44ff1fef1SKuninori Morimoto //
5460b42d1SKuninori Morimoto // Copyright 2009-2011 Wolfson Microelectronics PLC.
64ff1fef1SKuninori Morimoto // Copyright (C) 2019 Renesas Electronics Corp.
7460b42d1SKuninori Morimoto //
8460b42d1SKuninori Morimoto // Mark Brown <broonie@opensource.wolfsonmicro.com>
94ff1fef1SKuninori Morimoto // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
104ff1fef1SKuninori Morimoto //
114a81e8f3SKuninori Morimoto #include <linux/module.h>
12939a5cfbSKuninori Morimoto #include <linux/pm_runtime.h>
134ff1fef1SKuninori Morimoto #include <sound/soc.h>
148ac9e476SSrinivas Kandagatla #include <linux/bitops.h>
154ff1fef1SKuninori Morimoto 
16b296997cSSrinivas Kandagatla #define soc_component_ret(dai, ret) _soc_component_ret(dai, __func__, ret, -1)
17b296997cSSrinivas Kandagatla #define soc_component_ret_reg_rw(dai, ret, reg) _soc_component_ret(dai, __func__, ret, reg)
18e2329eebSKuninori Morimoto static inline int _soc_component_ret(struct snd_soc_component *component,
19b296997cSSrinivas Kandagatla 				     const char *func, int ret, int reg)
20e2329eebSKuninori Morimoto {
21e2329eebSKuninori Morimoto 	/* Positive/Zero values are not errors */
22e2329eebSKuninori Morimoto 	if (ret >= 0)
23e2329eebSKuninori Morimoto 		return ret;
24e2329eebSKuninori Morimoto 
25e2329eebSKuninori Morimoto 	/* Negative values might be errors */
26e2329eebSKuninori Morimoto 	switch (ret) {
27e2329eebSKuninori Morimoto 	case -EPROBE_DEFER:
28e2329eebSKuninori Morimoto 	case -ENOTSUPP:
29e2329eebSKuninori Morimoto 		break;
30e2329eebSKuninori Morimoto 	default:
31b296997cSSrinivas Kandagatla 		if (reg == -1)
32e2329eebSKuninori Morimoto 			dev_err(component->dev,
33e2329eebSKuninori Morimoto 				"ASoC: error at %s on %s: %d\n",
34e2329eebSKuninori Morimoto 				func, component->name, ret);
35b296997cSSrinivas Kandagatla 		else
36b296997cSSrinivas Kandagatla 			dev_err(component->dev,
37b296997cSSrinivas Kandagatla 				"ASoC: error at %s on %s for register: [0x%08x] %d\n",
38b296997cSSrinivas Kandagatla 				func, component->name, reg, ret);
39e2329eebSKuninori Morimoto 	}
40e2329eebSKuninori Morimoto 
41e2329eebSKuninori Morimoto 	return ret;
42e2329eebSKuninori Morimoto }
43e2329eebSKuninori Morimoto 
441da0b989SSrinivas Kandagatla static inline int soc_component_field_shift(struct snd_soc_component *component,
451da0b989SSrinivas Kandagatla 					    unsigned int mask)
461da0b989SSrinivas Kandagatla {
471da0b989SSrinivas Kandagatla 	if (!mask) {
481da0b989SSrinivas Kandagatla 		dev_err(component->dev,	"ASoC: error field mask is zero for %s\n",
491da0b989SSrinivas Kandagatla 			component->name);
501da0b989SSrinivas Kandagatla 		return 0;
511da0b989SSrinivas Kandagatla 	}
521da0b989SSrinivas Kandagatla 
538ac9e476SSrinivas Kandagatla 	return (ffs(mask) - 1);
541da0b989SSrinivas Kandagatla }
551da0b989SSrinivas Kandagatla 
5651aff91aSKuninori Morimoto /*
5751aff91aSKuninori Morimoto  * We might want to check substream by using list.
5851aff91aSKuninori Morimoto  * In such case, we can update these macros.
5951aff91aSKuninori Morimoto  */
6051aff91aSKuninori Morimoto #define soc_component_mark_push(component, substream, tgt)	((component)->mark_##tgt = substream)
6151aff91aSKuninori Morimoto #define soc_component_mark_pop(component, substream, tgt)	((component)->mark_##tgt = NULL)
6251aff91aSKuninori Morimoto #define soc_component_mark_match(component, substream, tgt)	((component)->mark_##tgt == substream)
6351aff91aSKuninori Morimoto 
64257c4dacSKuninori Morimoto void snd_soc_component_set_aux(struct snd_soc_component *component,
65257c4dacSKuninori Morimoto 			       struct snd_soc_aux_dev *aux)
66257c4dacSKuninori Morimoto {
67257c4dacSKuninori Morimoto 	component->init = (aux) ? aux->init : NULL;
68257c4dacSKuninori Morimoto }
69257c4dacSKuninori Morimoto 
70257c4dacSKuninori Morimoto int snd_soc_component_init(struct snd_soc_component *component)
71257c4dacSKuninori Morimoto {
72257c4dacSKuninori Morimoto 	int ret = 0;
73257c4dacSKuninori Morimoto 
74257c4dacSKuninori Morimoto 	if (component->init)
75257c4dacSKuninori Morimoto 		ret = component->init(component);
76257c4dacSKuninori Morimoto 
77257c4dacSKuninori Morimoto 	return soc_component_ret(component, ret);
78257c4dacSKuninori Morimoto }
79257c4dacSKuninori Morimoto 
804ff1fef1SKuninori Morimoto /**
814ff1fef1SKuninori Morimoto  * snd_soc_component_set_sysclk - configure COMPONENT system or master clock.
824ff1fef1SKuninori Morimoto  * @component: COMPONENT
834ff1fef1SKuninori Morimoto  * @clk_id: DAI specific clock ID
844ff1fef1SKuninori Morimoto  * @source: Source for the clock
854ff1fef1SKuninori Morimoto  * @freq: new clock frequency in Hz
864ff1fef1SKuninori Morimoto  * @dir: new clock direction - input/output.
874ff1fef1SKuninori Morimoto  *
884ff1fef1SKuninori Morimoto  * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
894ff1fef1SKuninori Morimoto  */
904ff1fef1SKuninori Morimoto int snd_soc_component_set_sysclk(struct snd_soc_component *component,
914ff1fef1SKuninori Morimoto 				 int clk_id, int source, unsigned int freq,
924ff1fef1SKuninori Morimoto 				 int dir)
934ff1fef1SKuninori Morimoto {
94e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
95e2329eebSKuninori Morimoto 
964ff1fef1SKuninori Morimoto 	if (component->driver->set_sysclk)
97e2329eebSKuninori Morimoto 		ret = component->driver->set_sysclk(component, clk_id, source,
984ff1fef1SKuninori Morimoto 						     freq, dir);
994ff1fef1SKuninori Morimoto 
100e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
1014ff1fef1SKuninori Morimoto }
1024ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
1034ff1fef1SKuninori Morimoto 
1044ff1fef1SKuninori Morimoto /*
1054ff1fef1SKuninori Morimoto  * snd_soc_component_set_pll - configure component PLL.
1064ff1fef1SKuninori Morimoto  * @component: COMPONENT
1074ff1fef1SKuninori Morimoto  * @pll_id: DAI specific PLL ID
1084ff1fef1SKuninori Morimoto  * @source: DAI specific source for the PLL
1094ff1fef1SKuninori Morimoto  * @freq_in: PLL input clock frequency in Hz
1104ff1fef1SKuninori Morimoto  * @freq_out: requested PLL output clock frequency in Hz
1114ff1fef1SKuninori Morimoto  *
1124ff1fef1SKuninori Morimoto  * Configures and enables PLL to generate output clock based on input clock.
1134ff1fef1SKuninori Morimoto  */
1144ff1fef1SKuninori Morimoto int snd_soc_component_set_pll(struct snd_soc_component *component, int pll_id,
1154ff1fef1SKuninori Morimoto 			      int source, unsigned int freq_in,
1164ff1fef1SKuninori Morimoto 			      unsigned int freq_out)
1174ff1fef1SKuninori Morimoto {
118e2329eebSKuninori Morimoto 	int ret = -EINVAL;
119e2329eebSKuninori Morimoto 
1204ff1fef1SKuninori Morimoto 	if (component->driver->set_pll)
121e2329eebSKuninori Morimoto 		ret = component->driver->set_pll(component, pll_id, source,
1224ff1fef1SKuninori Morimoto 						  freq_in, freq_out);
1234ff1fef1SKuninori Morimoto 
124e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
1254ff1fef1SKuninori Morimoto }
1264ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_pll);
1274ff1fef1SKuninori Morimoto 
1289d415fbfSKuninori Morimoto void snd_soc_component_seq_notifier(struct snd_soc_component *component,
1299d415fbfSKuninori Morimoto 				    enum snd_soc_dapm_type type, int subseq)
1309d415fbfSKuninori Morimoto {
1319d415fbfSKuninori Morimoto 	if (component->driver->seq_notifier)
1329d415fbfSKuninori Morimoto 		component->driver->seq_notifier(component, type, subseq);
1339d415fbfSKuninori Morimoto }
1349d415fbfSKuninori Morimoto 
1358e2a990dSKuninori Morimoto int snd_soc_component_stream_event(struct snd_soc_component *component,
1368e2a990dSKuninori Morimoto 				   int event)
1378e2a990dSKuninori Morimoto {
138e2329eebSKuninori Morimoto 	int ret = 0;
1398e2a990dSKuninori Morimoto 
140e2329eebSKuninori Morimoto 	if (component->driver->stream_event)
141e2329eebSKuninori Morimoto 		ret = component->driver->stream_event(component, event);
142e2329eebSKuninori Morimoto 
143e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
1448e2a990dSKuninori Morimoto }
1458e2a990dSKuninori Morimoto 
1467951b146SKuninori Morimoto int snd_soc_component_set_bias_level(struct snd_soc_component *component,
1477951b146SKuninori Morimoto 				     enum snd_soc_bias_level level)
1487951b146SKuninori Morimoto {
149e2329eebSKuninori Morimoto 	int ret = 0;
1507951b146SKuninori Morimoto 
151e2329eebSKuninori Morimoto 	if (component->driver->set_bias_level)
152e2329eebSKuninori Morimoto 		ret = component->driver->set_bias_level(component, level);
153e2329eebSKuninori Morimoto 
154e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
1557951b146SKuninori Morimoto }
1567951b146SKuninori Morimoto 
1574ca8701eSKuninori Morimoto int snd_soc_component_enable_pin(struct snd_soc_component *component,
1584ca8701eSKuninori Morimoto 				 const char *pin)
1594ca8701eSKuninori Morimoto {
16031428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
16131428c78SMark Brown 		snd_soc_component_get_dapm(component);
16231428c78SMark Brown 	return snd_soc_dapm_enable_pin(dapm, pin);
1634ca8701eSKuninori Morimoto }
1644ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
1654ff1fef1SKuninori Morimoto 
1664ff1fef1SKuninori Morimoto int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
1674ff1fef1SKuninori Morimoto 					  const char *pin)
1684ff1fef1SKuninori Morimoto {
16931428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
17031428c78SMark Brown 		snd_soc_component_get_dapm(component);
17131428c78SMark Brown 	return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
1724ff1fef1SKuninori Morimoto }
1734ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
1744ff1fef1SKuninori Morimoto 
1754ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin(struct snd_soc_component *component,
1764ff1fef1SKuninori Morimoto 				  const char *pin)
1774ff1fef1SKuninori Morimoto {
17831428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
17931428c78SMark Brown 		snd_soc_component_get_dapm(component);
18031428c78SMark Brown 	return snd_soc_dapm_disable_pin(dapm, pin);
1814ff1fef1SKuninori Morimoto }
1824ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
1834ff1fef1SKuninori Morimoto 
1844ff1fef1SKuninori Morimoto int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
1854ff1fef1SKuninori Morimoto 					   const char *pin)
1864ff1fef1SKuninori Morimoto {
18731428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
18831428c78SMark Brown 		snd_soc_component_get_dapm(component);
18931428c78SMark Brown 	return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
1904ff1fef1SKuninori Morimoto }
1914ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
1924ff1fef1SKuninori Morimoto 
1934ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin(struct snd_soc_component *component,
1944ff1fef1SKuninori Morimoto 			     const char *pin)
1954ff1fef1SKuninori Morimoto {
19631428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
19731428c78SMark Brown 		snd_soc_component_get_dapm(component);
19831428c78SMark Brown 	return snd_soc_dapm_nc_pin(dapm, pin);
1994ff1fef1SKuninori Morimoto }
2004ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
2014ff1fef1SKuninori Morimoto 
2024ff1fef1SKuninori Morimoto int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
2034ff1fef1SKuninori Morimoto 				      const char *pin)
2044ff1fef1SKuninori Morimoto {
20531428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
20631428c78SMark Brown 		snd_soc_component_get_dapm(component);
20731428c78SMark Brown 	return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
2084ff1fef1SKuninori Morimoto }
2094ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
2104ff1fef1SKuninori Morimoto 
2114ff1fef1SKuninori Morimoto int snd_soc_component_get_pin_status(struct snd_soc_component *component,
2124ff1fef1SKuninori Morimoto 				     const char *pin)
2134ff1fef1SKuninori Morimoto {
21431428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
21531428c78SMark Brown 		snd_soc_component_get_dapm(component);
21631428c78SMark Brown 	return snd_soc_dapm_get_pin_status(dapm, pin);
2174ff1fef1SKuninori Morimoto }
2184ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
2194ff1fef1SKuninori Morimoto 
2204ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
2214ff1fef1SKuninori Morimoto 				       const char *pin)
2224ff1fef1SKuninori Morimoto {
22331428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
22431428c78SMark Brown 		snd_soc_component_get_dapm(component);
22531428c78SMark Brown 	return snd_soc_dapm_force_enable_pin(dapm, pin);
2264ff1fef1SKuninori Morimoto }
2274ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
2284ff1fef1SKuninori Morimoto 
2294ff1fef1SKuninori Morimoto int snd_soc_component_force_enable_pin_unlocked(
2304ff1fef1SKuninori Morimoto 	struct snd_soc_component *component,
2314ff1fef1SKuninori Morimoto 	const char *pin)
2324ff1fef1SKuninori Morimoto {
23331428c78SMark Brown 	struct snd_soc_dapm_context *dapm =
23431428c78SMark Brown 		snd_soc_component_get_dapm(component);
23531428c78SMark Brown 	return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
2364ff1fef1SKuninori Morimoto }
2374ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
2384ff1fef1SKuninori Morimoto 
2394ff1fef1SKuninori Morimoto /**
2404ff1fef1SKuninori Morimoto  * snd_soc_component_set_jack - configure component jack.
2414ff1fef1SKuninori Morimoto  * @component: COMPONENTs
2424ff1fef1SKuninori Morimoto  * @jack: structure to use for the jack
2434ff1fef1SKuninori Morimoto  * @data: can be used if codec driver need extra data for configuring jack
2444ff1fef1SKuninori Morimoto  *
2454ff1fef1SKuninori Morimoto  * Configures and enables jack detection function.
2464ff1fef1SKuninori Morimoto  */
2474ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component,
2484ff1fef1SKuninori Morimoto 			       struct snd_soc_jack *jack, void *data)
2494ff1fef1SKuninori Morimoto {
250e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
2514ff1fef1SKuninori Morimoto 
252e2329eebSKuninori Morimoto 	if (component->driver->set_jack)
253e2329eebSKuninori Morimoto 		ret = component->driver->set_jack(component, jack, data);
254e2329eebSKuninori Morimoto 
255e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
2564ff1fef1SKuninori Morimoto }
2574ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
2584a81e8f3SKuninori Morimoto 
259*df55122bSAstrid Rost /**
260*df55122bSAstrid Rost  * snd_soc_component_get_jack_type
261*df55122bSAstrid Rost  * @component: COMPONENTs
262*df55122bSAstrid Rost  *
263*df55122bSAstrid Rost  * Returns the jack type of the component
264*df55122bSAstrid Rost  * This can either be the supported type or one read from
265*df55122bSAstrid Rost  * devicetree with the property: jack-type.
266*df55122bSAstrid Rost  */
267*df55122bSAstrid Rost int snd_soc_component_get_jack_type(
268*df55122bSAstrid Rost 	struct snd_soc_component *component)
269*df55122bSAstrid Rost {
270*df55122bSAstrid Rost 	int ret = -ENOTSUPP;
271*df55122bSAstrid Rost 
272*df55122bSAstrid Rost 	if (component->driver->get_jack_type)
273*df55122bSAstrid Rost 		ret = component->driver->get_jack_type(component);
274*df55122bSAstrid Rost 
275*df55122bSAstrid Rost 	return soc_component_ret(component, ret);
276*df55122bSAstrid Rost }
277*df55122bSAstrid Rost EXPORT_SYMBOL_GPL(snd_soc_component_get_jack_type);
278*df55122bSAstrid Rost 
2794a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component,
280a739fdc2SPeter Ujfalusi 				 void *mark, int upon_open)
2814a81e8f3SKuninori Morimoto {
282e2329eebSKuninori Morimoto 	int ret = 0;
283e2329eebSKuninori Morimoto 
2844a81e8f3SKuninori Morimoto 	if (component->driver->module_get_upon_open == !!upon_open &&
2854a81e8f3SKuninori Morimoto 	    !try_module_get(component->dev->driver->owner))
286e2329eebSKuninori Morimoto 		ret = -ENODEV;
2874a81e8f3SKuninori Morimoto 
288a739fdc2SPeter Ujfalusi 	/* mark module if succeeded */
28951aff91aSKuninori Morimoto 	if (ret == 0)
290a739fdc2SPeter Ujfalusi 		soc_component_mark_push(component, mark, module);
29151aff91aSKuninori Morimoto 
292e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
2934a81e8f3SKuninori Morimoto }
2944a81e8f3SKuninori Morimoto 
2954a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component,
296a739fdc2SPeter Ujfalusi 				  void *mark, int upon_open, int rollback)
2974a81e8f3SKuninori Morimoto {
298a739fdc2SPeter Ujfalusi 	if (rollback && !soc_component_mark_match(component, mark, module))
29951aff91aSKuninori Morimoto 		return;
30051aff91aSKuninori Morimoto 
3014a81e8f3SKuninori Morimoto 	if (component->driver->module_get_upon_open == !!upon_open)
3024a81e8f3SKuninori Morimoto 		module_put(component->dev->driver->owner);
30351aff91aSKuninori Morimoto 
304a739fdc2SPeter Ujfalusi 	/* remove the mark from module */
305a739fdc2SPeter Ujfalusi 	soc_component_mark_pop(component, mark, module);
3064a81e8f3SKuninori Morimoto }
307ae2f4849SKuninori Morimoto 
308ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component,
309ae2f4849SKuninori Morimoto 			   struct snd_pcm_substream *substream)
310ae2f4849SKuninori Morimoto {
311e2329eebSKuninori Morimoto 	int ret = 0;
312e2329eebSKuninori Morimoto 
313e2cb4a14SKuninori Morimoto 	if (component->driver->open)
314e2329eebSKuninori Morimoto 		ret = component->driver->open(component, substream);
315e2329eebSKuninori Morimoto 
31651aff91aSKuninori Morimoto 	/* mark substream if succeeded */
31751aff91aSKuninori Morimoto 	if (ret == 0)
31851aff91aSKuninori Morimoto 		soc_component_mark_push(component, substream, open);
31951aff91aSKuninori Morimoto 
320e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
321ae2f4849SKuninori Morimoto }
3223672beb8SKuninori Morimoto 
3233672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component,
32451aff91aSKuninori Morimoto 			    struct snd_pcm_substream *substream,
32551aff91aSKuninori Morimoto 			    int rollback)
3263672beb8SKuninori Morimoto {
327e2329eebSKuninori Morimoto 	int ret = 0;
328e2329eebSKuninori Morimoto 
32951aff91aSKuninori Morimoto 	if (rollback && !soc_component_mark_match(component, substream, open))
33051aff91aSKuninori Morimoto 		return 0;
33151aff91aSKuninori Morimoto 
332e2cb4a14SKuninori Morimoto 	if (component->driver->close)
333e2329eebSKuninori Morimoto 		ret = component->driver->close(component, substream);
334e2329eebSKuninori Morimoto 
33551aff91aSKuninori Morimoto 	/* remove marked substream */
33651aff91aSKuninori Morimoto 	soc_component_mark_pop(component, substream, open);
33751aff91aSKuninori Morimoto 
338e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
3393672beb8SKuninori Morimoto }
3406d537233SKuninori Morimoto 
34166c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component)
34266c51573SKuninori Morimoto {
34366c51573SKuninori Morimoto 	if (component->driver->suspend)
34466c51573SKuninori Morimoto 		component->driver->suspend(component);
34566c51573SKuninori Morimoto 	component->suspended = 1;
34666c51573SKuninori Morimoto }
3479a840cbaSKuninori Morimoto 
3489a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component)
3499a840cbaSKuninori Morimoto {
3509a840cbaSKuninori Morimoto 	if (component->driver->resume)
3519a840cbaSKuninori Morimoto 		component->driver->resume(component);
3529a840cbaSKuninori Morimoto 	component->suspended = 0;
3539a840cbaSKuninori Morimoto }
354e40fadbcSKuninori Morimoto 
355e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component)
356e40fadbcSKuninori Morimoto {
357e40fadbcSKuninori Morimoto 	return component->suspended;
358e40fadbcSKuninori Morimoto }
35908e837ddSKuninori Morimoto 
36008e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component)
36108e837ddSKuninori Morimoto {
362e2329eebSKuninori Morimoto 	int ret = 0;
36308e837ddSKuninori Morimoto 
364e2329eebSKuninori Morimoto 	if (component->driver->probe)
365e2329eebSKuninori Morimoto 		ret = component->driver->probe(component);
366e2329eebSKuninori Morimoto 
367e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
36808e837ddSKuninori Morimoto }
36903b34dd7SKuninori Morimoto 
37003b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component)
37103b34dd7SKuninori Morimoto {
37203b34dd7SKuninori Morimoto 	if (component->driver->remove)
37303b34dd7SKuninori Morimoto 		component->driver->remove(component);
37403b34dd7SKuninori Morimoto }
3752c7b1704SKuninori Morimoto 
3762c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
3772c7b1704SKuninori Morimoto 				      struct device_node *ep)
3782c7b1704SKuninori Morimoto {
379e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
3802c7b1704SKuninori Morimoto 
381e2329eebSKuninori Morimoto 	if (component->driver->of_xlate_dai_id)
382e2329eebSKuninori Morimoto 		ret = component->driver->of_xlate_dai_id(component, ep);
383e2329eebSKuninori Morimoto 
384e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
3852c7b1704SKuninori Morimoto }
386a2a34175SKuninori Morimoto 
387a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
388933f98beSKrzysztof Kozlowski 					const struct of_phandle_args *args,
389a2a34175SKuninori Morimoto 					const char **dai_name)
390a2a34175SKuninori Morimoto {
391a2a34175SKuninori Morimoto 	if (component->driver->of_xlate_dai_name)
392cc4d8cebSJerome Brunet 		return component->driver->of_xlate_dai_name(component,
393a2a34175SKuninori Morimoto 							    args, dai_name);
394cc4d8cebSJerome Brunet 	/*
395cc4d8cebSJerome Brunet 	 * Don't use soc_component_ret here because we may not want to report
396cc4d8cebSJerome Brunet 	 * the error just yet. If a device has more than one component, the
397cc4d8cebSJerome Brunet 	 * first may not match and we don't want spam the log with this.
398cc4d8cebSJerome Brunet 	 */
399cc4d8cebSJerome Brunet 	return -ENOTSUPP;
400a2a34175SKuninori Morimoto }
4010035e256SKuninori Morimoto 
402c7d75b59SKuninori Morimoto void snd_soc_component_setup_regmap(struct snd_soc_component *component)
403c7d75b59SKuninori Morimoto {
404c7d75b59SKuninori Morimoto 	int val_bytes = regmap_get_val_bytes(component->regmap);
405c7d75b59SKuninori Morimoto 
406c7d75b59SKuninori Morimoto 	/* Errors are legitimate for non-integer byte multiples */
407c7d75b59SKuninori Morimoto 	if (val_bytes > 0)
408c7d75b59SKuninori Morimoto 		component->val_bytes = val_bytes;
409c7d75b59SKuninori Morimoto }
410c7d75b59SKuninori Morimoto 
411c7d75b59SKuninori Morimoto #ifdef CONFIG_REGMAP
412c7d75b59SKuninori Morimoto 
413c7d75b59SKuninori Morimoto /**
414c7d75b59SKuninori Morimoto  * snd_soc_component_init_regmap() - Initialize regmap instance for the
415c7d75b59SKuninori Morimoto  *                                   component
416c7d75b59SKuninori Morimoto  * @component: The component for which to initialize the regmap instance
417c7d75b59SKuninori Morimoto  * @regmap: The regmap instance that should be used by the component
418c7d75b59SKuninori Morimoto  *
419c7d75b59SKuninori Morimoto  * This function allows deferred assignment of the regmap instance that is
420c7d75b59SKuninori Morimoto  * associated with the component. Only use this if the regmap instance is not
421c7d75b59SKuninori Morimoto  * yet ready when the component is registered. The function must also be called
422c7d75b59SKuninori Morimoto  * before the first IO attempt of the component.
423c7d75b59SKuninori Morimoto  */
424c7d75b59SKuninori Morimoto void snd_soc_component_init_regmap(struct snd_soc_component *component,
425c7d75b59SKuninori Morimoto 				   struct regmap *regmap)
426c7d75b59SKuninori Morimoto {
427c7d75b59SKuninori Morimoto 	component->regmap = regmap;
428c7d75b59SKuninori Morimoto 	snd_soc_component_setup_regmap(component);
429c7d75b59SKuninori Morimoto }
430c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);
431c7d75b59SKuninori Morimoto 
432c7d75b59SKuninori Morimoto /**
433c7d75b59SKuninori Morimoto  * snd_soc_component_exit_regmap() - De-initialize regmap instance for the
434c7d75b59SKuninori Morimoto  *                                   component
435c7d75b59SKuninori Morimoto  * @component: The component for which to de-initialize the regmap instance
436c7d75b59SKuninori Morimoto  *
437c7d75b59SKuninori Morimoto  * Calls regmap_exit() on the regmap instance associated to the component and
438c7d75b59SKuninori Morimoto  * removes the regmap instance from the component.
439c7d75b59SKuninori Morimoto  *
440c7d75b59SKuninori Morimoto  * This function should only be used if snd_soc_component_init_regmap() was used
441c7d75b59SKuninori Morimoto  * to initialize the regmap instance.
442c7d75b59SKuninori Morimoto  */
443c7d75b59SKuninori Morimoto void snd_soc_component_exit_regmap(struct snd_soc_component *component)
444c7d75b59SKuninori Morimoto {
445c7d75b59SKuninori Morimoto 	regmap_exit(component->regmap);
446c7d75b59SKuninori Morimoto 	component->regmap = NULL;
447c7d75b59SKuninori Morimoto }
448c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
449c7d75b59SKuninori Morimoto 
450c7d75b59SKuninori Morimoto #endif
451c7d75b59SKuninori Morimoto 
452cd46f382SPeter Ujfalusi int snd_soc_component_compr_open(struct snd_soc_component *component,
453cd46f382SPeter Ujfalusi 				 struct snd_compr_stream *cstream)
454a4e427c5SKuninori Morimoto {
455cd46f382SPeter Ujfalusi 	int ret = 0;
456a4e427c5SKuninori Morimoto 
457a4e427c5SKuninori Morimoto 	if (component->driver->compress_ops &&
458cd46f382SPeter Ujfalusi 	    component->driver->compress_ops->open)
459a4e427c5SKuninori Morimoto 		ret = component->driver->compress_ops->open(component, cstream);
460a4e427c5SKuninori Morimoto 
461cd46f382SPeter Ujfalusi 	/* mark substream if succeeded */
462cd46f382SPeter Ujfalusi 	if (ret == 0)
463cd46f382SPeter Ujfalusi 		soc_component_mark_push(component, cstream, compr_open);
464cd46f382SPeter Ujfalusi 
465cd46f382SPeter Ujfalusi 	return soc_component_ret(component, ret);
466a4e427c5SKuninori Morimoto }
467a4e427c5SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_open);
468a4e427c5SKuninori Morimoto 
469cd46f382SPeter Ujfalusi void snd_soc_component_compr_free(struct snd_soc_component *component,
470cd46f382SPeter Ujfalusi 				  struct snd_compr_stream *cstream,
471f94ba9acSKuninori Morimoto 				  int rollback)
472dbde5e21SKuninori Morimoto {
473f94ba9acSKuninori Morimoto 	if (rollback && !soc_component_mark_match(component, cstream, compr_open))
474cd46f382SPeter Ujfalusi 		return;
475dbde5e21SKuninori Morimoto 
476dbde5e21SKuninori Morimoto 	if (component->driver->compress_ops &&
477dbde5e21SKuninori Morimoto 	    component->driver->compress_ops->free)
478dbde5e21SKuninori Morimoto 		component->driver->compress_ops->free(component, cstream);
479f94ba9acSKuninori Morimoto 
480cd46f382SPeter Ujfalusi 	/* remove marked substream */
481f94ba9acSKuninori Morimoto 	soc_component_mark_pop(component, cstream, compr_open);
482dbde5e21SKuninori Morimoto }
483dbde5e21SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_free);
484dbde5e21SKuninori Morimoto 
48508aee251SKuninori Morimoto int snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd)
48608aee251SKuninori Morimoto {
48708aee251SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
48808aee251SKuninori Morimoto 	struct snd_soc_component *component;
48908aee251SKuninori Morimoto 	int i, ret;
49008aee251SKuninori Morimoto 
49108aee251SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
49208aee251SKuninori Morimoto 		if (component->driver->compress_ops &&
49308aee251SKuninori Morimoto 		    component->driver->compress_ops->trigger) {
49408aee251SKuninori Morimoto 			ret = component->driver->compress_ops->trigger(
49508aee251SKuninori Morimoto 				component, cstream, cmd);
49608aee251SKuninori Morimoto 			if (ret < 0)
49708aee251SKuninori Morimoto 				return soc_component_ret(component, ret);
49808aee251SKuninori Morimoto 		}
49908aee251SKuninori Morimoto 	}
50008aee251SKuninori Morimoto 
50108aee251SKuninori Morimoto 	return 0;
50208aee251SKuninori Morimoto }
50308aee251SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_trigger);
50408aee251SKuninori Morimoto 
505ff08cf80SKuninori Morimoto int snd_soc_component_compr_set_params(struct snd_compr_stream *cstream,
506ff08cf80SKuninori Morimoto 				       struct snd_compr_params *params)
507ff08cf80SKuninori Morimoto {
508ff08cf80SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
509ff08cf80SKuninori Morimoto 	struct snd_soc_component *component;
510ff08cf80SKuninori Morimoto 	int i, ret;
511ff08cf80SKuninori Morimoto 
512ff08cf80SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
513ff08cf80SKuninori Morimoto 		if (component->driver->compress_ops &&
514ff08cf80SKuninori Morimoto 		    component->driver->compress_ops->set_params) {
515ff08cf80SKuninori Morimoto 			ret = component->driver->compress_ops->set_params(
516ff08cf80SKuninori Morimoto 				component, cstream, params);
517ff08cf80SKuninori Morimoto 			if (ret < 0)
518ff08cf80SKuninori Morimoto 				return soc_component_ret(component, ret);
519ff08cf80SKuninori Morimoto 		}
520ff08cf80SKuninori Morimoto 	}
521ff08cf80SKuninori Morimoto 
522ff08cf80SKuninori Morimoto 	return 0;
523ff08cf80SKuninori Morimoto }
524ff08cf80SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_params);
525ff08cf80SKuninori Morimoto 
52677c221ecSKuninori Morimoto int snd_soc_component_compr_get_params(struct snd_compr_stream *cstream,
52777c221ecSKuninori Morimoto 				       struct snd_codec *params)
52877c221ecSKuninori Morimoto {
52977c221ecSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
53077c221ecSKuninori Morimoto 	struct snd_soc_component *component;
53177c221ecSKuninori Morimoto 	int i, ret;
53277c221ecSKuninori Morimoto 
53377c221ecSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
53477c221ecSKuninori Morimoto 		if (component->driver->compress_ops &&
53577c221ecSKuninori Morimoto 		    component->driver->compress_ops->get_params) {
53677c221ecSKuninori Morimoto 			ret = component->driver->compress_ops->get_params(
53777c221ecSKuninori Morimoto 				component, cstream, params);
53877c221ecSKuninori Morimoto 			return soc_component_ret(component, ret);
53977c221ecSKuninori Morimoto 		}
54077c221ecSKuninori Morimoto 	}
54177c221ecSKuninori Morimoto 
54277c221ecSKuninori Morimoto 	return 0;
54377c221ecSKuninori Morimoto }
54477c221ecSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_params);
54577c221ecSKuninori Morimoto 
546d67fcb2dSKuninori Morimoto int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream,
547d67fcb2dSKuninori Morimoto 				     struct snd_compr_caps *caps)
548d67fcb2dSKuninori Morimoto {
549d67fcb2dSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
550d67fcb2dSKuninori Morimoto 	struct snd_soc_component *component;
551d67fcb2dSKuninori Morimoto 	int i, ret = 0;
552d67fcb2dSKuninori Morimoto 
553d67fcb2dSKuninori Morimoto 	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
554d67fcb2dSKuninori Morimoto 
555d67fcb2dSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
556d67fcb2dSKuninori Morimoto 		if (component->driver->compress_ops &&
557d67fcb2dSKuninori Morimoto 		    component->driver->compress_ops->get_caps) {
558d67fcb2dSKuninori Morimoto 			ret = component->driver->compress_ops->get_caps(
559d67fcb2dSKuninori Morimoto 				component, cstream, caps);
560d67fcb2dSKuninori Morimoto 			break;
561d67fcb2dSKuninori Morimoto 		}
562d67fcb2dSKuninori Morimoto 	}
563d67fcb2dSKuninori Morimoto 
564d67fcb2dSKuninori Morimoto 	mutex_unlock(&rtd->card->pcm_mutex);
565d67fcb2dSKuninori Morimoto 
566d67fcb2dSKuninori Morimoto 	return soc_component_ret(component, ret);
567d67fcb2dSKuninori Morimoto }
568d67fcb2dSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_caps);
569d67fcb2dSKuninori Morimoto 
5700f6fe097SKuninori Morimoto int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream,
5710f6fe097SKuninori Morimoto 					   struct snd_compr_codec_caps *codec)
5720f6fe097SKuninori Morimoto {
5730f6fe097SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5740f6fe097SKuninori Morimoto 	struct snd_soc_component *component;
5750f6fe097SKuninori Morimoto 	int i, ret = 0;
5760f6fe097SKuninori Morimoto 
5770f6fe097SKuninori Morimoto 	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
5780f6fe097SKuninori Morimoto 
5790f6fe097SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
5800f6fe097SKuninori Morimoto 		if (component->driver->compress_ops &&
5810f6fe097SKuninori Morimoto 		    component->driver->compress_ops->get_codec_caps) {
5820f6fe097SKuninori Morimoto 			ret = component->driver->compress_ops->get_codec_caps(
5830f6fe097SKuninori Morimoto 				component, cstream, codec);
5840f6fe097SKuninori Morimoto 			break;
5850f6fe097SKuninori Morimoto 		}
5860f6fe097SKuninori Morimoto 	}
5870f6fe097SKuninori Morimoto 
5880f6fe097SKuninori Morimoto 	mutex_unlock(&rtd->card->pcm_mutex);
5890f6fe097SKuninori Morimoto 
5900f6fe097SKuninori Morimoto 	return soc_component_ret(component, ret);
5910f6fe097SKuninori Morimoto }
5920f6fe097SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_codec_caps);
5930f6fe097SKuninori Morimoto 
5940506b885SKuninori Morimoto int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
5950506b885SKuninori Morimoto {
5960506b885SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5970506b885SKuninori Morimoto 	struct snd_soc_component *component;
5980506b885SKuninori Morimoto 	int i, ret;
5990506b885SKuninori Morimoto 
6000506b885SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
6010506b885SKuninori Morimoto 		if (component->driver->compress_ops &&
6020506b885SKuninori Morimoto 		    component->driver->compress_ops->ack) {
6030506b885SKuninori Morimoto 			ret = component->driver->compress_ops->ack(
6040506b885SKuninori Morimoto 				component, cstream, bytes);
6050506b885SKuninori Morimoto 			if (ret < 0)
6060506b885SKuninori Morimoto 				return soc_component_ret(component, ret);
6070506b885SKuninori Morimoto 		}
6080506b885SKuninori Morimoto 	}
6090506b885SKuninori Morimoto 
6100506b885SKuninori Morimoto 	return 0;
6110506b885SKuninori Morimoto }
6120506b885SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack);
6130506b885SKuninori Morimoto 
61403ecea64SKuninori Morimoto int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream,
61503ecea64SKuninori Morimoto 				    struct snd_compr_tstamp *tstamp)
61603ecea64SKuninori Morimoto {
61703ecea64SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
61803ecea64SKuninori Morimoto 	struct snd_soc_component *component;
61903ecea64SKuninori Morimoto 	int i, ret;
62003ecea64SKuninori Morimoto 
62103ecea64SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
62203ecea64SKuninori Morimoto 		if (component->driver->compress_ops &&
62303ecea64SKuninori Morimoto 		    component->driver->compress_ops->pointer) {
62403ecea64SKuninori Morimoto 			ret = component->driver->compress_ops->pointer(
62503ecea64SKuninori Morimoto 				component, cstream, tstamp);
62603ecea64SKuninori Morimoto 			return soc_component_ret(component, ret);
62703ecea64SKuninori Morimoto 		}
62803ecea64SKuninori Morimoto 	}
62903ecea64SKuninori Morimoto 
63003ecea64SKuninori Morimoto 	return 0;
63103ecea64SKuninori Morimoto }
63203ecea64SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_pointer);
63303ecea64SKuninori Morimoto 
634b5852e66SKuninori Morimoto int snd_soc_component_compr_copy(struct snd_compr_stream *cstream,
635b5852e66SKuninori Morimoto 				 char __user *buf, size_t count)
636b5852e66SKuninori Morimoto {
637b5852e66SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
638b5852e66SKuninori Morimoto 	struct snd_soc_component *component;
639b5852e66SKuninori Morimoto 	int i, ret = 0;
640b5852e66SKuninori Morimoto 
641b5852e66SKuninori Morimoto 	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
642b5852e66SKuninori Morimoto 
643b5852e66SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
644b5852e66SKuninori Morimoto 		if (component->driver->compress_ops &&
645b5852e66SKuninori Morimoto 		    component->driver->compress_ops->copy) {
646b5852e66SKuninori Morimoto 			ret = component->driver->compress_ops->copy(
647b5852e66SKuninori Morimoto 				component, cstream, buf, count);
648b5852e66SKuninori Morimoto 			break;
649b5852e66SKuninori Morimoto 		}
650b5852e66SKuninori Morimoto 	}
651b5852e66SKuninori Morimoto 
652b5852e66SKuninori Morimoto 	mutex_unlock(&rtd->card->pcm_mutex);
653b5852e66SKuninori Morimoto 
654b5852e66SKuninori Morimoto 	return soc_component_ret(component, ret);
655b5852e66SKuninori Morimoto }
656b5852e66SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_copy);
657b5852e66SKuninori Morimoto 
6581b308fb1SKuninori Morimoto int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream,
6591b308fb1SKuninori Morimoto 					 struct snd_compr_metadata *metadata)
6601b308fb1SKuninori Morimoto {
6611b308fb1SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
6621b308fb1SKuninori Morimoto 	struct snd_soc_component *component;
6631b308fb1SKuninori Morimoto 	int i, ret;
6641b308fb1SKuninori Morimoto 
6651b308fb1SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
6661b308fb1SKuninori Morimoto 		if (component->driver->compress_ops &&
6671b308fb1SKuninori Morimoto 		    component->driver->compress_ops->set_metadata) {
6681b308fb1SKuninori Morimoto 			ret = component->driver->compress_ops->set_metadata(
6691b308fb1SKuninori Morimoto 				component, cstream, metadata);
6701b308fb1SKuninori Morimoto 			if (ret < 0)
6711b308fb1SKuninori Morimoto 				return soc_component_ret(component, ret);
6721b308fb1SKuninori Morimoto 		}
6731b308fb1SKuninori Morimoto 	}
6741b308fb1SKuninori Morimoto 
6751b308fb1SKuninori Morimoto 	return 0;
6761b308fb1SKuninori Morimoto }
6771b308fb1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_metadata);
6781b308fb1SKuninori Morimoto 
679bab78c23SKuninori Morimoto int snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream,
680bab78c23SKuninori Morimoto 					 struct snd_compr_metadata *metadata)
681bab78c23SKuninori Morimoto {
682bab78c23SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
683bab78c23SKuninori Morimoto 	struct snd_soc_component *component;
684bab78c23SKuninori Morimoto 	int i, ret;
685bab78c23SKuninori Morimoto 
686bab78c23SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
687bab78c23SKuninori Morimoto 		if (component->driver->compress_ops &&
688bab78c23SKuninori Morimoto 		    component->driver->compress_ops->get_metadata) {
689bab78c23SKuninori Morimoto 			ret = component->driver->compress_ops->get_metadata(
690bab78c23SKuninori Morimoto 				component, cstream, metadata);
691bab78c23SKuninori Morimoto 			return soc_component_ret(component, ret);
692bab78c23SKuninori Morimoto 		}
693bab78c23SKuninori Morimoto 	}
694bab78c23SKuninori Morimoto 
695bab78c23SKuninori Morimoto 	return 0;
696bab78c23SKuninori Morimoto }
697bab78c23SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_metadata);
698bab78c23SKuninori Morimoto 
699e8712315SKuninori Morimoto static unsigned int soc_component_read_no_lock(
700e8712315SKuninori Morimoto 	struct snd_soc_component *component,
701cf6e26c7SKuninori Morimoto 	unsigned int reg)
702460b42d1SKuninori Morimoto {
703460b42d1SKuninori Morimoto 	int ret;
704cf6e26c7SKuninori Morimoto 	unsigned int val = 0;
705460b42d1SKuninori Morimoto 
706460b42d1SKuninori Morimoto 	if (component->regmap)
707cf6e26c7SKuninori Morimoto 		ret = regmap_read(component->regmap, reg, &val);
708460b42d1SKuninori Morimoto 	else if (component->driver->read) {
709460b42d1SKuninori Morimoto 		ret = 0;
710cf6e26c7SKuninori Morimoto 		val = component->driver->read(component, reg);
711460b42d1SKuninori Morimoto 	}
712460b42d1SKuninori Morimoto 	else
713460b42d1SKuninori Morimoto 		ret = -EIO;
714460b42d1SKuninori Morimoto 
715460b42d1SKuninori Morimoto 	if (ret < 0)
716b296997cSSrinivas Kandagatla 		return soc_component_ret_reg_rw(component, ret, reg);
717460b42d1SKuninori Morimoto 
718460b42d1SKuninori Morimoto 	return val;
719460b42d1SKuninori Morimoto }
720e8712315SKuninori Morimoto 
721e8712315SKuninori Morimoto /**
722e8712315SKuninori Morimoto  * snd_soc_component_read() - Read register value
723e8712315SKuninori Morimoto  * @component: Component to read from
724e8712315SKuninori Morimoto  * @reg: Register to read
725e8712315SKuninori Morimoto  *
726e8712315SKuninori Morimoto  * Return: read value
727e8712315SKuninori Morimoto  */
728e8712315SKuninori Morimoto unsigned int snd_soc_component_read(struct snd_soc_component *component,
729e8712315SKuninori Morimoto 				    unsigned int reg)
730e8712315SKuninori Morimoto {
731e8712315SKuninori Morimoto 	unsigned int val;
732e8712315SKuninori Morimoto 
733e8712315SKuninori Morimoto 	mutex_lock(&component->io_mutex);
734e8712315SKuninori Morimoto 	val = soc_component_read_no_lock(component, reg);
735e8712315SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
736e8712315SKuninori Morimoto 
737e8712315SKuninori Morimoto 	return val;
738e8712315SKuninori Morimoto }
739cf6e26c7SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_read);
740460b42d1SKuninori Morimoto 
741e8712315SKuninori Morimoto static int soc_component_write_no_lock(
742e8712315SKuninori Morimoto 	struct snd_soc_component *component,
743e8712315SKuninori Morimoto 	unsigned int reg, unsigned int val)
744e8712315SKuninori Morimoto {
745e8712315SKuninori Morimoto 	int ret = -EIO;
746e8712315SKuninori Morimoto 
747e8712315SKuninori Morimoto 	if (component->regmap)
748e8712315SKuninori Morimoto 		ret = regmap_write(component->regmap, reg, val);
749e8712315SKuninori Morimoto 	else if (component->driver->write)
750e8712315SKuninori Morimoto 		ret = component->driver->write(component, reg, val);
751e8712315SKuninori Morimoto 
752b296997cSSrinivas Kandagatla 	return soc_component_ret_reg_rw(component, ret, reg);
753e8712315SKuninori Morimoto }
754e8712315SKuninori Morimoto 
755460b42d1SKuninori Morimoto /**
756460b42d1SKuninori Morimoto  * snd_soc_component_write() - Write register value
757460b42d1SKuninori Morimoto  * @component: Component to write to
758460b42d1SKuninori Morimoto  * @reg: Register to write
759460b42d1SKuninori Morimoto  * @val: Value to write to the register
760460b42d1SKuninori Morimoto  *
761460b42d1SKuninori Morimoto  * Return: 0 on success, a negative error code otherwise.
762460b42d1SKuninori Morimoto  */
763460b42d1SKuninori Morimoto int snd_soc_component_write(struct snd_soc_component *component,
764460b42d1SKuninori Morimoto 			    unsigned int reg, unsigned int val)
765460b42d1SKuninori Morimoto {
766e8712315SKuninori Morimoto 	int ret;
767460b42d1SKuninori Morimoto 
768e8712315SKuninori Morimoto 	mutex_lock(&component->io_mutex);
769e8712315SKuninori Morimoto 	ret = soc_component_write_no_lock(component, reg, val);
770e8712315SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
771460b42d1SKuninori Morimoto 
772e8712315SKuninori Morimoto 	return ret;
773460b42d1SKuninori Morimoto }
774460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_write);
775460b42d1SKuninori Morimoto 
776460b42d1SKuninori Morimoto static int snd_soc_component_update_bits_legacy(
777460b42d1SKuninori Morimoto 	struct snd_soc_component *component, unsigned int reg,
778460b42d1SKuninori Morimoto 	unsigned int mask, unsigned int val, bool *change)
779460b42d1SKuninori Morimoto {
780460b42d1SKuninori Morimoto 	unsigned int old, new;
781cf6e26c7SKuninori Morimoto 	int ret = 0;
782460b42d1SKuninori Morimoto 
783460b42d1SKuninori Morimoto 	mutex_lock(&component->io_mutex);
784460b42d1SKuninori Morimoto 
785e8712315SKuninori Morimoto 	old = soc_component_read_no_lock(component, reg);
786460b42d1SKuninori Morimoto 
787460b42d1SKuninori Morimoto 	new = (old & ~mask) | (val & mask);
788460b42d1SKuninori Morimoto 	*change = old != new;
789460b42d1SKuninori Morimoto 	if (*change)
790e8712315SKuninori Morimoto 		ret = soc_component_write_no_lock(component, reg, new);
791cf6e26c7SKuninori Morimoto 
792460b42d1SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
793460b42d1SKuninori Morimoto 
794b296997cSSrinivas Kandagatla 	return soc_component_ret_reg_rw(component, ret, reg);
795460b42d1SKuninori Morimoto }
796460b42d1SKuninori Morimoto 
797460b42d1SKuninori Morimoto /**
798460b42d1SKuninori Morimoto  * snd_soc_component_update_bits() - Perform read/modify/write cycle
799460b42d1SKuninori Morimoto  * @component: Component to update
800460b42d1SKuninori Morimoto  * @reg: Register to update
801460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to update
802460b42d1SKuninori Morimoto  * @val: New value for the bits specified by mask
803460b42d1SKuninori Morimoto  *
804460b42d1SKuninori Morimoto  * Return: 1 if the operation was successful and the value of the register
805460b42d1SKuninori Morimoto  * changed, 0 if the operation was successful, but the value did not change.
806460b42d1SKuninori Morimoto  * Returns a negative error code otherwise.
807460b42d1SKuninori Morimoto  */
808460b42d1SKuninori Morimoto int snd_soc_component_update_bits(struct snd_soc_component *component,
809460b42d1SKuninori Morimoto 				  unsigned int reg, unsigned int mask, unsigned int val)
810460b42d1SKuninori Morimoto {
811460b42d1SKuninori Morimoto 	bool change;
812460b42d1SKuninori Morimoto 	int ret;
813460b42d1SKuninori Morimoto 
814460b42d1SKuninori Morimoto 	if (component->regmap)
815460b42d1SKuninori Morimoto 		ret = regmap_update_bits_check(component->regmap, reg, mask,
816460b42d1SKuninori Morimoto 					       val, &change);
817460b42d1SKuninori Morimoto 	else
818460b42d1SKuninori Morimoto 		ret = snd_soc_component_update_bits_legacy(component, reg,
819460b42d1SKuninori Morimoto 							   mask, val, &change);
820460b42d1SKuninori Morimoto 
821460b42d1SKuninori Morimoto 	if (ret < 0)
822b296997cSSrinivas Kandagatla 		return soc_component_ret_reg_rw(component, ret, reg);
823460b42d1SKuninori Morimoto 	return change;
824460b42d1SKuninori Morimoto }
825460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
826460b42d1SKuninori Morimoto 
827460b42d1SKuninori Morimoto /**
828460b42d1SKuninori Morimoto  * snd_soc_component_update_bits_async() - Perform asynchronous
829460b42d1SKuninori Morimoto  *  read/modify/write cycle
830460b42d1SKuninori Morimoto  * @component: Component to update
831460b42d1SKuninori Morimoto  * @reg: Register to update
832460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to update
833460b42d1SKuninori Morimoto  * @val: New value for the bits specified by mask
834460b42d1SKuninori Morimoto  *
835460b42d1SKuninori Morimoto  * This function is similar to snd_soc_component_update_bits(), but the update
836460b42d1SKuninori Morimoto  * operation is scheduled asynchronously. This means it may not be completed
837460b42d1SKuninori Morimoto  * when the function returns. To make sure that all scheduled updates have been
838460b42d1SKuninori Morimoto  * completed snd_soc_component_async_complete() must be called.
839460b42d1SKuninori Morimoto  *
840460b42d1SKuninori Morimoto  * Return: 1 if the operation was successful and the value of the register
841460b42d1SKuninori Morimoto  * changed, 0 if the operation was successful, but the value did not change.
842460b42d1SKuninori Morimoto  * Returns a negative error code otherwise.
843460b42d1SKuninori Morimoto  */
844460b42d1SKuninori Morimoto int snd_soc_component_update_bits_async(struct snd_soc_component *component,
845460b42d1SKuninori Morimoto 					unsigned int reg, unsigned int mask, unsigned int val)
846460b42d1SKuninori Morimoto {
847460b42d1SKuninori Morimoto 	bool change;
848460b42d1SKuninori Morimoto 	int ret;
849460b42d1SKuninori Morimoto 
850460b42d1SKuninori Morimoto 	if (component->regmap)
851460b42d1SKuninori Morimoto 		ret = regmap_update_bits_check_async(component->regmap, reg,
852460b42d1SKuninori Morimoto 						     mask, val, &change);
853460b42d1SKuninori Morimoto 	else
854460b42d1SKuninori Morimoto 		ret = snd_soc_component_update_bits_legacy(component, reg,
855460b42d1SKuninori Morimoto 							   mask, val, &change);
856460b42d1SKuninori Morimoto 
857460b42d1SKuninori Morimoto 	if (ret < 0)
858b296997cSSrinivas Kandagatla 		return soc_component_ret_reg_rw(component, ret, reg);
859460b42d1SKuninori Morimoto 	return change;
860460b42d1SKuninori Morimoto }
861460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
862460b42d1SKuninori Morimoto 
863460b42d1SKuninori Morimoto /**
8641da0b989SSrinivas Kandagatla  * snd_soc_component_read_field() - Read register field value
8651da0b989SSrinivas Kandagatla  * @component: Component to read from
8661da0b989SSrinivas Kandagatla  * @reg: Register to read
8671da0b989SSrinivas Kandagatla  * @mask: mask of the register field
8681da0b989SSrinivas Kandagatla  *
8691da0b989SSrinivas Kandagatla  * Return: read value of register field.
8701da0b989SSrinivas Kandagatla  */
8711da0b989SSrinivas Kandagatla unsigned int snd_soc_component_read_field(struct snd_soc_component *component,
8721da0b989SSrinivas Kandagatla 					  unsigned int reg, unsigned int mask)
8731da0b989SSrinivas Kandagatla {
8741da0b989SSrinivas Kandagatla 	unsigned int val;
8751da0b989SSrinivas Kandagatla 
8761da0b989SSrinivas Kandagatla 	val = snd_soc_component_read(component, reg);
8771da0b989SSrinivas Kandagatla 
8781da0b989SSrinivas Kandagatla 	val = (val & mask) >> soc_component_field_shift(component, mask);
8791da0b989SSrinivas Kandagatla 
8801da0b989SSrinivas Kandagatla 	return val;
8811da0b989SSrinivas Kandagatla }
8821da0b989SSrinivas Kandagatla EXPORT_SYMBOL_GPL(snd_soc_component_read_field);
8831da0b989SSrinivas Kandagatla 
8841da0b989SSrinivas Kandagatla /**
8851da0b989SSrinivas Kandagatla  * snd_soc_component_write_field() - write to register field
8861da0b989SSrinivas Kandagatla  * @component: Component to write to
8871da0b989SSrinivas Kandagatla  * @reg: Register to write
8881da0b989SSrinivas Kandagatla  * @mask: mask of the register field to update
8891da0b989SSrinivas Kandagatla  * @val: value of the field to write
8901da0b989SSrinivas Kandagatla  *
8911da0b989SSrinivas Kandagatla  * Return: 1 for change, otherwise 0.
8921da0b989SSrinivas Kandagatla  */
8931da0b989SSrinivas Kandagatla int snd_soc_component_write_field(struct snd_soc_component *component,
8941da0b989SSrinivas Kandagatla 				  unsigned int reg, unsigned int mask,
8951da0b989SSrinivas Kandagatla 				  unsigned int val)
8961da0b989SSrinivas Kandagatla {
8971da0b989SSrinivas Kandagatla 
8981da0b989SSrinivas Kandagatla 	val = (val << soc_component_field_shift(component, mask)) & mask;
8991da0b989SSrinivas Kandagatla 
9001da0b989SSrinivas Kandagatla 	return snd_soc_component_update_bits(component, reg, mask, val);
9011da0b989SSrinivas Kandagatla }
9021da0b989SSrinivas Kandagatla EXPORT_SYMBOL_GPL(snd_soc_component_write_field);
9031da0b989SSrinivas Kandagatla 
9041da0b989SSrinivas Kandagatla /**
905460b42d1SKuninori Morimoto  * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
906460b42d1SKuninori Morimoto  * @component: Component for which to wait
907460b42d1SKuninori Morimoto  *
908460b42d1SKuninori Morimoto  * This function blocks until all asynchronous I/O which has previously been
909460b42d1SKuninori Morimoto  * scheduled using snd_soc_component_update_bits_async() has completed.
910460b42d1SKuninori Morimoto  */
911460b42d1SKuninori Morimoto void snd_soc_component_async_complete(struct snd_soc_component *component)
912460b42d1SKuninori Morimoto {
913460b42d1SKuninori Morimoto 	if (component->regmap)
914460b42d1SKuninori Morimoto 		regmap_async_complete(component->regmap);
915460b42d1SKuninori Morimoto }
916460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
917460b42d1SKuninori Morimoto 
918460b42d1SKuninori Morimoto /**
919460b42d1SKuninori Morimoto  * snd_soc_component_test_bits - Test register for change
920460b42d1SKuninori Morimoto  * @component: component
921460b42d1SKuninori Morimoto  * @reg: Register to test
922460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to test
923460b42d1SKuninori Morimoto  * @value: Value to test against
924460b42d1SKuninori Morimoto  *
925460b42d1SKuninori Morimoto  * Tests a register with a new value and checks if the new value is
926460b42d1SKuninori Morimoto  * different from the old value.
927460b42d1SKuninori Morimoto  *
928460b42d1SKuninori Morimoto  * Return: 1 for change, otherwise 0.
929460b42d1SKuninori Morimoto  */
930460b42d1SKuninori Morimoto int snd_soc_component_test_bits(struct snd_soc_component *component,
931460b42d1SKuninori Morimoto 				unsigned int reg, unsigned int mask, unsigned int value)
932460b42d1SKuninori Morimoto {
933460b42d1SKuninori Morimoto 	unsigned int old, new;
934460b42d1SKuninori Morimoto 
935cf6e26c7SKuninori Morimoto 	old = snd_soc_component_read(component, reg);
936460b42d1SKuninori Morimoto 	new = (old & ~mask) | value;
937460b42d1SKuninori Morimoto 	return old != new;
938460b42d1SKuninori Morimoto }
939460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
940460b42d1SKuninori Morimoto 
9410035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
9420035e256SKuninori Morimoto {
9430ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
9440035e256SKuninori Morimoto 	struct snd_soc_component *component;
945613fb500SKuninori Morimoto 	int i;
9460035e256SKuninori Morimoto 
9470035e256SKuninori Morimoto 	/* FIXME: use 1st pointer */
948613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
949e2cb4a14SKuninori Morimoto 		if (component->driver->pointer)
950e2cb4a14SKuninori Morimoto 			return component->driver->pointer(component, substream);
9510035e256SKuninori Morimoto 
9520035e256SKuninori Morimoto 	return 0;
9530035e256SKuninori Morimoto }
95496a47908SKuninori Morimoto 
955232213bdSCharles Keepax static bool snd_soc_component_is_codec_on_rtd(struct snd_soc_pcm_runtime *rtd,
956232213bdSCharles Keepax 					      struct snd_soc_component *component)
957232213bdSCharles Keepax {
958232213bdSCharles Keepax 	struct snd_soc_dai *dai;
959232213bdSCharles Keepax 	int i;
960232213bdSCharles Keepax 
961232213bdSCharles Keepax 	for_each_rtd_codec_dais(rtd, i, dai) {
962232213bdSCharles Keepax 		if (dai->component == component)
963232213bdSCharles Keepax 			return true;
964232213bdSCharles Keepax 	}
965232213bdSCharles Keepax 
966232213bdSCharles Keepax 	return false;
967232213bdSCharles Keepax }
968232213bdSCharles Keepax 
969403f830eSKuninori Morimoto void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
970403f830eSKuninori Morimoto 				 snd_pcm_sframes_t *cpu_delay,
971403f830eSKuninori Morimoto 				 snd_pcm_sframes_t *codec_delay)
972403f830eSKuninori Morimoto {
973403f830eSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
974403f830eSKuninori Morimoto 	struct snd_soc_component *component;
975403f830eSKuninori Morimoto 	snd_pcm_sframes_t delay;
976403f830eSKuninori Morimoto 	int i;
977403f830eSKuninori Morimoto 
978403f830eSKuninori Morimoto 	/*
979403f830eSKuninori Morimoto 	 * We're looking for the delay through the full audio path so it needs to
980403f830eSKuninori Morimoto 	 * be the maximum of the Components doing transmit and the maximum of the
981403f830eSKuninori Morimoto 	 * Components doing receive (ie, all CPUs and all CODECs) rather than
982403f830eSKuninori Morimoto 	 * just the maximum of all Components.
983403f830eSKuninori Morimoto 	 */
984403f830eSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
985403f830eSKuninori Morimoto 		if (!component->driver->delay)
986403f830eSKuninori Morimoto 			continue;
987403f830eSKuninori Morimoto 
988403f830eSKuninori Morimoto 		delay = component->driver->delay(component, substream);
989403f830eSKuninori Morimoto 
990232213bdSCharles Keepax 		if (snd_soc_component_is_codec_on_rtd(rtd, component))
991403f830eSKuninori Morimoto 			*codec_delay = max(*codec_delay, delay);
992403f830eSKuninori Morimoto 		else
993403f830eSKuninori Morimoto 			*cpu_delay = max(*cpu_delay, delay);
994403f830eSKuninori Morimoto 	}
995403f830eSKuninori Morimoto }
996403f830eSKuninori Morimoto 
99796a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
99896a47908SKuninori Morimoto 				unsigned int cmd, void *arg)
99996a47908SKuninori Morimoto {
10000ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
100196a47908SKuninori Morimoto 	struct snd_soc_component *component;
1002613fb500SKuninori Morimoto 	int i;
100396a47908SKuninori Morimoto 
100496a47908SKuninori Morimoto 	/* FIXME: use 1st ioctl */
1005613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
1006e2cb4a14SKuninori Morimoto 		if (component->driver->ioctl)
1007e2329eebSKuninori Morimoto 			return soc_component_ret(
1008e2329eebSKuninori Morimoto 				component,
1009e2329eebSKuninori Morimoto 				component->driver->ioctl(component,
1010e2329eebSKuninori Morimoto 							 substream, cmd, arg));
101196a47908SKuninori Morimoto 
101296a47908SKuninori Morimoto 	return snd_pcm_lib_ioctl(substream, cmd, arg);
101396a47908SKuninori Morimoto }
101482d81f5cSKuninori Morimoto 
10151e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream)
10161e5ddb6bSTakashi Iwai {
10170ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
10181e5ddb6bSTakashi Iwai 	struct snd_soc_component *component;
1019613fb500SKuninori Morimoto 	int i, ret;
10201e5ddb6bSTakashi Iwai 
1021613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1022f1861a7cSKuninori Morimoto 		if (component->driver->sync_stop) {
10231e5ddb6bSTakashi Iwai 			ret = component->driver->sync_stop(component,
10241e5ddb6bSTakashi Iwai 							   substream);
10251e5ddb6bSTakashi Iwai 			if (ret < 0)
1026be75db57SShengjiu Wang 				return soc_component_ret(component, ret);
10271e5ddb6bSTakashi Iwai 		}
10281e5ddb6bSTakashi Iwai 	}
10291e5ddb6bSTakashi Iwai 
10301e5ddb6bSTakashi Iwai 	return 0;
10311e5ddb6bSTakashi Iwai }
10321e5ddb6bSTakashi Iwai 
103382d81f5cSKuninori Morimoto int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream,
103482d81f5cSKuninori Morimoto 				    int channel, unsigned long pos,
103582d81f5cSKuninori Morimoto 				    void __user *buf, unsigned long bytes)
103682d81f5cSKuninori Morimoto {
10370ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
103882d81f5cSKuninori Morimoto 	struct snd_soc_component *component;
1039613fb500SKuninori Morimoto 	int i;
104082d81f5cSKuninori Morimoto 
104182d81f5cSKuninori Morimoto 	/* FIXME. it returns 1st copy now */
1042613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
1043e2cb4a14SKuninori Morimoto 		if (component->driver->copy_user)
1044e2329eebSKuninori Morimoto 			return soc_component_ret(
1045e2329eebSKuninori Morimoto 				component,
1046e2329eebSKuninori Morimoto 				component->driver->copy_user(
1047e2329eebSKuninori Morimoto 					component, substream, channel,
1048e2329eebSKuninori Morimoto 					pos, buf, bytes));
104982d81f5cSKuninori Morimoto 
105082d81f5cSKuninori Morimoto 	return -EINVAL;
105182d81f5cSKuninori Morimoto }
10529c712e4fSKuninori Morimoto 
10539c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
10549c712e4fSKuninori Morimoto 					unsigned long offset)
10559c712e4fSKuninori Morimoto {
10560ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
10579c712e4fSKuninori Morimoto 	struct snd_soc_component *component;
10589c712e4fSKuninori Morimoto 	struct page *page;
1059613fb500SKuninori Morimoto 	int i;
10609c712e4fSKuninori Morimoto 
10619c712e4fSKuninori Morimoto 	/* FIXME. it returns 1st page now */
1062613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1063e2cb4a14SKuninori Morimoto 		if (component->driver->page) {
1064e2cb4a14SKuninori Morimoto 			page = component->driver->page(component,
1065e2cb4a14SKuninori Morimoto 						       substream, offset);
1066e2cb4a14SKuninori Morimoto 			if (page)
1067e2cb4a14SKuninori Morimoto 				return page;
1068e2cb4a14SKuninori Morimoto 		}
10699c712e4fSKuninori Morimoto 	}
10709c712e4fSKuninori Morimoto 
10719c712e4fSKuninori Morimoto 	return NULL;
10729c712e4fSKuninori Morimoto }
1073205875e1SKuninori Morimoto 
1074205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
1075205875e1SKuninori Morimoto 			       struct vm_area_struct *vma)
1076205875e1SKuninori Morimoto {
10770ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1078205875e1SKuninori Morimoto 	struct snd_soc_component *component;
1079613fb500SKuninori Morimoto 	int i;
1080205875e1SKuninori Morimoto 
1081205875e1SKuninori Morimoto 	/* FIXME. it returns 1st mmap now */
1082613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
1083e2cb4a14SKuninori Morimoto 		if (component->driver->mmap)
1084be75db57SShengjiu Wang 			return soc_component_ret(
1085e2329eebSKuninori Morimoto 				component,
1086e2329eebSKuninori Morimoto 				component->driver->mmap(component,
1087e2329eebSKuninori Morimoto 							substream, vma));
1088205875e1SKuninori Morimoto 
1089205875e1SKuninori Morimoto 	return -EINVAL;
1090205875e1SKuninori Morimoto }
10917484291eSKuninori Morimoto 
1092b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd)
10937484291eSKuninori Morimoto {
10947484291eSKuninori Morimoto 	struct snd_soc_component *component;
10957484291eSKuninori Morimoto 	int ret;
1096613fb500SKuninori Morimoto 	int i;
10977484291eSKuninori Morimoto 
1098613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1099c64bfc90SKuninori Morimoto 		if (component->driver->pcm_construct) {
1100c64bfc90SKuninori Morimoto 			ret = component->driver->pcm_construct(component, rtd);
1101c64bfc90SKuninori Morimoto 			if (ret < 0)
1102be75db57SShengjiu Wang 				return soc_component_ret(component, ret);
1103c64bfc90SKuninori Morimoto 		}
11047484291eSKuninori Morimoto 	}
11057484291eSKuninori Morimoto 
11067484291eSKuninori Morimoto 	return 0;
11077484291eSKuninori Morimoto }
110879776da0SKuninori Morimoto 
1109b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd)
111079776da0SKuninori Morimoto {
111179776da0SKuninori Morimoto 	struct snd_soc_component *component;
1112613fb500SKuninori Morimoto 	int i;
111379776da0SKuninori Morimoto 
11148e3366caSTakashi Iwai 	if (!rtd->pcm)
11158e3366caSTakashi Iwai 		return;
11168e3366caSTakashi Iwai 
1117613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
1118c64bfc90SKuninori Morimoto 		if (component->driver->pcm_destruct)
1119b2b2afbbSKuninori Morimoto 			component->driver->pcm_destruct(component, rtd->pcm);
112079776da0SKuninori Morimoto }
11214f39514fSKuninori Morimoto 
11224f39514fSKuninori Morimoto int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream)
11234f39514fSKuninori Morimoto {
11240ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
11254f39514fSKuninori Morimoto 	struct snd_soc_component *component;
11264f39514fSKuninori Morimoto 	int i, ret;
11274f39514fSKuninori Morimoto 
11284f39514fSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
11294f39514fSKuninori Morimoto 		if (component->driver->prepare) {
11304f39514fSKuninori Morimoto 			ret = component->driver->prepare(component, substream);
11314f39514fSKuninori Morimoto 			if (ret < 0)
11324f39514fSKuninori Morimoto 				return soc_component_ret(component, ret);
11334f39514fSKuninori Morimoto 		}
11344f39514fSKuninori Morimoto 	}
11354f39514fSKuninori Morimoto 
11364f39514fSKuninori Morimoto 	return 0;
11374f39514fSKuninori Morimoto }
1138e1bafa82SKuninori Morimoto 
1139e1bafa82SKuninori Morimoto int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
11403a36a64aSKuninori Morimoto 				    struct snd_pcm_hw_params *params)
1141e1bafa82SKuninori Morimoto {
11420ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1143e1bafa82SKuninori Morimoto 	struct snd_soc_component *component;
1144e1bafa82SKuninori Morimoto 	int i, ret;
1145e1bafa82SKuninori Morimoto 
1146e1bafa82SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1147e1bafa82SKuninori Morimoto 		if (component->driver->hw_params) {
1148e1bafa82SKuninori Morimoto 			ret = component->driver->hw_params(component,
1149e1bafa82SKuninori Morimoto 							   substream, params);
11503a36a64aSKuninori Morimoto 			if (ret < 0)
1151e1bafa82SKuninori Morimoto 				return soc_component_ret(component, ret);
1152e1bafa82SKuninori Morimoto 		}
11533a36a64aSKuninori Morimoto 		/* mark substream if succeeded */
11543a36a64aSKuninori Morimoto 		soc_component_mark_push(component, substream, hw_params);
1155e1bafa82SKuninori Morimoto 	}
1156e1bafa82SKuninori Morimoto 
1157e1bafa82SKuninori Morimoto 	return 0;
1158e1bafa82SKuninori Morimoto }
115904751119SKuninori Morimoto 
116004751119SKuninori Morimoto void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
11613a36a64aSKuninori Morimoto 				   int rollback)
116204751119SKuninori Morimoto {
11630ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
116404751119SKuninori Morimoto 	struct snd_soc_component *component;
116504751119SKuninori Morimoto 	int i, ret;
116604751119SKuninori Morimoto 
116704751119SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
11683a36a64aSKuninori Morimoto 		if (rollback && !soc_component_mark_match(component, substream, hw_params))
11693a36a64aSKuninori Morimoto 			continue;
117004751119SKuninori Morimoto 
117104751119SKuninori Morimoto 		if (component->driver->hw_free) {
117204751119SKuninori Morimoto 			ret = component->driver->hw_free(component, substream);
117304751119SKuninori Morimoto 			if (ret < 0)
117404751119SKuninori Morimoto 				soc_component_ret(component, ret);
117504751119SKuninori Morimoto 		}
11763a36a64aSKuninori Morimoto 
11773a36a64aSKuninori Morimoto 		/* remove marked substream */
11783a36a64aSKuninori Morimoto 		soc_component_mark_pop(component, substream, hw_params);
117904751119SKuninori Morimoto 	}
118004751119SKuninori Morimoto }
118132fd1204SKuninori Morimoto 
11826374f493SKuninori Morimoto static int soc_component_trigger(struct snd_soc_component *component,
11836374f493SKuninori Morimoto 				 struct snd_pcm_substream *substream,
118432fd1204SKuninori Morimoto 				 int cmd)
118532fd1204SKuninori Morimoto {
11866374f493SKuninori Morimoto 	int ret = 0;
11876374f493SKuninori Morimoto 
11886374f493SKuninori Morimoto 	if (component->driver->trigger)
11896374f493SKuninori Morimoto 		ret = component->driver->trigger(component, substream, cmd);
11906374f493SKuninori Morimoto 
11916374f493SKuninori Morimoto 	return soc_component_ret(component, ret);
11926374f493SKuninori Morimoto }
11936374f493SKuninori Morimoto 
11946374f493SKuninori Morimoto int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
11956374f493SKuninori Morimoto 				  int cmd, int rollback)
11966374f493SKuninori Morimoto {
11970ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
119832fd1204SKuninori Morimoto 	struct snd_soc_component *component;
11996374f493SKuninori Morimoto 	int i, r, ret = 0;
120032fd1204SKuninori Morimoto 
12016374f493SKuninori Morimoto 	switch (cmd) {
12026374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_START:
12036374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_RESUME:
12046374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
120532fd1204SKuninori Morimoto 		for_each_rtd_components(rtd, i, component) {
12066374f493SKuninori Morimoto 			ret = soc_component_trigger(component, substream, cmd);
120732fd1204SKuninori Morimoto 			if (ret < 0)
12086374f493SKuninori Morimoto 				break;
12096374f493SKuninori Morimoto 			soc_component_mark_push(component, substream, trigger);
12106374f493SKuninori Morimoto 		}
12116374f493SKuninori Morimoto 		break;
12126374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_STOP:
12136374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_SUSPEND:
12146374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
12156374f493SKuninori Morimoto 		for_each_rtd_components(rtd, i, component) {
12166374f493SKuninori Morimoto 			if (rollback && !soc_component_mark_match(component, substream, trigger))
12176374f493SKuninori Morimoto 				continue;
12186374f493SKuninori Morimoto 
12196374f493SKuninori Morimoto 			r = soc_component_trigger(component, substream, cmd);
12206374f493SKuninori Morimoto 			if (r < 0)
12216374f493SKuninori Morimoto 				ret = r; /* use last ret */
12226374f493SKuninori Morimoto 			soc_component_mark_pop(component, substream, trigger);
122332fd1204SKuninori Morimoto 		}
122432fd1204SKuninori Morimoto 	}
122532fd1204SKuninori Morimoto 
12266374f493SKuninori Morimoto 	return ret;
122732fd1204SKuninori Morimoto }
1228939a5cfbSKuninori Morimoto 
1229939a5cfbSKuninori Morimoto int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
1230939a5cfbSKuninori Morimoto 					 void *stream)
1231939a5cfbSKuninori Morimoto {
1232939a5cfbSKuninori Morimoto 	struct snd_soc_component *component;
1233500b39daSKuninori Morimoto 	int i;
1234939a5cfbSKuninori Morimoto 
1235939a5cfbSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
12360c72dbc9SPeter Ujfalusi 		int ret = pm_runtime_get_sync(component->dev);
12370c72dbc9SPeter Ujfalusi 		if (ret < 0 && ret != -EACCES) {
12380c72dbc9SPeter Ujfalusi 			pm_runtime_put_noidle(component->dev);
1239939a5cfbSKuninori Morimoto 			return soc_component_ret(component, ret);
12400c72dbc9SPeter Ujfalusi 		}
1241939a5cfbSKuninori Morimoto 		/* mark stream if succeeded */
1242939a5cfbSKuninori Morimoto 		soc_component_mark_push(component, stream, pm);
1243939a5cfbSKuninori Morimoto 	}
1244939a5cfbSKuninori Morimoto 
1245939a5cfbSKuninori Morimoto 	return 0;
1246939a5cfbSKuninori Morimoto }
1247939a5cfbSKuninori Morimoto 
1248939a5cfbSKuninori Morimoto void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
1249939a5cfbSKuninori Morimoto 					  void *stream, int rollback)
1250939a5cfbSKuninori Morimoto {
1251939a5cfbSKuninori Morimoto 	struct snd_soc_component *component;
1252939a5cfbSKuninori Morimoto 	int i;
1253939a5cfbSKuninori Morimoto 
1254939a5cfbSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1255939a5cfbSKuninori Morimoto 		if (rollback && !soc_component_mark_match(component, stream, pm))
1256939a5cfbSKuninori Morimoto 			continue;
1257939a5cfbSKuninori Morimoto 
1258939a5cfbSKuninori Morimoto 		pm_runtime_mark_last_busy(component->dev);
1259939a5cfbSKuninori Morimoto 		pm_runtime_put_autosuspend(component->dev);
1260939a5cfbSKuninori Morimoto 
1261939a5cfbSKuninori Morimoto 		/* remove marked stream */
1262939a5cfbSKuninori Morimoto 		soc_component_mark_pop(component, stream, pm);
1263939a5cfbSKuninori Morimoto 	}
1264939a5cfbSKuninori Morimoto }
12658bdfc045SShengjiu Wang 
12668bdfc045SShengjiu Wang int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream)
12678bdfc045SShengjiu Wang {
12688bdfc045SShengjiu Wang 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
12698bdfc045SShengjiu Wang 	struct snd_soc_component *component;
12708bdfc045SShengjiu Wang 	int i;
12718bdfc045SShengjiu Wang 
12728bdfc045SShengjiu Wang 	/* FIXME: use 1st pointer */
12738bdfc045SShengjiu Wang 	for_each_rtd_components(rtd, i, component)
12748bdfc045SShengjiu Wang 		if (component->driver->ack)
12758bdfc045SShengjiu Wang 			return component->driver->ack(component, substream);
12768bdfc045SShengjiu Wang 
12778bdfc045SShengjiu Wang 	return 0;
12788bdfc045SShengjiu Wang }
1279