xref: /openbmc/linux/sound/soc/soc-component.c (revision 76aca10c)
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)
_soc_component_ret(struct snd_soc_component * component,const char * func,int ret,int 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 
soc_component_field_shift(struct snd_soc_component * component,unsigned int mask)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 
snd_soc_component_set_aux(struct snd_soc_component * component,struct snd_soc_aux_dev * aux)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 
snd_soc_component_init(struct snd_soc_component * component)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  */
snd_soc_component_set_sysclk(struct snd_soc_component * component,int clk_id,int source,unsigned int freq,int dir)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  */
snd_soc_component_set_pll(struct snd_soc_component * component,int pll_id,int source,unsigned int freq_in,unsigned int freq_out)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 
snd_soc_component_seq_notifier(struct snd_soc_component * component,enum snd_soc_dapm_type type,int subseq)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 
snd_soc_component_stream_event(struct snd_soc_component * component,int event)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 
snd_soc_component_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)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 
snd_soc_component_enable_pin(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_enable_pin_unlocked(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_disable_pin(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_disable_pin_unlocked(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_nc_pin(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_nc_pin_unlocked(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_get_pin_status(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_force_enable_pin(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_force_enable_pin_unlocked(struct snd_soc_component * component,const char * pin)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 
snd_soc_component_notify_control(struct snd_soc_component * component,const char * const ctl)239ace9ed54SCharles Keepax int snd_soc_component_notify_control(struct snd_soc_component *component,
240ace9ed54SCharles Keepax 				     const char * const ctl)
241ace9ed54SCharles Keepax {
242ace9ed54SCharles Keepax 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
243ace9ed54SCharles Keepax 	struct snd_kcontrol *kctl;
244ace9ed54SCharles Keepax 
245*76aca10cSKrzysztof Kozlowski 	/* When updating, change also snd_soc_dapm_widget_name_cmp() */
246ace9ed54SCharles Keepax 	if (component->name_prefix)
247ace9ed54SCharles Keepax 		snprintf(name, ARRAY_SIZE(name), "%s %s", component->name_prefix, ctl);
248ace9ed54SCharles Keepax 	else
249ace9ed54SCharles Keepax 		snprintf(name, ARRAY_SIZE(name), "%s", ctl);
250ace9ed54SCharles Keepax 
251ace9ed54SCharles Keepax 	kctl = snd_soc_card_get_kcontrol(component->card, name);
252ace9ed54SCharles Keepax 	if (!kctl)
253ace9ed54SCharles Keepax 		return soc_component_ret(component, -EINVAL);
254ace9ed54SCharles Keepax 
255ace9ed54SCharles Keepax 	snd_ctl_notify(component->card->snd_card,
256ace9ed54SCharles Keepax 		       SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
257ace9ed54SCharles Keepax 
258ace9ed54SCharles Keepax 	return 0;
259ace9ed54SCharles Keepax }
260ace9ed54SCharles Keepax EXPORT_SYMBOL_GPL(snd_soc_component_notify_control);
261ace9ed54SCharles Keepax 
2624ff1fef1SKuninori Morimoto /**
2634ff1fef1SKuninori Morimoto  * snd_soc_component_set_jack - configure component jack.
2644ff1fef1SKuninori Morimoto  * @component: COMPONENTs
2654ff1fef1SKuninori Morimoto  * @jack: structure to use for the jack
2664ff1fef1SKuninori Morimoto  * @data: can be used if codec driver need extra data for configuring jack
2674ff1fef1SKuninori Morimoto  *
2684ff1fef1SKuninori Morimoto  * Configures and enables jack detection function.
2694ff1fef1SKuninori Morimoto  */
snd_soc_component_set_jack(struct snd_soc_component * component,struct snd_soc_jack * jack,void * data)2704ff1fef1SKuninori Morimoto int snd_soc_component_set_jack(struct snd_soc_component *component,
2714ff1fef1SKuninori Morimoto 			       struct snd_soc_jack *jack, void *data)
2724ff1fef1SKuninori Morimoto {
273e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
2744ff1fef1SKuninori Morimoto 
275e2329eebSKuninori Morimoto 	if (component->driver->set_jack)
276e2329eebSKuninori Morimoto 		ret = component->driver->set_jack(component, jack, data);
277e2329eebSKuninori Morimoto 
278e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
2794ff1fef1SKuninori Morimoto }
2804ff1fef1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
2814a81e8f3SKuninori Morimoto 
282df55122bSAstrid Rost /**
283df55122bSAstrid Rost  * snd_soc_component_get_jack_type
284df55122bSAstrid Rost  * @component: COMPONENTs
285df55122bSAstrid Rost  *
286df55122bSAstrid Rost  * Returns the jack type of the component
287df55122bSAstrid Rost  * This can either be the supported type or one read from
288df55122bSAstrid Rost  * devicetree with the property: jack-type.
289df55122bSAstrid Rost  */
snd_soc_component_get_jack_type(struct snd_soc_component * component)290df55122bSAstrid Rost int snd_soc_component_get_jack_type(
291df55122bSAstrid Rost 	struct snd_soc_component *component)
292df55122bSAstrid Rost {
293df55122bSAstrid Rost 	int ret = -ENOTSUPP;
294df55122bSAstrid Rost 
295df55122bSAstrid Rost 	if (component->driver->get_jack_type)
296df55122bSAstrid Rost 		ret = component->driver->get_jack_type(component);
297df55122bSAstrid Rost 
298df55122bSAstrid Rost 	return soc_component_ret(component, ret);
299df55122bSAstrid Rost }
300df55122bSAstrid Rost EXPORT_SYMBOL_GPL(snd_soc_component_get_jack_type);
301df55122bSAstrid Rost 
snd_soc_component_module_get(struct snd_soc_component * component,void * mark,int upon_open)3024a81e8f3SKuninori Morimoto int snd_soc_component_module_get(struct snd_soc_component *component,
303a739fdc2SPeter Ujfalusi 				 void *mark, int upon_open)
3044a81e8f3SKuninori Morimoto {
305e2329eebSKuninori Morimoto 	int ret = 0;
306e2329eebSKuninori Morimoto 
3074a81e8f3SKuninori Morimoto 	if (component->driver->module_get_upon_open == !!upon_open &&
3084a81e8f3SKuninori Morimoto 	    !try_module_get(component->dev->driver->owner))
309e2329eebSKuninori Morimoto 		ret = -ENODEV;
3104a81e8f3SKuninori Morimoto 
311a739fdc2SPeter Ujfalusi 	/* mark module if succeeded */
31251aff91aSKuninori Morimoto 	if (ret == 0)
313a739fdc2SPeter Ujfalusi 		soc_component_mark_push(component, mark, module);
31451aff91aSKuninori Morimoto 
315e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
3164a81e8f3SKuninori Morimoto }
3174a81e8f3SKuninori Morimoto 
snd_soc_component_module_put(struct snd_soc_component * component,void * mark,int upon_open,int rollback)3184a81e8f3SKuninori Morimoto void snd_soc_component_module_put(struct snd_soc_component *component,
319a739fdc2SPeter Ujfalusi 				  void *mark, int upon_open, int rollback)
3204a81e8f3SKuninori Morimoto {
321a739fdc2SPeter Ujfalusi 	if (rollback && !soc_component_mark_match(component, mark, module))
32251aff91aSKuninori Morimoto 		return;
32351aff91aSKuninori Morimoto 
3244a81e8f3SKuninori Morimoto 	if (component->driver->module_get_upon_open == !!upon_open)
3254a81e8f3SKuninori Morimoto 		module_put(component->dev->driver->owner);
32651aff91aSKuninori Morimoto 
327a739fdc2SPeter Ujfalusi 	/* remove the mark from module */
328a739fdc2SPeter Ujfalusi 	soc_component_mark_pop(component, mark, module);
3294a81e8f3SKuninori Morimoto }
330ae2f4849SKuninori Morimoto 
snd_soc_component_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)331ae2f4849SKuninori Morimoto int snd_soc_component_open(struct snd_soc_component *component,
332ae2f4849SKuninori Morimoto 			   struct snd_pcm_substream *substream)
333ae2f4849SKuninori Morimoto {
334e2329eebSKuninori Morimoto 	int ret = 0;
335e2329eebSKuninori Morimoto 
336e2cb4a14SKuninori Morimoto 	if (component->driver->open)
337e2329eebSKuninori Morimoto 		ret = component->driver->open(component, substream);
338e2329eebSKuninori Morimoto 
33951aff91aSKuninori Morimoto 	/* mark substream if succeeded */
34051aff91aSKuninori Morimoto 	if (ret == 0)
34151aff91aSKuninori Morimoto 		soc_component_mark_push(component, substream, open);
34251aff91aSKuninori Morimoto 
343e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
344ae2f4849SKuninori Morimoto }
3453672beb8SKuninori Morimoto 
snd_soc_component_close(struct snd_soc_component * component,struct snd_pcm_substream * substream,int rollback)3463672beb8SKuninori Morimoto int snd_soc_component_close(struct snd_soc_component *component,
34751aff91aSKuninori Morimoto 			    struct snd_pcm_substream *substream,
34851aff91aSKuninori Morimoto 			    int rollback)
3493672beb8SKuninori Morimoto {
350e2329eebSKuninori Morimoto 	int ret = 0;
351e2329eebSKuninori Morimoto 
35251aff91aSKuninori Morimoto 	if (rollback && !soc_component_mark_match(component, substream, open))
35351aff91aSKuninori Morimoto 		return 0;
35451aff91aSKuninori Morimoto 
355e2cb4a14SKuninori Morimoto 	if (component->driver->close)
356e2329eebSKuninori Morimoto 		ret = component->driver->close(component, substream);
357e2329eebSKuninori Morimoto 
35851aff91aSKuninori Morimoto 	/* remove marked substream */
35951aff91aSKuninori Morimoto 	soc_component_mark_pop(component, substream, open);
36051aff91aSKuninori Morimoto 
361e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
3623672beb8SKuninori Morimoto }
3636d537233SKuninori Morimoto 
snd_soc_component_suspend(struct snd_soc_component * component)36466c51573SKuninori Morimoto void snd_soc_component_suspend(struct snd_soc_component *component)
36566c51573SKuninori Morimoto {
36666c51573SKuninori Morimoto 	if (component->driver->suspend)
36766c51573SKuninori Morimoto 		component->driver->suspend(component);
36866c51573SKuninori Morimoto 	component->suspended = 1;
36966c51573SKuninori Morimoto }
3709a840cbaSKuninori Morimoto 
snd_soc_component_resume(struct snd_soc_component * component)3719a840cbaSKuninori Morimoto void snd_soc_component_resume(struct snd_soc_component *component)
3729a840cbaSKuninori Morimoto {
3739a840cbaSKuninori Morimoto 	if (component->driver->resume)
3749a840cbaSKuninori Morimoto 		component->driver->resume(component);
3759a840cbaSKuninori Morimoto 	component->suspended = 0;
3769a840cbaSKuninori Morimoto }
377e40fadbcSKuninori Morimoto 
snd_soc_component_is_suspended(struct snd_soc_component * component)378e40fadbcSKuninori Morimoto int snd_soc_component_is_suspended(struct snd_soc_component *component)
379e40fadbcSKuninori Morimoto {
380e40fadbcSKuninori Morimoto 	return component->suspended;
381e40fadbcSKuninori Morimoto }
38208e837ddSKuninori Morimoto 
snd_soc_component_probe(struct snd_soc_component * component)38308e837ddSKuninori Morimoto int snd_soc_component_probe(struct snd_soc_component *component)
38408e837ddSKuninori Morimoto {
385e2329eebSKuninori Morimoto 	int ret = 0;
38608e837ddSKuninori Morimoto 
387e2329eebSKuninori Morimoto 	if (component->driver->probe)
388e2329eebSKuninori Morimoto 		ret = component->driver->probe(component);
389e2329eebSKuninori Morimoto 
390e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
39108e837ddSKuninori Morimoto }
39203b34dd7SKuninori Morimoto 
snd_soc_component_remove(struct snd_soc_component * component)39303b34dd7SKuninori Morimoto void snd_soc_component_remove(struct snd_soc_component *component)
39403b34dd7SKuninori Morimoto {
39503b34dd7SKuninori Morimoto 	if (component->driver->remove)
39603b34dd7SKuninori Morimoto 		component->driver->remove(component);
39703b34dd7SKuninori Morimoto }
3982c7b1704SKuninori Morimoto 
snd_soc_component_of_xlate_dai_id(struct snd_soc_component * component,struct device_node * ep)3992c7b1704SKuninori Morimoto int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component,
4002c7b1704SKuninori Morimoto 				      struct device_node *ep)
4012c7b1704SKuninori Morimoto {
402e2329eebSKuninori Morimoto 	int ret = -ENOTSUPP;
4032c7b1704SKuninori Morimoto 
404e2329eebSKuninori Morimoto 	if (component->driver->of_xlate_dai_id)
405e2329eebSKuninori Morimoto 		ret = component->driver->of_xlate_dai_id(component, ep);
406e2329eebSKuninori Morimoto 
407e2329eebSKuninori Morimoto 	return soc_component_ret(component, ret);
4082c7b1704SKuninori Morimoto }
409a2a34175SKuninori Morimoto 
snd_soc_component_of_xlate_dai_name(struct snd_soc_component * component,const struct of_phandle_args * args,const char ** dai_name)410a2a34175SKuninori Morimoto int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component,
411933f98beSKrzysztof Kozlowski 					const struct of_phandle_args *args,
412a2a34175SKuninori Morimoto 					const char **dai_name)
413a2a34175SKuninori Morimoto {
414a2a34175SKuninori Morimoto 	if (component->driver->of_xlate_dai_name)
415cc4d8cebSJerome Brunet 		return component->driver->of_xlate_dai_name(component,
416a2a34175SKuninori Morimoto 							    args, dai_name);
417cc4d8cebSJerome Brunet 	/*
418cc4d8cebSJerome Brunet 	 * Don't use soc_component_ret here because we may not want to report
419cc4d8cebSJerome Brunet 	 * the error just yet. If a device has more than one component, the
420cc4d8cebSJerome Brunet 	 * first may not match and we don't want spam the log with this.
421cc4d8cebSJerome Brunet 	 */
422cc4d8cebSJerome Brunet 	return -ENOTSUPP;
423a2a34175SKuninori Morimoto }
4240035e256SKuninori Morimoto 
snd_soc_component_setup_regmap(struct snd_soc_component * component)425c7d75b59SKuninori Morimoto void snd_soc_component_setup_regmap(struct snd_soc_component *component)
426c7d75b59SKuninori Morimoto {
427c7d75b59SKuninori Morimoto 	int val_bytes = regmap_get_val_bytes(component->regmap);
428c7d75b59SKuninori Morimoto 
429c7d75b59SKuninori Morimoto 	/* Errors are legitimate for non-integer byte multiples */
430c7d75b59SKuninori Morimoto 	if (val_bytes > 0)
431c7d75b59SKuninori Morimoto 		component->val_bytes = val_bytes;
432c7d75b59SKuninori Morimoto }
433c7d75b59SKuninori Morimoto 
434c7d75b59SKuninori Morimoto #ifdef CONFIG_REGMAP
435c7d75b59SKuninori Morimoto 
436c7d75b59SKuninori Morimoto /**
437c7d75b59SKuninori Morimoto  * snd_soc_component_init_regmap() - Initialize regmap instance for the
438c7d75b59SKuninori Morimoto  *                                   component
439c7d75b59SKuninori Morimoto  * @component: The component for which to initialize the regmap instance
440c7d75b59SKuninori Morimoto  * @regmap: The regmap instance that should be used by the component
441c7d75b59SKuninori Morimoto  *
442c7d75b59SKuninori Morimoto  * This function allows deferred assignment of the regmap instance that is
443c7d75b59SKuninori Morimoto  * associated with the component. Only use this if the regmap instance is not
444c7d75b59SKuninori Morimoto  * yet ready when the component is registered. The function must also be called
445c7d75b59SKuninori Morimoto  * before the first IO attempt of the component.
446c7d75b59SKuninori Morimoto  */
snd_soc_component_init_regmap(struct snd_soc_component * component,struct regmap * regmap)447c7d75b59SKuninori Morimoto void snd_soc_component_init_regmap(struct snd_soc_component *component,
448c7d75b59SKuninori Morimoto 				   struct regmap *regmap)
449c7d75b59SKuninori Morimoto {
450c7d75b59SKuninori Morimoto 	component->regmap = regmap;
451c7d75b59SKuninori Morimoto 	snd_soc_component_setup_regmap(component);
452c7d75b59SKuninori Morimoto }
453c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap);
454c7d75b59SKuninori Morimoto 
455c7d75b59SKuninori Morimoto /**
456c7d75b59SKuninori Morimoto  * snd_soc_component_exit_regmap() - De-initialize regmap instance for the
457c7d75b59SKuninori Morimoto  *                                   component
458c7d75b59SKuninori Morimoto  * @component: The component for which to de-initialize the regmap instance
459c7d75b59SKuninori Morimoto  *
460c7d75b59SKuninori Morimoto  * Calls regmap_exit() on the regmap instance associated to the component and
461c7d75b59SKuninori Morimoto  * removes the regmap instance from the component.
462c7d75b59SKuninori Morimoto  *
463c7d75b59SKuninori Morimoto  * This function should only be used if snd_soc_component_init_regmap() was used
464c7d75b59SKuninori Morimoto  * to initialize the regmap instance.
465c7d75b59SKuninori Morimoto  */
snd_soc_component_exit_regmap(struct snd_soc_component * component)466c7d75b59SKuninori Morimoto void snd_soc_component_exit_regmap(struct snd_soc_component *component)
467c7d75b59SKuninori Morimoto {
468c7d75b59SKuninori Morimoto 	regmap_exit(component->regmap);
469c7d75b59SKuninori Morimoto 	component->regmap = NULL;
470c7d75b59SKuninori Morimoto }
471c7d75b59SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
472c7d75b59SKuninori Morimoto 
473c7d75b59SKuninori Morimoto #endif
474c7d75b59SKuninori Morimoto 
snd_soc_component_compr_open(struct snd_soc_component * component,struct snd_compr_stream * cstream)475cd46f382SPeter Ujfalusi int snd_soc_component_compr_open(struct snd_soc_component *component,
476cd46f382SPeter Ujfalusi 				 struct snd_compr_stream *cstream)
477a4e427c5SKuninori Morimoto {
478cd46f382SPeter Ujfalusi 	int ret = 0;
479a4e427c5SKuninori Morimoto 
480a4e427c5SKuninori Morimoto 	if (component->driver->compress_ops &&
481cd46f382SPeter Ujfalusi 	    component->driver->compress_ops->open)
482a4e427c5SKuninori Morimoto 		ret = component->driver->compress_ops->open(component, cstream);
483a4e427c5SKuninori Morimoto 
484cd46f382SPeter Ujfalusi 	/* mark substream if succeeded */
485cd46f382SPeter Ujfalusi 	if (ret == 0)
486cd46f382SPeter Ujfalusi 		soc_component_mark_push(component, cstream, compr_open);
487cd46f382SPeter Ujfalusi 
488cd46f382SPeter Ujfalusi 	return soc_component_ret(component, ret);
489a4e427c5SKuninori Morimoto }
490a4e427c5SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_open);
491a4e427c5SKuninori Morimoto 
snd_soc_component_compr_free(struct snd_soc_component * component,struct snd_compr_stream * cstream,int rollback)492cd46f382SPeter Ujfalusi void snd_soc_component_compr_free(struct snd_soc_component *component,
493cd46f382SPeter Ujfalusi 				  struct snd_compr_stream *cstream,
494f94ba9acSKuninori Morimoto 				  int rollback)
495dbde5e21SKuninori Morimoto {
496f94ba9acSKuninori Morimoto 	if (rollback && !soc_component_mark_match(component, cstream, compr_open))
497cd46f382SPeter Ujfalusi 		return;
498dbde5e21SKuninori Morimoto 
499dbde5e21SKuninori Morimoto 	if (component->driver->compress_ops &&
500dbde5e21SKuninori Morimoto 	    component->driver->compress_ops->free)
501dbde5e21SKuninori Morimoto 		component->driver->compress_ops->free(component, cstream);
502f94ba9acSKuninori Morimoto 
503cd46f382SPeter Ujfalusi 	/* remove marked substream */
504f94ba9acSKuninori Morimoto 	soc_component_mark_pop(component, cstream, compr_open);
505dbde5e21SKuninori Morimoto }
506dbde5e21SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_free);
507dbde5e21SKuninori Morimoto 
snd_soc_component_compr_trigger(struct snd_compr_stream * cstream,int cmd)50808aee251SKuninori Morimoto int snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd)
50908aee251SKuninori Morimoto {
51008aee251SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
51108aee251SKuninori Morimoto 	struct snd_soc_component *component;
51208aee251SKuninori Morimoto 	int i, ret;
51308aee251SKuninori Morimoto 
51408aee251SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
51508aee251SKuninori Morimoto 		if (component->driver->compress_ops &&
51608aee251SKuninori Morimoto 		    component->driver->compress_ops->trigger) {
51708aee251SKuninori Morimoto 			ret = component->driver->compress_ops->trigger(
51808aee251SKuninori Morimoto 				component, cstream, cmd);
51908aee251SKuninori Morimoto 			if (ret < 0)
52008aee251SKuninori Morimoto 				return soc_component_ret(component, ret);
52108aee251SKuninori Morimoto 		}
52208aee251SKuninori Morimoto 	}
52308aee251SKuninori Morimoto 
52408aee251SKuninori Morimoto 	return 0;
52508aee251SKuninori Morimoto }
52608aee251SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_trigger);
52708aee251SKuninori Morimoto 
snd_soc_component_compr_set_params(struct snd_compr_stream * cstream,struct snd_compr_params * params)528ff08cf80SKuninori Morimoto int snd_soc_component_compr_set_params(struct snd_compr_stream *cstream,
529ff08cf80SKuninori Morimoto 				       struct snd_compr_params *params)
530ff08cf80SKuninori Morimoto {
531ff08cf80SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
532ff08cf80SKuninori Morimoto 	struct snd_soc_component *component;
533ff08cf80SKuninori Morimoto 	int i, ret;
534ff08cf80SKuninori Morimoto 
535ff08cf80SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
536ff08cf80SKuninori Morimoto 		if (component->driver->compress_ops &&
537ff08cf80SKuninori Morimoto 		    component->driver->compress_ops->set_params) {
538ff08cf80SKuninori Morimoto 			ret = component->driver->compress_ops->set_params(
539ff08cf80SKuninori Morimoto 				component, cstream, params);
540ff08cf80SKuninori Morimoto 			if (ret < 0)
541ff08cf80SKuninori Morimoto 				return soc_component_ret(component, ret);
542ff08cf80SKuninori Morimoto 		}
543ff08cf80SKuninori Morimoto 	}
544ff08cf80SKuninori Morimoto 
545ff08cf80SKuninori Morimoto 	return 0;
546ff08cf80SKuninori Morimoto }
547ff08cf80SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_params);
548ff08cf80SKuninori Morimoto 
snd_soc_component_compr_get_params(struct snd_compr_stream * cstream,struct snd_codec * params)54977c221ecSKuninori Morimoto int snd_soc_component_compr_get_params(struct snd_compr_stream *cstream,
55077c221ecSKuninori Morimoto 				       struct snd_codec *params)
55177c221ecSKuninori Morimoto {
55277c221ecSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
55377c221ecSKuninori Morimoto 	struct snd_soc_component *component;
55477c221ecSKuninori Morimoto 	int i, ret;
55577c221ecSKuninori Morimoto 
55677c221ecSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
55777c221ecSKuninori Morimoto 		if (component->driver->compress_ops &&
55877c221ecSKuninori Morimoto 		    component->driver->compress_ops->get_params) {
55977c221ecSKuninori Morimoto 			ret = component->driver->compress_ops->get_params(
56077c221ecSKuninori Morimoto 				component, cstream, params);
56177c221ecSKuninori Morimoto 			return soc_component_ret(component, ret);
56277c221ecSKuninori Morimoto 		}
56377c221ecSKuninori Morimoto 	}
56477c221ecSKuninori Morimoto 
56577c221ecSKuninori Morimoto 	return 0;
56677c221ecSKuninori Morimoto }
56777c221ecSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_params);
56877c221ecSKuninori Morimoto 
snd_soc_component_compr_get_caps(struct snd_compr_stream * cstream,struct snd_compr_caps * caps)569d67fcb2dSKuninori Morimoto int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream,
570d67fcb2dSKuninori Morimoto 				     struct snd_compr_caps *caps)
571d67fcb2dSKuninori Morimoto {
572d67fcb2dSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
573d67fcb2dSKuninori Morimoto 	struct snd_soc_component *component;
574d67fcb2dSKuninori Morimoto 	int i, ret = 0;
575d67fcb2dSKuninori Morimoto 
57638e42f6dSKuninori Morimoto 	snd_soc_dpcm_mutex_lock(rtd);
577d67fcb2dSKuninori Morimoto 
578d67fcb2dSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
579d67fcb2dSKuninori Morimoto 		if (component->driver->compress_ops &&
580d67fcb2dSKuninori Morimoto 		    component->driver->compress_ops->get_caps) {
581d67fcb2dSKuninori Morimoto 			ret = component->driver->compress_ops->get_caps(
582d67fcb2dSKuninori Morimoto 				component, cstream, caps);
583d67fcb2dSKuninori Morimoto 			break;
584d67fcb2dSKuninori Morimoto 		}
585d67fcb2dSKuninori Morimoto 	}
586d67fcb2dSKuninori Morimoto 
58738e42f6dSKuninori Morimoto 	snd_soc_dpcm_mutex_unlock(rtd);
588d67fcb2dSKuninori Morimoto 
589d67fcb2dSKuninori Morimoto 	return soc_component_ret(component, ret);
590d67fcb2dSKuninori Morimoto }
591d67fcb2dSKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_caps);
592d67fcb2dSKuninori Morimoto 
snd_soc_component_compr_get_codec_caps(struct snd_compr_stream * cstream,struct snd_compr_codec_caps * codec)5930f6fe097SKuninori Morimoto int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream,
5940f6fe097SKuninori Morimoto 					   struct snd_compr_codec_caps *codec)
5950f6fe097SKuninori Morimoto {
5960f6fe097SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5970f6fe097SKuninori Morimoto 	struct snd_soc_component *component;
5980f6fe097SKuninori Morimoto 	int i, ret = 0;
5990f6fe097SKuninori Morimoto 
60038e42f6dSKuninori Morimoto 	snd_soc_dpcm_mutex_lock(rtd);
6010f6fe097SKuninori Morimoto 
6020f6fe097SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
6030f6fe097SKuninori Morimoto 		if (component->driver->compress_ops &&
6040f6fe097SKuninori Morimoto 		    component->driver->compress_ops->get_codec_caps) {
6050f6fe097SKuninori Morimoto 			ret = component->driver->compress_ops->get_codec_caps(
6060f6fe097SKuninori Morimoto 				component, cstream, codec);
6070f6fe097SKuninori Morimoto 			break;
6080f6fe097SKuninori Morimoto 		}
6090f6fe097SKuninori Morimoto 	}
6100f6fe097SKuninori Morimoto 
61138e42f6dSKuninori Morimoto 	snd_soc_dpcm_mutex_unlock(rtd);
6120f6fe097SKuninori Morimoto 
6130f6fe097SKuninori Morimoto 	return soc_component_ret(component, ret);
6140f6fe097SKuninori Morimoto }
6150f6fe097SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_codec_caps);
6160f6fe097SKuninori Morimoto 
snd_soc_component_compr_ack(struct snd_compr_stream * cstream,size_t bytes)6170506b885SKuninori Morimoto int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
6180506b885SKuninori Morimoto {
6190506b885SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
6200506b885SKuninori Morimoto 	struct snd_soc_component *component;
6210506b885SKuninori Morimoto 	int i, ret;
6220506b885SKuninori Morimoto 
6230506b885SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
6240506b885SKuninori Morimoto 		if (component->driver->compress_ops &&
6250506b885SKuninori Morimoto 		    component->driver->compress_ops->ack) {
6260506b885SKuninori Morimoto 			ret = component->driver->compress_ops->ack(
6270506b885SKuninori Morimoto 				component, cstream, bytes);
6280506b885SKuninori Morimoto 			if (ret < 0)
6290506b885SKuninori Morimoto 				return soc_component_ret(component, ret);
6300506b885SKuninori Morimoto 		}
6310506b885SKuninori Morimoto 	}
6320506b885SKuninori Morimoto 
6330506b885SKuninori Morimoto 	return 0;
6340506b885SKuninori Morimoto }
6350506b885SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack);
6360506b885SKuninori Morimoto 
snd_soc_component_compr_pointer(struct snd_compr_stream * cstream,struct snd_compr_tstamp * tstamp)63703ecea64SKuninori Morimoto int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream,
63803ecea64SKuninori Morimoto 				    struct snd_compr_tstamp *tstamp)
63903ecea64SKuninori Morimoto {
64003ecea64SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
64103ecea64SKuninori Morimoto 	struct snd_soc_component *component;
64203ecea64SKuninori Morimoto 	int i, ret;
64303ecea64SKuninori Morimoto 
64403ecea64SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
64503ecea64SKuninori Morimoto 		if (component->driver->compress_ops &&
64603ecea64SKuninori Morimoto 		    component->driver->compress_ops->pointer) {
64703ecea64SKuninori Morimoto 			ret = component->driver->compress_ops->pointer(
64803ecea64SKuninori Morimoto 				component, cstream, tstamp);
64903ecea64SKuninori Morimoto 			return soc_component_ret(component, ret);
65003ecea64SKuninori Morimoto 		}
65103ecea64SKuninori Morimoto 	}
65203ecea64SKuninori Morimoto 
65303ecea64SKuninori Morimoto 	return 0;
65403ecea64SKuninori Morimoto }
65503ecea64SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_pointer);
65603ecea64SKuninori Morimoto 
snd_soc_component_compr_copy(struct snd_compr_stream * cstream,char __user * buf,size_t count)657b5852e66SKuninori Morimoto int snd_soc_component_compr_copy(struct snd_compr_stream *cstream,
658b5852e66SKuninori Morimoto 				 char __user *buf, size_t count)
659b5852e66SKuninori Morimoto {
660b5852e66SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
661b5852e66SKuninori Morimoto 	struct snd_soc_component *component;
662b5852e66SKuninori Morimoto 	int i, ret = 0;
663b5852e66SKuninori Morimoto 
66438e42f6dSKuninori Morimoto 	snd_soc_dpcm_mutex_lock(rtd);
665b5852e66SKuninori Morimoto 
666b5852e66SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
667b5852e66SKuninori Morimoto 		if (component->driver->compress_ops &&
668b5852e66SKuninori Morimoto 		    component->driver->compress_ops->copy) {
669b5852e66SKuninori Morimoto 			ret = component->driver->compress_ops->copy(
670b5852e66SKuninori Morimoto 				component, cstream, buf, count);
671b5852e66SKuninori Morimoto 			break;
672b5852e66SKuninori Morimoto 		}
673b5852e66SKuninori Morimoto 	}
674b5852e66SKuninori Morimoto 
67538e42f6dSKuninori Morimoto 	snd_soc_dpcm_mutex_unlock(rtd);
676b5852e66SKuninori Morimoto 
677b5852e66SKuninori Morimoto 	return soc_component_ret(component, ret);
678b5852e66SKuninori Morimoto }
679b5852e66SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_copy);
680b5852e66SKuninori Morimoto 
snd_soc_component_compr_set_metadata(struct snd_compr_stream * cstream,struct snd_compr_metadata * metadata)6811b308fb1SKuninori Morimoto int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream,
6821b308fb1SKuninori Morimoto 					 struct snd_compr_metadata *metadata)
6831b308fb1SKuninori Morimoto {
6841b308fb1SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
6851b308fb1SKuninori Morimoto 	struct snd_soc_component *component;
6861b308fb1SKuninori Morimoto 	int i, ret;
6871b308fb1SKuninori Morimoto 
6881b308fb1SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
6891b308fb1SKuninori Morimoto 		if (component->driver->compress_ops &&
6901b308fb1SKuninori Morimoto 		    component->driver->compress_ops->set_metadata) {
6911b308fb1SKuninori Morimoto 			ret = component->driver->compress_ops->set_metadata(
6921b308fb1SKuninori Morimoto 				component, cstream, metadata);
6931b308fb1SKuninori Morimoto 			if (ret < 0)
6941b308fb1SKuninori Morimoto 				return soc_component_ret(component, ret);
6951b308fb1SKuninori Morimoto 		}
6961b308fb1SKuninori Morimoto 	}
6971b308fb1SKuninori Morimoto 
6981b308fb1SKuninori Morimoto 	return 0;
6991b308fb1SKuninori Morimoto }
7001b308fb1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_metadata);
7011b308fb1SKuninori Morimoto 
snd_soc_component_compr_get_metadata(struct snd_compr_stream * cstream,struct snd_compr_metadata * metadata)702bab78c23SKuninori Morimoto int snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream,
703bab78c23SKuninori Morimoto 					 struct snd_compr_metadata *metadata)
704bab78c23SKuninori Morimoto {
705bab78c23SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
706bab78c23SKuninori Morimoto 	struct snd_soc_component *component;
707bab78c23SKuninori Morimoto 	int i, ret;
708bab78c23SKuninori Morimoto 
709bab78c23SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
710bab78c23SKuninori Morimoto 		if (component->driver->compress_ops &&
711bab78c23SKuninori Morimoto 		    component->driver->compress_ops->get_metadata) {
712bab78c23SKuninori Morimoto 			ret = component->driver->compress_ops->get_metadata(
713bab78c23SKuninori Morimoto 				component, cstream, metadata);
714bab78c23SKuninori Morimoto 			return soc_component_ret(component, ret);
715bab78c23SKuninori Morimoto 		}
716bab78c23SKuninori Morimoto 	}
717bab78c23SKuninori Morimoto 
718bab78c23SKuninori Morimoto 	return 0;
719bab78c23SKuninori Morimoto }
720bab78c23SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_metadata);
721bab78c23SKuninori Morimoto 
soc_component_read_no_lock(struct snd_soc_component * component,unsigned int reg)722e8712315SKuninori Morimoto static unsigned int soc_component_read_no_lock(
723e8712315SKuninori Morimoto 	struct snd_soc_component *component,
724cf6e26c7SKuninori Morimoto 	unsigned int reg)
725460b42d1SKuninori Morimoto {
726460b42d1SKuninori Morimoto 	int ret;
727cf6e26c7SKuninori Morimoto 	unsigned int val = 0;
728460b42d1SKuninori Morimoto 
729460b42d1SKuninori Morimoto 	if (component->regmap)
730cf6e26c7SKuninori Morimoto 		ret = regmap_read(component->regmap, reg, &val);
731460b42d1SKuninori Morimoto 	else if (component->driver->read) {
732460b42d1SKuninori Morimoto 		ret = 0;
733cf6e26c7SKuninori Morimoto 		val = component->driver->read(component, reg);
734460b42d1SKuninori Morimoto 	}
735460b42d1SKuninori Morimoto 	else
736460b42d1SKuninori Morimoto 		ret = -EIO;
737460b42d1SKuninori Morimoto 
738460b42d1SKuninori Morimoto 	if (ret < 0)
739b296997cSSrinivas Kandagatla 		return soc_component_ret_reg_rw(component, ret, reg);
740460b42d1SKuninori Morimoto 
741460b42d1SKuninori Morimoto 	return val;
742460b42d1SKuninori Morimoto }
743e8712315SKuninori Morimoto 
744e8712315SKuninori Morimoto /**
745e8712315SKuninori Morimoto  * snd_soc_component_read() - Read register value
746e8712315SKuninori Morimoto  * @component: Component to read from
747e8712315SKuninori Morimoto  * @reg: Register to read
748e8712315SKuninori Morimoto  *
749e8712315SKuninori Morimoto  * Return: read value
750e8712315SKuninori Morimoto  */
snd_soc_component_read(struct snd_soc_component * component,unsigned int reg)751e8712315SKuninori Morimoto unsigned int snd_soc_component_read(struct snd_soc_component *component,
752e8712315SKuninori Morimoto 				    unsigned int reg)
753e8712315SKuninori Morimoto {
754e8712315SKuninori Morimoto 	unsigned int val;
755e8712315SKuninori Morimoto 
756e8712315SKuninori Morimoto 	mutex_lock(&component->io_mutex);
757e8712315SKuninori Morimoto 	val = soc_component_read_no_lock(component, reg);
758e8712315SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
759e8712315SKuninori Morimoto 
760e8712315SKuninori Morimoto 	return val;
761e8712315SKuninori Morimoto }
762cf6e26c7SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_read);
763460b42d1SKuninori Morimoto 
soc_component_write_no_lock(struct snd_soc_component * component,unsigned int reg,unsigned int val)764e8712315SKuninori Morimoto static int soc_component_write_no_lock(
765e8712315SKuninori Morimoto 	struct snd_soc_component *component,
766e8712315SKuninori Morimoto 	unsigned int reg, unsigned int val)
767e8712315SKuninori Morimoto {
768e8712315SKuninori Morimoto 	int ret = -EIO;
769e8712315SKuninori Morimoto 
770e8712315SKuninori Morimoto 	if (component->regmap)
771e8712315SKuninori Morimoto 		ret = regmap_write(component->regmap, reg, val);
772e8712315SKuninori Morimoto 	else if (component->driver->write)
773e8712315SKuninori Morimoto 		ret = component->driver->write(component, reg, val);
774e8712315SKuninori Morimoto 
775b296997cSSrinivas Kandagatla 	return soc_component_ret_reg_rw(component, ret, reg);
776e8712315SKuninori Morimoto }
777e8712315SKuninori Morimoto 
778460b42d1SKuninori Morimoto /**
779460b42d1SKuninori Morimoto  * snd_soc_component_write() - Write register value
780460b42d1SKuninori Morimoto  * @component: Component to write to
781460b42d1SKuninori Morimoto  * @reg: Register to write
782460b42d1SKuninori Morimoto  * @val: Value to write to the register
783460b42d1SKuninori Morimoto  *
784460b42d1SKuninori Morimoto  * Return: 0 on success, a negative error code otherwise.
785460b42d1SKuninori Morimoto  */
snd_soc_component_write(struct snd_soc_component * component,unsigned int reg,unsigned int val)786460b42d1SKuninori Morimoto int snd_soc_component_write(struct snd_soc_component *component,
787460b42d1SKuninori Morimoto 			    unsigned int reg, unsigned int val)
788460b42d1SKuninori Morimoto {
789e8712315SKuninori Morimoto 	int ret;
790460b42d1SKuninori Morimoto 
791e8712315SKuninori Morimoto 	mutex_lock(&component->io_mutex);
792e8712315SKuninori Morimoto 	ret = soc_component_write_no_lock(component, reg, val);
793e8712315SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
794460b42d1SKuninori Morimoto 
795e8712315SKuninori Morimoto 	return ret;
796460b42d1SKuninori Morimoto }
797460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_write);
798460b42d1SKuninori Morimoto 
snd_soc_component_update_bits_legacy(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int val,bool * change)799460b42d1SKuninori Morimoto static int snd_soc_component_update_bits_legacy(
800460b42d1SKuninori Morimoto 	struct snd_soc_component *component, unsigned int reg,
801460b42d1SKuninori Morimoto 	unsigned int mask, unsigned int val, bool *change)
802460b42d1SKuninori Morimoto {
803460b42d1SKuninori Morimoto 	unsigned int old, new;
804cf6e26c7SKuninori Morimoto 	int ret = 0;
805460b42d1SKuninori Morimoto 
806460b42d1SKuninori Morimoto 	mutex_lock(&component->io_mutex);
807460b42d1SKuninori Morimoto 
808e8712315SKuninori Morimoto 	old = soc_component_read_no_lock(component, reg);
809460b42d1SKuninori Morimoto 
810460b42d1SKuninori Morimoto 	new = (old & ~mask) | (val & mask);
811460b42d1SKuninori Morimoto 	*change = old != new;
812460b42d1SKuninori Morimoto 	if (*change)
813e8712315SKuninori Morimoto 		ret = soc_component_write_no_lock(component, reg, new);
814cf6e26c7SKuninori Morimoto 
815460b42d1SKuninori Morimoto 	mutex_unlock(&component->io_mutex);
816460b42d1SKuninori Morimoto 
817b296997cSSrinivas Kandagatla 	return soc_component_ret_reg_rw(component, ret, reg);
818460b42d1SKuninori Morimoto }
819460b42d1SKuninori Morimoto 
820460b42d1SKuninori Morimoto /**
821460b42d1SKuninori Morimoto  * snd_soc_component_update_bits() - Perform read/modify/write cycle
822460b42d1SKuninori Morimoto  * @component: Component to update
823460b42d1SKuninori Morimoto  * @reg: Register to update
824460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to update
825460b42d1SKuninori Morimoto  * @val: New value for the bits specified by mask
826460b42d1SKuninori Morimoto  *
827460b42d1SKuninori Morimoto  * Return: 1 if the operation was successful and the value of the register
828460b42d1SKuninori Morimoto  * changed, 0 if the operation was successful, but the value did not change.
829460b42d1SKuninori Morimoto  * Returns a negative error code otherwise.
830460b42d1SKuninori Morimoto  */
snd_soc_component_update_bits(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int val)831460b42d1SKuninori Morimoto int snd_soc_component_update_bits(struct snd_soc_component *component,
832460b42d1SKuninori Morimoto 				  unsigned int reg, unsigned int mask, unsigned int val)
833460b42d1SKuninori Morimoto {
834460b42d1SKuninori Morimoto 	bool change;
835460b42d1SKuninori Morimoto 	int ret;
836460b42d1SKuninori Morimoto 
837460b42d1SKuninori Morimoto 	if (component->regmap)
838460b42d1SKuninori Morimoto 		ret = regmap_update_bits_check(component->regmap, reg, mask,
839460b42d1SKuninori Morimoto 					       val, &change);
840460b42d1SKuninori Morimoto 	else
841460b42d1SKuninori Morimoto 		ret = snd_soc_component_update_bits_legacy(component, reg,
842460b42d1SKuninori Morimoto 							   mask, val, &change);
843460b42d1SKuninori Morimoto 
844460b42d1SKuninori Morimoto 	if (ret < 0)
845b296997cSSrinivas Kandagatla 		return soc_component_ret_reg_rw(component, ret, reg);
846460b42d1SKuninori Morimoto 	return change;
847460b42d1SKuninori Morimoto }
848460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits);
849460b42d1SKuninori Morimoto 
850460b42d1SKuninori Morimoto /**
851460b42d1SKuninori Morimoto  * snd_soc_component_update_bits_async() - Perform asynchronous
852460b42d1SKuninori Morimoto  *  read/modify/write cycle
853460b42d1SKuninori Morimoto  * @component: Component to update
854460b42d1SKuninori Morimoto  * @reg: Register to update
855460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to update
856460b42d1SKuninori Morimoto  * @val: New value for the bits specified by mask
857460b42d1SKuninori Morimoto  *
858460b42d1SKuninori Morimoto  * This function is similar to snd_soc_component_update_bits(), but the update
859460b42d1SKuninori Morimoto  * operation is scheduled asynchronously. This means it may not be completed
860460b42d1SKuninori Morimoto  * when the function returns. To make sure that all scheduled updates have been
861460b42d1SKuninori Morimoto  * completed snd_soc_component_async_complete() must be called.
862460b42d1SKuninori Morimoto  *
863460b42d1SKuninori Morimoto  * Return: 1 if the operation was successful and the value of the register
864460b42d1SKuninori Morimoto  * changed, 0 if the operation was successful, but the value did not change.
865460b42d1SKuninori Morimoto  * Returns a negative error code otherwise.
866460b42d1SKuninori Morimoto  */
snd_soc_component_update_bits_async(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int val)867460b42d1SKuninori Morimoto int snd_soc_component_update_bits_async(struct snd_soc_component *component,
868460b42d1SKuninori Morimoto 					unsigned int reg, unsigned int mask, unsigned int val)
869460b42d1SKuninori Morimoto {
870460b42d1SKuninori Morimoto 	bool change;
871460b42d1SKuninori Morimoto 	int ret;
872460b42d1SKuninori Morimoto 
873460b42d1SKuninori Morimoto 	if (component->regmap)
874460b42d1SKuninori Morimoto 		ret = regmap_update_bits_check_async(component->regmap, reg,
875460b42d1SKuninori Morimoto 						     mask, val, &change);
876460b42d1SKuninori Morimoto 	else
877460b42d1SKuninori Morimoto 		ret = snd_soc_component_update_bits_legacy(component, reg,
878460b42d1SKuninori Morimoto 							   mask, val, &change);
879460b42d1SKuninori Morimoto 
880460b42d1SKuninori Morimoto 	if (ret < 0)
881b296997cSSrinivas Kandagatla 		return soc_component_ret_reg_rw(component, ret, reg);
882460b42d1SKuninori Morimoto 	return change;
883460b42d1SKuninori Morimoto }
884460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_update_bits_async);
885460b42d1SKuninori Morimoto 
886460b42d1SKuninori Morimoto /**
8871da0b989SSrinivas Kandagatla  * snd_soc_component_read_field() - Read register field value
8881da0b989SSrinivas Kandagatla  * @component: Component to read from
8891da0b989SSrinivas Kandagatla  * @reg: Register to read
8901da0b989SSrinivas Kandagatla  * @mask: mask of the register field
8911da0b989SSrinivas Kandagatla  *
8921da0b989SSrinivas Kandagatla  * Return: read value of register field.
8931da0b989SSrinivas Kandagatla  */
snd_soc_component_read_field(struct snd_soc_component * component,unsigned int reg,unsigned int mask)8941da0b989SSrinivas Kandagatla unsigned int snd_soc_component_read_field(struct snd_soc_component *component,
8951da0b989SSrinivas Kandagatla 					  unsigned int reg, unsigned int mask)
8961da0b989SSrinivas Kandagatla {
8971da0b989SSrinivas Kandagatla 	unsigned int val;
8981da0b989SSrinivas Kandagatla 
8991da0b989SSrinivas Kandagatla 	val = snd_soc_component_read(component, reg);
9001da0b989SSrinivas Kandagatla 
9011da0b989SSrinivas Kandagatla 	val = (val & mask) >> soc_component_field_shift(component, mask);
9021da0b989SSrinivas Kandagatla 
9031da0b989SSrinivas Kandagatla 	return val;
9041da0b989SSrinivas Kandagatla }
9051da0b989SSrinivas Kandagatla EXPORT_SYMBOL_GPL(snd_soc_component_read_field);
9061da0b989SSrinivas Kandagatla 
9071da0b989SSrinivas Kandagatla /**
9081da0b989SSrinivas Kandagatla  * snd_soc_component_write_field() - write to register field
9091da0b989SSrinivas Kandagatla  * @component: Component to write to
9101da0b989SSrinivas Kandagatla  * @reg: Register to write
9111da0b989SSrinivas Kandagatla  * @mask: mask of the register field to update
9121da0b989SSrinivas Kandagatla  * @val: value of the field to write
9131da0b989SSrinivas Kandagatla  *
9141da0b989SSrinivas Kandagatla  * Return: 1 for change, otherwise 0.
9151da0b989SSrinivas Kandagatla  */
snd_soc_component_write_field(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int val)9161da0b989SSrinivas Kandagatla int snd_soc_component_write_field(struct snd_soc_component *component,
9171da0b989SSrinivas Kandagatla 				  unsigned int reg, unsigned int mask,
9181da0b989SSrinivas Kandagatla 				  unsigned int val)
9191da0b989SSrinivas Kandagatla {
9201da0b989SSrinivas Kandagatla 
9211da0b989SSrinivas Kandagatla 	val = (val << soc_component_field_shift(component, mask)) & mask;
9221da0b989SSrinivas Kandagatla 
9231da0b989SSrinivas Kandagatla 	return snd_soc_component_update_bits(component, reg, mask, val);
9241da0b989SSrinivas Kandagatla }
9251da0b989SSrinivas Kandagatla EXPORT_SYMBOL_GPL(snd_soc_component_write_field);
9261da0b989SSrinivas Kandagatla 
9271da0b989SSrinivas Kandagatla /**
928460b42d1SKuninori Morimoto  * snd_soc_component_async_complete() - Ensure asynchronous I/O has completed
929460b42d1SKuninori Morimoto  * @component: Component for which to wait
930460b42d1SKuninori Morimoto  *
931460b42d1SKuninori Morimoto  * This function blocks until all asynchronous I/O which has previously been
932460b42d1SKuninori Morimoto  * scheduled using snd_soc_component_update_bits_async() has completed.
933460b42d1SKuninori Morimoto  */
snd_soc_component_async_complete(struct snd_soc_component * component)934460b42d1SKuninori Morimoto void snd_soc_component_async_complete(struct snd_soc_component *component)
935460b42d1SKuninori Morimoto {
936460b42d1SKuninori Morimoto 	if (component->regmap)
937460b42d1SKuninori Morimoto 		regmap_async_complete(component->regmap);
938460b42d1SKuninori Morimoto }
939460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_async_complete);
940460b42d1SKuninori Morimoto 
941460b42d1SKuninori Morimoto /**
942460b42d1SKuninori Morimoto  * snd_soc_component_test_bits - Test register for change
943460b42d1SKuninori Morimoto  * @component: component
944460b42d1SKuninori Morimoto  * @reg: Register to test
945460b42d1SKuninori Morimoto  * @mask: Mask that specifies which bits to test
946460b42d1SKuninori Morimoto  * @value: Value to test against
947460b42d1SKuninori Morimoto  *
948460b42d1SKuninori Morimoto  * Tests a register with a new value and checks if the new value is
949460b42d1SKuninori Morimoto  * different from the old value.
950460b42d1SKuninori Morimoto  *
951460b42d1SKuninori Morimoto  * Return: 1 for change, otherwise 0.
952460b42d1SKuninori Morimoto  */
snd_soc_component_test_bits(struct snd_soc_component * component,unsigned int reg,unsigned int mask,unsigned int value)953460b42d1SKuninori Morimoto int snd_soc_component_test_bits(struct snd_soc_component *component,
954460b42d1SKuninori Morimoto 				unsigned int reg, unsigned int mask, unsigned int value)
955460b42d1SKuninori Morimoto {
956460b42d1SKuninori Morimoto 	unsigned int old, new;
957460b42d1SKuninori Morimoto 
958cf6e26c7SKuninori Morimoto 	old = snd_soc_component_read(component, reg);
959460b42d1SKuninori Morimoto 	new = (old & ~mask) | value;
960460b42d1SKuninori Morimoto 	return old != new;
961460b42d1SKuninori Morimoto }
962460b42d1SKuninori Morimoto EXPORT_SYMBOL_GPL(snd_soc_component_test_bits);
963460b42d1SKuninori Morimoto 
snd_soc_pcm_component_pointer(struct snd_pcm_substream * substream)9640035e256SKuninori Morimoto int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
9650035e256SKuninori Morimoto {
9660ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
9670035e256SKuninori Morimoto 	struct snd_soc_component *component;
968613fb500SKuninori Morimoto 	int i;
9690035e256SKuninori Morimoto 
9700035e256SKuninori Morimoto 	/* FIXME: use 1st pointer */
971613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
972e2cb4a14SKuninori Morimoto 		if (component->driver->pointer)
973e2cb4a14SKuninori Morimoto 			return component->driver->pointer(component, substream);
9740035e256SKuninori Morimoto 
9750035e256SKuninori Morimoto 	return 0;
9760035e256SKuninori Morimoto }
97796a47908SKuninori Morimoto 
snd_soc_component_is_codec_on_rtd(struct snd_soc_pcm_runtime * rtd,struct snd_soc_component * component)978232213bdSCharles Keepax static bool snd_soc_component_is_codec_on_rtd(struct snd_soc_pcm_runtime *rtd,
979232213bdSCharles Keepax 					      struct snd_soc_component *component)
980232213bdSCharles Keepax {
981232213bdSCharles Keepax 	struct snd_soc_dai *dai;
982232213bdSCharles Keepax 	int i;
983232213bdSCharles Keepax 
984232213bdSCharles Keepax 	for_each_rtd_codec_dais(rtd, i, dai) {
985232213bdSCharles Keepax 		if (dai->component == component)
986232213bdSCharles Keepax 			return true;
987232213bdSCharles Keepax 	}
988232213bdSCharles Keepax 
989232213bdSCharles Keepax 	return false;
990232213bdSCharles Keepax }
991232213bdSCharles Keepax 
snd_soc_pcm_component_delay(struct snd_pcm_substream * substream,snd_pcm_sframes_t * cpu_delay,snd_pcm_sframes_t * codec_delay)992403f830eSKuninori Morimoto void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
993403f830eSKuninori Morimoto 				 snd_pcm_sframes_t *cpu_delay,
994403f830eSKuninori Morimoto 				 snd_pcm_sframes_t *codec_delay)
995403f830eSKuninori Morimoto {
996403f830eSKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
997403f830eSKuninori Morimoto 	struct snd_soc_component *component;
998403f830eSKuninori Morimoto 	snd_pcm_sframes_t delay;
999403f830eSKuninori Morimoto 	int i;
1000403f830eSKuninori Morimoto 
1001403f830eSKuninori Morimoto 	/*
1002403f830eSKuninori Morimoto 	 * We're looking for the delay through the full audio path so it needs to
1003403f830eSKuninori Morimoto 	 * be the maximum of the Components doing transmit and the maximum of the
1004403f830eSKuninori Morimoto 	 * Components doing receive (ie, all CPUs and all CODECs) rather than
1005403f830eSKuninori Morimoto 	 * just the maximum of all Components.
1006403f830eSKuninori Morimoto 	 */
1007403f830eSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1008403f830eSKuninori Morimoto 		if (!component->driver->delay)
1009403f830eSKuninori Morimoto 			continue;
1010403f830eSKuninori Morimoto 
1011403f830eSKuninori Morimoto 		delay = component->driver->delay(component, substream);
1012403f830eSKuninori Morimoto 
1013232213bdSCharles Keepax 		if (snd_soc_component_is_codec_on_rtd(rtd, component))
1014403f830eSKuninori Morimoto 			*codec_delay = max(*codec_delay, delay);
1015403f830eSKuninori Morimoto 		else
1016403f830eSKuninori Morimoto 			*cpu_delay = max(*cpu_delay, delay);
1017403f830eSKuninori Morimoto 	}
1018403f830eSKuninori Morimoto }
1019403f830eSKuninori Morimoto 
snd_soc_pcm_component_ioctl(struct snd_pcm_substream * substream,unsigned int cmd,void * arg)102096a47908SKuninori Morimoto int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
102196a47908SKuninori Morimoto 				unsigned int cmd, void *arg)
102296a47908SKuninori Morimoto {
10230ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
102496a47908SKuninori Morimoto 	struct snd_soc_component *component;
1025613fb500SKuninori Morimoto 	int i;
102696a47908SKuninori Morimoto 
102796a47908SKuninori Morimoto 	/* FIXME: use 1st ioctl */
1028613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
1029e2cb4a14SKuninori Morimoto 		if (component->driver->ioctl)
1030e2329eebSKuninori Morimoto 			return soc_component_ret(
1031e2329eebSKuninori Morimoto 				component,
1032e2329eebSKuninori Morimoto 				component->driver->ioctl(component,
1033e2329eebSKuninori Morimoto 							 substream, cmd, arg));
103496a47908SKuninori Morimoto 
103596a47908SKuninori Morimoto 	return snd_pcm_lib_ioctl(substream, cmd, arg);
103696a47908SKuninori Morimoto }
103782d81f5cSKuninori Morimoto 
snd_soc_pcm_component_sync_stop(struct snd_pcm_substream * substream)10381e5ddb6bSTakashi Iwai int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream)
10391e5ddb6bSTakashi Iwai {
10400ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
10411e5ddb6bSTakashi Iwai 	struct snd_soc_component *component;
1042613fb500SKuninori Morimoto 	int i, ret;
10431e5ddb6bSTakashi Iwai 
1044613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1045f1861a7cSKuninori Morimoto 		if (component->driver->sync_stop) {
10461e5ddb6bSTakashi Iwai 			ret = component->driver->sync_stop(component,
10471e5ddb6bSTakashi Iwai 							   substream);
10481e5ddb6bSTakashi Iwai 			if (ret < 0)
1049be75db57SShengjiu Wang 				return soc_component_ret(component, ret);
10501e5ddb6bSTakashi Iwai 		}
10511e5ddb6bSTakashi Iwai 	}
10521e5ddb6bSTakashi Iwai 
10531e5ddb6bSTakashi Iwai 	return 0;
10541e5ddb6bSTakashi Iwai }
10551e5ddb6bSTakashi Iwai 
snd_soc_pcm_component_copy(struct snd_pcm_substream * substream,int channel,unsigned long pos,struct iov_iter * iter,unsigned long bytes)105666201cacSTakashi Iwai int snd_soc_pcm_component_copy(struct snd_pcm_substream *substream,
105766201cacSTakashi Iwai 			       int channel, unsigned long pos,
1058ef98a488STakashi Iwai 			       struct iov_iter *iter, unsigned long bytes)
105966201cacSTakashi Iwai {
106066201cacSTakashi Iwai 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
106166201cacSTakashi Iwai 	struct snd_soc_component *component;
106266201cacSTakashi Iwai 	int i;
106366201cacSTakashi Iwai 
106466201cacSTakashi Iwai 	/* FIXME. it returns 1st copy now */
106566201cacSTakashi Iwai 	for_each_rtd_components(rtd, i, component)
106666201cacSTakashi Iwai 		if (component->driver->copy)
106766201cacSTakashi Iwai 			return soc_component_ret(component,
106866201cacSTakashi Iwai 				component->driver->copy(component, substream,
1069ef98a488STakashi Iwai 					channel, pos, iter, bytes));
107066201cacSTakashi Iwai 
107166201cacSTakashi Iwai 	return -EINVAL;
107266201cacSTakashi Iwai }
107366201cacSTakashi Iwai 
snd_soc_pcm_component_page(struct snd_pcm_substream * substream,unsigned long offset)10749c712e4fSKuninori Morimoto struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream,
10759c712e4fSKuninori Morimoto 					unsigned long offset)
10769c712e4fSKuninori Morimoto {
10770ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
10789c712e4fSKuninori Morimoto 	struct snd_soc_component *component;
10799c712e4fSKuninori Morimoto 	struct page *page;
1080613fb500SKuninori Morimoto 	int i;
10819c712e4fSKuninori Morimoto 
10829c712e4fSKuninori Morimoto 	/* FIXME. it returns 1st page now */
1083613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1084e2cb4a14SKuninori Morimoto 		if (component->driver->page) {
1085e2cb4a14SKuninori Morimoto 			page = component->driver->page(component,
1086e2cb4a14SKuninori Morimoto 						       substream, offset);
1087e2cb4a14SKuninori Morimoto 			if (page)
1088e2cb4a14SKuninori Morimoto 				return page;
1089e2cb4a14SKuninori Morimoto 		}
10909c712e4fSKuninori Morimoto 	}
10919c712e4fSKuninori Morimoto 
10929c712e4fSKuninori Morimoto 	return NULL;
10939c712e4fSKuninori Morimoto }
1094205875e1SKuninori Morimoto 
snd_soc_pcm_component_mmap(struct snd_pcm_substream * substream,struct vm_area_struct * vma)1095205875e1SKuninori Morimoto int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream,
1096205875e1SKuninori Morimoto 			       struct vm_area_struct *vma)
1097205875e1SKuninori Morimoto {
10980ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1099205875e1SKuninori Morimoto 	struct snd_soc_component *component;
1100613fb500SKuninori Morimoto 	int i;
1101205875e1SKuninori Morimoto 
1102205875e1SKuninori Morimoto 	/* FIXME. it returns 1st mmap now */
1103613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
1104e2cb4a14SKuninori Morimoto 		if (component->driver->mmap)
1105be75db57SShengjiu Wang 			return soc_component_ret(
1106e2329eebSKuninori Morimoto 				component,
1107e2329eebSKuninori Morimoto 				component->driver->mmap(component,
1108e2329eebSKuninori Morimoto 							substream, vma));
1109205875e1SKuninori Morimoto 
1110205875e1SKuninori Morimoto 	return -EINVAL;
1111205875e1SKuninori Morimoto }
11127484291eSKuninori Morimoto 
snd_soc_pcm_component_new(struct snd_soc_pcm_runtime * rtd)1113b2b2afbbSKuninori Morimoto int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd)
11147484291eSKuninori Morimoto {
11157484291eSKuninori Morimoto 	struct snd_soc_component *component;
11167484291eSKuninori Morimoto 	int ret;
1117613fb500SKuninori Morimoto 	int i;
11187484291eSKuninori Morimoto 
1119613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1120c64bfc90SKuninori Morimoto 		if (component->driver->pcm_construct) {
1121c64bfc90SKuninori Morimoto 			ret = component->driver->pcm_construct(component, rtd);
1122c64bfc90SKuninori Morimoto 			if (ret < 0)
1123be75db57SShengjiu Wang 				return soc_component_ret(component, ret);
1124c64bfc90SKuninori Morimoto 		}
11257484291eSKuninori Morimoto 	}
11267484291eSKuninori Morimoto 
11277484291eSKuninori Morimoto 	return 0;
11287484291eSKuninori Morimoto }
112979776da0SKuninori Morimoto 
snd_soc_pcm_component_free(struct snd_soc_pcm_runtime * rtd)1130b2b2afbbSKuninori Morimoto void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd)
113179776da0SKuninori Morimoto {
113279776da0SKuninori Morimoto 	struct snd_soc_component *component;
1133613fb500SKuninori Morimoto 	int i;
113479776da0SKuninori Morimoto 
11358e3366caSTakashi Iwai 	if (!rtd->pcm)
11368e3366caSTakashi Iwai 		return;
11378e3366caSTakashi Iwai 
1138613fb500SKuninori Morimoto 	for_each_rtd_components(rtd, i, component)
1139c64bfc90SKuninori Morimoto 		if (component->driver->pcm_destruct)
1140b2b2afbbSKuninori Morimoto 			component->driver->pcm_destruct(component, rtd->pcm);
114179776da0SKuninori Morimoto }
11424f39514fSKuninori Morimoto 
snd_soc_pcm_component_prepare(struct snd_pcm_substream * substream)11434f39514fSKuninori Morimoto int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream)
11444f39514fSKuninori Morimoto {
11450ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
11464f39514fSKuninori Morimoto 	struct snd_soc_component *component;
11474f39514fSKuninori Morimoto 	int i, ret;
11484f39514fSKuninori Morimoto 
11494f39514fSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
11504f39514fSKuninori Morimoto 		if (component->driver->prepare) {
11514f39514fSKuninori Morimoto 			ret = component->driver->prepare(component, substream);
11524f39514fSKuninori Morimoto 			if (ret < 0)
11534f39514fSKuninori Morimoto 				return soc_component_ret(component, ret);
11544f39514fSKuninori Morimoto 		}
11554f39514fSKuninori Morimoto 	}
11564f39514fSKuninori Morimoto 
11574f39514fSKuninori Morimoto 	return 0;
11584f39514fSKuninori Morimoto }
1159e1bafa82SKuninori Morimoto 
snd_soc_pcm_component_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)1160e1bafa82SKuninori Morimoto int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
11613a36a64aSKuninori Morimoto 				    struct snd_pcm_hw_params *params)
1162e1bafa82SKuninori Morimoto {
11630ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
1164e1bafa82SKuninori Morimoto 	struct snd_soc_component *component;
1165e1bafa82SKuninori Morimoto 	int i, ret;
1166e1bafa82SKuninori Morimoto 
1167e1bafa82SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1168e1bafa82SKuninori Morimoto 		if (component->driver->hw_params) {
1169e1bafa82SKuninori Morimoto 			ret = component->driver->hw_params(component,
1170e1bafa82SKuninori Morimoto 							   substream, params);
11713a36a64aSKuninori Morimoto 			if (ret < 0)
1172e1bafa82SKuninori Morimoto 				return soc_component_ret(component, ret);
1173e1bafa82SKuninori Morimoto 		}
11743a36a64aSKuninori Morimoto 		/* mark substream if succeeded */
11753a36a64aSKuninori Morimoto 		soc_component_mark_push(component, substream, hw_params);
1176e1bafa82SKuninori Morimoto 	}
1177e1bafa82SKuninori Morimoto 
1178e1bafa82SKuninori Morimoto 	return 0;
1179e1bafa82SKuninori Morimoto }
118004751119SKuninori Morimoto 
snd_soc_pcm_component_hw_free(struct snd_pcm_substream * substream,int rollback)118104751119SKuninori Morimoto void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
11823a36a64aSKuninori Morimoto 				   int rollback)
118304751119SKuninori Morimoto {
11840ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
118504751119SKuninori Morimoto 	struct snd_soc_component *component;
118604751119SKuninori Morimoto 	int i, ret;
118704751119SKuninori Morimoto 
118804751119SKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
11893a36a64aSKuninori Morimoto 		if (rollback && !soc_component_mark_match(component, substream, hw_params))
11903a36a64aSKuninori Morimoto 			continue;
119104751119SKuninori Morimoto 
119204751119SKuninori Morimoto 		if (component->driver->hw_free) {
119304751119SKuninori Morimoto 			ret = component->driver->hw_free(component, substream);
119404751119SKuninori Morimoto 			if (ret < 0)
119504751119SKuninori Morimoto 				soc_component_ret(component, ret);
119604751119SKuninori Morimoto 		}
11973a36a64aSKuninori Morimoto 
11983a36a64aSKuninori Morimoto 		/* remove marked substream */
11993a36a64aSKuninori Morimoto 		soc_component_mark_pop(component, substream, hw_params);
120004751119SKuninori Morimoto 	}
120104751119SKuninori Morimoto }
120232fd1204SKuninori Morimoto 
soc_component_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)12036374f493SKuninori Morimoto static int soc_component_trigger(struct snd_soc_component *component,
12046374f493SKuninori Morimoto 				 struct snd_pcm_substream *substream,
120532fd1204SKuninori Morimoto 				 int cmd)
120632fd1204SKuninori Morimoto {
12076374f493SKuninori Morimoto 	int ret = 0;
12086374f493SKuninori Morimoto 
12096374f493SKuninori Morimoto 	if (component->driver->trigger)
12106374f493SKuninori Morimoto 		ret = component->driver->trigger(component, substream, cmd);
12116374f493SKuninori Morimoto 
12126374f493SKuninori Morimoto 	return soc_component_ret(component, ret);
12136374f493SKuninori Morimoto }
12146374f493SKuninori Morimoto 
snd_soc_pcm_component_trigger(struct snd_pcm_substream * substream,int cmd,int rollback)12156374f493SKuninori Morimoto int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
12166374f493SKuninori Morimoto 				  int cmd, int rollback)
12176374f493SKuninori Morimoto {
12180ceef681SKuninori Morimoto 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
121932fd1204SKuninori Morimoto 	struct snd_soc_component *component;
12206374f493SKuninori Morimoto 	int i, r, ret = 0;
122132fd1204SKuninori Morimoto 
12226374f493SKuninori Morimoto 	switch (cmd) {
12236374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_START:
12246374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_RESUME:
12256374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
122632fd1204SKuninori Morimoto 		for_each_rtd_components(rtd, i, component) {
12276374f493SKuninori Morimoto 			ret = soc_component_trigger(component, substream, cmd);
122832fd1204SKuninori Morimoto 			if (ret < 0)
12296374f493SKuninori Morimoto 				break;
12306374f493SKuninori Morimoto 			soc_component_mark_push(component, substream, trigger);
12316374f493SKuninori Morimoto 		}
12326374f493SKuninori Morimoto 		break;
12336374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_STOP:
12346374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_SUSPEND:
12356374f493SKuninori Morimoto 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
12366374f493SKuninori Morimoto 		for_each_rtd_components(rtd, i, component) {
12376374f493SKuninori Morimoto 			if (rollback && !soc_component_mark_match(component, substream, trigger))
12386374f493SKuninori Morimoto 				continue;
12396374f493SKuninori Morimoto 
12406374f493SKuninori Morimoto 			r = soc_component_trigger(component, substream, cmd);
12416374f493SKuninori Morimoto 			if (r < 0)
12426374f493SKuninori Morimoto 				ret = r; /* use last ret */
12436374f493SKuninori Morimoto 			soc_component_mark_pop(component, substream, trigger);
124432fd1204SKuninori Morimoto 		}
124532fd1204SKuninori Morimoto 	}
124632fd1204SKuninori Morimoto 
12476374f493SKuninori Morimoto 	return ret;
124832fd1204SKuninori Morimoto }
1249939a5cfbSKuninori Morimoto 
snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime * rtd,void * stream)1250939a5cfbSKuninori Morimoto int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
1251939a5cfbSKuninori Morimoto 					 void *stream)
1252939a5cfbSKuninori Morimoto {
1253939a5cfbSKuninori Morimoto 	struct snd_soc_component *component;
1254500b39daSKuninori Morimoto 	int i;
1255939a5cfbSKuninori Morimoto 
1256939a5cfbSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
12570c72dbc9SPeter Ujfalusi 		int ret = pm_runtime_get_sync(component->dev);
12580c72dbc9SPeter Ujfalusi 		if (ret < 0 && ret != -EACCES) {
12590c72dbc9SPeter Ujfalusi 			pm_runtime_put_noidle(component->dev);
1260939a5cfbSKuninori Morimoto 			return soc_component_ret(component, ret);
12610c72dbc9SPeter Ujfalusi 		}
1262939a5cfbSKuninori Morimoto 		/* mark stream if succeeded */
1263939a5cfbSKuninori Morimoto 		soc_component_mark_push(component, stream, pm);
1264939a5cfbSKuninori Morimoto 	}
1265939a5cfbSKuninori Morimoto 
1266939a5cfbSKuninori Morimoto 	return 0;
1267939a5cfbSKuninori Morimoto }
1268939a5cfbSKuninori Morimoto 
snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime * rtd,void * stream,int rollback)1269939a5cfbSKuninori Morimoto void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
1270939a5cfbSKuninori Morimoto 					  void *stream, int rollback)
1271939a5cfbSKuninori Morimoto {
1272939a5cfbSKuninori Morimoto 	struct snd_soc_component *component;
1273939a5cfbSKuninori Morimoto 	int i;
1274939a5cfbSKuninori Morimoto 
1275939a5cfbSKuninori Morimoto 	for_each_rtd_components(rtd, i, component) {
1276939a5cfbSKuninori Morimoto 		if (rollback && !soc_component_mark_match(component, stream, pm))
1277939a5cfbSKuninori Morimoto 			continue;
1278939a5cfbSKuninori Morimoto 
1279939a5cfbSKuninori Morimoto 		pm_runtime_mark_last_busy(component->dev);
1280939a5cfbSKuninori Morimoto 		pm_runtime_put_autosuspend(component->dev);
1281939a5cfbSKuninori Morimoto 
1282939a5cfbSKuninori Morimoto 		/* remove marked stream */
1283939a5cfbSKuninori Morimoto 		soc_component_mark_pop(component, stream, pm);
1284939a5cfbSKuninori Morimoto 	}
1285939a5cfbSKuninori Morimoto }
12868bdfc045SShengjiu Wang 
snd_soc_pcm_component_ack(struct snd_pcm_substream * substream)12878bdfc045SShengjiu Wang int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream)
12888bdfc045SShengjiu Wang {
12898bdfc045SShengjiu Wang 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
12908bdfc045SShengjiu Wang 	struct snd_soc_component *component;
12918bdfc045SShengjiu Wang 	int i;
12928bdfc045SShengjiu Wang 
12938bdfc045SShengjiu Wang 	/* FIXME: use 1st pointer */
12948bdfc045SShengjiu Wang 	for_each_rtd_components(rtd, i, component)
12958bdfc045SShengjiu Wang 		if (component->driver->ack)
12968bdfc045SShengjiu Wang 			return component->driver->ack(component, substream);
12978bdfc045SShengjiu Wang 
12988bdfc045SShengjiu Wang 	return 0;
12998bdfc045SShengjiu Wang }
1300