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